diff --git a/3rdparty/spirv-tools/test/CMakeLists.txt b/3rdparty/spirv-tools/test/CMakeLists.txt deleted file mode 100644 index 3dca430c8..000000000 --- a/3rdparty/spirv-tools/test/CMakeLists.txt +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright (c) 2015-2016 The Khronos Group 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. - -# Add a SPIR-V Tools unit test. Signature: -# add_spvtools_unittest( -# TARGET target_name -# SRCS src_file.h src_file.cpp -# LIBS lib1 lib2 -# ) - -if (NOT "${SPIRV_SKIP_TESTS}") - if (TARGET gmock_main) - message(STATUS "Found Google Mock, building tests.") - else() - message(STATUS "Did not find googletest, tests will not be built. " - "To enable tests place googletest in '/external/googletest'.") - endif() -endif() - -function(add_spvtools_unittest) - if (NOT "${SPIRV_SKIP_TESTS}" AND TARGET gmock_main) - set(one_value_args TARGET PCH_FILE) - set(multi_value_args SRCS LIBS ENVIRONMENT) - cmake_parse_arguments( - ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN}) - set(target test_${ARG_TARGET}) - set(SRC_COPY ${ARG_SRCS}) - if (DEFINED ARG_PCH_FILE) - spvtools_pch(SRC_COPY ${ARG_PCH_FILE}) - endif() - add_executable(${target} ${SRC_COPY}) - spvtools_default_compile_options(${target}) - if(${COMPILER_IS_LIKE_GNU}) - target_compile_options(${target} PRIVATE -Wno-undef) - # Effcee and RE2 headers exhibit shadowing. - target_compile_options(${target} PRIVATE -Wno-shadow) - endif() - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - # Disable C4503 "decorated name length exceeded" warning, - # triggered by some heavily templated types. - # We don't care much about that in test code. - # Important to do since we have warnings-as-errors. - target_compile_options(${target} PRIVATE /wd4503) - # Googletest accidentally turns off support for ::testing::Combine - # in VS 2017. See https://github.com/google/googletest/issues/1352 - # Forcibly turn it on again. - target_compile_options(${target} PRIVATE /DGTEST_HAS_COMBINE=1) - endif() - target_include_directories(${target} PRIVATE - ${SPIRV_HEADER_INCLUDE_DIR} - ${spirv-tools_SOURCE_DIR} - ${spirv-tools_SOURCE_DIR}/include - ${spirv-tools_SOURCE_DIR}/test - ${spirv-tools_BINARY_DIR} - ${gtest_SOURCE_DIR}/include - ${gmock_SOURCE_DIR}/include - ) - if (TARGET effcee) - # If using Effcee for testing, then add its include directory. - target_include_directories(${target} PRIVATE ${effcee_SOURCE_DIR}) - endif() - target_link_libraries(${target} PRIVATE ${ARG_LIBS}) - if (TARGET effcee) - target_link_libraries(${target} PRIVATE effcee) - endif() - target_link_libraries(${target} PRIVATE gmock_main) - add_test(NAME spirv-tools-${target} COMMAND ${target}) - if (DEFINED ARG_ENVIRONMENT) - set_tests_properties(spirv-tools-${target} PROPERTIES ENVIRONMENT ${ARG_ENVIRONMENT}) - endif() - set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools tests") - endif() -endfunction() - -set(TEST_SOURCES - test_fixture.h - unit_spirv.h - - assembly_context_test.cpp - assembly_format_test.cpp - binary_destroy_test.cpp - binary_endianness_test.cpp - binary_header_get_test.cpp - binary_parse_test.cpp - binary_strnlen_s_test.cpp - binary_to_text_test.cpp - binary_to_text.literal_test.cpp - comment_test.cpp - diagnostic_test.cpp - enum_string_mapping_test.cpp - enum_set_test.cpp - ext_inst.debuginfo_test.cpp - ext_inst.glsl_test.cpp - ext_inst.opencl_test.cpp - fix_word_test.cpp - generator_magic_number_test.cpp - hex_float_test.cpp - immediate_int_test.cpp - libspirv_macros_test.cpp - log_test.cpp - named_id_test.cpp - name_mapper_test.cpp - opcode_make_test.cpp - opcode_require_capabilities_test.cpp - opcode_split_test.cpp - opcode_table_get_test.cpp - operand_capabilities_test.cpp - operand_test.cpp - operand_pattern_test.cpp - parse_number_test.cpp - preserve_numeric_ids_test.cpp - software_version_test.cpp - string_utils_test.cpp - target_env_test.cpp - text_advance_test.cpp - text_destroy_test.cpp - text_literal_test.cpp - text_start_new_inst_test.cpp - text_to_binary.annotation_test.cpp - text_to_binary.barrier_test.cpp - text_to_binary.composite_test.cpp - text_to_binary.constant_test.cpp - text_to_binary.control_flow_test.cpp - text_to_binary_test.cpp - text_to_binary.debug_test.cpp - text_to_binary.device_side_enqueue_test.cpp - text_to_binary.extension_test.cpp - text_to_binary.function_test.cpp - text_to_binary.group_test.cpp - text_to_binary.image_test.cpp - text_to_binary.literal_test.cpp - text_to_binary.memory_test.cpp - text_to_binary.misc_test.cpp - text_to_binary.mode_setting_test.cpp - text_to_binary.pipe_storage_test.cpp - text_to_binary.type_declaration_test.cpp - text_to_binary.subgroup_dispatch_test.cpp - text_to_binary.reserved_sampling_test.cpp - text_word_get_test.cpp - - unit_spirv.cpp -) - -spvtools_pch(TEST_SOURCES pch_test) - -add_spvtools_unittest( - TARGET spirv_unit_tests - SRCS ${TEST_SOURCES} - LIBS ${SPIRV_TOOLS}) - -add_spvtools_unittest( - TARGET c_interface - SRCS c_interface_test.cpp - LIBS ${SPIRV_TOOLS}) - -add_spvtools_unittest( - TARGET c_interface_shared - SRCS c_interface_test.cpp - LIBS ${SPIRV_TOOLS}-shared - ENVIRONMENT PATH=$) - -add_spvtools_unittest( - TARGET cpp_interface - SRCS cpp_interface_test.cpp - LIBS SPIRV-Tools-opt) - -if (${SPIRV_TIMER_ENABLED}) -add_spvtools_unittest( - TARGET timer - SRCS timer_test.cpp - LIBS ${SPIRV_TOOLS}) -endif() - - -add_subdirectory(link) -add_subdirectory(opt) -add_subdirectory(reduce) -add_subdirectory(fuzz) -add_subdirectory(tools) -add_subdirectory(util) -add_subdirectory(val) diff --git a/3rdparty/spirv-tools/test/assembly_context_test.cpp b/3rdparty/spirv-tools/test/assembly_context_test.cpp deleted file mode 100644 index c8aa06be7..000000000 --- a/3rdparty/spirv-tools/test/assembly_context_test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/instruction.h" -#include "source/util/string_utils.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::AutoText; -using spvtest::Concatenate; -using ::testing::Eq; - -struct EncodeStringCase { - std::string str; - std::vector initial_contents; -}; - -using EncodeStringTest = ::testing::TestWithParam; - -TEST_P(EncodeStringTest, Sample) { - AssemblyContext context(AutoText(""), nullptr); - spv_instruction_t inst; - inst.words = GetParam().initial_contents; - ASSERT_EQ(SPV_SUCCESS, - context.binaryEncodeString(GetParam().str.c_str(), &inst)); - // We already trust MakeVector - EXPECT_THAT(inst.words, Eq(Concatenate({GetParam().initial_contents, - utils::MakeVector(GetParam().str)}))); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - BinaryEncodeString, EncodeStringTest, - ::testing::ValuesIn(std::vector{ - // Use cases that exercise at least one to two words, - // and both empty and non-empty initial contents. - {"", {}}, - {"", {1,2,3}}, - {"a", {}}, - {"a", {4}}, - {"ab", {4}}, - {"abc", {}}, - {"abc", {18}}, - {"abcd", {}}, - {"abcd", {22}}, - {"abcde", {4}}, - {"abcdef", {}}, - {"abcdef", {99,42}}, - {"abcdefg", {}}, - {"abcdefg", {101}}, - {"abcdefgh", {}}, - {"abcdefgh", {102, 103, 104}}, - // A very long string, encoded after an initial word. - // SPIR-V limits strings to 65535 characters. - {std::string(65535, 'a'), {1}}, - })); -// clang-format on - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/assembly_format_test.cpp b/3rdparty/spirv-tools/test/assembly_format_test.cpp deleted file mode 100644 index 718e6d3ce..000000000 --- a/3rdparty/spirv-tools/test/assembly_format_test.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/test_fixture.h" - -namespace svptools { -namespace { - -using spvtest::ScopedContext; -using spvtest::TextToBinaryTest; - -TEST_F(TextToBinaryTest, InstOpcodeProducesResultIDButNoIDDefinedFails) { - SetText("OpTypeMatrix %1 %2 1000"); - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, - spvTextToBinary(ScopedContext().context, text.str, text.length, - &binary, &diagnostic)); - ASSERT_NE(nullptr, diagnostic); - EXPECT_STREQ( - "Expected at the beginning of an instruction, found " - "'OpTypeMatrix'.", - diagnostic->error); - EXPECT_EQ(0u, diagnostic->position.line); -} - -TEST_F(TextToBinaryTest, - InstDefinesResultIDButOpcodeDoesNotProduceAResultFails) { - SetText("\n\n%foo = OpName %1 \"bar\""); - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, - spvTextToBinary(ScopedContext().context, text.str, text.length, - &binary, &diagnostic)); - ASSERT_NE(nullptr, diagnostic); - EXPECT_STREQ( - "Cannot set ID %foo because OpName does not produce a result ID.", - diagnostic->error); - EXPECT_EQ(2u, diagnostic->position.line); -} - -} // namespace -} // namespace svptools diff --git a/3rdparty/spirv-tools/test/binary_destroy_test.cpp b/3rdparty/spirv-tools/test/binary_destroy_test.cpp deleted file mode 100644 index e3870c9f0..000000000 --- a/3rdparty/spirv-tools/test/binary_destroy_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using spvtest::ScopedContext; - -TEST(BinaryDestroy, Null) { - // There is no state or return value to check. Just check - // for the ability to call the API without abnormal termination. - spvBinaryDestroy(nullptr); -} - -using BinaryDestroySomething = spvtest::TextToBinaryTest; - -// Checks safety of destroying a validly constructed binary. -TEST_F(BinaryDestroySomething, Default) { - // Use a binary object constructed by the API instead of rolling our own. - SetText("OpSource OpenCL_C 120"); - spv_binary my_binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(ScopedContext().context, text.str, - text.length, &my_binary, &diagnostic)); - ASSERT_NE(nullptr, my_binary); - spvBinaryDestroy(my_binary); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/binary_endianness_test.cpp b/3rdparty/spirv-tools/test/binary_endianness_test.cpp deleted file mode 100644 index 3cd405d52..000000000 --- a/3rdparty/spirv-tools/test/binary_endianness_test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -TEST(BinaryEndianness, InvalidCode) { - uint32_t invalidMagicNumber[] = {0}; - spv_const_binary_t binary = {invalidMagicNumber, 1}; - spv_endianness_t endian; - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, spvBinaryEndianness(&binary, &endian)); -} - -TEST(BinaryEndianness, Little) { - uint32_t magicNumber; - if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) { - magicNumber = 0x07230203; - } else { - magicNumber = 0x03022307; - } - spv_const_binary_t binary = {&magicNumber, 1}; - spv_endianness_t endian; - ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian)); - ASSERT_EQ(SPV_ENDIANNESS_LITTLE, endian); -} - -TEST(BinaryEndianness, Big) { - uint32_t magicNumber; - if (I32_ENDIAN_HOST == I32_ENDIAN_BIG) { - magicNumber = 0x07230203; - } else { - magicNumber = 0x03022307; - } - spv_const_binary_t binary = {&magicNumber, 1}; - spv_endianness_t endian; - ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian)); - ASSERT_EQ(SPV_ENDIANNESS_BIG, endian); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/binary_header_get_test.cpp b/3rdparty/spirv-tools/test/binary_header_get_test.cpp deleted file mode 100644 index f8f6bdbd8..000000000 --- a/3rdparty/spirv-tools/test/binary_header_get_test.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "source/spirv_constant.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -class BinaryHeaderGet : public ::testing::Test { - public: - BinaryHeaderGet() { memset(code, 0, sizeof(code)); } - - virtual void SetUp() { - code[0] = SpvMagicNumber; - code[1] = SpvVersion; - code[2] = SPV_GENERATOR_CODEPLAY; - code[3] = 1; // NOTE: Bound - code[4] = 0; // NOTE: Schema; reserved - code[5] = 0; // NOTE: Instructions - - binary.code = code; - binary.wordCount = 6; - } - spv_const_binary_t get_const_binary() { - return spv_const_binary_t{binary.code, binary.wordCount}; - } - virtual void TearDown() {} - - uint32_t code[6]; - spv_binary_t binary; -}; - -TEST_F(BinaryHeaderGet, Default) { - spv_endianness_t endian; - spv_const_binary_t const_bin = get_const_binary(); - ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&const_bin, &endian)); - - spv_header_t header; - ASSERT_EQ(SPV_SUCCESS, spvBinaryHeaderGet(&const_bin, endian, &header)); - - ASSERT_EQ(static_cast(SpvMagicNumber), header.magic); - // Expect SPIRV-Headers updated to SPIR-V 1.5. - ASSERT_EQ(0x00010500u, header.version); - ASSERT_EQ(static_cast(SPV_GENERATOR_CODEPLAY), header.generator); - ASSERT_EQ(1u, header.bound); - ASSERT_EQ(0u, header.schema); - ASSERT_EQ(&code[5], header.instructions); -} - -TEST_F(BinaryHeaderGet, InvalidCode) { - spv_const_binary_t my_binary = {nullptr, 0}; - spv_header_t header; - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryHeaderGet(&my_binary, SPV_ENDIANNESS_LITTLE, &header)); -} - -TEST_F(BinaryHeaderGet, InvalidPointerHeader) { - spv_const_binary_t const_bin = get_const_binary(); - ASSERT_EQ(SPV_ERROR_INVALID_POINTER, - spvBinaryHeaderGet(&const_bin, SPV_ENDIANNESS_LITTLE, nullptr)); -} - -TEST_F(BinaryHeaderGet, TruncatedHeader) { - for (uint8_t i = 1; i < SPV_INDEX_INSTRUCTION; i++) { - binary.wordCount = i; - spv_const_binary_t const_bin = get_const_binary(); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryHeaderGet(&const_bin, SPV_ENDIANNESS_LITTLE, nullptr)); - } -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/binary_parse_test.cpp b/3rdparty/spirv-tools/test/binary_parse_test.cpp deleted file mode 100644 index 54664fce7..000000000 --- a/3rdparty/spirv-tools/test/binary_parse_test.cpp +++ /dev/null @@ -1,893 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/latest_version_opencl_std_header.h" -#include "source/table.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -// Returns true if two spv_parsed_operand_t values are equal. -// To use this operator, this definition must appear in the same namespace -// as spv_parsed_operand_t. -static bool operator==(const spv_parsed_operand_t& a, - const spv_parsed_operand_t& b) { - return a.offset == b.offset && a.num_words == b.num_words && - a.type == b.type && a.number_kind == b.number_kind && - a.number_bit_width == b.number_bit_width; -} - -namespace spvtools { -namespace { - -using ::spvtest::Concatenate; -using ::spvtest::MakeInstruction; -using utils::MakeVector; -using ::spvtest::ScopedContext; -using ::testing::_; -using ::testing::AnyOf; -using ::testing::Eq; -using ::testing::InSequence; -using ::testing::Return; - -// An easily-constructible and comparable object for the contents of an -// spv_parsed_instruction_t. Unlike spv_parsed_instruction_t, owns the memory -// of its components. -struct ParsedInstruction { - explicit ParsedInstruction(const spv_parsed_instruction_t& inst) - : words(inst.words, inst.words + inst.num_words), - opcode(static_cast(inst.opcode)), - ext_inst_type(inst.ext_inst_type), - type_id(inst.type_id), - result_id(inst.result_id), - operands(inst.operands, inst.operands + inst.num_operands) {} - - std::vector words; - SpvOp opcode; - spv_ext_inst_type_t ext_inst_type; - uint32_t type_id; - uint32_t result_id; - std::vector operands; - - bool operator==(const ParsedInstruction& b) const { - return words == b.words && opcode == b.opcode && - ext_inst_type == b.ext_inst_type && type_id == b.type_id && - result_id == b.result_id && operands == b.operands; - } -}; - -// Prints a ParsedInstruction object to the given output stream, and returns -// the stream. -std::ostream& operator<<(std::ostream& os, const ParsedInstruction& inst) { - os << "\nParsedInstruction( {"; - spvtest::PrintTo(spvtest::WordVector(inst.words), &os); - os << "}, opcode: " << int(inst.opcode) - << " ext_inst_type: " << int(inst.ext_inst_type) - << " type_id: " << inst.type_id << " result_id: " << inst.result_id; - for (const auto& operand : inst.operands) { - os << " { offset: " << operand.offset << " num_words: " << operand.num_words - << " type: " << int(operand.type) - << " number_kind: " << int(operand.number_kind) - << " number_bit_width: " << int(operand.number_bit_width) << "}"; - } - os << ")"; - return os; -} - -// Sanity check for the equality operator on ParsedInstruction. -TEST(ParsedInstruction, ZeroInitializedAreEqual) { - spv_parsed_instruction_t pi = {}; - ParsedInstruction a(pi); - ParsedInstruction b(pi); - EXPECT_THAT(a, ::testing::TypedEq(b)); -} - -// Googlemock class receiving Header/Instruction calls from spvBinaryParse(). -class MockParseClient { - public: - MOCK_METHOD6(Header, spv_result_t(spv_endianness_t endian, uint32_t magic, - uint32_t version, uint32_t generator, - uint32_t id_bound, uint32_t reserved)); - MOCK_METHOD1(Instruction, spv_result_t(const ParsedInstruction&)); -}; - -// Casts user_data as MockParseClient and invokes its Header(). -spv_result_t invoke_header(void* user_data, spv_endianness_t endian, - uint32_t magic, uint32_t version, uint32_t generator, - uint32_t id_bound, uint32_t reserved) { - return static_cast(user_data)->Header( - endian, magic, version, generator, id_bound, reserved); -} - -// Casts user_data as MockParseClient and invokes its Instruction(). -spv_result_t invoke_instruction( - void* user_data, const spv_parsed_instruction_t* parsed_instruction) { - return static_cast(user_data)->Instruction( - ParsedInstruction(*parsed_instruction)); -} - -// The SPIR-V module header words for the Khronos Assembler generator, -// for a module with an ID bound of 1. -const uint32_t kHeaderForBound1[] = { - SpvMagicNumber, SpvVersion, - SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), 1 /*bound*/, - 0 /*schema*/}; - -// Returns the expected SPIR-V module header words for the Khronos -// Assembler generator, and with a given Id bound. -std::vector ExpectedHeaderForBound(uint32_t bound) { - return {SpvMagicNumber, 0x10000, - SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), bound, 0}; -} - -// Returns a parsed operand for a non-number value at the given word offset -// within an instruction. -spv_parsed_operand_t MakeSimpleOperand(uint16_t offset, - spv_operand_type_t type) { - return {offset, 1, type, SPV_NUMBER_NONE, 0}; -} - -// Returns a parsed operand for a literal unsigned integer value at the given -// word offset within an instruction. -spv_parsed_operand_t MakeLiteralNumberOperand(uint16_t offset) { - return {offset, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, - 32}; -} - -// Returns a parsed operand for a literal string value at the given -// word offset within an instruction. -spv_parsed_operand_t MakeLiteralStringOperand(uint16_t offset, - uint16_t length) { - return {offset, length, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_NUMBER_NONE, 0}; -} - -// Returns a ParsedInstruction for an OpTypeVoid instruction that would -// generate the given result Id. -ParsedInstruction MakeParsedVoidTypeInstruction(uint32_t result_id) { - const auto void_inst = MakeInstruction(SpvOpTypeVoid, {result_id}); - const auto void_operands = std::vector{ - MakeSimpleOperand(1, SPV_OPERAND_TYPE_RESULT_ID)}; - const spv_parsed_instruction_t parsed_void_inst = { - void_inst.data(), - static_cast(void_inst.size()), - SpvOpTypeVoid, - SPV_EXT_INST_TYPE_NONE, - 0, // type id - result_id, - void_operands.data(), - static_cast(void_operands.size())}; - return ParsedInstruction(parsed_void_inst); -} - -// Returns a ParsedInstruction for an OpTypeInt instruction that generates -// the given result Id for a 32-bit signed integer scalar type. -ParsedInstruction MakeParsedInt32TypeInstruction(uint32_t result_id) { - const auto i32_inst = MakeInstruction(SpvOpTypeInt, {result_id, 32, 1}); - const auto i32_operands = std::vector{ - MakeSimpleOperand(1, SPV_OPERAND_TYPE_RESULT_ID), - MakeLiteralNumberOperand(2), MakeLiteralNumberOperand(3)}; - spv_parsed_instruction_t parsed_i32_inst = { - i32_inst.data(), - static_cast(i32_inst.size()), - SpvOpTypeInt, - SPV_EXT_INST_TYPE_NONE, - 0, // type id - result_id, - i32_operands.data(), - static_cast(i32_operands.size())}; - return ParsedInstruction(parsed_i32_inst); -} - -class BinaryParseTest : public spvtest::TextToBinaryTestBase<::testing::Test> { - protected: - ~BinaryParseTest() { spvDiagnosticDestroy(diagnostic_); } - - void Parse(const SpirvVector& words, spv_result_t expected_result, - bool flip_words = false) { - SpirvVector flipped_words(words); - SCOPED_TRACE(flip_words ? "Flipped Endianness" : "Normal Endianness"); - if (flip_words) { - std::transform(flipped_words.begin(), flipped_words.end(), - flipped_words.begin(), [](const uint32_t raw_word) { - return spvFixWord(raw_word, - I32_ENDIAN_HOST == I32_ENDIAN_BIG - ? SPV_ENDIANNESS_LITTLE - : SPV_ENDIANNESS_BIG); - }); - } - EXPECT_EQ(expected_result, - spvBinaryParse(ScopedContext().context, &client_, - flipped_words.data(), flipped_words.size(), - invoke_header, invoke_instruction, &diagnostic_)); - } - - spv_diagnostic diagnostic_ = nullptr; - MockParseClient client_; -}; - -// Adds an EXPECT_CALL to client_->Header() with appropriate parameters, -// including bound. Returns the EXPECT_CALL result. -#define EXPECT_HEADER(bound) \ - EXPECT_CALL( \ - client_, \ - Header(AnyOf(SPV_ENDIANNESS_LITTLE, SPV_ENDIANNESS_BIG), SpvMagicNumber, \ - 0x10000, SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), \ - bound, 0 /*reserved*/)) - -static const bool kSwapEndians[] = {false, true}; - -TEST_F(BinaryParseTest, EmptyModuleHasValidHeaderAndNoInstructionCallbacks) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully(""); - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - Parse(words, SPV_SUCCESS, endian_swap); - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, NullDiagnosticsIsOkForGoodParse) { - const auto words = CompileSuccessfully(""); - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ( - SPV_SUCCESS, - spvBinaryParse(ScopedContext().context, &client_, words.data(), - words.size(), invoke_header, invoke_instruction, nullptr)); -} - -TEST_F(BinaryParseTest, NullDiagnosticsIsOkForBadParse) { - auto words = CompileSuccessfully(""); - words.push_back(0xffffffff); // Certainly invalid instruction header. - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ( - SPV_ERROR_INVALID_BINARY, - spvBinaryParse(ScopedContext().context, &client_, words.data(), - words.size(), invoke_header, invoke_instruction, nullptr)); -} - -// Make sure that we don't blow up when both the consumer and the diagnostic are -// null. -TEST_F(BinaryParseTest, NullConsumerNullDiagnosticsForBadParse) { - auto words = CompileSuccessfully(""); - - auto ctx = spvtools::Context(SPV_ENV_UNIVERSAL_1_1); - ctx.SetMessageConsumer(nullptr); - - words.push_back(0xffffffff); // Certainly invalid instruction header. - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryParse(ctx.CContext(), &client_, words.data(), words.size(), - invoke_header, invoke_instruction, nullptr)); -} - -TEST_F(BinaryParseTest, SpecifyConsumerNullDiagnosticsForGoodParse) { - const auto words = CompileSuccessfully(""); - - auto ctx = spvtools::Context(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - ctx.SetMessageConsumer([&invocation](spv_message_level_t, const char*, - const spv_position_t&, - const char*) { ++invocation; }); - - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ(SPV_SUCCESS, - spvBinaryParse(ctx.CContext(), &client_, words.data(), words.size(), - invoke_header, invoke_instruction, nullptr)); - EXPECT_EQ(0, invocation); -} - -TEST_F(BinaryParseTest, SpecifyConsumerNullDiagnosticsForBadParse) { - auto words = CompileSuccessfully(""); - - auto ctx = spvtools::Context(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - ctx.SetMessageConsumer( - [&invocation](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - ++invocation; - EXPECT_EQ(SPV_MSG_ERROR, level); - EXPECT_STREQ("input", source); - EXPECT_EQ(0u, position.line); - EXPECT_EQ(0u, position.column); - EXPECT_EQ(1u, position.index); - EXPECT_STREQ("Invalid opcode: 65535", message); - }); - - words.push_back(0xffffffff); // Certainly invalid instruction header. - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryParse(ctx.CContext(), &client_, words.data(), words.size(), - invoke_header, invoke_instruction, nullptr)); - EXPECT_EQ(1, invocation); -} - -TEST_F(BinaryParseTest, SpecifyConsumerSpecifyDiagnosticsForGoodParse) { - const auto words = CompileSuccessfully(""); - - auto ctx = spvtools::Context(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - ctx.SetMessageConsumer([&invocation](spv_message_level_t, const char*, - const spv_position_t&, - const char*) { ++invocation; }); - - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ(SPV_SUCCESS, - spvBinaryParse(ctx.CContext(), &client_, words.data(), words.size(), - invoke_header, invoke_instruction, &diagnostic_)); - EXPECT_EQ(0, invocation); - EXPECT_EQ(nullptr, diagnostic_); -} - -TEST_F(BinaryParseTest, SpecifyConsumerSpecifyDiagnosticsForBadParse) { - auto words = CompileSuccessfully(""); - - auto ctx = spvtools::Context(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - ctx.SetMessageConsumer([&invocation](spv_message_level_t, const char*, - const spv_position_t&, - const char*) { ++invocation; }); - - words.push_back(0xffffffff); // Certainly invalid instruction header. - EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryParse(ctx.CContext(), &client_, words.data(), words.size(), - invoke_header, invoke_instruction, &diagnostic_)); - EXPECT_EQ(0, invocation); - EXPECT_STREQ("Invalid opcode: 65535", diagnostic_->error); -} - -TEST_F(BinaryParseTest, - ModuleWithSingleInstructionHasValidHeaderAndInstructionCallback) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully("%1 = OpTypeVoid"); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(2).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1))) - .WillOnce(Return(SPV_SUCCESS)); - Parse(words, SPV_SUCCESS, endian_swap); - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, NullHeaderCallbackIsIgnored) { - const auto words = CompileSuccessfully("%1 = OpTypeVoid"); - EXPECT_CALL(client_, Header(_, _, _, _, _, _)) - .Times(0); // No header callback. - EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1))) - .WillOnce(Return(SPV_SUCCESS)); - EXPECT_EQ(SPV_SUCCESS, spvBinaryParse(ScopedContext().context, &client_, - words.data(), words.size(), nullptr, - invoke_instruction, &diagnostic_)); - EXPECT_EQ(nullptr, diagnostic_); -} - -TEST_F(BinaryParseTest, NullInstructionCallbackIsIgnored) { - const auto words = CompileSuccessfully("%1 = OpTypeVoid"); - EXPECT_HEADER((2)).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).Times(0); // No instruction callback. - EXPECT_EQ(SPV_SUCCESS, - spvBinaryParse(ScopedContext().context, &client_, words.data(), - words.size(), invoke_header, nullptr, &diagnostic_)); - EXPECT_EQ(nullptr, diagnostic_); -} - -// Check the result of multiple instruction callbacks. -// -// This test exercises non-default values for the following members of the -// spv_parsed_instruction_t struct: words, num_words, opcode, result_id, -// operands, num_operands. -TEST_F(BinaryParseTest, TwoScalarTypesGenerateTwoInstructionCallbacks) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully( - "%1 = OpTypeVoid " - "%2 = OpTypeInt 32 1"); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(3).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1))) - .WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(MakeParsedInt32TypeInstruction(2))) - .WillOnce(Return(SPV_SUCCESS)); - Parse(words, SPV_SUCCESS, endian_swap); - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, EarlyReturnWithZeroPassingCallbacks) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully( - "%1 = OpTypeVoid " - "%2 = OpTypeInt 32 1"); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(3).WillOnce(Return(SPV_ERROR_INVALID_BINARY)); - // Early exit means no calls to Instruction(). - EXPECT_CALL(client_, Instruction(_)).Times(0); - Parse(words, SPV_ERROR_INVALID_BINARY, endian_swap); - // On error, the binary parser doesn't generate its own diagnostics. - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, - EarlyReturnWithZeroPassingCallbacksAndSpecifiedResultCode) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully( - "%1 = OpTypeVoid " - "%2 = OpTypeInt 32 1"); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(3).WillOnce(Return(SPV_REQUESTED_TERMINATION)); - // Early exit means no calls to Instruction(). - EXPECT_CALL(client_, Instruction(_)).Times(0); - Parse(words, SPV_REQUESTED_TERMINATION, endian_swap); - // On early termination, the binary parser doesn't generate its own - // diagnostics. - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, EarlyReturnWithOnePassingCallback) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully( - "%1 = OpTypeVoid " - "%2 = OpTypeInt 32 1 " - "%3 = OpTypeFloat 32"); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(4).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1))) - .WillOnce(Return(SPV_REQUESTED_TERMINATION)); - Parse(words, SPV_REQUESTED_TERMINATION, endian_swap); - // On early termination, the binary parser doesn't generate its own - // diagnostics. - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, EarlyReturnWithTwoPassingCallbacks) { - for (bool endian_swap : kSwapEndians) { - const auto words = CompileSuccessfully( - "%1 = OpTypeVoid " - "%2 = OpTypeInt 32 1 " - "%3 = OpTypeFloat 32"); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(4).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(MakeParsedVoidTypeInstruction(1))) - .WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(MakeParsedInt32TypeInstruction(2))) - .WillOnce(Return(SPV_REQUESTED_TERMINATION)); - Parse(words, SPV_REQUESTED_TERMINATION, endian_swap); - // On early termination, the binary parser doesn't generate its own - // diagnostics. - EXPECT_EQ(nullptr, diagnostic_); - } -} - -TEST_F(BinaryParseTest, InstructionWithStringOperand) { - const std::string str = - "the future is already here, it's just not evenly distributed"; - const auto str_words = MakeVector(str); - const auto instruction = MakeInstruction(SpvOpName, {99}, str_words); - const auto words = Concatenate({ExpectedHeaderForBound(100), instruction}); - InSequence calls_expected_in_specific_order; - EXPECT_HEADER(100).WillOnce(Return(SPV_SUCCESS)); - const auto operands = std::vector{ - MakeSimpleOperand(1, SPV_OPERAND_TYPE_ID), - MakeLiteralStringOperand(2, static_cast(str_words.size()))}; - EXPECT_CALL(client_, - Instruction(ParsedInstruction(spv_parsed_instruction_t{ - instruction.data(), static_cast(instruction.size()), - SpvOpName, SPV_EXT_INST_TYPE_NONE, 0 /*type id*/, - 0 /* No result id for OpName*/, operands.data(), - static_cast(operands.size())}))) - .WillOnce(Return(SPV_SUCCESS)); - // Since we are actually checking the output, don't test the - // endian-swapped version. - Parse(words, SPV_SUCCESS, false); - EXPECT_EQ(nullptr, diagnostic_); -} - -// Checks for non-zero values for the result_id and ext_inst_type members -// spv_parsed_instruction_t. -TEST_F(BinaryParseTest, ExtendedInstruction) { - const auto words = CompileSuccessfully( - "%extcl = OpExtInstImport \"OpenCL.std\" " - "%result = OpExtInst %float %extcl sqrt %x"); - EXPECT_HEADER(5).WillOnce(Return(SPV_SUCCESS)); - EXPECT_CALL(client_, Instruction(_)).WillOnce(Return(SPV_SUCCESS)); - // We're only interested in the second call to Instruction(): - const auto operands = std::vector{ - MakeSimpleOperand(1, SPV_OPERAND_TYPE_TYPE_ID), - MakeSimpleOperand(2, SPV_OPERAND_TYPE_RESULT_ID), - MakeSimpleOperand(3, - SPV_OPERAND_TYPE_ID), // Extended instruction set Id - MakeSimpleOperand(4, SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER), - MakeSimpleOperand(5, SPV_OPERAND_TYPE_ID), // Id of the argument - }; - const auto instruction = MakeInstruction( - SpvOpExtInst, - {2, 3, 1, static_cast(OpenCLLIB::Entrypoints::Sqrt), 4}); - EXPECT_CALL(client_, - Instruction(ParsedInstruction(spv_parsed_instruction_t{ - instruction.data(), static_cast(instruction.size()), - SpvOpExtInst, SPV_EXT_INST_TYPE_OPENCL_STD, 2 /*type id*/, - 3 /*result id*/, operands.data(), - static_cast(operands.size())}))) - .WillOnce(Return(SPV_SUCCESS)); - // Since we are actually checking the output, don't test the - // endian-swapped version. - Parse(words, SPV_SUCCESS, false); - EXPECT_EQ(nullptr, diagnostic_); -} - -// A binary parser diagnostic test case where we provide the words array -// pointer and word count explicitly. -struct WordsAndCountDiagnosticCase { - const uint32_t* words; - size_t num_words; - std::string expected_diagnostic; -}; - -using BinaryParseWordsAndCountDiagnosticTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(BinaryParseWordsAndCountDiagnosticTest, WordAndCountCases) { - EXPECT_EQ( - SPV_ERROR_INVALID_BINARY, - spvBinaryParse(ScopedContext().context, nullptr, GetParam().words, - GetParam().num_words, nullptr, nullptr, &diagnostic)); - ASSERT_NE(nullptr, diagnostic); - EXPECT_THAT(diagnostic->error, Eq(GetParam().expected_diagnostic)); -} - -INSTANTIATE_TEST_SUITE_P( - BinaryParseDiagnostic, BinaryParseWordsAndCountDiagnosticTest, - ::testing::ValuesIn(std::vector{ - {nullptr, 0, "Missing module."}, - {kHeaderForBound1, 0, - "Module has incomplete header: only 0 words instead of 5"}, - {kHeaderForBound1, 1, - "Module has incomplete header: only 1 words instead of 5"}, - {kHeaderForBound1, 2, - "Module has incomplete header: only 2 words instead of 5"}, - {kHeaderForBound1, 3, - "Module has incomplete header: only 3 words instead of 5"}, - {kHeaderForBound1, 4, - "Module has incomplete header: only 4 words instead of 5"}, - })); - -// A binary parser diagnostic test case where a vector of words is -// provided. We'll use this to express cases that can't be created -// via the assembler. Either we want to make a malformed instruction, -// or an invalid case the assembler would reject. -struct WordVectorDiagnosticCase { - std::vector words; - std::string expected_diagnostic; -}; - -using BinaryParseWordVectorDiagnosticTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(BinaryParseWordVectorDiagnosticTest, WordVectorCases) { - const auto& words = GetParam().words; - EXPECT_THAT(spvBinaryParse(ScopedContext().context, nullptr, words.data(), - words.size(), nullptr, nullptr, &diagnostic), - AnyOf(SPV_ERROR_INVALID_BINARY, SPV_ERROR_INVALID_ID)); - ASSERT_NE(nullptr, diagnostic); - EXPECT_THAT(diagnostic->error, Eq(GetParam().expected_diagnostic)); -} - -INSTANTIATE_TEST_SUITE_P( - BinaryParseDiagnostic, BinaryParseWordVectorDiagnosticTest, - ::testing::ValuesIn(std::vector{ - {Concatenate({ExpectedHeaderForBound(1), {spvOpcodeMake(0, SpvOpNop)}}), - "Invalid instruction word count: 0"}, - {Concatenate( - {ExpectedHeaderForBound(1), - {spvOpcodeMake(1, static_cast( - std::numeric_limits::max()))}}), - "Invalid opcode: 65535"}, - {Concatenate({ExpectedHeaderForBound(1), - MakeInstruction(SpvOpNop, {42})}), - "Invalid instruction OpNop starting at word 5: expected " - "no more operands after 1 words, but stated word count is 2."}, - // Supply several more unexpectd words. - {Concatenate({ExpectedHeaderForBound(1), - MakeInstruction(SpvOpNop, {42, 43, 44, 45, 46, 47})}), - "Invalid instruction OpNop starting at word 5: expected " - "no more operands after 1 words, but stated word count is 7."}, - {Concatenate({ExpectedHeaderForBound(1), - MakeInstruction(SpvOpTypeVoid, {1, 2})}), - "Invalid instruction OpTypeVoid starting at word 5: expected " - "no more operands after 2 words, but stated word count is 3."}, - {Concatenate({ExpectedHeaderForBound(1), - MakeInstruction(SpvOpTypeVoid, {1, 2, 5, 9, 10})}), - "Invalid instruction OpTypeVoid starting at word 5: expected " - "no more operands after 2 words, but stated word count is 6."}, - {Concatenate({ExpectedHeaderForBound(1), - MakeInstruction(SpvOpTypeInt, {1, 32, 1, 9})}), - "Invalid instruction OpTypeInt starting at word 5: expected " - "no more operands after 4 words, but stated word count is 5."}, - {Concatenate({ExpectedHeaderForBound(1), - MakeInstruction(SpvOpTypeInt, {1})}), - "End of input reached while decoding OpTypeInt starting at word 5:" - " expected more operands after 2 words."}, - - // Check several cases for running off the end of input. - - // Detect a missing single word operand. - {Concatenate({ExpectedHeaderForBound(1), - {spvOpcodeMake(2, SpvOpTypeStruct)}}), - "End of input reached while decoding OpTypeStruct starting at word" - " 5: missing result ID operand at word offset 1."}, - // Detect this a missing a multi-word operand to OpConstant. - // We also lie and say the OpConstant instruction has 5 words when - // it only has 3. Corresponds to something like this: - // %1 = OpTypeInt 64 0 - // %2 = OpConstant %1 - {Concatenate({ExpectedHeaderForBound(3), - {MakeInstruction(SpvOpTypeInt, {1, 64, 0})}, - {spvOpcodeMake(5, SpvOpConstant), 1, 2}}), - "End of input reached while decoding OpConstant starting at word" - " 9: missing possibly multi-word literal number operand at word " - "offset 3."}, - // Detect when we provide only one word from the 64-bit literal, - // and again lie about the number of words in the instruction. - {Concatenate({ExpectedHeaderForBound(3), - {MakeInstruction(SpvOpTypeInt, {1, 64, 0})}, - {spvOpcodeMake(5, SpvOpConstant), 1, 2, 42}}), - "End of input reached while decoding OpConstant starting at word" - " 9: truncated possibly multi-word literal number operand at word " - "offset 3."}, - // Detect when a required string operand is missing. - // Also, lie about the length of the instruction. - {Concatenate({ExpectedHeaderForBound(3), - {spvOpcodeMake(3, SpvOpString), 1}}), - "End of input reached while decoding OpString starting at word" - " 5: missing literal string operand at word offset 2."}, - // Detect when a required string operand is truncated: it's missing - // a null terminator. Catching the error avoids a buffer overrun. - {Concatenate({ExpectedHeaderForBound(3), - {spvOpcodeMake(4, SpvOpString), 1, 0x41414141, - 0x41414141}}), - "End of input reached while decoding OpString starting at word" - " 5: truncated literal string operand at word offset 2."}, - // Detect when an optional string operand is truncated: it's missing - // a null terminator. Catching the error avoids a buffer overrun. - // (It is valid for an optional string operand to be absent.) - {Concatenate({ExpectedHeaderForBound(3), - {spvOpcodeMake(6, SpvOpSource), - static_cast(SpvSourceLanguageOpenCL_C), 210, - 1 /* file id */, - /*start of string*/ 0x41414141, 0x41414141}}), - "End of input reached while decoding OpSource starting at word" - " 5: truncated literal string operand at word offset 4."}, - - // (End of input exhaustion test cases.) - - // In this case the instruction word count is too small, where - // it would truncate a multi-word operand to OpConstant. - {Concatenate({ExpectedHeaderForBound(3), - {MakeInstruction(SpvOpTypeInt, {1, 64, 0})}, - {spvOpcodeMake(4, SpvOpConstant), 1, 2, 44, 44}}), - "Invalid word count: OpConstant starting at word 9 says it has 4" - " words, but found 5 words instead."}, - // Word count is to small, where it would truncate a literal string. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(3, SpvOpString), 1, 0x41414141, 0}}), - "Invalid word count: OpString starting at word 5 says it has 3" - " words, but found 4 words instead."}, - // Word count is too large. The string terminates before the last - // word. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(4, SpvOpString), 1 /* result id */}, - MakeVector("abc"), - {0 /* this word does not belong*/}}), - "Invalid instruction OpString starting at word 5: expected no more" - " operands after 3 words, but stated word count is 4."}, - // Word count is too large. There are too many words after the string - // literal. A linkage attribute decoration is the only case in SPIR-V - // where a string operand is followed by another operand. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(6, SpvOpDecorate), 1 /* target id */, - static_cast(SpvDecorationLinkageAttributes)}, - MakeVector("abc"), - {static_cast(SpvLinkageTypeImport), - 0 /* does not belong */}}), - "Invalid instruction OpDecorate starting at word 5: expected no more" - " operands after 5 words, but stated word count is 6."}, - // Like the previous case, but with 5 extra words. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(10, SpvOpDecorate), 1 /* target id */, - static_cast(SpvDecorationLinkageAttributes)}, - MakeVector("abc"), - {static_cast(SpvLinkageTypeImport), - /* don't belong */ 0, 1, 2, 3, 4}}), - "Invalid instruction OpDecorate starting at word 5: expected no more" - " operands after 5 words, but stated word count is 10."}, - // Like the previous two cases, but with OpMemberDecorate. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(7, SpvOpMemberDecorate), 1 /* target id */, - 42 /* member index */, - static_cast(SpvDecorationLinkageAttributes)}, - MakeVector("abc"), - {static_cast(SpvLinkageTypeImport), - 0 /* does not belong */}}), - "Invalid instruction OpMemberDecorate starting at word 5: expected no" - " more operands after 6 words, but stated word count is 7."}, - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(11, SpvOpMemberDecorate), - 1 /* target id */, 42 /* member index */, - static_cast(SpvDecorationLinkageAttributes)}, - MakeVector("abc"), - {static_cast(SpvLinkageTypeImport), - /* don't belong */ 0, 1, 2, 3, 4}}), - "Invalid instruction OpMemberDecorate starting at word 5: expected no" - " more operands after 6 words, but stated word count is 11."}, - // Word count is too large. There should be no more words - // after the RelaxedPrecision decoration. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(4, SpvOpDecorate), 1 /* target id */, - static_cast(SpvDecorationRelaxedPrecision), - 0 /* does not belong */}}), - "Invalid instruction OpDecorate starting at word 5: expected no" - " more operands after 3 words, but stated word count is 4."}, - // Word count is too large. There should be only one word after - // the SpecId decoration enum word. - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(5, SpvOpDecorate), 1 /* target id */, - static_cast(SpvDecorationSpecId), - 42 /* the spec id */, 0 /* does not belong */}}), - "Invalid instruction OpDecorate starting at word 5: expected no" - " more operands after 4 words, but stated word count is 5."}, - {Concatenate({ExpectedHeaderForBound(2), - {spvOpcodeMake(2, SpvOpTypeVoid), 0}}), - "Error: Result Id is 0"}, - {Concatenate({ - ExpectedHeaderForBound(2), - {spvOpcodeMake(2, SpvOpTypeVoid), 1}, - {spvOpcodeMake(2, SpvOpTypeBool), 1}, - }), - "Id 1 is defined more than once"}, - {Concatenate({ExpectedHeaderForBound(3), - MakeInstruction(SpvOpExtInst, {2, 3, 100, 4, 5})}), - "OpExtInst set Id 100 does not reference an OpExtInstImport result " - "Id"}, - {Concatenate({ExpectedHeaderForBound(101), - MakeInstruction(SpvOpExtInstImport, {100}, - MakeVector("OpenCL.std")), - // OpenCL cos is #14 - MakeInstruction(SpvOpExtInst, {2, 3, 100, 14, 5, 999})}), - "Invalid instruction OpExtInst starting at word 10: expected no " - "more operands after 6 words, but stated word count is 7."}, - // In this case, the OpSwitch selector refers to an invalid ID. - {Concatenate({ExpectedHeaderForBound(3), - MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}), - "Invalid OpSwitch: selector id 1 has no type"}, - // In this case, the OpSwitch selector refers to an ID that has - // no type. - {Concatenate({ExpectedHeaderForBound(3), - MakeInstruction(SpvOpLabel, {1}), - MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}), - "Invalid OpSwitch: selector id 1 has no type"}, - {Concatenate({ExpectedHeaderForBound(3), - MakeInstruction(SpvOpTypeInt, {1, 32, 0}), - MakeInstruction(SpvOpSwitch, {1, 3, 42, 3})}), - "Invalid OpSwitch: selector id 1 is a type, not a value"}, - {Concatenate({ExpectedHeaderForBound(3), - MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0x78f00000}), - MakeInstruction(SpvOpSwitch, {2, 3, 42, 3})}), - "Invalid OpSwitch: selector id 2 is not a scalar integer"}, - {Concatenate({ExpectedHeaderForBound(3), - MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("invalid-import"))}), - "Invalid extended instruction import 'invalid-import'"}, - {Concatenate({ - ExpectedHeaderForBound(3), - MakeInstruction(SpvOpTypeInt, {1, 32, 0}), - MakeInstruction(SpvOpConstant, {2, 2, 42}), - }), - "Type Id 2 is not a type"}, - {Concatenate({ - ExpectedHeaderForBound(3), - MakeInstruction(SpvOpTypeBool, {1}), - MakeInstruction(SpvOpConstant, {1, 2, 42}), - }), - "Type Id 1 is not a scalar numeric type"}, - })); - -// A binary parser diagnostic case generated from an assembly text input. -struct AssemblyDiagnosticCase { - std::string assembly; - std::string expected_diagnostic; -}; - -using BinaryParseAssemblyDiagnosticTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(BinaryParseAssemblyDiagnosticTest, AssemblyCases) { - auto words = CompileSuccessfully(GetParam().assembly); - EXPECT_THAT(spvBinaryParse(ScopedContext().context, nullptr, words.data(), - words.size(), nullptr, nullptr, &diagnostic), - AnyOf(SPV_ERROR_INVALID_BINARY, SPV_ERROR_INVALID_ID)); - ASSERT_NE(nullptr, diagnostic); - EXPECT_THAT(diagnostic->error, Eq(GetParam().expected_diagnostic)); -} - -INSTANTIATE_TEST_SUITE_P( - BinaryParseDiagnostic, BinaryParseAssemblyDiagnosticTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpConstant !0 42", "Error: Type Id is 0"}, - // A required id is 0. - {"OpName !0 \"foo\"", "Id is 0"}, - // An optional id is 0, in this case the optional - // initializer. - {"%2 = OpVariable %1 CrossWorkgroup !0", "Id is 0"}, - {"OpControlBarrier !0 %1 %2", "scope ID is 0"}, - {"OpControlBarrier %1 !0 %2", "scope ID is 0"}, - {"OpControlBarrier %1 %2 !0", "memory semantics ID is 0"}, - {"%import = OpExtInstImport \"GLSL.std.450\" " - "%result = OpExtInst %type %import !999999 %x", - "Invalid extended instruction number: 999999"}, - {"%2 = OpSpecConstantOp %1 !1000 %2", - "Invalid OpSpecConstantOp opcode: 1000"}, - {"OpCapability !9999", "Invalid capability operand: 9999"}, - {"OpSource !9999 100", "Invalid source language operand: 9999"}, - {"OpEntryPoint !9999", "Invalid execution model operand: 9999"}, - {"OpMemoryModel !9999", "Invalid addressing model operand: 9999"}, - {"OpMemoryModel Logical !9999", "Invalid memory model operand: 9999"}, - {"OpExecutionMode %1 !9999", "Invalid execution mode operand: 9999"}, - {"OpTypeForwardPointer %1 !9999", - "Invalid storage class operand: 9999"}, - {"%2 = OpTypeImage %1 !9999", "Invalid dimensionality operand: 9999"}, - {"%2 = OpTypeImage %1 1D 0 0 0 0 !9999", - "Invalid image format operand: 9999"}, - {"OpDecorate %1 FPRoundingMode !9999", - "Invalid floating-point rounding mode operand: 9999"}, - {"OpDecorate %1 LinkageAttributes \"C\" !9999", - "Invalid linkage type operand: 9999"}, - {"%1 = OpTypePipe !9999", "Invalid access qualifier operand: 9999"}, - {"OpDecorate %1 FuncParamAttr !9999", - "Invalid function parameter attribute operand: 9999"}, - {"OpDecorate %1 !9999", "Invalid decoration operand: 9999"}, - {"OpDecorate %1 BuiltIn !9999", "Invalid built-in operand: 9999"}, - {"%2 = OpGroupIAdd %1 %3 !9999", - "Invalid group operation operand: 9999"}, - {"OpDecorate %1 FPFastMathMode !63", - "Invalid floating-point fast math mode operand: 63 has invalid mask " - "component 32"}, - {"%2 = OpFunction %2 !31", - "Invalid function control operand: 31 has invalid mask component 16"}, - {"OpLoopMerge %1 %2 !1027", - "Invalid loop control operand: 1027 has invalid mask component 1024"}, - {"%2 = OpImageFetch %1 %image %coord !32770", - "Invalid image operand: 32770 has invalid mask component 32768"}, - {"OpSelectionMerge %1 !7", - "Invalid selection control operand: 7 has invalid mask component 4"}, - })); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/binary_strnlen_s_test.cpp b/3rdparty/spirv-tools/test/binary_strnlen_s_test.cpp deleted file mode 100644 index 5f43bde67..000000000 --- a/3rdparty/spirv-tools/test/binary_strnlen_s_test.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -TEST(Strnlen, Samples) { - EXPECT_EQ(0u, spv_strnlen_s(nullptr, 0)); - EXPECT_EQ(0u, spv_strnlen_s(nullptr, 5)); - EXPECT_EQ(0u, spv_strnlen_s("abc", 0)); - EXPECT_EQ(1u, spv_strnlen_s("abc", 1)); - EXPECT_EQ(3u, spv_strnlen_s("abc", 3)); - EXPECT_EQ(3u, spv_strnlen_s("abc\0", 5)); - EXPECT_EQ(0u, spv_strnlen_s("\0", 5)); - EXPECT_EQ(1u, spv_strnlen_s("a\0c", 5)); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/binary_to_text.literal_test.cpp b/3rdparty/spirv-tools/test/binary_to_text.literal_test.cpp deleted file mode 100644 index 02daac761..000000000 --- a/3rdparty/spirv-tools/test/binary_to_text.literal_test.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::testing::Eq; -using RoundTripLiteralsTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(RoundTripLiteralsTest, Sample) { - EXPECT_THAT(EncodeAndDecodeSuccessfully(GetParam()), Eq(GetParam())); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - StringLiterals, RoundTripLiteralsTest, - ::testing::ValuesIn(std::vector{ - "OpName %1 \"\"\n", // empty - "OpName %1 \"foo\"\n", // normal - "OpName %1 \"foo bar\"\n", // string with spaces - "OpName %1 \"foo\tbar\"\n", // string with tab - "OpName %1 \"\tfoo\"\n", // starts with tab - "OpName %1 \" foo\"\n", // starts with space - "OpName %1 \"foo \"\n", // ends with space - "OpName %1 \"foo\t\"\n", // ends with tab - "OpName %1 \"foo\nbar\"\n", // contains newline - "OpName %1 \"\nfoo\nbar\"\n", // starts with newline - "OpName %1 \"\n\n\nfoo\nbar\"\n", // multiple newlines - "OpName %1 \"\\\"foo\nbar\\\"\"\n", // escaped quote - "OpName %1 \"\\\\foo\nbar\\\\\"\n", // escaped backslash - "OpName %1 \"\xE4\xBA\xB2\"\n", // UTF-8 - })); -// clang-format on - -using RoundTripSpecialCaseLiteralsTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -// Test case where the generated disassembly is not the same as the -// assembly passed in. -TEST_P(RoundTripSpecialCaseLiteralsTest, Sample) { - EXPECT_THAT(EncodeAndDecodeSuccessfully(std::get<0>(GetParam())), - Eq(std::get<1>(GetParam()))); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - StringLiterals, RoundTripSpecialCaseLiteralsTest, - ::testing::ValuesIn(std::vector>{ - {"OpName %1 \"\\foo\"\n", "OpName %1 \"foo\"\n"}, // Escape f - {"OpName %1 \"\\\nfoo\"\n", "OpName %1 \"\nfoo\"\n"}, // Escape newline - {"OpName %1 \"\\\xE4\xBA\xB2\"\n", "OpName %1 \"\xE4\xBA\xB2\"\n"}, // Escape utf-8 - })); -// clang-format on - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/binary_to_text_test.cpp b/3rdparty/spirv-tools/test/binary_to_text_test.cpp deleted file mode 100644 index e8a02fd59..000000000 --- a/3rdparty/spirv-tools/test/binary_to_text_test.cpp +++ /dev/null @@ -1,561 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/spirv_constant.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::AutoText; -using spvtest::ScopedContext; -using spvtest::TextToBinaryTest; -using ::testing::Combine; -using ::testing::Eq; -using ::testing::HasSubstr; - -class BinaryToText : public ::testing::Test { - public: - BinaryToText() - : context(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)), binary(nullptr) {} - ~BinaryToText() { - spvBinaryDestroy(binary); - spvContextDestroy(context); - } - - virtual void SetUp() { - const char* textStr = R"( - OpSource OpenCL_C 12 - OpMemoryModel Physical64 OpenCL - OpSourceExtension "PlaceholderExtensionName" - OpEntryPoint Kernel %1 "foo" - OpExecutionMode %1 LocalSizeHint 1 1 1 - %2 = OpTypeVoid - %3 = OpTypeBool - %4 = OpTypeInt 8 0 - %5 = OpTypeInt 8 1 - %6 = OpTypeInt 16 0 - %7 = OpTypeInt 16 1 - %8 = OpTypeInt 32 0 - %9 = OpTypeInt 32 1 -%10 = OpTypeInt 64 0 -%11 = OpTypeInt 64 1 -%12 = OpTypeFloat 16 -%13 = OpTypeFloat 32 -%14 = OpTypeFloat 64 -%15 = OpTypeVector %4 2 -)"; - spv_text_t text = {textStr, strlen(textStr)}; - spv_diagnostic diagnostic = nullptr; - spv_result_t error = - spvTextToBinary(context, text.str, text.length, &binary, &diagnostic); - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - ASSERT_EQ(SPV_SUCCESS, error); - } - - virtual void TearDown() { - spvBinaryDestroy(binary); - binary = nullptr; - } - - // Compiles the given assembly text, and saves it into 'binary'. - void CompileSuccessfully(std::string text) { - spvBinaryDestroy(binary); - binary = nullptr; - spv_diagnostic diagnostic = nullptr; - EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, text.c_str(), text.size(), - &binary, &diagnostic)); - } - - spv_context context; - spv_binary binary; -}; - -TEST_F(BinaryToText, Default) { - spv_text text = nullptr; - spv_diagnostic diagnostic = nullptr; - ASSERT_EQ( - SPV_SUCCESS, - spvBinaryToText(context, binary->code, binary->wordCount, - SPV_BINARY_TO_TEXT_OPTION_NONE, &text, &diagnostic)); - printf("%s", text->str); - spvTextDestroy(text); -} - -TEST_F(BinaryToText, MissingModule) { - spv_text text; - spv_diagnostic diagnostic = nullptr; - EXPECT_EQ( - SPV_ERROR_INVALID_BINARY, - spvBinaryToText(context, nullptr, 42, SPV_BINARY_TO_TEXT_OPTION_NONE, - &text, &diagnostic)); - EXPECT_THAT(diagnostic->error, Eq(std::string("Missing module."))); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - } -} - -TEST_F(BinaryToText, TruncatedModule) { - // Make a valid module with zero instructions. - CompileSuccessfully(""); - EXPECT_EQ(SPV_INDEX_INSTRUCTION, binary->wordCount); - - for (size_t length = 0; length < SPV_INDEX_INSTRUCTION; length++) { - spv_text text = nullptr; - spv_diagnostic diagnostic = nullptr; - EXPECT_EQ( - SPV_ERROR_INVALID_BINARY, - spvBinaryToText(context, binary->code, length, - SPV_BINARY_TO_TEXT_OPTION_NONE, &text, &diagnostic)); - ASSERT_NE(nullptr, diagnostic); - std::stringstream expected; - expected << "Module has incomplete header: only " << length - << " words instead of " << SPV_INDEX_INSTRUCTION; - EXPECT_THAT(diagnostic->error, Eq(expected.str())); - spvDiagnosticDestroy(diagnostic); - } -} - -TEST_F(BinaryToText, InvalidMagicNumber) { - CompileSuccessfully(""); - std::vector damaged_binary(binary->code, - binary->code + binary->wordCount); - damaged_binary[SPV_INDEX_MAGIC_NUMBER] ^= 123; - - spv_diagnostic diagnostic = nullptr; - spv_text text; - EXPECT_EQ( - SPV_ERROR_INVALID_BINARY, - spvBinaryToText(context, damaged_binary.data(), damaged_binary.size(), - SPV_BINARY_TO_TEXT_OPTION_NONE, &text, &diagnostic)); - ASSERT_NE(nullptr, diagnostic); - std::stringstream expected; - expected << "Invalid SPIR-V magic number '" << std::hex - << damaged_binary[SPV_INDEX_MAGIC_NUMBER] << "'."; - EXPECT_THAT(diagnostic->error, Eq(expected.str())); - spvDiagnosticDestroy(diagnostic); -} - -struct FailedDecodeCase { - std::string source_text; - std::vector appended_instruction; - std::string expected_error_message; -}; - -using BinaryToTextFail = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(BinaryToTextFail, EncodeSuccessfullyDecodeFailed) { - EXPECT_THAT(EncodeSuccessfullyDecodeFailed(GetParam().source_text, - GetParam().appended_instruction), - Eq(GetParam().expected_error_message)); -} - -INSTANTIATE_TEST_SUITE_P( - InvalidIds, BinaryToTextFail, - ::testing::ValuesIn(std::vector{ - {"", spvtest::MakeInstruction(SpvOpTypeVoid, {0}), - "Error: Result Id is 0"}, - {"", spvtest::MakeInstruction(SpvOpConstant, {0, 1, 42}), - "Error: Type Id is 0"}, - {"%1 = OpTypeVoid", spvtest::MakeInstruction(SpvOpTypeVoid, {1}), - "Id 1 is defined more than once"}, - {"%1 = OpTypeVoid\n" - "%2 = OpNot %1 %foo", - spvtest::MakeInstruction(SpvOpNot, {1, 2, 3}), - "Id 2 is defined more than once"}, - {"%1 = OpTypeVoid\n" - "%2 = OpNot %1 %foo", - spvtest::MakeInstruction(SpvOpNot, {1, 1, 3}), - "Id 1 is defined more than once"}, - // The following are the two failure cases for - // Parser::setNumericTypeInfoForType. - {"", spvtest::MakeInstruction(SpvOpConstant, {500, 1, 42}), - "Type Id 500 is not a type"}, - {"%1 = OpTypeInt 32 0\n" - "%2 = OpTypeVector %1 4", - spvtest::MakeInstruction(SpvOpConstant, {2, 3, 999}), - "Type Id 2 is not a scalar numeric type"}, - })); - -INSTANTIATE_TEST_SUITE_P( - InvalidIdsCheckedDuringLiteralCaseParsing, BinaryToTextFail, - ::testing::ValuesIn(std::vector{ - {"", spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}), - "Invalid OpSwitch: selector id 1 has no type"}, - {"%1 = OpTypeVoid\n", - spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}), - "Invalid OpSwitch: selector id 1 is a type, not a value"}, - {"%1 = OpConstantTrue !500", - spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}), - "Type Id 500 is not a type"}, - {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 1.5", - spvtest::MakeInstruction(SpvOpSwitch, {2, 3, 4, 5}), - "Invalid OpSwitch: selector id 2 is not a scalar integer"}, - })); - -TEST_F(TextToBinaryTest, OneInstruction) { - const std::string input = "OpSource OpenCL_C 12\n"; - EXPECT_EQ(input, EncodeAndDecodeSuccessfully(input)); -} - -// Exercise the case where an operand itself has operands. -// This could detect problems in updating the expected-set-of-operands -// list. -TEST_F(TextToBinaryTest, OperandWithOperands) { - const std::string input = R"(OpEntryPoint Kernel %1 "foo" -OpExecutionMode %1 LocalSizeHint 100 200 300 -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%1 = OpFunction %1 None %3 -)"; - EXPECT_EQ(input, EncodeAndDecodeSuccessfully(input)); -} - -using RoundTripInstructionsTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(RoundTripInstructionsTest, Sample) { - EXPECT_THAT(EncodeAndDecodeSuccessfully(std::get<1>(GetParam()), - SPV_BINARY_TO_TEXT_OPTION_NONE, - std::get<0>(GetParam())), - Eq(std::get<1>(GetParam()))); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - NumericLiterals, RoundTripInstructionsTest, - // This test is independent of environment, so just test the one. - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "%1 = OpTypeInt 12 0\n%2 = OpConstant %1 1867\n", - "%1 = OpTypeInt 12 1\n%2 = OpConstant %1 1867\n", - "%1 = OpTypeInt 12 1\n%2 = OpConstant %1 -1867\n", - "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 1867\n", - "%1 = OpTypeInt 32 1\n%2 = OpConstant %1 1867\n", - "%1 = OpTypeInt 32 1\n%2 = OpConstant %1 -1867\n", - "%1 = OpTypeInt 64 0\n%2 = OpConstant %1 18446744073709551615\n", - "%1 = OpTypeInt 64 1\n%2 = OpConstant %1 9223372036854775807\n", - "%1 = OpTypeInt 64 1\n%2 = OpConstant %1 -9223372036854775808\n", - // 16-bit floats print as hex floats. - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ff4p+16\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.d2cp-10\n", - // 32-bit floats - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -3.125\n", - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128\n", // NaN - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128\n", // NaN - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128\n", // Inf - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128\n", // -Inf - // 64-bit floats - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -3.125\n", - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.ffffffffffffap-1023\n", // small normal - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.ffffffffffffap-1023\n", - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024\n", // NaN - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0002p+1024\n", // NaN - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024\n", // Inf - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024\n", // -Inf - }))); -// clang-format on - -INSTANTIATE_TEST_SUITE_P( - MemoryAccessMasks, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "OpStore %1 %2\n", // 3 words long. - "OpStore %1 %2 None\n", // 4 words long, explicit final 0. - "OpStore %1 %2 Volatile\n", - "OpStore %1 %2 Aligned 8\n", - "OpStore %1 %2 Nontemporal\n", - // Combinations show the names from LSB to MSB - "OpStore %1 %2 Volatile|Aligned 16\n", - "OpStore %1 %2 Volatile|Nontemporal\n", - "OpStore %1 %2 Volatile|Aligned|Nontemporal 32\n", - }))); - -INSTANTIATE_TEST_SUITE_P( - FPFastMathModeMasks, RoundTripInstructionsTest, - Combine( - ::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "OpDecorate %1 FPFastMathMode None\n", - "OpDecorate %1 FPFastMathMode NotNaN\n", - "OpDecorate %1 FPFastMathMode NotInf\n", - "OpDecorate %1 FPFastMathMode NSZ\n", - "OpDecorate %1 FPFastMathMode AllowRecip\n", - "OpDecorate %1 FPFastMathMode Fast\n", - // Combinations show the names from LSB to MSB - "OpDecorate %1 FPFastMathMode NotNaN|NotInf\n", - "OpDecorate %1 FPFastMathMode NSZ|AllowRecip\n", - "OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|Fast\n", - }))); - -INSTANTIATE_TEST_SUITE_P( - LoopControlMasks, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2), - ::testing::ValuesIn(std::vector{ - "OpLoopMerge %1 %2 None\n", - "OpLoopMerge %1 %2 Unroll\n", - "OpLoopMerge %1 %2 DontUnroll\n", - "OpLoopMerge %1 %2 Unroll|DontUnroll\n", - }))); - -INSTANTIATE_TEST_SUITE_P(LoopControlMasksV11, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, - SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "OpLoopMerge %1 %2 DependencyInfinite\n", - "OpLoopMerge %1 %2 DependencyLength 8\n", - }))); - -INSTANTIATE_TEST_SUITE_P( - SelectionControlMasks, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2), - ::testing::ValuesIn(std::vector{ - "OpSelectionMerge %1 None\n", - "OpSelectionMerge %1 Flatten\n", - "OpSelectionMerge %1 DontFlatten\n", - "OpSelectionMerge %1 Flatten|DontFlatten\n", - }))); - -INSTANTIATE_TEST_SUITE_P( - FunctionControlMasks, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "%2 = OpFunction %1 None %3\n", - "%2 = OpFunction %1 Inline %3\n", - "%2 = OpFunction %1 DontInline %3\n", - "%2 = OpFunction %1 Pure %3\n", - "%2 = OpFunction %1 Const %3\n", - "%2 = OpFunction %1 Inline|Pure|Const %3\n", - "%2 = OpFunction %1 DontInline|Const %3\n", - }))); - -INSTANTIATE_TEST_SUITE_P( - ImageMasks, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "%2 = OpImageFetch %1 %3 %4\n", - "%2 = OpImageFetch %1 %3 %4 None\n", - "%2 = OpImageFetch %1 %3 %4 Bias %5\n", - "%2 = OpImageFetch %1 %3 %4 Lod %5\n", - "%2 = OpImageFetch %1 %3 %4 Grad %5 %6\n", - "%2 = OpImageFetch %1 %3 %4 ConstOffset %5\n", - "%2 = OpImageFetch %1 %3 %4 Offset %5\n", - "%2 = OpImageFetch %1 %3 %4 ConstOffsets %5\n", - "%2 = OpImageFetch %1 %3 %4 Sample %5\n", - "%2 = OpImageFetch %1 %3 %4 MinLod %5\n", - "%2 = OpImageFetch %1 %3 %4 Bias|Lod|Grad %5 %6 %7 %8\n", - "%2 = OpImageFetch %1 %3 %4 ConstOffset|Offset|ConstOffsets" - " %5 %6 %7\n", - "%2 = OpImageFetch %1 %3 %4 Sample|MinLod %5 %6\n", - "%2 = OpImageFetch %1 %3 %4" - " Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod" - " %5 %6 %7 %8 %9 %10 %11 %12 %13\n"}))); - -INSTANTIATE_TEST_SUITE_P( - NewInstructionsInSPIRV1_2, RoundTripInstructionsTest, - Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ::testing::ValuesIn(std::vector{ - "OpExecutionModeId %1 SubgroupsPerWorkgroupId %2\n", - "OpExecutionModeId %1 LocalSizeId %2 %3 %4\n", - "OpExecutionModeId %1 LocalSizeHintId %2\n", - "OpDecorateId %1 AlignmentId %2\n", - "OpDecorateId %1 MaxByteOffsetId %2\n", - }))); - -using MaskSorting = TextToBinaryTest; - -TEST_F(MaskSorting, MasksAreSortedFromLSBToMSB) { - EXPECT_THAT(EncodeAndDecodeSuccessfully( - "OpStore %1 %2 Nontemporal|Aligned|Volatile 32"), - Eq("OpStore %1 %2 Volatile|Aligned|Nontemporal 32\n")); - EXPECT_THAT( - EncodeAndDecodeSuccessfully( - "OpDecorate %1 FPFastMathMode NotInf|Fast|AllowRecip|NotNaN|NSZ"), - Eq("OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|Fast\n")); - EXPECT_THAT( - EncodeAndDecodeSuccessfully("OpLoopMerge %1 %2 DontUnroll|Unroll"), - Eq("OpLoopMerge %1 %2 Unroll|DontUnroll\n")); - EXPECT_THAT( - EncodeAndDecodeSuccessfully("OpSelectionMerge %1 DontFlatten|Flatten"), - Eq("OpSelectionMerge %1 Flatten|DontFlatten\n")); - EXPECT_THAT(EncodeAndDecodeSuccessfully( - "%2 = OpFunction %1 DontInline|Const|Pure|Inline %3"), - Eq("%2 = OpFunction %1 Inline|DontInline|Pure|Const %3\n")); - EXPECT_THAT(EncodeAndDecodeSuccessfully( - "%2 = OpImageFetch %1 %3 %4" - " MinLod|Sample|Offset|Lod|Grad|ConstOffsets|ConstOffset|Bias" - " %5 %6 %7 %8 %9 %10 %11 %12 %13\n"), - Eq("%2 = OpImageFetch %1 %3 %4" - " Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod" - " %5 %6 %7 %8 %9 %10 %11 %12 %13\n")); -} - -using OperandTypeTest = TextToBinaryTest; - -TEST_F(OperandTypeTest, OptionalTypedLiteralNumber) { - const std::string input = - "%1 = OpTypeInt 32 0\n" - "%2 = OpConstant %1 42\n" - "OpSwitch %2 %3 100 %4\n"; - EXPECT_EQ(input, EncodeAndDecodeSuccessfully(input)); -} - -using IndentTest = spvtest::TextToBinaryTest; - -TEST_F(IndentTest, Sample) { - const std::string input = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 %3 %4 %5 %6 %7 %8 %9 %10 ; force IDs into double digits -%11 = OpConstant %1 42 -OpStore %2 %3 Aligned|Volatile 4 ; bogus, but not indented -)"; - const std::string expected = - R"( OpCapability Shader - OpMemoryModel Logical GLSL450 - %1 = OpTypeInt 32 0 - %2 = OpTypeStruct %1 %3 %4 %5 %6 %7 %8 %9 %10 - %11 = OpConstant %1 42 - OpStore %2 %3 Volatile|Aligned 4 -)"; - EXPECT_THAT( - EncodeAndDecodeSuccessfully(input, SPV_BINARY_TO_TEXT_OPTION_INDENT), - expected); -} - -using FriendlyNameDisassemblyTest = spvtest::TextToBinaryTest; - -TEST_F(FriendlyNameDisassemblyTest, Sample) { - const std::string input = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 %3 %4 %5 %6 %7 %8 %9 %10 ; force IDs into double digits -%11 = OpConstant %1 42 -)"; - const std::string expected = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -%uint = OpTypeInt 32 0 -%_struct_2 = OpTypeStruct %uint %3 %4 %5 %6 %7 %8 %9 %10 -%uint_42 = OpConstant %uint 42 -)"; - EXPECT_THAT(EncodeAndDecodeSuccessfully( - input, SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES), - expected); -} - -TEST_F(TextToBinaryTest, ShowByteOffsetsWhenRequested) { - const std::string input = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeVoid -)"; - const std::string expected = - R"(OpCapability Shader ; 0x00000014 -OpMemoryModel Logical GLSL450 ; 0x0000001c -%1 = OpTypeInt 32 0 ; 0x00000028 -%2 = OpTypeVoid ; 0x00000038 -)"; - EXPECT_THAT(EncodeAndDecodeSuccessfully( - input, SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET), - expected); -} - -// Test version string. -TEST_F(TextToBinaryTest, VersionString) { - auto words = CompileSuccessfully(""); - spv_text decoded_text = nullptr; - EXPECT_THAT(spvBinaryToText(ScopedContext().context, words.data(), - words.size(), SPV_BINARY_TO_TEXT_OPTION_NONE, - &decoded_text, &diagnostic), - Eq(SPV_SUCCESS)); - EXPECT_EQ(nullptr, diagnostic); - - EXPECT_THAT(decoded_text->str, HasSubstr("Version: 1.0\n")) - << EncodeAndDecodeSuccessfully(""); - spvTextDestroy(decoded_text); -} - -// Test generator string. - -// A test case for the generator string. This allows us to -// test both of the 16-bit components of the generator word. -struct GeneratorStringCase { - uint16_t generator; - uint16_t misc; - std::string expected; -}; - -using GeneratorStringTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(GeneratorStringTest, Sample) { - auto words = CompileSuccessfully(""); - EXPECT_EQ(2u, SPV_INDEX_GENERATOR_NUMBER); - words[SPV_INDEX_GENERATOR_NUMBER] = - SPV_GENERATOR_WORD(GetParam().generator, GetParam().misc); - - spv_text decoded_text = nullptr; - EXPECT_THAT(spvBinaryToText(ScopedContext().context, words.data(), - words.size(), SPV_BINARY_TO_TEXT_OPTION_NONE, - &decoded_text, &diagnostic), - Eq(SPV_SUCCESS)); - EXPECT_THAT(diagnostic, Eq(nullptr)); - EXPECT_THAT(std::string(decoded_text->str), HasSubstr(GetParam().expected)); - spvTextDestroy(decoded_text); -} - -INSTANTIATE_TEST_SUITE_P(GeneratorStrings, GeneratorStringTest, - ::testing::ValuesIn(std::vector{ - {SPV_GENERATOR_KHRONOS, 12, "Khronos; 12"}, - {SPV_GENERATOR_LUNARG, 99, "LunarG; 99"}, - {SPV_GENERATOR_VALVE, 1, "Valve; 1"}, - {SPV_GENERATOR_CODEPLAY, 65535, "Codeplay; 65535"}, - {SPV_GENERATOR_NVIDIA, 19, "NVIDIA; 19"}, - {SPV_GENERATOR_ARM, 1000, "ARM; 1000"}, - {SPV_GENERATOR_KHRONOS_LLVM_TRANSLATOR, 38, - "Khronos LLVM/SPIR-V Translator; 38"}, - {SPV_GENERATOR_KHRONOS_ASSEMBLER, 2, - "Khronos SPIR-V Tools Assembler; 2"}, - {SPV_GENERATOR_KHRONOS_GLSLANG, 1, - "Khronos Glslang Reference Front End; 1"}, - {1000, 18, "Unknown(1000); 18"}, - {65535, 32767, "Unknown(65535); 32767"}, - })); - -// TODO(dneto): Test new instructions and enums in SPIR-V 1.3 - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/c_interface_test.cpp b/3rdparty/spirv-tools/test/c_interface_test.cpp deleted file mode 100644 index 841bb2c6b..000000000 --- a/3rdparty/spirv-tools/test/c_interface_test.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// 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 "gtest/gtest.h" -#include "source/table.h" -#include "spirv-tools/libspirv.h" - -namespace spvtools { -namespace { - -// TODO(antiagainst): Use public C API for setting the consumer once exists. -#ifndef SPIRV_TOOLS_SHAREDLIB -void SetContextMessageConsumer(spv_context context, MessageConsumer consumer) { - spvtools::SetContextMessageConsumer(context, consumer); -} -#else -void SetContextMessageConsumer(spv_context, MessageConsumer) {} -#endif - -// The default consumer is a null std::function. -TEST(CInterface, DefaultConsumerNullDiagnosticForValidInput) { - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - const char input_text[] = - "OpCapability Shader\n" - "OpCapability Linkage\n" - "OpMemoryModel Logical GLSL450"; - - spv_binary binary = nullptr; - EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - - { - // Sadly the compiler don't allow me to feed binary directly to - // spvValidate(). - spv_const_binary_t b{binary->code, binary->wordCount}; - EXPECT_EQ(SPV_SUCCESS, spvValidate(context, &b, nullptr)); - } - - spv_text text = nullptr; - EXPECT_EQ(SPV_SUCCESS, spvBinaryToText(context, binary->code, - binary->wordCount, 0, &text, nullptr)); - - spvTextDestroy(text); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -// The default consumer is a null std::function. -TEST(CInterface, DefaultConsumerNullDiagnosticForInvalidAssembling) { - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - const char input_text[] = "%1 = OpName"; - - spv_binary binary = nullptr; - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, - spvTextToBinary(context, input_text, sizeof(input_text), &binary, - nullptr)); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -// The default consumer is a null std::function. -TEST(CInterface, DefaultConsumerNullDiagnosticForInvalidDiassembling) { - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - const char input_text[] = "OpNop"; - - spv_binary binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - // Change OpNop to an invalid (wordcount|opcode) word. - binary->code[binary->wordCount - 1] = 0xffffffff; - - spv_text text = nullptr; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryToText(context, binary->code, binary->wordCount, 0, &text, - nullptr)); - - spvTextDestroy(text); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -// The default consumer is a null std::function. -TEST(CInterface, DefaultConsumerNullDiagnosticForInvalidValidating) { - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - const char input_text[] = "OpNop"; - - spv_binary binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - - spv_const_binary_t b{binary->code, binary->wordCount}; - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, spvValidate(context, &b, nullptr)); - - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -TEST(CInterface, SpecifyConsumerNullDiagnosticForAssembling) { - const char input_text[] = " OpName\n"; - - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - SetContextMessageConsumer( - context, - [&invocation](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - ++invocation; - EXPECT_EQ(SPV_MSG_ERROR, level); - // The error happens at scanning the begining of second line. - EXPECT_STREQ("input", source); - EXPECT_EQ(1u, position.line); - EXPECT_EQ(0u, position.column); - EXPECT_EQ(12u, position.index); - EXPECT_STREQ("Expected operand, found end of stream.", message); - }); - - spv_binary binary = nullptr; - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, - spvTextToBinary(context, input_text, sizeof(input_text), &binary, - nullptr)); -#ifndef SPIRV_TOOLS_SHAREDLIB - EXPECT_EQ(1, invocation); -#endif - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -TEST(CInterface, SpecifyConsumerNullDiagnosticForDisassembling) { - const char input_text[] = "OpNop"; - - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - SetContextMessageConsumer( - context, - [&invocation](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - ++invocation; - EXPECT_EQ(SPV_MSG_ERROR, level); - EXPECT_STREQ("input", source); - EXPECT_EQ(0u, position.line); - EXPECT_EQ(0u, position.column); - EXPECT_EQ(1u, position.index); - EXPECT_STREQ("Invalid opcode: 65535", message); - }); - - spv_binary binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - // Change OpNop to an invalid (wordcount|opcode) word. - binary->code[binary->wordCount - 1] = 0xffffffff; - - spv_text text = nullptr; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryToText(context, binary->code, binary->wordCount, 0, &text, - nullptr)); -#ifndef SPIRV_TOOLS_SHAREDLIB - EXPECT_EQ(1, invocation); -#endif - - spvTextDestroy(text); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -TEST(CInterface, SpecifyConsumerNullDiagnosticForValidating) { - const char input_text[] = "OpNop"; - - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - SetContextMessageConsumer( - context, - [&invocation](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - ++invocation; - EXPECT_EQ(SPV_MSG_ERROR, level); - EXPECT_STREQ("input", source); - EXPECT_EQ(0u, position.line); - EXPECT_EQ(0u, position.column); - // TODO(antiagainst): what validation reports is not a word offset here. - // It is inconsistent with diassembler. Should be fixed. - EXPECT_EQ(1u, position.index); - EXPECT_STREQ( - "Nop cannot appear before the memory model instruction\n" - " OpNop\n", - message); - }); - - spv_binary binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - - spv_const_binary_t b{binary->code, binary->wordCount}; - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, spvValidate(context, &b, nullptr)); -#ifndef SPIRV_TOOLS_SHAREDLIB - EXPECT_EQ(1, invocation); -#endif - - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -// When having both a consumer and an diagnostic object, the diagnostic object -// should take priority. -TEST(CInterface, SpecifyConsumerSpecifyDiagnosticForAssembling) { - const char input_text[] = " OpName"; - - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - SetContextMessageConsumer( - context, - [&invocation](spv_message_level_t, const char*, const spv_position_t&, - const char*) { ++invocation; }); - - spv_binary binary = nullptr; - spv_diagnostic diagnostic = nullptr; - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, - spvTextToBinary(context, input_text, sizeof(input_text), &binary, - &diagnostic)); - EXPECT_EQ(0, invocation); // Consumer should not be invoked at all. - EXPECT_STREQ("Expected operand, found end of stream.", diagnostic->error); - - spvDiagnosticDestroy(diagnostic); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -TEST(CInterface, SpecifyConsumerSpecifyDiagnosticForDisassembling) { - const char input_text[] = "OpNop"; - - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - SetContextMessageConsumer( - context, - [&invocation](spv_message_level_t, const char*, const spv_position_t&, - const char*) { ++invocation; }); - - spv_binary binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - // Change OpNop to an invalid (wordcount|opcode) word. - binary->code[binary->wordCount - 1] = 0xffffffff; - - spv_diagnostic diagnostic = nullptr; - spv_text text = nullptr; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - spvBinaryToText(context, binary->code, binary->wordCount, 0, &text, - &diagnostic)); - - EXPECT_EQ(0, invocation); // Consumer should not be invoked at all. - EXPECT_STREQ("Invalid opcode: 65535", diagnostic->error); - - spvTextDestroy(text); - spvDiagnosticDestroy(diagnostic); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -TEST(CInterface, SpecifyConsumerSpecifyDiagnosticForValidating) { - const char input_text[] = "OpNop"; - - auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - int invocation = 0; - SetContextMessageConsumer( - context, - [&invocation](spv_message_level_t, const char*, const spv_position_t&, - const char*) { ++invocation; }); - - spv_binary binary = nullptr; - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text, - sizeof(input_text), &binary, nullptr)); - - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t b{binary->code, binary->wordCount}; - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, spvValidate(context, &b, &diagnostic)); - - EXPECT_EQ(0, invocation); // Consumer should not be invoked at all. - EXPECT_STREQ( - "Nop cannot appear before the memory model instruction\n" - " OpNop\n", - diagnostic->error); - - spvDiagnosticDestroy(diagnostic); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/comment_test.cpp b/3rdparty/spirv-tools/test/comment_test.cpp deleted file mode 100644 index 49f8df651..000000000 --- a/3rdparty/spirv-tools/test/comment_test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::Concatenate; -using spvtest::MakeInstruction; -using utils::MakeVector; -using spvtest::TextToBinaryTest; -using testing::Eq; - -TEST_F(TextToBinaryTest, Whitespace) { - std::string input = R"( -; I'm a proud comment at the beginning of the file -; I hide: OpCapability Shader - OpMemoryModel Logical Simple ; comment after instruction -;;;;;;;; many ;'s - %glsl450 = OpExtInstImport "GLSL.std.450" - ; comment indented -)"; - - EXPECT_THAT( - CompiledInstructions(input), - Eq(Concatenate({MakeInstruction(SpvOpMemoryModel, - {uint32_t(SpvAddressingModelLogical), - uint32_t(SpvMemoryModelSimple)}), - MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("GLSL.std.450"))}))); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/cpp_interface_test.cpp b/3rdparty/spirv-tools/test/cpp_interface_test.cpp deleted file mode 100644 index 538d40fd4..000000000 --- a/3rdparty/spirv-tools/test/cpp_interface_test.cpp +++ /dev/null @@ -1,328 +0,0 @@ -// 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "spirv-tools/optimizer.hpp" -#include "spirv/1.1/spirv.h" - -namespace spvtools { -namespace { - -using ::testing::ContainerEq; -using ::testing::HasSubstr; - -// Return a string that contains the minimum instructions needed to form -// a valid module. Other instructions can be appended to this string. -std::string Header() { - return R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -)"; -} - -// When we assemble with a target environment of SPIR-V 1.1, we expect -// the following in the module header version word. -const uint32_t kExpectedSpvVersion = 0x10100; - -TEST(CppInterface, SuccessfulRoundTrip) { - const std::string input_text = "%2 = OpSizeOf %1 %3\n"; - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - - std::vector binary; - EXPECT_TRUE(t.Assemble(input_text, &binary)); - EXPECT_TRUE(binary.size() > 5u); - EXPECT_EQ(SpvMagicNumber, binary[0]); - EXPECT_EQ(kExpectedSpvVersion, binary[1]); - - // This cannot pass validation since %1 is not defined. - t.SetMessageConsumer([](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - EXPECT_EQ(SPV_MSG_ERROR, level); - EXPECT_STREQ("input", source); - EXPECT_EQ(0u, position.line); - EXPECT_EQ(0u, position.column); - EXPECT_EQ(1u, position.index); - EXPECT_STREQ("ID 1[%1] has not been defined\n %2 = OpSizeOf %1 %3\n", - message); - }); - EXPECT_FALSE(t.Validate(binary)); - - std::string output_text; - EXPECT_TRUE(t.Disassemble(binary, &output_text)); - EXPECT_EQ(input_text, output_text); -} - -TEST(CppInterface, AssembleEmptyModule) { - std::vector binary(10, 42); - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - EXPECT_TRUE(t.Assemble("", &binary)); - // We only have the header. - EXPECT_EQ(5u, binary.size()); - EXPECT_EQ(SpvMagicNumber, binary[0]); - EXPECT_EQ(kExpectedSpvVersion, binary[1]); -} - -TEST(CppInterface, AssembleOverloads) { - const std::string input_text = "%2 = OpSizeOf %1 %3\n"; - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - { - std::vector binary; - EXPECT_TRUE(t.Assemble(input_text, &binary)); - EXPECT_TRUE(binary.size() > 5u); - EXPECT_EQ(SpvMagicNumber, binary[0]); - EXPECT_EQ(kExpectedSpvVersion, binary[1]); - } - { - std::vector binary; - EXPECT_TRUE(t.Assemble(input_text.data(), input_text.size(), &binary)); - EXPECT_TRUE(binary.size() > 5u); - EXPECT_EQ(SpvMagicNumber, binary[0]); - EXPECT_EQ(kExpectedSpvVersion, binary[1]); - } - { // Ignore the last newline. - std::vector binary; - EXPECT_TRUE(t.Assemble(input_text.data(), input_text.size() - 1, &binary)); - EXPECT_TRUE(binary.size() > 5u); - EXPECT_EQ(SpvMagicNumber, binary[0]); - EXPECT_EQ(kExpectedSpvVersion, binary[1]); - } -} - -TEST(CppInterface, DisassembleEmptyModule) { - std::string text(10, 'x'); - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - int invocation_count = 0; - t.SetMessageConsumer( - [&invocation_count](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - ++invocation_count; - EXPECT_EQ(SPV_MSG_ERROR, level); - EXPECT_STREQ("input", source); - EXPECT_EQ(0u, position.line); - EXPECT_EQ(0u, position.column); - EXPECT_EQ(0u, position.index); - EXPECT_STREQ("Missing module.", message); - }); - EXPECT_FALSE(t.Disassemble({}, &text)); - EXPECT_EQ("xxxxxxxxxx", text); // The original string is unmodified. - EXPECT_EQ(1, invocation_count); -} - -TEST(CppInterface, DisassembleOverloads) { - const std::string input_text = "%2 = OpSizeOf %1 %3\n"; - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - - std::vector binary; - EXPECT_TRUE(t.Assemble(input_text, &binary)); - - { - std::string output_text; - EXPECT_TRUE(t.Disassemble(binary, &output_text)); - EXPECT_EQ(input_text, output_text); - } - { - std::string output_text; - EXPECT_TRUE(t.Disassemble(binary.data(), binary.size(), &output_text)); - EXPECT_EQ(input_text, output_text); - } -} - -TEST(CppInterface, SuccessfulValidation) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - int invocation_count = 0; - t.SetMessageConsumer([&invocation_count](spv_message_level_t, const char*, - const spv_position_t&, const char*) { - ++invocation_count; - }); - - std::vector binary; - EXPECT_TRUE(t.Assemble(Header(), &binary)); - EXPECT_TRUE(t.Validate(binary)); - EXPECT_EQ(0, invocation_count); -} - -TEST(CppInterface, ValidateOverloads) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::vector binary; - EXPECT_TRUE(t.Assemble(Header(), &binary)); - - { EXPECT_TRUE(t.Validate(binary)); } - { EXPECT_TRUE(t.Validate(binary.data(), binary.size())); } -} - -TEST(CppInterface, ValidateEmptyModule) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - int invocation_count = 0; - t.SetMessageConsumer( - [&invocation_count](spv_message_level_t level, const char* source, - const spv_position_t& position, const char* message) { - ++invocation_count; - EXPECT_EQ(SPV_MSG_ERROR, level); - EXPECT_STREQ("input", source); - EXPECT_EQ(0u, position.line); - EXPECT_EQ(0u, position.column); - EXPECT_EQ(0u, position.index); - EXPECT_STREQ("Invalid SPIR-V magic number.", message); - }); - EXPECT_FALSE(t.Validate({})); - EXPECT_EQ(1, invocation_count); -} - -// Returns the assembly for a SPIR-V module with a struct declaration -// with the given number of members. -std::string MakeModuleHavingStruct(int num_members) { - std::stringstream os; - os << Header(); - os << R"(%1 = OpTypeInt 32 0 - %2 = OpTypeStruct)"; - for (int i = 0; i < num_members; i++) os << " %1"; - return os.str(); -} - -TEST(CppInterface, ValidateWithOptionsPass) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::vector binary; - EXPECT_TRUE(t.Assemble(MakeModuleHavingStruct(10), &binary)); - const ValidatorOptions opts; - - EXPECT_TRUE(t.Validate(binary.data(), binary.size(), opts)); -} - -TEST(CppInterface, ValidateWithOptionsFail) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::vector binary; - EXPECT_TRUE(t.Assemble(MakeModuleHavingStruct(10), &binary)); - ValidatorOptions opts; - opts.SetUniversalLimit(spv_validator_limit_max_struct_members, 9); - std::stringstream os; - t.SetMessageConsumer([&os](spv_message_level_t, const char*, - const spv_position_t&, - const char* message) { os << message; }); - - EXPECT_FALSE(t.Validate(binary.data(), binary.size(), opts)); - EXPECT_THAT( - os.str(), - HasSubstr( - "Number of OpTypeStruct members (10) has exceeded the limit (9)")); -} - -// Checks that after running the given optimizer |opt| on the given |original| -// source code, we can get the given |optimized| source code. -void CheckOptimization(const std::string& original, - const std::string& optimized, const Optimizer& opt) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::vector original_binary; - ASSERT_TRUE(t.Assemble(original, &original_binary)); - - std::vector optimized_binary; - EXPECT_TRUE(opt.Run(original_binary.data(), original_binary.size(), - &optimized_binary)); - - std::string optimized_text; - EXPECT_TRUE(t.Disassemble(optimized_binary, &optimized_text)); - EXPECT_EQ(optimized, optimized_text); -} - -TEST(CppInterface, OptimizeEmptyModule) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::vector binary; - EXPECT_TRUE(t.Assemble("", &binary)); - - Optimizer o(SPV_ENV_UNIVERSAL_1_1); - o.RegisterPass(CreateStripDebugInfoPass()); - - // Fails to validate. - EXPECT_FALSE(o.Run(binary.data(), binary.size(), &binary)); -} - -TEST(CppInterface, OptimizeModifiedModule) { - Optimizer o(SPV_ENV_UNIVERSAL_1_1); - o.RegisterPass(CreateStripDebugInfoPass()); - CheckOptimization(Header() + "OpSource GLSL 450", Header(), o); -} - -TEST(CppInterface, OptimizeMulitplePasses) { - std::string original_text = Header() + - "OpSource GLSL 450 " - "OpDecorate %true SpecId 1 " - "%bool = OpTypeBool " - "%true = OpSpecConstantTrue %bool"; - - Optimizer o(SPV_ENV_UNIVERSAL_1_1); - o.RegisterPass(CreateStripDebugInfoPass()) - .RegisterPass(CreateFreezeSpecConstantValuePass()); - - std::string expected_text = Header() + - "%bool = OpTypeBool\n" - "%true = OpConstantTrue %bool\n"; - - CheckOptimization(original_text, expected_text, o); -} - -TEST(CppInterface, OptimizeDoNothingWithPassToken) { - CreateFreezeSpecConstantValuePass(); - auto token = CreateUnifyConstantPass(); -} - -TEST(CppInterface, OptimizeReassignPassToken) { - auto token = CreateNullPass(); - token = CreateStripDebugInfoPass(); - - CheckOptimization( - Header() + "OpSource GLSL 450", Header(), - Optimizer(SPV_ENV_UNIVERSAL_1_1).RegisterPass(std::move(token))); -} - -TEST(CppInterface, OptimizeMoveConstructPassToken) { - auto token1 = CreateStripDebugInfoPass(); - Optimizer::PassToken token2(std::move(token1)); - - CheckOptimization( - Header() + "OpSource GLSL 450", Header(), - Optimizer(SPV_ENV_UNIVERSAL_1_1).RegisterPass(std::move(token2))); -} - -TEST(CppInterface, OptimizeMoveAssignPassToken) { - auto token1 = CreateStripDebugInfoPass(); - auto token2 = CreateNullPass(); - token2 = std::move(token1); - - CheckOptimization( - Header() + "OpSource GLSL 450", Header(), - Optimizer(SPV_ENV_UNIVERSAL_1_1).RegisterPass(std::move(token2))); -} - -TEST(CppInterface, OptimizeSameAddressForOriginalOptimizedBinary) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::vector binary; - ASSERT_TRUE(t.Assemble(Header() + "OpSource GLSL 450", &binary)); - - EXPECT_TRUE(Optimizer(SPV_ENV_UNIVERSAL_1_1) - .RegisterPass(CreateStripDebugInfoPass()) - .Run(binary.data(), binary.size(), &binary)); - - std::string optimized_text; - EXPECT_TRUE(t.Disassemble(binary, &optimized_text)); - EXPECT_EQ(Header(), optimized_text); -} - -// TODO(antiagainst): tests for SetMessageConsumer(). - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/diagnostic_test.cpp b/3rdparty/spirv-tools/test/diagnostic_test.cpp deleted file mode 100644 index f86bae113..000000000 --- a/3rdparty/spirv-tools/test/diagnostic_test.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::testing::Eq; - -// Returns a newly created diagnostic value. -spv_diagnostic MakeValidDiagnostic() { - spv_position_t position = {}; - spv_diagnostic diagnostic = spvDiagnosticCreate(&position, ""); - EXPECT_NE(nullptr, diagnostic); - return diagnostic; -} - -TEST(Diagnostic, DestroyNull) { spvDiagnosticDestroy(nullptr); } - -TEST(Diagnostic, DestroyValidDiagnostic) { - spv_diagnostic diagnostic = MakeValidDiagnostic(); - spvDiagnosticDestroy(diagnostic); - // We aren't allowed to use the diagnostic pointer anymore. - // So we can't test its behaviour. -} - -TEST(Diagnostic, DestroyValidDiagnosticAfterReassignment) { - spv_diagnostic diagnostic = MakeValidDiagnostic(); - spv_diagnostic second_diagnostic = MakeValidDiagnostic(); - EXPECT_TRUE(diagnostic != second_diagnostic); - spvDiagnosticDestroy(diagnostic); - diagnostic = second_diagnostic; - spvDiagnosticDestroy(diagnostic); -} - -TEST(Diagnostic, PrintDefault) { - char message[] = "Test Diagnostic!"; - spv_diagnostic_t diagnostic = {{2, 3, 5}, message}; - // TODO: Redirect stderr - ASSERT_EQ(SPV_SUCCESS, spvDiagnosticPrint(&diagnostic)); - // TODO: Validate the output of spvDiagnosticPrint() - // TODO: Remove the redirection of stderr -} - -TEST(Diagnostic, PrintInvalidDiagnostic) { - ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC, spvDiagnosticPrint(nullptr)); -} - -// TODO(dneto): We should be able to redirect the diagnostic printing. -// Once we do that, we can test diagnostic corner cases. - -TEST(DiagnosticStream, ConversionToResultType) { - // Check after the DiagnosticStream object is destroyed. - spv_result_t value; - { value = DiagnosticStream({}, nullptr, "", SPV_ERROR_INVALID_TEXT); } - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, value); - - // Check implicit conversion via plain assignment. - value = DiagnosticStream({}, nullptr, "", SPV_SUCCESS); - EXPECT_EQ(SPV_SUCCESS, value); - - // Check conversion via constructor. - EXPECT_EQ(SPV_FAILED_MATCH, - spv_result_t(DiagnosticStream({}, nullptr, "", SPV_FAILED_MATCH))); -} - -TEST( - DiagnosticStream, - MoveConstructorPreservesPreviousMessagesAndPreventsOutputFromExpiringValue) { - std::ostringstream messages; - int message_count = 0; - auto consumer = [&messages, &message_count](spv_message_level_t, const char*, - const spv_position_t&, - const char* msg) { - message_count++; - messages << msg; - }; - - // Enclose the DiagnosticStream variables in a scope to force destruction. - { - DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY); - ds0 << "First"; - DiagnosticStream ds1(std::move(ds0)); - ds1 << "Second"; - } - EXPECT_THAT(message_count, Eq(1)); - EXPECT_THAT(messages.str(), Eq("FirstSecond")); -} - -TEST(DiagnosticStream, MoveConstructorCanBeDirectlyShiftedTo) { - std::ostringstream messages; - int message_count = 0; - auto consumer = [&messages, &message_count](spv_message_level_t, const char*, - const spv_position_t&, - const char* msg) { - message_count++; - messages << msg; - }; - - // Enclose the DiagnosticStream variables in a scope to force destruction. - { - DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY); - ds0 << "First"; - std::move(ds0) << "Second"; - } - EXPECT_THAT(message_count, Eq(1)); - EXPECT_THAT(messages.str(), Eq("FirstSecond")); -} - -TEST(DiagnosticStream, DiagnosticFromLambdaReturnCanStillBeUsed) { - std::ostringstream messages; - int message_count = 0; - auto consumer = [&messages, &message_count](spv_message_level_t, const char*, - const spv_position_t&, - const char* msg) { - message_count++; - messages << msg; - }; - - { - auto emitter = [&consumer]() -> DiagnosticStream { - DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY); - ds0 << "First"; - return ds0; - }; - emitter() << "Second"; - } - EXPECT_THAT(message_count, Eq(1)); - EXPECT_THAT(messages.str(), Eq("FirstSecond")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/enum_set_test.cpp b/3rdparty/spirv-tools/test/enum_set_test.cpp deleted file mode 100644 index 047d6427c..000000000 --- a/3rdparty/spirv-tools/test/enum_set_test.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// 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 "gmock/gmock.h" -#include "source/enum_set.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::ElementsIn; -using ::testing::Eq; -using ::testing::ValuesIn; - -TEST(EnumSet, IsEmpty1) { - EnumSet set; - EXPECT_TRUE(set.IsEmpty()); - set.Add(0); - EXPECT_FALSE(set.IsEmpty()); -} - -TEST(EnumSet, IsEmpty2) { - EnumSet set; - EXPECT_TRUE(set.IsEmpty()); - set.Add(150); - EXPECT_FALSE(set.IsEmpty()); -} - -TEST(EnumSet, IsEmpty3) { - EnumSet set(4); - EXPECT_FALSE(set.IsEmpty()); -} - -TEST(EnumSet, IsEmpty4) { - EnumSet set(300); - EXPECT_FALSE(set.IsEmpty()); -} - -TEST(EnumSetHasAnyOf, EmptySetEmptyQuery) { - const EnumSet set; - const EnumSet empty; - EXPECT_TRUE(set.HasAnyOf(empty)); - EXPECT_TRUE(EnumSet().HasAnyOf(EnumSet())); -} - -TEST(EnumSetHasAnyOf, MaskSetEmptyQuery) { - EnumSet set; - const EnumSet empty; - set.Add(5); - set.Add(8); - EXPECT_TRUE(set.HasAnyOf(empty)); -} - -TEST(EnumSetHasAnyOf, OverflowSetEmptyQuery) { - EnumSet set; - const EnumSet empty; - set.Add(200); - set.Add(300); - EXPECT_TRUE(set.HasAnyOf(empty)); -} - -TEST(EnumSetHasAnyOf, EmptyQuery) { - EnumSet set; - const EnumSet empty; - set.Add(5); - set.Add(8); - set.Add(200); - set.Add(300); - EXPECT_TRUE(set.HasAnyOf(empty)); -} - -TEST(EnumSetHasAnyOf, EmptyQueryAlwaysTrue) { - EnumSet set; - const EnumSet empty; - EXPECT_TRUE(set.HasAnyOf(empty)); - set.Add(5); - EXPECT_TRUE(set.HasAnyOf(empty)); - - EXPECT_TRUE(EnumSet(100).HasAnyOf(EnumSet())); -} - -TEST(EnumSetHasAnyOf, ReflexiveMask) { - EnumSet set(3); - set.Add(24); - set.Add(30); - EXPECT_TRUE(set.HasAnyOf(set)); -} - -TEST(EnumSetHasAnyOf, ReflexiveOverflow) { - EnumSet set(200); - set.Add(300); - set.Add(400); - EXPECT_TRUE(set.HasAnyOf(set)); -} - -TEST(EnumSetHasAnyOf, Reflexive) { - EnumSet set(3); - set.Add(24); - set.Add(300); - set.Add(400); - EXPECT_TRUE(set.HasAnyOf(set)); -} - -TEST(EnumSetHasAnyOf, EmptySetHasNone) { - EnumSet set; - EnumSet items; - for (uint32_t i = 0; i < 200; ++i) { - items.Add(i); - EXPECT_FALSE(set.HasAnyOf(items)); - EXPECT_FALSE(set.HasAnyOf(EnumSet(i))); - } -} - -TEST(EnumSetHasAnyOf, MaskSetMaskQuery) { - EnumSet set(0); - EnumSet items(1); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(2); - items.Add(3); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(3); - EXPECT_TRUE(set.HasAnyOf(items)); - set.Add(4); - EXPECT_TRUE(set.HasAnyOf(items)); -} - -TEST(EnumSetHasAnyOf, OverflowSetOverflowQuery) { - EnumSet set(100); - EnumSet items(200); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(300); - items.Add(400); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(200); - EXPECT_TRUE(set.HasAnyOf(items)); - set.Add(500); - EXPECT_TRUE(set.HasAnyOf(items)); -} - -TEST(EnumSetHasAnyOf, GeneralCase) { - EnumSet set(0); - EnumSet items(100); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(300); - items.Add(4); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(5); - items.Add(500); - EXPECT_FALSE(set.HasAnyOf(items)); - set.Add(500); - EXPECT_TRUE(set.HasAnyOf(items)); - EXPECT_FALSE(set.HasAnyOf(EnumSet(20))); - EXPECT_FALSE(set.HasAnyOf(EnumSet(600))); - EXPECT_TRUE(set.HasAnyOf(EnumSet(5))); - EXPECT_TRUE(set.HasAnyOf(EnumSet(300))); - EXPECT_TRUE(set.HasAnyOf(EnumSet(0))); -} - -TEST(EnumSet, DefaultIsEmpty) { - EnumSet set; - for (uint32_t i = 0; i < 1000; ++i) { - EXPECT_FALSE(set.Contains(i)); - } -} - -TEST(CapabilitySet, ConstructSingleMemberMatrix) { - CapabilitySet s(SpvCapabilityMatrix); - EXPECT_TRUE(s.Contains(SpvCapabilityMatrix)); - EXPECT_FALSE(s.Contains(SpvCapabilityShader)); - EXPECT_FALSE(s.Contains(static_cast(1000))); -} - -TEST(CapabilitySet, ConstructSingleMemberMaxInMask) { - CapabilitySet s(static_cast(63)); - EXPECT_FALSE(s.Contains(SpvCapabilityMatrix)); - EXPECT_FALSE(s.Contains(SpvCapabilityShader)); - EXPECT_TRUE(s.Contains(static_cast(63))); - EXPECT_FALSE(s.Contains(static_cast(64))); - EXPECT_FALSE(s.Contains(static_cast(1000))); -} - -TEST(CapabilitySet, ConstructSingleMemberMinOverflow) { - // Check the first one that forces overflow beyond the mask. - CapabilitySet s(static_cast(64)); - EXPECT_FALSE(s.Contains(SpvCapabilityMatrix)); - EXPECT_FALSE(s.Contains(SpvCapabilityShader)); - EXPECT_FALSE(s.Contains(static_cast(63))); - EXPECT_TRUE(s.Contains(static_cast(64))); - EXPECT_FALSE(s.Contains(static_cast(1000))); -} - -TEST(CapabilitySet, ConstructSingleMemberMaxOverflow) { - // Check the max 32-bit signed int. - CapabilitySet s(static_cast(0x7fffffffu)); - EXPECT_FALSE(s.Contains(SpvCapabilityMatrix)); - EXPECT_FALSE(s.Contains(SpvCapabilityShader)); - EXPECT_FALSE(s.Contains(static_cast(1000))); - EXPECT_TRUE(s.Contains(static_cast(0x7fffffffu))); -} - -TEST(CapabilitySet, AddEnum) { - CapabilitySet s(SpvCapabilityShader); - s.Add(SpvCapabilityKernel); - s.Add(static_cast(42)); - EXPECT_FALSE(s.Contains(SpvCapabilityMatrix)); - EXPECT_TRUE(s.Contains(SpvCapabilityShader)); - EXPECT_TRUE(s.Contains(SpvCapabilityKernel)); - EXPECT_TRUE(s.Contains(static_cast(42))); -} - -TEST(CapabilitySet, InitializerListEmpty) { - CapabilitySet s{}; - for (uint32_t i = 0; i < 1000; i++) { - EXPECT_FALSE(s.Contains(static_cast(i))); - } -} - -struct ForEachCase { - CapabilitySet capabilities; - std::vector expected; -}; - -using CapabilitySetForEachTest = ::testing::TestWithParam; - -TEST_P(CapabilitySetForEachTest, CallsAsExpected) { - EXPECT_THAT(ElementsIn(GetParam().capabilities), Eq(GetParam().expected)); -} - -TEST_P(CapabilitySetForEachTest, CopyConstructor) { - CapabilitySet copy(GetParam().capabilities); - EXPECT_THAT(ElementsIn(copy), Eq(GetParam().expected)); -} - -TEST_P(CapabilitySetForEachTest, MoveConstructor) { - // We need a writable copy to move from. - CapabilitySet copy(GetParam().capabilities); - CapabilitySet moved(std::move(copy)); - EXPECT_THAT(ElementsIn(moved), Eq(GetParam().expected)); - - // The moved-from set is empty. - EXPECT_THAT(ElementsIn(copy), Eq(std::vector{})); -} - -TEST_P(CapabilitySetForEachTest, OperatorEquals) { - CapabilitySet assigned = GetParam().capabilities; - EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected)); -} - -TEST_P(CapabilitySetForEachTest, OperatorEqualsSelfAssign) { - CapabilitySet assigned{GetParam().capabilities}; - assigned = assigned; - EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected)); -} - -INSTANTIATE_TEST_SUITE_P(Samples, CapabilitySetForEachTest, - ValuesIn(std::vector{ - {{}, {}}, - {{SpvCapabilityMatrix}, {SpvCapabilityMatrix}}, - {{SpvCapabilityKernel, SpvCapabilityShader}, - {SpvCapabilityShader, SpvCapabilityKernel}}, - {{static_cast(999)}, - {static_cast(999)}}, - {{static_cast(0x7fffffff)}, - {static_cast(0x7fffffff)}}, - // Mixture and out of order - {{static_cast(0x7fffffff), - static_cast(100), - SpvCapabilityShader, SpvCapabilityMatrix}, - {SpvCapabilityMatrix, SpvCapabilityShader, - static_cast(100), - static_cast(0x7fffffff)}}, - })); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/enum_string_mapping_test.cpp b/3rdparty/spirv-tools/test/enum_string_mapping_test.cpp deleted file mode 100644 index a0379c18c..000000000 --- a/3rdparty/spirv-tools/test/enum_string_mapping_test.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for OpExtension validator rules. - -#include -#include -#include - -#include "gtest/gtest.h" -#include "source/enum_string_mapping.h" -#include "source/extensions.h" - -namespace spvtools { -namespace { - -using ::testing::Values; -using ::testing::ValuesIn; - -using ExtensionTest = - ::testing::TestWithParam>; -using UnknownExtensionTest = ::testing::TestWithParam; -using CapabilityTest = - ::testing::TestWithParam>; - -TEST_P(ExtensionTest, TestExtensionFromString) { - const std::pair& param = GetParam(); - const Extension extension = param.first; - const std::string extension_str = param.second; - Extension result_extension; - ASSERT_TRUE(GetExtensionFromString(extension_str.c_str(), &result_extension)); - EXPECT_EQ(extension, result_extension); -} - -TEST_P(ExtensionTest, TestExtensionToString) { - const std::pair& param = GetParam(); - const Extension extension = param.first; - const std::string extension_str = param.second; - const std::string result_str = ExtensionToString(extension); - EXPECT_EQ(extension_str, result_str); -} - -TEST_P(UnknownExtensionTest, TestExtensionFromStringFails) { - Extension result_extension; - ASSERT_FALSE(GetExtensionFromString(GetParam().c_str(), &result_extension)); -} - -TEST_P(CapabilityTest, TestCapabilityToString) { - const std::pair& param = GetParam(); - const SpvCapability capability = param.first; - const std::string capability_str = param.second; - const std::string result_str = CapabilityToString(capability); - EXPECT_EQ(capability_str, result_str); -} - -INSTANTIATE_TEST_SUITE_P( - AllExtensions, ExtensionTest, - ValuesIn(std::vector>({ - {Extension::kSPV_KHR_16bit_storage, "SPV_KHR_16bit_storage"}, - {Extension::kSPV_KHR_device_group, "SPV_KHR_device_group"}, - {Extension::kSPV_KHR_multiview, "SPV_KHR_multiview"}, - {Extension::kSPV_KHR_shader_ballot, "SPV_KHR_shader_ballot"}, - {Extension::kSPV_KHR_shader_draw_parameters, - "SPV_KHR_shader_draw_parameters"}, - {Extension::kSPV_KHR_subgroup_vote, "SPV_KHR_subgroup_vote"}, - {Extension::kSPV_NVX_multiview_per_view_attributes, - "SPV_NVX_multiview_per_view_attributes"}, - {Extension::kSPV_NV_geometry_shader_passthrough, - "SPV_NV_geometry_shader_passthrough"}, - {Extension::kSPV_NV_sample_mask_override_coverage, - "SPV_NV_sample_mask_override_coverage"}, - {Extension::kSPV_NV_stereo_view_rendering, - "SPV_NV_stereo_view_rendering"}, - {Extension::kSPV_NV_viewport_array2, "SPV_NV_viewport_array2"}, - {Extension::kSPV_GOOGLE_decorate_string, "SPV_GOOGLE_decorate_string"}, - {Extension::kSPV_GOOGLE_hlsl_functionality1, - "SPV_GOOGLE_hlsl_functionality1"}, - {Extension::kSPV_KHR_8bit_storage, "SPV_KHR_8bit_storage"}, - }))); - -INSTANTIATE_TEST_SUITE_P(UnknownExtensions, UnknownExtensionTest, - Values("", "SPV_KHR_", "SPV_KHR_device_group_ERROR", - /*alphabetically before all extensions*/ "A", - /*alphabetically after all extensions*/ "Z", - "SPV_ERROR_random_string_hfsdklhlktherh")); - -INSTANTIATE_TEST_SUITE_P( - AllCapabilities, CapabilityTest, - ValuesIn(std::vector>( - {{SpvCapabilityMatrix, "Matrix"}, - {SpvCapabilityShader, "Shader"}, - {SpvCapabilityGeometry, "Geometry"}, - {SpvCapabilityTessellation, "Tessellation"}, - {SpvCapabilityAddresses, "Addresses"}, - {SpvCapabilityLinkage, "Linkage"}, - {SpvCapabilityKernel, "Kernel"}, - {SpvCapabilityVector16, "Vector16"}, - {SpvCapabilityFloat16Buffer, "Float16Buffer"}, - {SpvCapabilityFloat16, "Float16"}, - {SpvCapabilityFloat64, "Float64"}, - {SpvCapabilityInt64, "Int64"}, - {SpvCapabilityInt64Atomics, "Int64Atomics"}, - {SpvCapabilityImageBasic, "ImageBasic"}, - {SpvCapabilityImageReadWrite, "ImageReadWrite"}, - {SpvCapabilityImageMipmap, "ImageMipmap"}, - {SpvCapabilityPipes, "Pipes"}, - {SpvCapabilityGroups, "Groups"}, - {SpvCapabilityDeviceEnqueue, "DeviceEnqueue"}, - {SpvCapabilityLiteralSampler, "LiteralSampler"}, - {SpvCapabilityAtomicStorage, "AtomicStorage"}, - {SpvCapabilityInt16, "Int16"}, - {SpvCapabilityTessellationPointSize, "TessellationPointSize"}, - {SpvCapabilityGeometryPointSize, "GeometryPointSize"}, - {SpvCapabilityImageGatherExtended, "ImageGatherExtended"}, - {SpvCapabilityStorageImageMultisample, "StorageImageMultisample"}, - {SpvCapabilityUniformBufferArrayDynamicIndexing, - "UniformBufferArrayDynamicIndexing"}, - {SpvCapabilitySampledImageArrayDynamicIndexing, - "SampledImageArrayDynamicIndexing"}, - {SpvCapabilityStorageBufferArrayDynamicIndexing, - "StorageBufferArrayDynamicIndexing"}, - {SpvCapabilityStorageImageArrayDynamicIndexing, - "StorageImageArrayDynamicIndexing"}, - {SpvCapabilityClipDistance, "ClipDistance"}, - {SpvCapabilityCullDistance, "CullDistance"}, - {SpvCapabilityImageCubeArray, "ImageCubeArray"}, - {SpvCapabilitySampleRateShading, "SampleRateShading"}, - {SpvCapabilityImageRect, "ImageRect"}, - {SpvCapabilitySampledRect, "SampledRect"}, - {SpvCapabilityGenericPointer, "GenericPointer"}, - {SpvCapabilityInt8, "Int8"}, - {SpvCapabilityInputAttachment, "InputAttachment"}, - {SpvCapabilitySparseResidency, "SparseResidency"}, - {SpvCapabilityMinLod, "MinLod"}, - {SpvCapabilitySampled1D, "Sampled1D"}, - {SpvCapabilityImage1D, "Image1D"}, - {SpvCapabilitySampledCubeArray, "SampledCubeArray"}, - {SpvCapabilitySampledBuffer, "SampledBuffer"}, - {SpvCapabilityImageBuffer, "ImageBuffer"}, - {SpvCapabilityImageMSArray, "ImageMSArray"}, - {SpvCapabilityStorageImageExtendedFormats, - "StorageImageExtendedFormats"}, - {SpvCapabilityImageQuery, "ImageQuery"}, - {SpvCapabilityDerivativeControl, "DerivativeControl"}, - {SpvCapabilityInterpolationFunction, "InterpolationFunction"}, - {SpvCapabilityTransformFeedback, "TransformFeedback"}, - {SpvCapabilityGeometryStreams, "GeometryStreams"}, - {SpvCapabilityStorageImageReadWithoutFormat, - "StorageImageReadWithoutFormat"}, - {SpvCapabilityStorageImageWriteWithoutFormat, - "StorageImageWriteWithoutFormat"}, - {SpvCapabilityMultiViewport, "MultiViewport"}, - {SpvCapabilitySubgroupDispatch, "SubgroupDispatch"}, - {SpvCapabilityNamedBarrier, "NamedBarrier"}, - {SpvCapabilityPipeStorage, "PipeStorage"}, - {SpvCapabilitySubgroupBallotKHR, "SubgroupBallotKHR"}, - {SpvCapabilityDrawParameters, "DrawParameters"}, - {SpvCapabilitySubgroupVoteKHR, "SubgroupVoteKHR"}, - {SpvCapabilityStorageBuffer16BitAccess, "StorageBuffer16BitAccess"}, - {SpvCapabilityStorageUniformBufferBlock16, - "StorageBuffer16BitAccess"}, // Preferred name - {SpvCapabilityUniformAndStorageBuffer16BitAccess, - "UniformAndStorageBuffer16BitAccess"}, - {SpvCapabilityStorageUniform16, - "UniformAndStorageBuffer16BitAccess"}, // Preferred name - {SpvCapabilityStoragePushConstant16, "StoragePushConstant16"}, - {SpvCapabilityStorageInputOutput16, "StorageInputOutput16"}, - {SpvCapabilityDeviceGroup, "DeviceGroup"}, - {SpvCapabilityMultiView, "MultiView"}, - {SpvCapabilitySampleMaskOverrideCoverageNV, - "SampleMaskOverrideCoverageNV"}, - {SpvCapabilityGeometryShaderPassthroughNV, - "GeometryShaderPassthroughNV"}, - // The next two are different names for the same token. - {SpvCapabilityShaderViewportIndexLayerNV, - "ShaderViewportIndexLayerEXT"}, - {SpvCapabilityShaderViewportIndexLayerEXT, - "ShaderViewportIndexLayerEXT"}, - {SpvCapabilityShaderViewportMaskNV, "ShaderViewportMaskNV"}, - {SpvCapabilityShaderStereoViewNV, "ShaderStereoViewNV"}, - {SpvCapabilityPerViewAttributesNV, "PerViewAttributesNV"}}))); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/ext_inst.debuginfo_test.cpp b/3rdparty/spirv-tools/test/ext_inst.debuginfo_test.cpp deleted file mode 100644 index 9090c2473..000000000 --- a/3rdparty/spirv-tools/test/ext_inst.debuginfo_test.cpp +++ /dev/null @@ -1,815 +0,0 @@ -// Copyright (c) 2017 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 "DebugInfo.h" -#include "gmock/gmock.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -// This file tests the correctness of encoding and decoding of instructions -// involving the DebugInfo extended instruction set. -// Semantic correctness should be the responsibility of validator. -// -// See https://www.khronos.org/registry/spir-v/specs/1.0/DebugInfo.html - -namespace spvtools { -namespace { - -using spvtest::Concatenate; -using spvtest::MakeInstruction; -using utils::MakeVector; -using testing::Eq; - -struct InstructionCase { - uint32_t opcode; - std::string name; - std::string operands; - std::vector expected_operands; -}; - -using ExtInstDebugInfoRoundTripTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; -using ExtInstDebugInfoRoundTripTestExplicit = spvtest::TextToBinaryTest; - -TEST_P(ExtInstDebugInfoRoundTripTest, ParameterizedExtInst) { - const std::string input = - "%1 = OpExtInstImport \"DebugInfo\"\n" - "%3 = OpExtInst %2 %1 " + - GetParam().name + GetParam().operands + "\n"; - // First make sure it assembles correctly. - EXPECT_THAT( - CompiledInstructions(input), - Eq(Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode}, - GetParam().expected_operands)}))) - << input; - // Now check the round trip through the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input; -} - -#define CASE_0(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, "", {} \ - } - -#define CASE_ILL(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0 " " #L1, { \ - 4, L0, L1 \ - } \ - } - -#define CASE_IL(Enum, L0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0, { 4, L0 } \ - } - -#define CASE_I(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4", { 4 } \ - } - -#define CASE_II(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5", { 4, 5 } \ - } - -#define CASE_III(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6", { 4, 5, 6 } \ - } - -#define CASE_IIII(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7", { \ - 4, 5, 6, 7 \ - } \ - } - -#define CASE_IIIII(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 %8", { \ - 4, 5, 6, 7, 8 \ - } \ - } - -#define CASE_IIIIII(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 %8 %9", { \ - 4, 5, 6, 7, 8, 9 \ - } \ - } - -#define CASE_IIIIIII(Enum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 %8 %9 %10", { \ - 4, 5, 6, 7, 8, 9, 10 \ - } \ - } - -#define CASE_IIILLI(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7", { \ - 4, 5, 6, L0, L1, 7 \ - } \ - } - -#define CASE_IIILLIL(Enum, L0, L1, L2) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 " #L2, { \ - 4, 5, 6, L0, L1, 7, L2 \ - } \ - } - -#define CASE_IE(Enum, E0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #E0, { \ - 4, uint32_t(DebugInfo##E0) \ - } \ - } - -#define CASE_IIE(Enum, E0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 " #E0, { \ - 4, 5, uint32_t(DebugInfo##E0) \ - } \ - } - -#define CASE_ISF(Enum, S0, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #S0 " " Fstr, { \ - 4, uint32_t(SpvStorageClass##S0), Fnum \ - } \ - } - -#define CASE_LII(Enum, L0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #L0 " %4 %5", { \ - L0, 4, 5 \ - } \ - } - -#define CASE_ILI(Enum, L0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0 " %5", { \ - 4, L0, 5 \ - } \ - } - -#define CASE_ILII(Enum, L0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #L0 " %5 %6", { \ - 4, L0, 5, 6 \ - } \ - } - -#define CASE_ILLII(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 " #L0 " " #L1 " %5 %6", { \ - 4, L0, L1, 5, 6 \ - } \ - } - -#define CASE_IIILLIIF(Enum, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr, { \ - 4, 5, 6, L0, L1, 7, 8, Fnum \ - } \ - } - -#define CASE_IIILLIIFII(Enum, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " %9 %10", { \ - 4, 5, 6, L0, L1, 7, 8, Fnum, 9, 10 \ - } \ - } - -#define CASE_IIILLIIFIIII(Enum, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " %9 %10 %11 %12", { \ - 4, 5, 6, L0, L1, 7, 8, Fnum, 9, 10, 11, 12 \ - } \ - } - -#define CASE_IIILLIIFIIIIII(Enum, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " %9 %10 %11 %12 %13 %14", { \ - 4, 5, 6, L0, L1, 7, 8, Fnum, 9, 10, 11, 12, 13, 14 \ - } \ - } - -#define CASE_IEILLIIF(Enum, E0, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr, { \ - 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum \ - } \ - } - -#define CASE_IEILLIIFI(Enum, E0, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8", { \ - 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8 \ - } \ - } - -#define CASE_IEILLIIFII(Enum, E0, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8 %9", { \ - 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8, 9 \ - } \ - } - -#define CASE_IEILLIIFIII(Enum, E0, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8 %9 %10", { \ - 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8, 9, 10 \ - } \ - } - -#define CASE_IEILLIIFIIII(Enum, E0, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 " #E0 " %5 " #L0 " " #L1 " %6 %7 " Fstr " %8 %9 %10 %11", { \ - 4, uint32_t(DebugInfo##E0), 5, L0, L1, 6, 7, Fnum, 8, 9, 10, 11 \ - } \ - } - -#define CASE_IIILLIIIF(Enum, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 %9 " Fstr, { \ - 4, 5, 6, L0, L1, 7, 8, 9, Fnum \ - } \ - } - -#define CASE_IIILLIIIFI(Enum, L0, L1, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 %9 " Fstr " %10", { \ - 4, 5, 6, L0, L1, 7, 8, 9, Fnum, 10 \ - } \ - } - -#define CASE_IIIIF(Enum, Fstr, Fnum) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 %7 " Fstr, { \ - 4, 5, 6, 7, Fnum \ - } \ - } - -#define CASE_IIILL(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 %5 %6 " #L0 " " #L1, { \ - 4, 5, 6, L0, L1 \ - } \ - } - -#define CASE_IIIILL(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 %7 " #L0 " " #L1, { \ - 4, 5, 6, 7, L0, L1 \ - } \ - } - -#define CASE_IILLI(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 " #L0 " " #L1 " %6", { \ - 4, 5, L0, L1, 6 \ - } \ - } - -#define CASE_IILLII(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 " #L0 " " #L1 " %6 %7", { \ - 4, 5, L0, L1, 6, 7 \ - } \ - } - -#define CASE_IILLIII(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 " #L0 " " #L1 " %6 %7 %8", { \ - 4, 5, L0, L1, 6, 7, 8 \ - } \ - } - -#define CASE_IILLIIII(Enum, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 " #L0 " " #L1 " %6 %7 %8 %9", { \ - 4, 5, L0, L1, 6, 7, 8, 9 \ - } \ - } - -#define CASE_IIILLIIFLI(Enum, L0, L1, Fstr, Fnum, L2) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " " #L2 " %9", { \ - 4, 5, 6, L0, L1, 7, 8, Fnum, L2, 9 \ - } \ - } - -#define CASE_IIILLIIFLII(Enum, L0, L1, Fstr, Fnum, L2) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, \ - " %4 %5 %6 " #L0 " " #L1 " %7 %8 " Fstr " " #L2 " %9 %10", { \ - 4, 5, 6, L0, L1, 7, 8, Fnum, L2, 9, 10 \ - } \ - } - -#define CASE_E(Enum, E0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #E0, { \ - uint32_t(DebugInfo##E0) \ - } \ - } - -#define CASE_EL(Enum, E0, L0) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #E0 " " #L0, { \ - uint32_t(DebugInfo##E0), L0 \ - } \ - } - -#define CASE_ELL(Enum, E0, L0, L1) \ - { \ - uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " " #E0 " " #L0 " " #L1, { \ - uint32_t(DebugInfo##E0), L0, L1 \ - } \ - } - -// DebugInfo 4.1 Absent Debugging Information -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugInfoNone, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_0(InfoNone), // enum value 0 - }))); - -// DebugInfo 4.2 Compilation Unit -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugCompilationUnit, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_ILL(CompilationUnit, 100, 42), - }))); - -// DebugInfo 4.3 Type instructions -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeBasic, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIE(TypeBasic, Unspecified), - CASE_IIE(TypeBasic, Address), - CASE_IIE(TypeBasic, Boolean), - CASE_IIE(TypeBasic, Float), - CASE_IIE(TypeBasic, Signed), - CASE_IIE(TypeBasic, SignedChar), - CASE_IIE(TypeBasic, Unsigned), - CASE_IIE(TypeBasic, UnsignedChar), - }))); - -// The FlagIsPublic is value is (1 << 0) | (1 << 2) which is the same -// as the bitwise-OR of FlagIsProtected and FlagIsPrivate. -// The disassembler will emit the compound expression instead. -// There is no simple fix for this. This enum is not really a mask -// for the bottom two bits. -TEST_F(ExtInstDebugInfoRoundTripTestExplicit, FlagIsPublic) { - const std::string prefix = - "%1 = OpExtInstImport \"DebugInfo\"\n" - "%3 = OpExtInst %2 %1 DebugTypePointer %4 Private "; - const std::string input = prefix + "FlagIsPublic\n"; - const std::string expected = prefix + "FlagIsProtected|FlagIsPrivate\n"; - // First make sure it assembles correctly. - EXPECT_THAT( - CompiledInstructions(input), - Eq(Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, DebugInfoDebugTypePointer, 4, - uint32_t(SpvStorageClassPrivate), - DebugInfoFlagIsPublic})}))) - << input; - // Now check the round trip through the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(expected)) << input; -} - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugTypePointer, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - - //// Use each flag independently. - CASE_ISF(TypePointer, Private, "FlagIsProtected", - uint32_t(DebugInfoFlagIsProtected)), - CASE_ISF(TypePointer, Private, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - - // FlagIsPublic is tested above. - - CASE_ISF(TypePointer, Private, "FlagIsLocal", - uint32_t(DebugInfoFlagIsLocal)), - CASE_ISF(TypePointer, Private, "FlagIsDefinition", - uint32_t(DebugInfoFlagIsDefinition)), - CASE_ISF(TypePointer, Private, "FlagFwdDecl", - uint32_t(DebugInfoFlagFwdDecl)), - CASE_ISF(TypePointer, Private, "FlagArtificial", - uint32_t(DebugInfoFlagArtificial)), - CASE_ISF(TypePointer, Private, "FlagExplicit", - uint32_t(DebugInfoFlagExplicit)), - CASE_ISF(TypePointer, Private, "FlagPrototyped", - uint32_t(DebugInfoFlagPrototyped)), - CASE_ISF(TypePointer, Private, "FlagObjectPointer", - uint32_t(DebugInfoFlagObjectPointer)), - CASE_ISF(TypePointer, Private, "FlagStaticMember", - uint32_t(DebugInfoFlagStaticMember)), - CASE_ISF(TypePointer, Private, "FlagIndirectVariable", - uint32_t(DebugInfoFlagIndirectVariable)), - CASE_ISF(TypePointer, Private, "FlagLValueReference", - uint32_t(DebugInfoFlagLValueReference)), - CASE_ISF(TypePointer, Private, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized)), - - //// Use flags in combination, and try different storage classes. - CASE_ISF(TypePointer, Function, "FlagIsProtected|FlagIsPrivate", - uint32_t(DebugInfoFlagIsProtected) | - uint32_t(DebugInfoFlagIsPrivate)), - CASE_ISF( - TypePointer, Workgroup, - "FlagIsPrivate|FlagFwdDecl|FlagIndirectVariable|FlagIsOptimized", - uint32_t(DebugInfoFlagIsPrivate) | uint32_t(DebugInfoFlagFwdDecl) | - uint32_t(DebugInfoFlagIndirectVariable) | - uint32_t(DebugInfoFlagIsOptimized)), - - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeQualifier, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IE(TypeQualifier, ConstType), - CASE_IE(TypeQualifier, VolatileType), - CASE_IE(TypeQualifier, RestrictType), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeArray, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_II(TypeArray), - CASE_III(TypeArray), - CASE_IIII(TypeArray), - CASE_IIIII(TypeArray), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeVector, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IL(TypeVector, 2), - CASE_IL(TypeVector, 3), - CASE_IL(TypeVector, 4), - CASE_IL(TypeVector, 16), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypedef, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLI(Typedef, 12, 13), - CASE_IIILLI(Typedef, 14, 99), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeFunction, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_I(TypeFunction), - CASE_II(TypeFunction), - CASE_III(TypeFunction), - CASE_IIII(TypeFunction), - CASE_IIIII(TypeFunction), - }))); - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugTypeEnum, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLIIFII( - TypeEnum, 12, 13, - "FlagIsPrivate|FlagFwdDecl|FlagIndirectVariable|FlagIsOptimized", - uint32_t(DebugInfoFlagIsPrivate) | uint32_t(DebugInfoFlagFwdDecl) | - uint32_t(DebugInfoFlagIndirectVariable) | - uint32_t(DebugInfoFlagIsOptimized)), - CASE_IIILLIIFIIII(TypeEnum, 17, 18, "FlagStaticMember", - uint32_t(DebugInfoFlagStaticMember)), - CASE_IIILLIIFIIIIII(TypeEnum, 99, 1, "FlagStaticMember", - uint32_t(DebugInfoFlagStaticMember)), - }))); - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugTypeComposite, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IEILLIIF( - TypeComposite, Class, 12, 13, - "FlagIsPrivate|FlagFwdDecl|FlagIndirectVariable|FlagIsOptimized", - uint32_t(DebugInfoFlagIsPrivate) | uint32_t(DebugInfoFlagFwdDecl) | - uint32_t(DebugInfoFlagIndirectVariable) | - uint32_t(DebugInfoFlagIsOptimized)), - // Cover all tag values: Class, Structure, Union - CASE_IEILLIIF(TypeComposite, Class, 12, 13, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IEILLIIF(TypeComposite, Structure, 12, 13, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IEILLIIF(TypeComposite, Union, 12, 13, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - // Now add members - CASE_IEILLIIFI(TypeComposite, Class, 9, 10, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IEILLIIFII(TypeComposite, Class, 9, 10, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IEILLIIFIII(TypeComposite, Class, 9, 10, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IEILLIIFIIII(TypeComposite, Class, 9, 10, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - }))); - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugTypeMember, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLIIIF(TypeMember, 12, 13, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IIILLIIIF(TypeMember, 99, 100, "FlagIsPrivate|FlagFwdDecl", - uint32_t(DebugInfoFlagIsPrivate) | - uint32_t(DebugInfoFlagFwdDecl)), - // Add the optional Id argument. - CASE_IIILLIIIFI(TypeMember, 12, 13, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - }))); - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugTypeInheritance, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIIIF(TypeInheritance, "FlagIsPrivate", - uint32_t(DebugInfoFlagIsPrivate)), - CASE_IIIIF(TypeInheritance, "FlagIsPrivate|FlagFwdDecl", - uint32_t(DebugInfoFlagIsPrivate) | - uint32_t(DebugInfoFlagFwdDecl)), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypePtrToMember, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_II(TypePtrToMember), - }))); - -// DebugInfo 4.4 Templates - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeTemplate, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_II(TypeTemplate), - CASE_III(TypeTemplate), - CASE_IIII(TypeTemplate), - CASE_IIIII(TypeTemplate), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeTemplateParameter, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIIILL(TypeTemplateParameter, 1, 2), - CASE_IIIILL(TypeTemplateParameter, 99, 102), - CASE_IIIILL(TypeTemplateParameter, 10, 7), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeTemplateTemplateParameter, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILL(TypeTemplateTemplateParameter, 1, 2), - CASE_IIILL(TypeTemplateTemplateParameter, 99, 102), - CASE_IIILL(TypeTemplateTemplateParameter, 10, 7), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugTypeTemplateParameterPack, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IILLI(TypeTemplateParameterPack, 1, 2), - CASE_IILLII(TypeTemplateParameterPack, 99, 102), - CASE_IILLIII(TypeTemplateParameterPack, 10, 7), - CASE_IILLIIII(TypeTemplateParameterPack, 10, 7), - }))); - -// DebugInfo 4.5 Global Variables - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugGlobalVariable, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLIIIF(GlobalVariable, 1, 2, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized)), - CASE_IIILLIIIF(GlobalVariable, 42, 43, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized)), - CASE_IIILLIIIFI(GlobalVariable, 1, 2, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized)), - CASE_IIILLIIIFI(GlobalVariable, 42, 43, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized)), - }))); - -// DebugInfo 4.6 Functions - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugFunctionDeclaration, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLIIF(FunctionDeclaration, 1, 2, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized)), - CASE_IIILLIIF(FunctionDeclaration, 42, 43, "FlagFwdDecl", - uint32_t(DebugInfoFlagFwdDecl)), - }))); - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugFunction, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLIIFLI(Function, 1, 2, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized), 3), - CASE_IIILLIIFLI(Function, 42, 43, "FlagFwdDecl", - uint32_t(DebugInfoFlagFwdDecl), 44), - // Add the optional declaration Id. - CASE_IIILLIIFLII(Function, 1, 2, "FlagIsOptimized", - uint32_t(DebugInfoFlagIsOptimized), 3), - CASE_IIILLIIFLII(Function, 42, 43, "FlagFwdDecl", - uint32_t(DebugInfoFlagFwdDecl), 44), - }))); - -// DebugInfo 4.7 Local Information - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugLexicalBlock, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_ILLII(LexicalBlock, 1, 2), - CASE_ILLII(LexicalBlock, 42, 43), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugLexicalBlockDiscriminator, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_ILI(LexicalBlockDiscriminator, 1), - CASE_ILI(LexicalBlockDiscriminator, 42), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugScope, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_I(Scope), - CASE_II(Scope), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugNoScope, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_0(NoScope), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugInlinedAt, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_LII(InlinedAt, 1), - CASE_LII(InlinedAt, 42), - }))); - -// DebugInfo 4.8 Local Variables - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugLocalVariable, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_IIILLI(LocalVariable, 1, 2), - CASE_IIILLI(LocalVariable, 42, 43), - CASE_IIILLIL(LocalVariable, 1, 2, 3), - CASE_IIILLIL(LocalVariable, 42, 43, 44), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugInlinedVariable, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_II(InlinedVariable), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugDebugDeclare, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_III(Declare), - }))); - -INSTANTIATE_TEST_SUITE_P( - DebugInfoDebugDebugValue, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_III(Value), - CASE_IIII(Value), - CASE_IIIII(Value), - CASE_IIIIII(Value), - // Test up to 4 id parameters. We can always try more. - CASE_IIIIIII(Value), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugDebugOperation, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_E(Operation, Deref), - CASE_E(Operation, Plus), - CASE_E(Operation, Minus), - CASE_EL(Operation, PlusUconst, 1), - CASE_EL(Operation, PlusUconst, 42), - CASE_ELL(Operation, BitPiece, 1, 2), - CASE_ELL(Operation, BitPiece, 4, 5), - CASE_E(Operation, Swap), - CASE_E(Operation, Xderef), - CASE_E(Operation, StackValue), - CASE_EL(Operation, Constu, 1), - CASE_EL(Operation, Constu, 42), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugDebugExpression, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_0(Expression), - CASE_I(Expression), - CASE_II(Expression), - CASE_III(Expression), - CASE_IIII(Expression), - CASE_IIIII(Expression), - CASE_IIIIII(Expression), - CASE_IIIIIII(Expression), - }))); - -// DebugInfo 4.9 Macros - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugMacroDef, ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_ILI(MacroDef, 1), - CASE_ILI(MacroDef, 42), - CASE_ILII(MacroDef, 1), - CASE_ILII(MacroDef, 42), - }))); - -INSTANTIATE_TEST_SUITE_P(DebugInfoDebugMacroUndef, - ExtInstDebugInfoRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE_ILI(MacroUndef, 1), - CASE_ILI(MacroUndef, 42), - }))); - -#undef CASE_0 -#undef CASE_ILL -#undef CASE_IL -#undef CASE_I -#undef CASE_II -#undef CASE_III -#undef CASE_IIII -#undef CASE_IIIII -#undef CASE_IIIIII -#undef CASE_IIIIIII -#undef CASE_IIILLI -#undef CASE_IIILLIL -#undef CASE_IE -#undef CASE_IIE -#undef CASE_ISF -#undef CASE_LII -#undef CASE_ILI -#undef CASE_ILII -#undef CASE_ILLII -#undef CASE_IIILLIIF -#undef CASE_IIILLIIFII -#undef CASE_IIILLIIFIIII -#undef CASE_IIILLIIFIIIIII -#undef CASE_IEILLIIF -#undef CASE_IEILLIIFI -#undef CASE_IEILLIIFII -#undef CASE_IEILLIIFIII -#undef CASE_IEILLIIFIIII -#undef CASE_IIILLIIIF -#undef CASE_IIILLIIIFI -#undef CASE_IIIIF -#undef CASE_IIILL -#undef CASE_IIIILL -#undef CASE_IILLI -#undef CASE_IILLII -#undef CASE_IILLIII -#undef CASE_IILLIIII -#undef CASE_IIILLIIFLI -#undef CASE_IIILLIIFLII -#undef CASE_E -#undef CASE_EL -#undef CASE_ELL - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/ext_inst.glsl_test.cpp b/3rdparty/spirv-tools/test/ext_inst.glsl_test.cpp deleted file mode 100644 index 41d222f47..000000000 --- a/3rdparty/spirv-tools/test/ext_inst.glsl_test.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "source/latest_version_glsl_std_450_header.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -/// Context for an extended instruction. -/// -/// Information about a GLSL extended instruction (including its opname, return -/// type, etc.) and related instructions used to generate the return type and -/// constant as the operands. Used in generating extended instruction tests. -struct ExtInstContext { - const char* extInstOpName; - const char* extInstOperandVars; - /// The following fields are used to check the SPIR-V binary representation - /// of this instruction. - uint32_t extInstOpcode; ///< Opcode value for this extended instruction. - uint32_t extInstLength; ///< Wordcount of this extended instruction. - std::vector extInstOperandIds; ///< Ids for operands. -}; - -using ExtInstGLSLstd450RoundTripTest = ::testing::TestWithParam; - -TEST_P(ExtInstGLSLstd450RoundTripTest, ParameterizedExtInst) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); - const std::string spirv = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical Simple -OpEntryPoint Vertex %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%2 = OpFunction %3 None %5 -%6 = OpLabel -%8 = OpExtInst %7 %1 )" + std::string(GetParam().extInstOpName) + - " " + GetParam().extInstOperandVars + R"( -OpReturn -OpFunctionEnd -)"; - const std::string spirv_header = - R"(; SPIR-V -; Version: 1.0 -; Generator: Khronos SPIR-V Tools Assembler; 0 -; Bound: 9 -; Schema: 0)"; - spv_binary binary = nullptr; - spv_diagnostic diagnostic; - spv_result_t error = spvTextToBinary(context, spirv.c_str(), spirv.size(), - &binary, &diagnostic); - if (error) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - ASSERT_EQ(SPV_SUCCESS, error) - << "Source was: " << std::endl - << spirv << std::endl - << "Test case for : " << GetParam().extInstOpName << std::endl; - } - - // Check we do have the extended instruction's corresponding binary code in - // the generated SPIR-V binary. - std::vector expected_contains( - {12 /*OpExtInst*/ | GetParam().extInstLength << 16, 7 /*return type*/, - 8 /*result id*/, 1 /*glsl450 import*/, GetParam().extInstOpcode}); - for (uint32_t operand : GetParam().extInstOperandIds) { - expected_contains.push_back(operand); - } - EXPECT_NE(binary->code + binary->wordCount, - std::search(binary->code, binary->code + binary->wordCount, - expected_contains.begin(), expected_contains.end())) - << "Cannot find\n" - << spvtest::WordVector(expected_contains).str() << "in\n" - << spvtest::WordVector(*binary).str(); - - // Check round trip gives the same text. - spv_text output_text = nullptr; - error = spvBinaryToText(context, binary->code, binary->wordCount, - SPV_BINARY_TO_TEXT_OPTION_NONE, &output_text, - &diagnostic); - - if (error) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - ASSERT_EQ(SPV_SUCCESS, error); - } - EXPECT_EQ(spirv_header + spirv, output_text->str); - spvTextDestroy(output_text); - spvBinaryDestroy(binary); - spvContextDestroy(context); -} - -INSTANTIATE_TEST_SUITE_P( - ExtInstParameters, ExtInstGLSLstd450RoundTripTest, - ::testing::ValuesIn(std::vector({ - // We are only testing the correctness of encoding and decoding here. - // Semantic correctness should be the responsibility of validator. So - // some of the instructions below have incorrect operand and/or return - // types, e.g, Modf, ModfStruct, etc. - {"Round", "%5", 1, 6, {5}}, - {"RoundEven", "%5", 2, 6, {5}}, - {"Trunc", "%5", 3, 6, {5}}, - {"FAbs", "%5", 4, 6, {5}}, - {"SAbs", "%5", 5, 6, {5}}, - {"FSign", "%5", 6, 6, {5}}, - {"SSign", "%5", 7, 6, {5}}, - {"Floor", "%5", 8, 6, {5}}, - {"Ceil", "%5", 9, 6, {5}}, - {"Fract", "%5", 10, 6, {5}}, - {"Radians", "%5", 11, 6, {5}}, - {"Degrees", "%5", 12, 6, {5}}, - {"Sin", "%5", 13, 6, {5}}, - {"Cos", "%5", 14, 6, {5}}, - {"Tan", "%5", 15, 6, {5}}, - {"Asin", "%5", 16, 6, {5}}, - {"Acos", "%5", 17, 6, {5}}, - {"Atan", "%5", 18, 6, {5}}, - {"Sinh", "%5", 19, 6, {5}}, - {"Cosh", "%5", 20, 6, {5}}, - {"Tanh", "%5", 21, 6, {5}}, - {"Asinh", "%5", 22, 6, {5}}, - {"Acosh", "%5", 23, 6, {5}}, - {"Atanh", "%5", 24, 6, {5}}, - {"Atan2", "%5 %5", 25, 7, {5, 5}}, - {"Pow", "%5 %5", 26, 7, {5, 5}}, - {"Exp", "%5", 27, 6, {5}}, - {"Log", "%5", 28, 6, {5}}, - {"Exp2", "%5", 29, 6, {5}}, - {"Log2", "%5", 30, 6, {5}}, - {"Sqrt", "%5", 31, 6, {5}}, - {"InverseSqrt", "%5", 32, 6, {5}}, - {"Determinant", "%5", 33, 6, {5}}, - {"MatrixInverse", "%5", 34, 6, {5}}, - {"Modf", "%5 %5", 35, 7, {5, 5}}, - {"ModfStruct", "%5", 36, 6, {5}}, - {"FMin", "%5 %5", 37, 7, {5, 5}}, - {"UMin", "%5 %5", 38, 7, {5, 5}}, - {"SMin", "%5 %5", 39, 7, {5, 5}}, - {"FMax", "%5 %5", 40, 7, {5, 5}}, - {"UMax", "%5 %5", 41, 7, {5, 5}}, - {"SMax", "%5 %5", 42, 7, {5, 5}}, - {"FClamp", "%5 %5 %5", 43, 8, {5, 5, 5}}, - {"UClamp", "%5 %5 %5", 44, 8, {5, 5, 5}}, - {"SClamp", "%5 %5 %5", 45, 8, {5, 5, 5}}, - {"FMix", "%5 %5 %5", 46, 8, {5, 5, 5}}, - {"IMix", "%5 %5 %5", 47, 8, {5, 5, 5}}, // Bug 15452. Reserved. - {"Step", "%5 %5", 48, 7, {5, 5}}, - {"SmoothStep", "%5 %5 %5", 49, 8, {5, 5, 5}}, - {"Fma", "%5 %5 %5", 50, 8, {5, 5, 5}}, - {"Frexp", "%5 %5", 51, 7, {5, 5}}, - {"FrexpStruct", "%5", 52, 6, {5}}, - {"Ldexp", "%5 %5", 53, 7, {5, 5}}, - {"PackSnorm4x8", "%5", 54, 6, {5}}, - {"PackUnorm4x8", "%5", 55, 6, {5}}, - {"PackSnorm2x16", "%5", 56, 6, {5}}, - {"PackUnorm2x16", "%5", 57, 6, {5}}, - {"PackHalf2x16", "%5", 58, 6, {5}}, - {"PackDouble2x32", "%5", 59, 6, {5}}, - {"UnpackSnorm2x16", "%5", 60, 6, {5}}, - {"UnpackUnorm2x16", "%5", 61, 6, {5}}, - {"UnpackHalf2x16", "%5", 62, 6, {5}}, - {"UnpackSnorm4x8", "%5", 63, 6, {5}}, - {"UnpackUnorm4x8", "%5", 64, 6, {5}}, - {"UnpackDouble2x32", "%5", 65, 6, {5}}, - {"Length", "%5", 66, 6, {5}}, - {"Distance", "%5 %5", 67, 7, {5, 5}}, - {"Cross", "%5 %5", 68, 7, {5, 5}}, - {"Normalize", "%5", 69, 6, {5}}, - // clang-format off - {"FaceForward", "%5 %5 %5", 70, 8, {5, 5, 5}}, - // clang-format on - {"Reflect", "%5 %5", 71, 7, {5, 5}}, - {"Refract", "%5 %5 %5", 72, 8, {5, 5, 5}}, - {"FindILsb", "%5", 73, 6, {5}}, - {"FindSMsb", "%5", 74, 6, {5}}, - {"FindUMsb", "%5", 75, 6, {5}}, - {"InterpolateAtCentroid", "%5", 76, 6, {5}}, - // clang-format off - {"InterpolateAtSample", "%5 %5", 77, 7, {5, 5}}, - {"InterpolateAtOffset", "%5 %5", 78, 7, {5, 5}}, - // clang-format on - {"NMin", "%5 %5", 79, 7, {5, 5}}, - {"NMax", "%5 %5", 80, 7, {5, 5}}, - {"NClamp", "%5 %5 %5", 81, 8, {5, 5, 5}}, - }))); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/ext_inst.opencl_test.cpp b/3rdparty/spirv-tools/test/ext_inst.opencl_test.cpp deleted file mode 100644 index 7547d9224..000000000 --- a/3rdparty/spirv-tools/test/ext_inst.opencl_test.cpp +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/latest_version_opencl_std_header.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::Concatenate; -using spvtest::MakeInstruction; -using utils::MakeVector; -using spvtest::TextToBinaryTest; -using testing::Eq; - -struct InstructionCase { - uint32_t opcode; - std::string name; - std::string operands; - std::vector expected_operands; -}; - -using ExtInstOpenCLStdRoundTripTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(ExtInstOpenCLStdRoundTripTest, ParameterizedExtInst) { - // This example should not validate. - const std::string input = - "%1 = OpExtInstImport \"OpenCL.std\"\n" - "%3 = OpExtInst %2 %1 " + - GetParam().name + " " + GetParam().operands + "\n"; - // First make sure it assembles correctly. - EXPECT_THAT( - CompiledInstructions(input), - Eq(Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode}, - GetParam().expected_operands)}))) - << input; - // Now check the round trip through the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input; -} - -#define CASE1(Enum, Name) \ - { \ - uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4", { 4 } \ - } -#define CASE2(Enum, Name) \ - { \ - uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5", { 4, 5 } \ - } -#define CASE3(Enum, Name) \ - { \ - uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6", { 4, 5, 6 } \ - } -#define CASE4(Enum, Name) \ - { \ - uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 %7", { \ - 4, 5, 6, 7 \ - } \ - } -#define CASE2Lit(Enum, Name, LiteralNumber) \ - { \ - uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 " #LiteralNumber, { \ - 4, 5, LiteralNumber \ - } \ - } -#define CASE3Round(Enum, Name, Mode) \ - { \ - uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 " #Mode, { \ - 4, 5, 6, uint32_t(SpvFPRoundingMode##Mode) \ - } \ - } - -// clang-format off -// OpenCL.std: 2.1 Math extended instructions -INSTANTIATE_TEST_SUITE_P( - OpenCLMath, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - // We are only testing the correctness of encoding and decoding here. - // Semantic correctness should be the responsibility of validator. - CASE1(Acos, acos), // enum value 0 - CASE1(Acosh, acosh), - CASE1(Acospi, acospi), - CASE1(Asin, asin), - CASE1(Asinh, asinh), - CASE1(Asinh, asinh), - CASE1(Asinpi, asinpi), - CASE1(Atan, atan), - CASE2(Atan2, atan2), - CASE1(Atanh, atanh), - CASE1(Atanpi, atanpi), - CASE2(Atan2pi, atan2pi), - CASE1(Cbrt, cbrt), - CASE1(Ceil, ceil), - CASE1(Ceil, ceil), - CASE2(Copysign, copysign), - CASE1(Cos, cos), - CASE1(Cosh, cosh), - CASE1(Cospi, cospi), - CASE1(Erfc, erfc), - CASE1(Erf, erf), - CASE1(Exp, exp), - CASE1(Exp2, exp2), - CASE1(Exp10, exp10), - CASE1(Expm1, expm1), - CASE1(Fabs, fabs), - CASE2(Fdim, fdim), - CASE1(Floor, floor), - CASE3(Fma, fma), - CASE2(Fmax, fmax), - CASE2(Fmin, fmin), - CASE2(Fmod, fmod), - CASE2(Fract, fract), - CASE2(Frexp, frexp), - CASE2(Hypot, hypot), - CASE1(Ilogb, ilogb), - CASE2(Ldexp, ldexp), - CASE1(Lgamma, lgamma), - CASE2(Lgamma_r, lgamma_r), - CASE1(Log, log), - CASE1(Log2, log2), - CASE1(Log10, log10), - CASE1(Log1p, log1p), - CASE3(Mad, mad), - CASE2(Maxmag, maxmag), - CASE2(Minmag, minmag), - CASE2(Modf, modf), - CASE1(Nan, nan), - CASE2(Nextafter, nextafter), - CASE2(Pow, pow), - CASE2(Pown, pown), - CASE2(Powr, powr), - CASE2(Remainder, remainder), - CASE3(Remquo, remquo), - CASE1(Rint, rint), - CASE2(Rootn, rootn), - CASE1(Round, round), - CASE1(Rsqrt, rsqrt), - CASE1(Sin, sin), - CASE2(Sincos, sincos), - CASE1(Sinh, sinh), - CASE1(Sinpi, sinpi), - CASE1(Sqrt, sqrt), - CASE1(Tan, tan), - CASE1(Tanh, tanh), - CASE1(Tanpi, tanpi), - CASE1(Tgamma, tgamma), - CASE1(Trunc, trunc), - CASE1(Half_cos, half_cos), - CASE2(Half_divide, half_divide), - CASE1(Half_exp, half_exp), - CASE1(Half_exp2, half_exp2), - CASE1(Half_exp10, half_exp10), - CASE1(Half_log, half_log), - CASE1(Half_log2, half_log2), - CASE1(Half_log10, half_log10), - CASE2(Half_powr, half_powr), - CASE1(Half_recip, half_recip), - CASE1(Half_rsqrt, half_rsqrt), - CASE1(Half_sin, half_sin), - CASE1(Half_sqrt, half_sqrt), - CASE1(Half_tan, half_tan), - CASE1(Native_cos, native_cos), - CASE2(Native_divide, native_divide), - CASE1(Native_exp, native_exp), - CASE1(Native_exp2, native_exp2), - CASE1(Native_exp10, native_exp10), - CASE1(Native_log, native_log), - CASE1(Native_log10, native_log10), - CASE2(Native_powr, native_powr), - CASE1(Native_recip, native_recip), - CASE1(Native_rsqrt, native_rsqrt), - CASE1(Native_sin, native_sin), - CASE1(Native_sqrt, native_sqrt), - CASE1(Native_tan, native_tan), // enum value 94 - }))); - -// OpenCL.std: 2.1 Integer instructions -INSTANTIATE_TEST_SUITE_P( - OpenCLInteger, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE1(SAbs, s_abs), // enum value 141 - CASE2(SAbs_diff, s_abs_diff), - CASE2(SAdd_sat, s_add_sat), - CASE2(UAdd_sat, u_add_sat), - CASE2(SHadd, s_hadd), - CASE2(UHadd, u_hadd), - CASE2(SRhadd, s_rhadd), - CASE2(SRhadd, s_rhadd), - CASE3(SClamp, s_clamp), - CASE3(UClamp, u_clamp), - CASE1(Clz, clz), - CASE1(Ctz, ctz), - CASE3(SMad_hi, s_mad_hi), - CASE3(UMad_sat, u_mad_sat), - CASE3(SMad_sat, s_mad_sat), - CASE2(SMax, s_max), - CASE2(UMax, u_max), - CASE2(SMin, s_min), - CASE2(UMin, u_min), - CASE2(SMul_hi, s_mul_hi), - CASE2(Rotate, rotate), - CASE2(SSub_sat, s_sub_sat), - CASE2(USub_sat, u_sub_sat), - CASE2(U_Upsample, u_upsample), - CASE2(S_Upsample, s_upsample), - CASE1(Popcount, popcount), - CASE3(SMad24, s_mad24), - CASE3(UMad24, u_mad24), - CASE2(SMul24, s_mul24), - CASE2(UMul24, u_mul24), // enum value 170 - CASE1(UAbs, u_abs), // enum value 201 - CASE2(UAbs_diff, u_abs_diff), - CASE2(UMul_hi, u_mul_hi), - CASE3(UMad_hi, u_mad_hi), // enum value 204 - }))); - -// OpenCL.std: 2.3 Common instrucitons -INSTANTIATE_TEST_SUITE_P( - OpenCLCommon, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE3(FClamp, fclamp), // enum value 95 - CASE1(Degrees, degrees), - CASE2(FMax_common, fmax_common), - CASE2(FMin_common, fmin_common), - CASE3(Mix, mix), - CASE1(Radians, radians), - CASE2(Step, step), - CASE3(Smoothstep, smoothstep), - CASE1(Sign, sign), // enum value 103 - }))); - -// OpenCL.std: 2.4 Geometric instructions -INSTANTIATE_TEST_SUITE_P( - OpenCLGeometric, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE2(Cross, cross), // enum value 104 - CASE2(Distance, distance), - CASE1(Length, length), - CASE1(Normalize, normalize), - CASE2(Fast_distance, fast_distance), - CASE1(Fast_length, fast_length), - CASE1(Fast_normalize, fast_normalize), // enum value 110 - }))); - -// OpenCL.std: 2.5 Relational instructions -INSTANTIATE_TEST_SUITE_P( - OpenCLRelational, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE3(Bitselect, bitselect), // enum value 186 - CASE3(Select, select), // enum value 187 - }))); - -// OpenCL.std: 2.6 Vector data load and store instructions -INSTANTIATE_TEST_SUITE_P( - OpenCLVectorLoadStore, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - // The last argument to Vloadn must be one of 2, 3, 4, 8, 16. - CASE2Lit(Vloadn, vloadn, 2), - CASE2Lit(Vloadn, vloadn, 3), - CASE2Lit(Vloadn, vloadn, 4), - CASE2Lit(Vloadn, vloadn, 8), - CASE2Lit(Vloadn, vloadn, 16), - CASE3(Vstoren, vstoren), - CASE2(Vload_half, vload_half), - CASE2Lit(Vload_halfn, vload_halfn, 2), - CASE2Lit(Vload_halfn, vload_halfn, 3), - CASE2Lit(Vload_halfn, vload_halfn, 4), - CASE2Lit(Vload_halfn, vload_halfn, 8), - CASE2Lit(Vload_halfn, vload_halfn, 16), - CASE3(Vstore_half, vstore_half), - // Try all the rounding modes. - CASE3Round(Vstore_half_r, vstore_half_r, RTE), - CASE3Round(Vstore_half_r, vstore_half_r, RTZ), - CASE3Round(Vstore_half_r, vstore_half_r, RTP), - CASE3Round(Vstore_half_r, vstore_half_r, RTN), - CASE3(Vstore_halfn, vstore_halfn), - CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTE), - CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTZ), - CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTP), - CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTN), - CASE2Lit(Vloada_halfn, vloada_halfn, 2), - CASE2Lit(Vloada_halfn, vloada_halfn, 3), - CASE2Lit(Vloada_halfn, vloada_halfn, 4), - CASE2Lit(Vloada_halfn, vloada_halfn, 8), - CASE2Lit(Vloada_halfn, vloada_halfn, 16), - CASE3(Vstorea_halfn, vstorea_halfn), - CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTE), - CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTZ), - CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTP), - CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTN), - }))); - -// OpenCL.std: 2.7 Miscellaneous vector instructions -INSTANTIATE_TEST_SUITE_P( - OpenCLMiscellaneousVector, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE2(Shuffle, shuffle), - CASE3(Shuffle2, shuffle2), - }))); - -// OpenCL.std: 2.8 Miscellaneous instructions - -#define PREFIX uint32_t(OpenCLLIB::Entrypoints::Printf), "printf" -INSTANTIATE_TEST_SUITE_P( - OpenCLMiscPrintf, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - // Printf is interesting because it takes a variable number of arguments. - // Start with zero optional arguments. - {PREFIX, "%4", {4}}, - {PREFIX, "%4 %5", {4, 5}}, - {PREFIX, "%4 %5 %6", {4, 5, 6}}, - {PREFIX, "%4 %5 %6 %7", {4, 5, 6, 7}}, - {PREFIX, "%4 %5 %6 %7 %8", {4, 5, 6, 7, 8}}, - {PREFIX, "%4 %5 %6 %7 %8 %9", {4, 5, 6, 7, 8, 9}}, - {PREFIX, "%4 %5 %6 %7 %8 %9 %10", {4, 5, 6, 7, 8, 9, 10}}, - {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11", {4, 5, 6, 7, 8, 9, 10, 11}}, - {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12", - {4, 5, 6, 7, 8, 9, 10, 11, 12}}, - {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13", - {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}, - {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14", - {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}, - }))); -#undef PREFIX - -INSTANTIATE_TEST_SUITE_P( - OpenCLMiscPrefetch, ExtInstOpenCLStdRoundTripTest, - ::testing::ValuesIn(std::vector({ - CASE2(Prefetch, prefetch), - }))); - -// OpenCL.std: 2.9.1 Image encoding -// No new instructions defined in this section. - -// OpenCL.std: 2.9.2 Sampler encoding -// No new instructions defined in this section. - -// OpenCL.std: 2.9.3 Image read -// No new instructions defined in this section. -// Use core instruction OpImageSampleExplicitLod instead. - -// OpenCL.std: 2.9.4 Image write -// No new instructions defined in this section. - -// clang-format on - -#undef CASE1 -#undef CASE2 -#undef CASE3 -#undef CASE4 -#undef CASE2Lit -#undef CASE3Round - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fix_word_test.cpp b/3rdparty/spirv-tools/test/fix_word_test.cpp deleted file mode 100644 index b8c3a33d5..000000000 --- a/3rdparty/spirv-tools/test/fix_word_test.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -TEST(FixWord, Default) { - spv_endianness_t endian; - if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) { - endian = SPV_ENDIANNESS_LITTLE; - } else { - endian = SPV_ENDIANNESS_BIG; - } - uint32_t word = 0x53780921; - ASSERT_EQ(word, spvFixWord(word, endian)); -} - -TEST(FixWord, Reorder) { - spv_endianness_t endian; - if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) { - endian = SPV_ENDIANNESS_BIG; - } else { - endian = SPV_ENDIANNESS_LITTLE; - } - uint32_t word = 0x53780921; - uint32_t result = 0x21097853; - ASSERT_EQ(result, spvFixWord(word, endian)); -} - -TEST(FixDoubleWord, Default) { - spv_endianness_t endian = - (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE ? SPV_ENDIANNESS_LITTLE - : SPV_ENDIANNESS_BIG); - uint32_t low = 0x53780921; - uint32_t high = 0xdeadbeef; - uint64_t result = 0xdeadbeef53780921; - ASSERT_EQ(result, spvFixDoubleWord(low, high, endian)); -} - -TEST(FixDoubleWord, Reorder) { - spv_endianness_t endian = - (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE ? SPV_ENDIANNESS_BIG - : SPV_ENDIANNESS_LITTLE); - uint32_t low = 0x53780921; - uint32_t high = 0xdeadbeef; - uint64_t result = 0xefbeadde21097853; - ASSERT_EQ(result, spvFixDoubleWord(low, high, endian)); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/CMakeLists.txt b/3rdparty/spirv-tools/test/fuzz/CMakeLists.txt deleted file mode 100644 index b38f35e9d..000000000 --- a/3rdparty/spirv-tools/test/fuzz/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2019 Google LLC -# -# 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. - -if (${SPIRV_BUILD_FUZZER}) - - set(SOURCES - fuzz_test_util.h - - data_synonym_transformation_test.cpp - equivalence_relation_test.cpp - fact_manager_test.cpp - fuzz_test_util.cpp - fuzzer_pass_add_useful_constructs_test.cpp - instruction_descriptor_test.cpp - transformation_add_constant_boolean_test.cpp - transformation_add_constant_scalar_test.cpp - transformation_add_dead_break_test.cpp - transformation_add_dead_continue_test.cpp - transformation_add_no_contraction_decoration_test.cpp - transformation_add_type_boolean_test.cpp - transformation_add_type_float_test.cpp - transformation_add_type_int_test.cpp - transformation_add_type_pointer_test.cpp - transformation_composite_construct_test.cpp - transformation_composite_extract_test.cpp - transformation_copy_object_test.cpp - transformation_move_block_down_test.cpp - transformation_replace_boolean_constant_with_constant_binary_test.cpp - transformation_replace_constant_with_uniform_test.cpp - transformation_replace_id_with_synonym_test.cpp - transformation_set_function_control_test.cpp - transformation_set_loop_control_test.cpp - transformation_set_memory_operands_mask_test.cpp - transformation_set_selection_control_test.cpp - transformation_split_block_test.cpp - transformation_vector_shuffle_test.cpp - uniform_buffer_element_descriptor_test.cpp) - - if (${SPIRV_ENABLE_LONG_FUZZER_TESTS}) - # These are long-running tests that depend on random seeds. We do not want - # to run them during regular whole-project CI because they may reveal - # spirv-fuzz bugs in changes that are totally unrelated to spirv-fuzz, - # which would be counfounding. Instead, they should be run regularly but - # separately. - set(SOURCES ${SOURCES} - fuzzer_replayer_test.cpp - fuzzer_shrinker_test.cpp) - endif() - - add_spvtools_unittest(TARGET fuzz - SRCS ${SOURCES} - LIBS SPIRV-Tools-fuzz - ) -endif() diff --git a/3rdparty/spirv-tools/test/fuzz/data_synonym_transformation_test.cpp b/3rdparty/spirv-tools/test/fuzz/data_synonym_transformation_test.cpp deleted file mode 100644 index 21ea068ff..000000000 --- a/3rdparty/spirv-tools/test/fuzz/data_synonym_transformation_test.cpp +++ /dev/null @@ -1,1122 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/data_descriptor.h" -#include "source/fuzz/id_use_descriptor.h" -#include "source/fuzz/instruction_descriptor.h" -#include "source/fuzz/transformation_composite_extract.h" -#include "source/fuzz/transformation_replace_id_with_synonym.h" -#include "source/fuzz/transformation_vector_shuffle.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -// This file captures tests that check correctness of the collective use of a -// number of transformations that relate to data synonyms. - -protobufs::Fact MakeSynonymFact(uint32_t first_id, - std::vector&& first_indices, - uint32_t second_id, - std::vector&& second_indices) { - protobufs::FactDataSynonym data_synonym_fact; - *data_synonym_fact.mutable_data1() = - MakeDataDescriptor(first_id, std::move(first_indices)); - *data_synonym_fact.mutable_data2() = - MakeDataDescriptor(second_id, std::move(second_indices)); - protobufs::Fact result; - *result.mutable_data_synonym_fact() = data_synonym_fact; - return result; -} - -TEST(DataSynonymTransformationTest, ArrayCompositeSynonyms) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %11 "A" - OpName %20 "B" - OpName %31 "g" - OpName %35 "h" - OpDecorate %11 RelaxedPrecision - OpDecorate %22 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - OpDecorate %35 RelaxedPrecision - OpDecorate %36 RelaxedPrecision - OpDecorate %40 RelaxedPrecision - OpDecorate %41 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 3 - %9 = OpTypeArray %6 %8 - %10 = OpTypePointer Function %9 - %12 = OpConstant %6 0 - %13 = OpConstant %6 3 - %14 = OpTypePointer Function %6 - %16 = OpTypeFloat 32 - %17 = OpConstant %7 4 - %18 = OpTypeArray %16 %17 - %19 = OpTypePointer Function %18 - %24 = OpTypePointer Function %16 - %28 = OpConstant %16 42 - %30 = OpConstant %6 2 - %34 = OpConstant %6 1 - %38 = OpConstant %6 42 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %20 = OpVariable %19 Function - %31 = OpVariable %24 Function - %35 = OpVariable %14 Function - %15 = OpAccessChain %14 %11 %12 - %21 = OpAccessChain %14 %11 %12 - %22 = OpLoad %6 %21 - %100 = OpCompositeConstruct %9 %12 %13 %22 - OpStore %15 %13 - %23 = OpConvertSToF %16 %22 - %25 = OpAccessChain %24 %20 %12 - OpStore %25 %23 - %26 = OpAccessChain %14 %11 %12 - %27 = OpLoad %6 %26 - %29 = OpAccessChain %24 %20 %27 - OpStore %29 %28 - %32 = OpLoad %16 %31 - %101 = OpCompositeConstruct %18 %28 %23 %32 %23 - %50 = OpCopyObject %16 %23 - %51 = OpCopyObject %16 %23 - %33 = OpAccessChain %24 %20 %30 - OpStore %33 %28 - OpStore %33 %32 - %36 = OpLoad %6 %35 - %37 = OpAccessChain %14 %11 %34 - OpStore %37 %36 - %39 = OpAccessChain %14 %11 %12 - %40 = OpLoad %6 %39 - %41 = OpIAdd %6 %38 %40 - %42 = OpAccessChain %14 %11 %30 - OpStore %42 %41 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - fact_manager.AddFact(MakeSynonymFact(12, {}, 100, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(13, {}, 100, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(22, {}, 100, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(28, {}, 101, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(23, {}, 101, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(32, {}, 101, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(23, {}, 101, {3}), context.get()); - - // Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12' - auto instruction_descriptor_1 = - MakeInstructionDescriptor(25, SpvOpAccessChain, 0); - auto good_extract_1 = - TransformationCompositeExtract(instruction_descriptor_1, 102, 100, {0}); - // Bad: id already in use - auto bad_extract_1 = TransformationCompositeExtract( - MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 25, 100, {0}); - ASSERT_TRUE(good_extract_1.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(bad_extract_1.IsApplicable(context.get(), fact_manager)); - good_extract_1.Apply(context.get(), &fact_manager); - auto replacement_1 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(12, instruction_descriptor_1, 1), 102); - ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager)); - replacement_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %13 with %100[1] in 'OpStore %15 %13' - auto instruction_descriptor_2 = MakeInstructionDescriptor(100, SpvOpStore, 0); - auto good_extract_2 = - TransformationCompositeExtract(instruction_descriptor_2, 103, 100, {1}); - // No bad example provided here. - ASSERT_TRUE(good_extract_2.IsApplicable(context.get(), fact_manager)); - good_extract_2.Apply(context.get(), &fact_manager); - auto replacement_2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(13, instruction_descriptor_2, 1), 103); - ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager)); - replacement_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22' - auto instruction_descriptor_3 = - MakeInstructionDescriptor(23, SpvOpConvertSToF, 0); - auto good_extract_3 = - TransformationCompositeExtract(instruction_descriptor_3, 104, 100, {2}); - ASSERT_TRUE(good_extract_3.IsApplicable(context.get(), fact_manager)); - good_extract_3.Apply(context.get(), &fact_manager); - auto replacement_3 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(22, instruction_descriptor_3, 0), 104); - // Bad: wrong input operand index - auto bad_replacement_3 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(22, instruction_descriptor_3, 1), 104); - ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(bad_replacement_3.IsApplicable(context.get(), fact_manager)); - replacement_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %28 with %101[0] in 'OpStore %33 %28' - auto instruction_descriptor_4 = MakeInstructionDescriptor(33, SpvOpStore, 0); - auto good_extract_4 = - TransformationCompositeExtract(instruction_descriptor_4, 105, 101, {0}); - // Bad: instruction descriptor does not identify an appropriate instruction - auto bad_extract_4 = TransformationCompositeExtract( - MakeInstructionDescriptor(33, SpvOpCopyObject, 0), 105, 101, {0}); - ASSERT_TRUE(good_extract_4.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(bad_extract_4.IsApplicable(context.get(), fact_manager)); - good_extract_4.Apply(context.get(), &fact_manager); - auto replacement_4 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(28, instruction_descriptor_4, 1), 105); - ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager)); - replacement_4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23' - auto instruction_descriptor_5 = - MakeInstructionDescriptor(50, SpvOpCopyObject, 0); - auto good_extract_5 = - TransformationCompositeExtract(instruction_descriptor_5, 106, 101, {1}); - ASSERT_TRUE(good_extract_5.IsApplicable(context.get(), fact_manager)); - good_extract_5.Apply(context.get(), &fact_manager); - auto replacement_5 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 106); - // Bad: wrong synonym fact being used - auto bad_replacement_5 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 105); - ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(bad_replacement_5.IsApplicable(context.get(), fact_manager)); - replacement_5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %32 with %101[2] in 'OpStore %33 %32' - auto instruction_descriptor_6 = MakeInstructionDescriptor(33, SpvOpStore, 1); - auto good_extract_6 = - TransformationCompositeExtract(instruction_descriptor_6, 107, 101, {2}); - // Bad: id 1001 does not exist - auto bad_extract_6 = - TransformationCompositeExtract(instruction_descriptor_6, 107, 1001, {2}); - ASSERT_TRUE(good_extract_6.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(bad_extract_6.IsApplicable(context.get(), fact_manager)); - good_extract_6.Apply(context.get(), &fact_manager); - auto replacement_6 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(32, instruction_descriptor_6, 1), 107); - ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager)); - replacement_6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23' - auto instruction_descriptor_7 = - MakeInstructionDescriptor(51, SpvOpCopyObject, 0); - auto good_extract_7 = - TransformationCompositeExtract(instruction_descriptor_7, 108, 101, {3}); - ASSERT_TRUE(good_extract_7.IsApplicable(context.get(), fact_manager)); - good_extract_7.Apply(context.get(), &fact_manager); - auto replacement_7 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(23, instruction_descriptor_7, 0), 108); - // Bad: use id 0 is invalid - auto bad_replacement_7 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(0, instruction_descriptor_7, 0), 108); - ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(bad_replacement_7.IsApplicable(context.get(), fact_manager)); - replacement_7.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %11 "A" - OpName %20 "B" - OpName %31 "g" - OpName %35 "h" - OpDecorate %11 RelaxedPrecision - OpDecorate %22 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - OpDecorate %35 RelaxedPrecision - OpDecorate %36 RelaxedPrecision - OpDecorate %40 RelaxedPrecision - OpDecorate %41 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 3 - %9 = OpTypeArray %6 %8 - %10 = OpTypePointer Function %9 - %12 = OpConstant %6 0 - %13 = OpConstant %6 3 - %14 = OpTypePointer Function %6 - %16 = OpTypeFloat 32 - %17 = OpConstant %7 4 - %18 = OpTypeArray %16 %17 - %19 = OpTypePointer Function %18 - %24 = OpTypePointer Function %16 - %28 = OpConstant %16 42 - %30 = OpConstant %6 2 - %34 = OpConstant %6 1 - %38 = OpConstant %6 42 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %20 = OpVariable %19 Function - %31 = OpVariable %24 Function - %35 = OpVariable %14 Function - %15 = OpAccessChain %14 %11 %12 - %21 = OpAccessChain %14 %11 %12 - %22 = OpLoad %6 %21 - %100 = OpCompositeConstruct %9 %12 %13 %22 - %103 = OpCompositeExtract %6 %100 1 - OpStore %15 %103 - %104 = OpCompositeExtract %6 %100 2 - %23 = OpConvertSToF %16 %104 - %102 = OpCompositeExtract %6 %100 0 - %25 = OpAccessChain %24 %20 %102 - OpStore %25 %23 - %26 = OpAccessChain %14 %11 %12 - %27 = OpLoad %6 %26 - %29 = OpAccessChain %24 %20 %27 - OpStore %29 %28 - %32 = OpLoad %16 %31 - %101 = OpCompositeConstruct %18 %28 %23 %32 %23 - %106 = OpCompositeExtract %16 %101 1 - %50 = OpCopyObject %16 %106 - %108 = OpCompositeExtract %16 %101 3 - %51 = OpCopyObject %16 %108 - %33 = OpAccessChain %24 %20 %30 - %105 = OpCompositeExtract %16 %101 0 - OpStore %33 %105 - %107 = OpCompositeExtract %16 %101 2 - OpStore %33 %107 - %36 = OpLoad %6 %35 - %37 = OpAccessChain %14 %11 %34 - OpStore %37 %36 - %39 = OpAccessChain %14 %11 %12 - %40 = OpLoad %6 %39 - %41 = OpIAdd %6 %38 %40 - %42 = OpAccessChain %14 %11 %30 - OpStore %42 %41 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(DataSynonymTransformationTest, MatrixCompositeSynonyms) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %10 "m" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %50 = OpUndef %7 - %8 = OpTypeMatrix %7 3 - %9 = OpTypePointer Function %8 - %11 = OpTypeInt 32 1 - %12 = OpConstant %11 0 - %13 = OpConstant %6 1 - %14 = OpConstantComposite %7 %13 %13 %13 %13 - %15 = OpTypePointer Function %7 - %17 = OpConstant %11 1 - %18 = OpConstant %6 2 - %19 = OpConstantComposite %7 %18 %18 %18 %18 - %21 = OpConstant %11 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %10 = OpVariable %9 Function - %16 = OpAccessChain %15 %10 %12 - OpStore %16 %14 - %20 = OpAccessChain %15 %10 %17 - OpStore %20 %19 - %22 = OpAccessChain %15 %10 %12 - %23 = OpLoad %7 %22 - %24 = OpAccessChain %15 %10 %17 - %25 = OpLoad %7 %24 - %100 = OpCompositeConstruct %8 %23 %25 %50 - %26 = OpFAdd %7 %23 %25 - %27 = OpAccessChain %15 %10 %21 - OpStore %27 %26 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - fact_manager.AddFact(MakeSynonymFact(23, {}, 100, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(25, {}, 100, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(50, {}, 100, {2}), context.get()); - - // Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25' - auto instruction_descriptor_1 = MakeInstructionDescriptor(26, SpvOpFAdd, 0); - auto extract_1 = - TransformationCompositeExtract(instruction_descriptor_1, 101, 100, {0}); - ASSERT_TRUE(extract_1.IsApplicable(context.get(), fact_manager)); - extract_1.Apply(context.get(), &fact_manager); - auto replacement_1 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(23, instruction_descriptor_1, 0), 101); - ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager)); - replacement_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25' - auto instruction_descriptor_2 = MakeInstructionDescriptor(26, SpvOpFAdd, 0); - auto extract_2 = - TransformationCompositeExtract(instruction_descriptor_2, 102, 100, {1}); - ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager)); - extract_2.Apply(context.get(), &fact_manager); - auto replacement_2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(25, instruction_descriptor_2, 1), 102); - ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager)); - replacement_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %10 "m" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %50 = OpUndef %7 - %8 = OpTypeMatrix %7 3 - %9 = OpTypePointer Function %8 - %11 = OpTypeInt 32 1 - %12 = OpConstant %11 0 - %13 = OpConstant %6 1 - %14 = OpConstantComposite %7 %13 %13 %13 %13 - %15 = OpTypePointer Function %7 - %17 = OpConstant %11 1 - %18 = OpConstant %6 2 - %19 = OpConstantComposite %7 %18 %18 %18 %18 - %21 = OpConstant %11 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %10 = OpVariable %9 Function - %16 = OpAccessChain %15 %10 %12 - OpStore %16 %14 - %20 = OpAccessChain %15 %10 %17 - OpStore %20 %19 - %22 = OpAccessChain %15 %10 %12 - %23 = OpLoad %7 %22 - %24 = OpAccessChain %15 %10 %17 - %25 = OpLoad %7 %24 - %100 = OpCompositeConstruct %8 %23 %25 %50 - %101 = OpCompositeExtract %7 %100 0 - %102 = OpCompositeExtract %7 %100 1 - %26 = OpFAdd %7 %101 %102 - %27 = OpAccessChain %15 %10 %21 - OpStore %27 %26 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(DataSynonymTransformationTest, StructCompositeSynonyms) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "Inner" - OpMemberName %9 0 "a" - OpMemberName %9 1 "b" - OpName %11 "i1" - OpName %17 "i2" - OpName %31 "Point" - OpMemberName %31 0 "x" - OpMemberName %31 1 "y" - OpMemberName %31 2 "z" - OpName %32 "Outer" - OpMemberName %32 0 "c" - OpMemberName %32 1 "d" - OpName %34 "o1" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFloat 32 - %8 = OpTypeVector %7 2 - %9 = OpTypeStruct %6 %8 - %10 = OpTypePointer Function %9 - %12 = OpConstant %6 1 - %13 = OpConstant %7 2 - %14 = OpConstant %7 3 - %15 = OpConstantComposite %8 %13 %14 - %16 = OpConstantComposite %9 %12 %15 - %18 = OpConstant %6 0 - %19 = OpTypePointer Function %6 - %24 = OpTypePointer Function %8 - %27 = OpConstant %7 4 - %31 = OpTypeStruct %7 %7 %7 - %32 = OpTypeStruct %9 %31 - %33 = OpTypePointer Function %32 - %36 = OpConstant %7 10 - %37 = OpTypeInt 32 0 - %38 = OpConstant %37 0 - %39 = OpTypePointer Function %7 - %42 = OpConstant %37 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %17 = OpVariable %10 Function - %34 = OpVariable %33 Function - %101 = OpCompositeConstruct %31 %27 %36 %27 - OpStore %11 %16 - %20 = OpAccessChain %19 %11 %18 - %21 = OpLoad %6 %20 - %22 = OpIAdd %6 %21 %12 - %102 = OpCompositeConstruct %9 %22 %15 - %23 = OpAccessChain %19 %17 %18 - OpStore %23 %22 - %25 = OpAccessChain %24 %17 %12 - %26 = OpLoad %8 %25 - %28 = OpCompositeConstruct %8 %27 %27 - %29 = OpFAdd %8 %26 %28 - %30 = OpAccessChain %24 %17 %12 - OpStore %30 %29 - %35 = OpLoad %9 %11 - %40 = OpAccessChain %39 %11 %12 %38 - %41 = OpLoad %7 %40 - %43 = OpAccessChain %39 %11 %12 %42 - %44 = OpLoad %7 %43 - %45 = OpCompositeConstruct %31 %36 %41 %44 - %100 = OpCompositeConstruct %32 %16 %45 - %46 = OpCompositeConstruct %32 %35 %45 - OpStore %34 %46 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - fact_manager.AddFact(MakeSynonymFact(16, {}, 100, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(45, {}, 100, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(27, {}, 101, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(36, {}, 101, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(27, {}, 101, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(22, {}, 102, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(15, {}, 102, {1}), context.get()); - - // Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45' - auto instruction_descriptor_1 = - MakeInstructionDescriptor(46, SpvOpCompositeConstruct, 0); - auto extract_1 = - TransformationCompositeExtract(instruction_descriptor_1, 201, 100, {1}); - ASSERT_TRUE(extract_1.IsApplicable(context.get(), fact_manager)); - extract_1.Apply(context.get(), &fact_manager); - auto replacement_1 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(45, instruction_descriptor_1, 1), 201); - ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager)); - replacement_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace second occurrence of %27 with %101[0] in '%28 = - // OpCompositeConstruct %8 %27 %27' - auto instruction_descriptor_2 = - MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0); - auto extract_2 = - TransformationCompositeExtract(instruction_descriptor_2, 202, 101, {0}); - ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager)); - extract_2.Apply(context.get(), &fact_manager); - auto replacement_2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(27, instruction_descriptor_2, 1), 202); - ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager)); - replacement_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44' - auto instruction_descriptor_3 = - MakeInstructionDescriptor(45, SpvOpCompositeConstruct, 0); - auto extract_3 = - TransformationCompositeExtract(instruction_descriptor_3, 203, 101, {1}); - ASSERT_TRUE(extract_3.IsApplicable(context.get(), fact_manager)); - extract_3.Apply(context.get(), &fact_manager); - auto replacement_3 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(36, instruction_descriptor_3, 0), 203); - ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager)); - replacement_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct - // %8 %27 %27' - auto instruction_descriptor_4 = - MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0); - auto extract_4 = - TransformationCompositeExtract(instruction_descriptor_4, 204, 101, {2}); - ASSERT_TRUE(extract_4.IsApplicable(context.get(), fact_manager)); - extract_4.Apply(context.get(), &fact_manager); - auto replacement_4 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(27, instruction_descriptor_4, 0), 204); - ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager)); - replacement_4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %22 with %102[0] in 'OpStore %23 %22' - auto instruction_descriptor_5 = MakeInstructionDescriptor(23, SpvOpStore, 0); - auto extract_5 = - TransformationCompositeExtract(instruction_descriptor_5, 205, 102, {0}); - ASSERT_TRUE(extract_5.IsApplicable(context.get(), fact_manager)); - extract_5.Apply(context.get(), &fact_manager); - auto replacement_5 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(22, instruction_descriptor_5, 1), 205); - ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager)); - replacement_5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "Inner" - OpMemberName %9 0 "a" - OpMemberName %9 1 "b" - OpName %11 "i1" - OpName %17 "i2" - OpName %31 "Point" - OpMemberName %31 0 "x" - OpMemberName %31 1 "y" - OpMemberName %31 2 "z" - OpName %32 "Outer" - OpMemberName %32 0 "c" - OpMemberName %32 1 "d" - OpName %34 "o1" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFloat 32 - %8 = OpTypeVector %7 2 - %9 = OpTypeStruct %6 %8 - %10 = OpTypePointer Function %9 - %12 = OpConstant %6 1 - %13 = OpConstant %7 2 - %14 = OpConstant %7 3 - %15 = OpConstantComposite %8 %13 %14 - %16 = OpConstantComposite %9 %12 %15 - %18 = OpConstant %6 0 - %19 = OpTypePointer Function %6 - %24 = OpTypePointer Function %8 - %27 = OpConstant %7 4 - %31 = OpTypeStruct %7 %7 %7 - %32 = OpTypeStruct %9 %31 - %33 = OpTypePointer Function %32 - %36 = OpConstant %7 10 - %37 = OpTypeInt 32 0 - %38 = OpConstant %37 0 - %39 = OpTypePointer Function %7 - %42 = OpConstant %37 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %17 = OpVariable %10 Function - %34 = OpVariable %33 Function - %101 = OpCompositeConstruct %31 %27 %36 %27 - OpStore %11 %16 - %20 = OpAccessChain %19 %11 %18 - %21 = OpLoad %6 %20 - %22 = OpIAdd %6 %21 %12 - %102 = OpCompositeConstruct %9 %22 %15 - %23 = OpAccessChain %19 %17 %18 - %205 = OpCompositeExtract %6 %102 0 - OpStore %23 %205 - %25 = OpAccessChain %24 %17 %12 - %26 = OpLoad %8 %25 - %202 = OpCompositeExtract %7 %101 0 - %204 = OpCompositeExtract %7 %101 2 - %28 = OpCompositeConstruct %8 %204 %202 - %29 = OpFAdd %8 %26 %28 - %30 = OpAccessChain %24 %17 %12 - OpStore %30 %29 - %35 = OpLoad %9 %11 - %40 = OpAccessChain %39 %11 %12 %38 - %41 = OpLoad %7 %40 - %43 = OpAccessChain %39 %11 %12 %42 - %44 = OpLoad %7 %43 - %203 = OpCompositeExtract %7 %101 1 - %45 = OpCompositeConstruct %31 %203 %41 %44 - %100 = OpCompositeConstruct %32 %16 %45 - %201 = OpCompositeExtract %31 %100 1 - %46 = OpCompositeConstruct %32 %35 %201 - OpStore %34 %46 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(DataSynonymTransformationTest, VectorCompositeSynonyms) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "f" - OpName %12 "v2" - OpName %18 "v3" - OpName %23 "v4" - OpName %32 "b" - OpName %36 "bv2" - OpName %41 "bv3" - OpName %50 "bv4" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 42 - %10 = OpTypeVector %6 2 - %11 = OpTypePointer Function %10 - %16 = OpTypeVector %6 3 - %17 = OpTypePointer Function %16 - %21 = OpTypeVector %6 4 - %22 = OpTypePointer Function %21 - %30 = OpTypeBool - %31 = OpTypePointer Function %30 - %33 = OpConstantFalse %30 - %34 = OpTypeVector %30 2 - %35 = OpTypePointer Function %34 - %37 = OpConstantTrue %30 - %38 = OpConstantComposite %34 %37 %37 - %39 = OpTypeVector %30 3 - %40 = OpTypePointer Function %39 - %48 = OpTypeVector %30 4 - %49 = OpTypePointer Function %48 - %51 = OpTypeInt 32 0 - %52 = OpConstant %51 2 - %55 = OpConstant %6 0 - %57 = OpConstant %51 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %18 = OpVariable %17 Function - %23 = OpVariable %22 Function - %32 = OpVariable %31 Function - %36 = OpVariable %35 Function - %41 = OpVariable %40 Function - %50 = OpVariable %49 Function - OpStore %8 %9 - %13 = OpLoad %6 %8 - %14 = OpLoad %6 %8 - %15 = OpCompositeConstruct %10 %13 %14 - OpStore %12 %15 - %19 = OpLoad %10 %12 - %20 = OpVectorShuffle %16 %19 %19 0 0 1 - OpStore %18 %20 - %24 = OpLoad %16 %18 - %25 = OpLoad %6 %8 - %26 = OpCompositeExtract %6 %24 0 - %27 = OpCompositeExtract %6 %24 1 - %28 = OpCompositeExtract %6 %24 2 - %29 = OpCompositeConstruct %21 %26 %27 %28 %25 - OpStore %23 %29 - OpStore %32 %33 - OpStore %36 %38 - %42 = OpLoad %30 %32 - %43 = OpLoad %34 %36 - %44 = OpVectorShuffle %34 %43 %43 0 0 - %45 = OpCompositeExtract %30 %44 0 - %46 = OpCompositeExtract %30 %44 1 - %47 = OpCompositeConstruct %39 %42 %45 %46 - OpStore %41 %47 - %53 = OpAccessChain %7 %23 %52 - %54 = OpLoad %6 %53 - - %100 = OpCompositeConstruct %21 %20 %54 - %101 = OpCompositeConstruct %21 %15 %19 - %102 = OpCompositeConstruct %16 %27 %15 - %103 = OpCompositeConstruct %48 %33 %47 - %104 = OpCompositeConstruct %34 %42 %45 - %105 = OpCompositeConstruct %39 %38 %46 - - %86 = OpCopyObject %30 %33 - %56 = OpFOrdNotEqual %30 %54 %55 - %80 = OpCopyObject %16 %20 - %58 = OpAccessChain %7 %18 %57 - %59 = OpLoad %6 %58 - %60 = OpFOrdNotEqual %30 %59 %55 - %61 = OpLoad %34 %36 - %62 = OpLogicalAnd %30 %45 %46 - %63 = OpLogicalOr %30 %45 %46 - %64 = OpCompositeConstruct %48 %56 %60 %62 %63 - OpStore %12 %15 - %81 = OpVectorShuffle %16 %19 %19 0 0 1 - %82 = OpCompositeConstruct %21 %26 %27 %28 %25 - %83 = OpCopyObject %10 %15 - %84 = OpCopyObject %39 %47 - OpStore %50 %64 - %85 = OpCopyObject %30 %42 - OpStore %36 %38 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - fact_manager.AddFact(MakeSynonymFact(20, {0}, 100, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(20, {1}, 100, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(20, {2}, 100, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(54, {}, 100, {3}), context.get()); - fact_manager.AddFact(MakeSynonymFact(15, {0}, 101, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(15, {1}, 101, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(19, {0}, 101, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(19, {1}, 101, {3}), context.get()); - fact_manager.AddFact(MakeSynonymFact(27, {}, 102, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(15, {0}, 102, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(15, {1}, 102, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(33, {}, 103, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(47, {0}, 103, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(47, {1}, 103, {2}), context.get()); - fact_manager.AddFact(MakeSynonymFact(47, {2}, 103, {3}), context.get()); - fact_manager.AddFact(MakeSynonymFact(42, {}, 104, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(45, {}, 104, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(38, {0}, 105, {0}), context.get()); - fact_manager.AddFact(MakeSynonymFact(38, {1}, 105, {1}), context.get()); - fact_manager.AddFact(MakeSynonymFact(46, {}, 105, {2}), context.get()); - - // Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20' - auto instruction_descriptor_1 = - MakeInstructionDescriptor(80, SpvOpCopyObject, 0); - auto shuffle_1 = TransformationVectorShuffle(instruction_descriptor_1, 200, - 100, 100, {0, 1, 2}); - ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), fact_manager)); - shuffle_1.Apply(context.get(), &fact_manager); - auto replacement_1 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(20, instruction_descriptor_1, 0), 200); - ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager)); - replacement_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55' - auto instruction_descriptor_2 = - MakeInstructionDescriptor(56, SpvOpFOrdNotEqual, 0); - auto extract_2 = - TransformationCompositeExtract(instruction_descriptor_2, 201, 100, {3}); - - ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager)); - extract_2.Apply(context.get(), &fact_manager); - auto replacement_2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(54, instruction_descriptor_2, 0), 201); - ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager)); - replacement_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %15 with %101[0:1] in 'OpStore %12 %15' - auto instruction_descriptor_3 = MakeInstructionDescriptor(64, SpvOpStore, 0); - auto shuffle_3 = TransformationVectorShuffle(instruction_descriptor_3, 202, - 101, 101, {0, 1}); - ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), fact_manager)); - shuffle_3.Apply(context.get(), &fact_manager); - auto replacement_3 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(15, instruction_descriptor_3, 1), 202); - ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager)); - replacement_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %19 with %101[2:3] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1' - auto instruction_descriptor_4 = - MakeInstructionDescriptor(81, SpvOpVectorShuffle, 0); - auto shuffle_4 = TransformationVectorShuffle(instruction_descriptor_4, 203, - 101, 101, {2, 3}); - ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), fact_manager)); - shuffle_4.Apply(context.get(), &fact_manager); - auto replacement_4 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(19, instruction_descriptor_4, 0), 203); - ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager)); - replacement_4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28 - // %25' - auto instruction_descriptor_5 = - MakeInstructionDescriptor(82, SpvOpCompositeConstruct, 0); - auto extract_5 = - TransformationCompositeExtract(instruction_descriptor_5, 204, 102, {0}); - - ASSERT_TRUE(extract_5.IsApplicable(context.get(), fact_manager)); - extract_5.Apply(context.get(), &fact_manager); - auto replacement_5 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(27, instruction_descriptor_5, 1), 204); - ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager)); - replacement_5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %15 with %102[1:2] in '%83 = OpCopyObject %10 %15' - auto instruction_descriptor_6 = - MakeInstructionDescriptor(83, SpvOpCopyObject, 0); - auto shuffle_6 = TransformationVectorShuffle(instruction_descriptor_6, 205, - 102, 102, {1, 2}); - ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), fact_manager)); - shuffle_6.Apply(context.get(), &fact_manager); - auto replacement_6 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(15, instruction_descriptor_6, 0), 205); - ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager)); - replacement_6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33' - auto instruction_descriptor_7 = - MakeInstructionDescriptor(86, SpvOpCopyObject, 0); - auto extract_7 = - TransformationCompositeExtract(instruction_descriptor_7, 206, 103, {0}); - ASSERT_TRUE(extract_7.IsApplicable(context.get(), fact_manager)); - extract_7.Apply(context.get(), &fact_manager); - auto replacement_7 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(33, instruction_descriptor_7, 0), 206); - ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager)); - replacement_7.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %47 with %103[1:3] in '%84 = OpCopyObject %39 %47' - auto instruction_descriptor_8 = - MakeInstructionDescriptor(84, SpvOpCopyObject, 0); - auto shuffle_8 = TransformationVectorShuffle(instruction_descriptor_8, 207, - 103, 103, {1, 2, 3}); - ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), fact_manager)); - shuffle_8.Apply(context.get(), &fact_manager); - auto replacement_8 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(47, instruction_descriptor_8, 0), 207); - ASSERT_TRUE(replacement_8.IsApplicable(context.get(), fact_manager)); - replacement_8.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42' - auto instruction_descriptor_9 = - MakeInstructionDescriptor(85, SpvOpCopyObject, 0); - auto extract_9 = - TransformationCompositeExtract(instruction_descriptor_9, 208, 104, {0}); - ASSERT_TRUE(extract_9.IsApplicable(context.get(), fact_manager)); - extract_9.Apply(context.get(), &fact_manager); - auto replacement_9 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(42, instruction_descriptor_9, 0), 208); - ASSERT_TRUE(replacement_9.IsApplicable(context.get(), fact_manager)); - replacement_9.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46' - auto instruction_descriptor_10 = - MakeInstructionDescriptor(63, SpvOpLogicalOr, 0); - auto extract_10 = - TransformationCompositeExtract(instruction_descriptor_10, 209, 104, {1}); - ASSERT_TRUE(extract_10.IsApplicable(context.get(), fact_manager)); - extract_10.Apply(context.get(), &fact_manager); - auto replacement_10 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(45, instruction_descriptor_10, 0), 209); - ASSERT_TRUE(replacement_10.IsApplicable(context.get(), fact_manager)); - replacement_10.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %38 with %105[0:1] in 'OpStore %36 %38' - auto instruction_descriptor_11 = MakeInstructionDescriptor(85, SpvOpStore, 0); - auto shuffle_11 = TransformationVectorShuffle(instruction_descriptor_11, 210, - 105, 105, {0, 1}); - ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), fact_manager)); - shuffle_11.Apply(context.get(), &fact_manager); - auto replacement_11 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(38, instruction_descriptor_11, 1), 210); - ASSERT_TRUE(replacement_11.IsApplicable(context.get(), fact_manager)); - replacement_11.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46' - auto instruction_descriptor_12 = - MakeInstructionDescriptor(62, SpvOpLogicalAnd, 0); - auto extract_12 = - TransformationCompositeExtract(instruction_descriptor_12, 211, 105, {2}); - ASSERT_TRUE(extract_12.IsApplicable(context.get(), fact_manager)); - extract_12.Apply(context.get(), &fact_manager); - auto replacement_12 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(46, instruction_descriptor_12, 1), 211); - ASSERT_TRUE(replacement_12.IsApplicable(context.get(), fact_manager)); - replacement_12.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "f" - OpName %12 "v2" - OpName %18 "v3" - OpName %23 "v4" - OpName %32 "b" - OpName %36 "bv2" - OpName %41 "bv3" - OpName %50 "bv4" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 42 - %10 = OpTypeVector %6 2 - %11 = OpTypePointer Function %10 - %16 = OpTypeVector %6 3 - %17 = OpTypePointer Function %16 - %21 = OpTypeVector %6 4 - %22 = OpTypePointer Function %21 - %30 = OpTypeBool - %31 = OpTypePointer Function %30 - %33 = OpConstantFalse %30 - %34 = OpTypeVector %30 2 - %35 = OpTypePointer Function %34 - %37 = OpConstantTrue %30 - %38 = OpConstantComposite %34 %37 %37 - %39 = OpTypeVector %30 3 - %40 = OpTypePointer Function %39 - %48 = OpTypeVector %30 4 - %49 = OpTypePointer Function %48 - %51 = OpTypeInt 32 0 - %52 = OpConstant %51 2 - %55 = OpConstant %6 0 - %57 = OpConstant %51 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %18 = OpVariable %17 Function - %23 = OpVariable %22 Function - %32 = OpVariable %31 Function - %36 = OpVariable %35 Function - %41 = OpVariable %40 Function - %50 = OpVariable %49 Function - OpStore %8 %9 - %13 = OpLoad %6 %8 - %14 = OpLoad %6 %8 - %15 = OpCompositeConstruct %10 %13 %14 - OpStore %12 %15 - %19 = OpLoad %10 %12 - %20 = OpVectorShuffle %16 %19 %19 0 0 1 - OpStore %18 %20 - %24 = OpLoad %16 %18 - %25 = OpLoad %6 %8 - %26 = OpCompositeExtract %6 %24 0 - %27 = OpCompositeExtract %6 %24 1 - %28 = OpCompositeExtract %6 %24 2 - %29 = OpCompositeConstruct %21 %26 %27 %28 %25 - OpStore %23 %29 - OpStore %32 %33 - OpStore %36 %38 - %42 = OpLoad %30 %32 - %43 = OpLoad %34 %36 - %44 = OpVectorShuffle %34 %43 %43 0 0 - %45 = OpCompositeExtract %30 %44 0 - %46 = OpCompositeExtract %30 %44 1 - %47 = OpCompositeConstruct %39 %42 %45 %46 - OpStore %41 %47 - %53 = OpAccessChain %7 %23 %52 - %54 = OpLoad %6 %53 - - %100 = OpCompositeConstruct %21 %20 %54 - %101 = OpCompositeConstruct %21 %15 %19 - %102 = OpCompositeConstruct %16 %27 %15 - %103 = OpCompositeConstruct %48 %33 %47 - %104 = OpCompositeConstruct %34 %42 %45 - %105 = OpCompositeConstruct %39 %38 %46 - - %206 = OpCompositeExtract %30 %103 0 - %86 = OpCopyObject %30 %206 - %201 = OpCompositeExtract %6 %100 3 - %56 = OpFOrdNotEqual %30 %201 %55 - %200 = OpVectorShuffle %16 %100 %100 0 1 2 - %80 = OpCopyObject %16 %200 - %58 = OpAccessChain %7 %18 %57 - %59 = OpLoad %6 %58 - %60 = OpFOrdNotEqual %30 %59 %55 - %61 = OpLoad %34 %36 - %211 = OpCompositeExtract %30 %105 2 - %62 = OpLogicalAnd %30 %45 %211 - %209 = OpCompositeExtract %30 %104 1 - %63 = OpLogicalOr %30 %209 %46 - %64 = OpCompositeConstruct %48 %56 %60 %62 %63 - %202 = OpVectorShuffle %10 %101 %101 0 1 - OpStore %12 %202 - %203 = OpVectorShuffle %10 %101 %101 2 3 - %81 = OpVectorShuffle %16 %203 %19 0 0 1 - %204 = OpCompositeExtract %6 %102 0 - %82 = OpCompositeConstruct %21 %26 %204 %28 %25 - %205 = OpVectorShuffle %10 %102 %102 1 2 - %83 = OpCopyObject %10 %205 - %207 = OpVectorShuffle %39 %103 %103 1 2 3 - %84 = OpCopyObject %39 %207 - OpStore %50 %64 - %208 = OpCompositeExtract %30 %104 0 - %85 = OpCopyObject %30 %208 - %210 = OpVectorShuffle %34 %105 %105 0 1 - OpStore %36 %210 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/equivalence_relation_test.cpp b/3rdparty/spirv-tools/test/fuzz/equivalence_relation_test.cpp deleted file mode 100644 index 3f2ea58fe..000000000 --- a/3rdparty/spirv-tools/test/fuzz/equivalence_relation_test.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/fuzz/equivalence_relation.h" - -namespace spvtools { -namespace fuzz { -namespace { - -struct UInt32Equals { - bool operator()(const uint32_t* first, const uint32_t* second) const { - return *first == *second; - } -}; - -struct UInt32Hash { - size_t operator()(const uint32_t* element) const { - return static_cast(*element); - } -}; - -std::vector ToUIntVector( - const std::vector& pointers) { - std::vector result; - for (auto pointer : pointers) { - result.push_back(*pointer); - } - return result; -} - -TEST(EquivalenceRelationTest, BasicTest) { - EquivalenceRelation relation; - ASSERT_TRUE(relation.GetAllKnownValues().empty()); - - for (uint32_t element = 2; element < 80; element += 2) { - relation.MakeEquivalent(0, element); - relation.MakeEquivalent(element - 1, element + 1); - } - - for (uint32_t element = 82; element < 100; element += 2) { - relation.MakeEquivalent(80, element); - relation.MakeEquivalent(element - 1, element + 1); - } - - relation.MakeEquivalent(78, 80); - - std::vector class1; - for (uint32_t element = 0; element < 98; element += 2) { - ASSERT_TRUE(relation.IsEquivalent(0, element)); - ASSERT_TRUE(relation.IsEquivalent(element, element + 2)); - class1.push_back(element); - } - class1.push_back(98); - - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(0)), - testing::WhenSorted(class1)); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(4)), - testing::WhenSorted(class1)); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(40)), - testing::WhenSorted(class1)); - - std::vector class2; - for (uint32_t element = 1; element < 79; element += 2) { - ASSERT_TRUE(relation.IsEquivalent(1, element)); - ASSERT_TRUE(relation.IsEquivalent(element, element + 2)); - class2.push_back(element); - } - class2.push_back(79); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(1)), - testing::WhenSorted(class2)); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(11)), - testing::WhenSorted(class2)); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(31)), - testing::WhenSorted(class2)); - - std::vector class3; - for (uint32_t element = 81; element < 99; element += 2) { - ASSERT_TRUE(relation.IsEquivalent(81, element)); - ASSERT_TRUE(relation.IsEquivalent(element, element + 2)); - class3.push_back(element); - } - class3.push_back(99); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(81)), - testing::WhenSorted(class3)); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(91)), - testing::WhenSorted(class3)); - ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(99)), - testing::WhenSorted(class3)); - - bool first = true; - std::vector previous_class; - for (auto representative : relation.GetEquivalenceClassRepresentatives()) { - std::vector current_class = - relation.GetEquivalenceClass(*representative); - ASSERT_TRUE(std::find(current_class.begin(), current_class.end(), - representative) != current_class.end()); - if (!first) { - ASSERT_TRUE(std::find(previous_class.begin(), previous_class.end(), - representative) == previous_class.end()); - } - previous_class = current_class; - first = false; - } -} - -TEST(EquivalenceRelationTest, DeterministicEquivalenceClassOrder) { - EquivalenceRelation relation1; - EquivalenceRelation relation2; - - for (uint32_t i = 0; i < 1000; ++i) { - if (i >= 10) { - relation1.MakeEquivalent(i, i - 10); - relation2.MakeEquivalent(i, i - 10); - } - } - - // We constructed the equivalence relations in the same way, so we would like - // them to have identical representatives, and identically-ordered equivalence - // classes per representative. - ASSERT_THAT(ToUIntVector(relation1.GetEquivalenceClassRepresentatives()), - ToUIntVector(relation2.GetEquivalenceClassRepresentatives())); - for (auto representative : relation1.GetEquivalenceClassRepresentatives()) { - ASSERT_THAT(ToUIntVector(relation1.GetEquivalenceClass(*representative)), - ToUIntVector(relation2.GetEquivalenceClass(*representative))); - } -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/fact_manager_test.cpp b/3rdparty/spirv-tools/test/fuzz/fact_manager_test.cpp deleted file mode 100644 index b3f32cd51..000000000 --- a/3rdparty/spirv-tools/test/fuzz/fact_manager_test.cpp +++ /dev/null @@ -1,1178 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/fact_manager.h" -#include "source/fuzz/uniform_buffer_element_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -using opt::analysis::BoolConstant; -using opt::analysis::FloatConstant; -using opt::analysis::IntConstant; -using opt::analysis::ScalarConstant; - -using opt::analysis::Bool; -using opt::analysis::Float; -using opt::analysis::Integer; -using opt::analysis::Type; - -bool AddFactHelper( - FactManager* fact_manager, opt::IRContext* context, - std::vector&& words, - const protobufs::UniformBufferElementDescriptor& descriptor) { - protobufs::FactConstantUniform constant_uniform_fact; - for (auto word : words) { - constant_uniform_fact.add_constant_word(word); - } - *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() = - descriptor; - protobufs::Fact fact; - *fact.mutable_constant_uniform_fact() = constant_uniform_fact; - return fact_manager->AddFact(fact, context); -} - -TEST(FactManagerTest, ConstantsAvailableViaUniforms) { - std::string shader = R"( - OpCapability Shader - OpCapability Int64 - OpCapability Float64 - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpDecorate %100 DescriptorSet 0 - OpDecorate %100 Binding 0 - OpDecorate %200 DescriptorSet 0 - OpDecorate %200 Binding 1 - OpDecorate %300 DescriptorSet 0 - OpDecorate %300 Binding 2 - OpDecorate %400 DescriptorSet 0 - OpDecorate %400 Binding 3 - OpDecorate %500 DescriptorSet 0 - OpDecorate %500 Binding 4 - OpDecorate %600 DescriptorSet 0 - OpDecorate %600 Binding 5 - OpDecorate %700 DescriptorSet 0 - OpDecorate %700 Binding 6 - OpDecorate %800 DescriptorSet 1 - OpDecorate %800 Binding 0 - OpDecorate %900 DescriptorSet 1 - OpDecorate %900 Binding 1 - OpDecorate %1000 DescriptorSet 1 - OpDecorate %1000 Binding 2 - OpDecorate %1100 DescriptorSet 1 - OpDecorate %1100 Binding 3 - OpDecorate %1200 DescriptorSet 1 - OpDecorate %1200 Binding 4 - OpDecorate %1300 DescriptorSet 1 - OpDecorate %1300 Binding 5 - OpDecorate %1400 DescriptorSet 1 - OpDecorate %1400 Binding 6 - OpDecorate %1500 DescriptorSet 2 - OpDecorate %1500 Binding 0 - OpDecorate %1600 DescriptorSet 2 - OpDecorate %1600 Binding 1 - OpDecorate %1700 DescriptorSet 2 - OpDecorate %1700 Binding 2 - OpDecorate %1800 DescriptorSet 2 - OpDecorate %1800 Binding 3 - OpDecorate %1900 DescriptorSet 2 - OpDecorate %1900 Binding 4 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 0 - %11 = OpTypeInt 32 1 - %12 = OpTypeInt 64 0 - %13 = OpTypeInt 64 1 - %15 = OpTypeFloat 32 - %16 = OpTypeFloat 64 - %17 = OpConstant %11 5 - %18 = OpConstant %11 20 - %19 = OpTypeVector %10 4 - %20 = OpConstant %11 6 - %21 = OpTypeVector %12 4 - %22 = OpConstant %11 10 - %23 = OpTypeVector %11 4 - - %102 = OpTypeStruct %10 %10 %23 - %101 = OpTypePointer Uniform %102 - %100 = OpVariable %101 Uniform - - %203 = OpTypeArray %23 %17 - %202 = OpTypeArray %203 %18 - %201 = OpTypePointer Uniform %202 - %200 = OpVariable %201 Uniform - - %305 = OpTypeStruct %16 %16 %16 %11 %16 - %304 = OpTypeStruct %16 %16 %305 - %303 = OpTypeStruct %304 - %302 = OpTypeStruct %10 %303 - %301 = OpTypePointer Uniform %302 - %300 = OpVariable %301 Uniform - - %400 = OpVariable %101 Uniform - - %500 = OpVariable %201 Uniform - - %604 = OpTypeArray %13 %20 - %603 = OpTypeArray %604 %20 - %602 = OpTypeArray %603 %20 - %601 = OpTypePointer Uniform %602 - %600 = OpVariable %601 Uniform - - %703 = OpTypeArray %13 %20 - %702 = OpTypeArray %703 %20 - %701 = OpTypePointer Uniform %702 - %700 = OpVariable %701 Uniform - - %802 = OpTypeStruct %702 %602 %19 %202 %302 - %801 = OpTypePointer Uniform %802 - %800 = OpVariable %801 Uniform - - %902 = OpTypeStruct %702 %802 %19 %202 %302 - %901 = OpTypePointer Uniform %902 - %900 = OpVariable %901 Uniform - - %1003 = OpTypeStruct %802 - %1002 = OpTypeArray %1003 %20 - %1001 = OpTypePointer Uniform %1002 - %1000 = OpVariable %1001 Uniform - - %1101 = OpTypePointer Uniform %21 - %1100 = OpVariable %1101 Uniform - - %1202 = OpTypeArray %21 %20 - %1201 = OpTypePointer Uniform %1202 - %1200 = OpVariable %1201 Uniform - - %1302 = OpTypeArray %21 %20 - %1301 = OpTypePointer Uniform %1302 - %1300 = OpVariable %1301 Uniform - - %1402 = OpTypeArray %15 %22 - %1401 = OpTypePointer Uniform %1402 - %1400 = OpVariable %1401 Uniform - - %1501 = OpTypePointer Uniform %1402 - %1500 = OpVariable %1501 Uniform - - %1602 = OpTypeArray %1402 %22 - %1601 = OpTypePointer Uniform %1602 - %1600 = OpVariable %1601 Uniform - - %1704 = OpTypeStruct %16 %16 %16 - %1703 = OpTypeArray %1704 %22 - %1702 = OpTypeArray %1703 %22 - %1701 = OpTypePointer Uniform %1702 - %1700 = OpVariable %1701 Uniform - - %1800 = OpVariable %1701 Uniform - - %1906 = OpTypeStruct %16 - %1905 = OpTypeStruct %1906 - %1904 = OpTypeStruct %1905 - %1903 = OpTypeStruct %1904 - %1902 = OpTypeStruct %1903 - %1901 = OpTypePointer Uniform %1902 - %1900 = OpVariable %1901 Uniform - - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - uint32_t buffer_int32_min[1]; - uint32_t buffer_int64_1[2]; - uint32_t buffer_int64_max[2]; - uint32_t buffer_uint64_1[2]; - uint32_t buffer_uint64_max[2]; - uint32_t buffer_float_10[1]; - uint32_t buffer_double_10[2]; - uint32_t buffer_double_20[2]; - - { - int32_t temp = std::numeric_limits::min(); - std::memcpy(&buffer_int32_min, &temp, sizeof(temp)); - } - - { - int64_t temp = 1; - std::memcpy(&buffer_int64_1, &temp, sizeof(temp)); - } - - { - int64_t temp = std::numeric_limits::max(); - std::memcpy(&buffer_int64_max, &temp, sizeof(temp)); - } - - { - uint64_t temp = 1; - std::memcpy(&buffer_uint64_1, &temp, sizeof(temp)); - } - - { - uint64_t temp = std::numeric_limits::max(); - std::memcpy(&buffer_uint64_max, &temp, sizeof(temp)); - } - - { - float temp = 10.0f; - std::memcpy(&buffer_float_10, &temp, sizeof(float)); - } - - { - double temp = 10.0; - std::memcpy(&buffer_double_10, &temp, sizeof(temp)); - } - - { - double temp = 20.0; - std::memcpy(&buffer_double_20, &temp, sizeof(temp)); - } - - FactManager fact_manager; - - uint32_t type_int32_id = 11; - uint32_t type_int64_id = 13; - uint32_t type_uint32_id = 10; - uint32_t type_uint64_id = 12; - uint32_t type_float_id = 15; - uint32_t type_double_id = 16; - - // Initially there should be no facts about uniforms. - ASSERT_TRUE(fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_uint32_id) - .empty()); - - // In the comments that follow we write v[...][...] to refer to uniform - // variable v indexed with some given indices, when in practice v is - // identified via a (descriptor set, binding) pair. - - // 100[2][3] == int(1) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1}, - MakeUniformBufferElementDescriptor(0, 0, {2, 3}))); - - // 200[1][2][3] == int(1) - ASSERT_TRUE( - AddFactHelper(&fact_manager, context.get(), {1}, - MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3}))); - - // 300[1][0][2][3] == int(1) - ASSERT_TRUE( - AddFactHelper(&fact_manager, context.get(), {1}, - MakeUniformBufferElementDescriptor(0, 2, {1, 0, 2, 3}))); - - // 400[2][3] = int32_min - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_int32_min[0]}, - MakeUniformBufferElementDescriptor(0, 3, {2, 3}))); - - // 500[1][2][3] = int32_min - ASSERT_TRUE( - AddFactHelper(&fact_manager, context.get(), {buffer_int32_min[0]}, - MakeUniformBufferElementDescriptor(0, 4, {1, 2, 3}))); - - // 600[1][2][3] = int64_max - ASSERT_TRUE(AddFactHelper( - &fact_manager, context.get(), {buffer_int64_max[0], buffer_int64_max[1]}, - MakeUniformBufferElementDescriptor(0, 5, {1, 2, 3}))); - - // 700[1][1] = int64_max - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), - {buffer_int64_max[0], buffer_int64_max[1]}, - MakeUniformBufferElementDescriptor(0, 6, {1, 1}))); - - // 800[2][3] = uint(1) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1}, - MakeUniformBufferElementDescriptor(1, 0, {2, 3}))); - - // 900[1][2][3] = uint(1) - ASSERT_TRUE( - AddFactHelper(&fact_manager, context.get(), {1}, - MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3}))); - - // 1000[1][0][2][3] = uint(1) - ASSERT_TRUE( - AddFactHelper(&fact_manager, context.get(), {1}, - MakeUniformBufferElementDescriptor(1, 2, {1, 0, 2, 3}))); - - // 1100[0] = uint64(1) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), - {buffer_uint64_1[0], buffer_uint64_1[1]}, - MakeUniformBufferElementDescriptor(1, 3, {0}))); - - // 1200[0][0] = uint64_max - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), - {buffer_uint64_max[0], buffer_uint64_max[1]}, - MakeUniformBufferElementDescriptor(1, 4, {0, 0}))); - - // 1300[1][0] = uint64_max - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), - {buffer_uint64_max[0], buffer_uint64_max[1]}, - MakeUniformBufferElementDescriptor(1, 5, {1, 0}))); - - // 1400[6] = float(10.0) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]}, - MakeUniformBufferElementDescriptor(1, 6, {6}))); - - // 1500[7] = float(10.0) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]}, - MakeUniformBufferElementDescriptor(2, 0, {7}))); - - // 1600[9][9] = float(10.0) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]}, - MakeUniformBufferElementDescriptor(2, 1, {9, 9}))); - - // 1700[9][9][1] = double(10.0) - ASSERT_TRUE(AddFactHelper( - &fact_manager, context.get(), {buffer_double_10[0], buffer_double_10[1]}, - MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1}))); - - // 1800[9][9][2] = double(10.0) - ASSERT_TRUE(AddFactHelper( - &fact_manager, context.get(), {buffer_double_10[0], buffer_double_10[1]}, - MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2}))); - - // 1900[0][0][0][0][0] = double(20.0) - ASSERT_TRUE(AddFactHelper( - &fact_manager, context.get(), {buffer_double_20[0], buffer_double_20[1]}, - MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0}))); - - opt::Instruction::OperandList operands = { - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_int32_id, 50, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int32_min[0]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_int32_id, 51, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_int64_id, 52, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_uint32_id, 53, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_uint64_id, 54, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_uint64_id, 55, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_float_10[0]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_float_id, 56, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_double_id, 57, operands)); - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_double_id, 58, operands)); - - // A duplicate of the constant with id 59. - operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, type_int32_id, 59, operands)); - - context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); - - // Constants 1 and int32_min are available. - ASSERT_EQ(2, fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_int32_id) - .size()); - // Constant int64_max is available. - ASSERT_EQ(1, fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_int64_id) - .size()); - // Constant 1u is available. - ASSERT_EQ(1, fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_uint32_id) - .size()); - // Constants 1u and uint64_max are available. - ASSERT_EQ(2, fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_uint64_id) - .size()); - // Constant 10.0 is available. - ASSERT_EQ(1, fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_float_id) - .size()); - // Constants 10.0 and 20.0 are available. - ASSERT_EQ(2, fact_manager - .GetConstantsAvailableFromUniformsForType(context.get(), - type_double_id) - .size()); - - ASSERT_EQ(std::numeric_limits::max(), - context->get_constant_mgr() - ->FindDeclaredConstant( - fact_manager.GetConstantsAvailableFromUniformsForType( - context.get(), type_int64_id)[0]) - ->AsIntConstant() - ->GetS64()); - ASSERT_EQ(1, context->get_constant_mgr() - ->FindDeclaredConstant( - fact_manager.GetConstantsAvailableFromUniformsForType( - context.get(), type_uint32_id)[0]) - ->AsIntConstant() - ->GetU32()); - ASSERT_EQ(10.0f, - context->get_constant_mgr() - ->FindDeclaredConstant( - fact_manager.GetConstantsAvailableFromUniformsForType( - context.get(), type_float_id)[0]) - ->AsFloatConstant() - ->GetFloat()); - const std::vector& double_constant_ids = - fact_manager.GetConstantsAvailableFromUniformsForType(context.get(), - type_double_id); - ASSERT_EQ(10.0, context->get_constant_mgr() - ->FindDeclaredConstant(double_constant_ids[0]) - ->AsFloatConstant() - ->GetDouble()); - ASSERT_EQ(20.0, context->get_constant_mgr() - ->FindDeclaredConstant(double_constant_ids[1]) - ->AsFloatConstant() - ->GetDouble()); - - const std::vector - descriptors_for_double_10 = fact_manager.GetUniformDescriptorsForConstant( - context.get(), double_constant_ids[0]); - ASSERT_EQ(2, descriptors_for_double_10.size()); - { - auto temp = MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1}); - ASSERT_TRUE(UniformBufferElementDescriptorEquals()( - &temp, &descriptors_for_double_10[0])); - } - { - auto temp = MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2}); - ASSERT_TRUE(UniformBufferElementDescriptorEquals()( - &temp, &descriptors_for_double_10[1])); - } - const std::vector - descriptors_for_double_20 = fact_manager.GetUniformDescriptorsForConstant( - context.get(), double_constant_ids[1]); - ASSERT_EQ(1, descriptors_for_double_20.size()); - { - auto temp = MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0}); - ASSERT_TRUE(UniformBufferElementDescriptorEquals()( - &temp, &descriptors_for_double_20[0])); - } - - auto constant_1_id = fact_manager.GetConstantFromUniformDescriptor( - context.get(), MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2})); - ASSERT_TRUE(constant_1_id); - - auto constant_2_id = fact_manager.GetConstantFromUniformDescriptor( - context.get(), MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0})); - ASSERT_TRUE(constant_2_id); - - ASSERT_EQ(double_constant_ids[0], constant_1_id); - - ASSERT_EQ(double_constant_ids[1], constant_2_id); -} - -TEST(FactManagerTest, TwoConstantsWithSameValue) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "buf" - OpMemberName %10 0 "a" - OpName %12 "" - OpDecorate %8 RelaxedPrecision - OpMemberDecorate %10 0 RelaxedPrecision - OpMemberDecorate %10 0 Offset 0 - OpDecorate %10 Block - OpDecorate %12 DescriptorSet 0 - OpDecorate %12 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %20 = OpConstant %6 1 - %10 = OpTypeStruct %6 - %11 = OpTypePointer Uniform %10 - %12 = OpVariable %11 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto uniform_buffer_element_descriptor = - MakeUniformBufferElementDescriptor(0, 0, {0}); - - // (0, 0, [0]) = int(1) - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1}, - uniform_buffer_element_descriptor)); - auto constants = - fact_manager.GetConstantsAvailableFromUniformsForType(context.get(), 6); - ASSERT_EQ(1, constants.size()); - ASSERT_TRUE(constants[0] == 9 || constants[0] == 20); - - auto constant = fact_manager.GetConstantFromUniformDescriptor( - context.get(), uniform_buffer_element_descriptor); - ASSERT_TRUE(constant == 9 || constant == 20); - - // Because the constants with ids 9 and 20 are equal, we should get the same - // single uniform buffer element descriptor when we look up the descriptors - // for either one of them. - for (auto constant_id : {9u, 20u}) { - auto descriptors = fact_manager.GetUniformDescriptorsForConstant( - context.get(), constant_id); - ASSERT_EQ(1, descriptors.size()); - ASSERT_TRUE(UniformBufferElementDescriptorEquals()( - &uniform_buffer_element_descriptor, &descriptors[0])); - } -} - -TEST(FactManagerTest, NonFiniteFactsAreNotValid) { - std::string shader = R"( - OpCapability Shader - OpCapability Float64 - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %7 "buf" - OpMemberName %7 0 "f" - OpMemberName %7 1 "d" - OpName %9 "" - OpMemberDecorate %7 0 Offset 0 - OpMemberDecorate %7 1 Offset 8 - OpDecorate %7 Block - OpDecorate %9 DescriptorSet 0 - OpDecorate %9 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %10 = OpTypeFloat 64 - %7 = OpTypeStruct %6 %10 - %8 = OpTypePointer Uniform %7 - %9 = OpVariable %8 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - auto uniform_buffer_element_descriptor_f = - MakeUniformBufferElementDescriptor(0, 0, {0}); - - auto uniform_buffer_element_descriptor_d = - MakeUniformBufferElementDescriptor(0, 0, {1}); - - if (std::numeric_limits::has_infinity) { - // f == +inf - float positive_infinity_float = std::numeric_limits::infinity(); - uint32_t words[1]; - memcpy(words, &positive_infinity_float, sizeof(float)); - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {words[0]}, - uniform_buffer_element_descriptor_f)); - // f == -inf - float negative_infinity_float = std::numeric_limits::infinity(); - memcpy(words, &negative_infinity_float, sizeof(float)); - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {words[0]}, - uniform_buffer_element_descriptor_f)); - } - - if (std::numeric_limits::has_quiet_NaN) { - // f == NaN - float quiet_nan_float = std::numeric_limits::quiet_NaN(); - uint32_t words[1]; - memcpy(words, &quiet_nan_float, sizeof(float)); - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {words[0]}, - uniform_buffer_element_descriptor_f)); - } - - if (std::numeric_limits::has_infinity) { - // d == +inf - double positive_infinity_double = std::numeric_limits::infinity(); - uint32_t words[2]; - memcpy(words, &positive_infinity_double, sizeof(double)); - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), - {words[0], words[1]}, - uniform_buffer_element_descriptor_d)); - // d == -inf - double negative_infinity_double = -std::numeric_limits::infinity(); - memcpy(words, &negative_infinity_double, sizeof(double)); - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), - {words[0], words[1]}, - uniform_buffer_element_descriptor_d)); - } - - if (std::numeric_limits::has_quiet_NaN) { - // d == NaN - double quiet_nan_double = std::numeric_limits::quiet_NaN(); - uint32_t words[2]; - memcpy(words, &quiet_nan_double, sizeof(double)); - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), - {words[0], words[1]}, - uniform_buffer_element_descriptor_d)); - } -} - -TEST(FactManagerTest, AmbiguousFact) { - // This test came from the following GLSL: - // - // #version 310 es - // - // precision highp float; - // - // layout(set = 0, binding = 0) uniform buf { - // float f; - // }; - // - // layout(set = 0, binding = 0) uniform buf2 { - // float g; - // }; - // - // void main() { - // - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %7 "buf" - OpMemberName %7 0 "f" - OpName %9 "" - OpName %10 "buf2" - OpMemberName %10 0 "g" - OpName %12 "" - OpMemberDecorate %7 0 Offset 0 - OpDecorate %7 Block - OpDecorate %9 DescriptorSet 0 - OpDecorate %9 Binding 0 - OpMemberDecorate %10 0 Offset 0 - OpDecorate %10 Block - OpDecorate %12 DescriptorSet 0 - OpDecorate %12 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeStruct %6 - %8 = OpTypePointer Uniform %7 - %9 = OpVariable %8 Uniform - %10 = OpTypeStruct %6 - %11 = OpTypePointer Uniform %10 - %12 = OpVariable %11 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - auto uniform_buffer_element_descriptor = - MakeUniformBufferElementDescriptor(0, 0, {0}); - - // The fact cannot be added because it is ambiguous: there are two uniforms - // with descriptor set 0 and binding 0. - ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {1}, - uniform_buffer_element_descriptor)); -} - -TEST(FactManagerTest, DataSynonymFacts) { - // The SPIR-V types and constants come from the following code. The body of - // the SPIR-V function then constructs a composite that is synonymous with - // myT. - // - // #version 310 es - // - // precision highp float; - // - // struct S { - // int a; - // uvec2 b; - // }; - // - // struct T { - // bool c[5]; - // mat4x2 d; - // S e; - // }; - // - // void main() { - // T myT = T(bool[5](true, false, true, false, true), - // mat4x2(vec2(1.0, 2.0), vec2(3.0, 4.0), - // vec2(5.0, 6.0), vec2(7.0, 8.0)), - // S(10, uvec2(100u, 200u))); - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %15 "S" - OpMemberName %15 0 "a" - OpMemberName %15 1 "b" - OpName %16 "T" - OpMemberName %16 0 "c" - OpMemberName %16 1 "d" - OpMemberName %16 2 "e" - OpName %18 "myT" - OpMemberDecorate %15 0 RelaxedPrecision - OpMemberDecorate %15 1 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 5 - %9 = OpTypeArray %6 %8 - %10 = OpTypeFloat 32 - %11 = OpTypeVector %10 2 - %12 = OpTypeMatrix %11 4 - %13 = OpTypeInt 32 1 - %14 = OpTypeVector %7 2 - %15 = OpTypeStruct %13 %14 - %16 = OpTypeStruct %9 %12 %15 - %17 = OpTypePointer Function %16 - %19 = OpConstantTrue %6 - %20 = OpConstantFalse %6 - %21 = OpConstantComposite %9 %19 %20 %19 %20 %19 - %22 = OpConstant %10 1 - %23 = OpConstant %10 2 - %24 = OpConstantComposite %11 %22 %23 - %25 = OpConstant %10 3 - %26 = OpConstant %10 4 - %27 = OpConstantComposite %11 %25 %26 - %28 = OpConstant %10 5 - %29 = OpConstant %10 6 - %30 = OpConstantComposite %11 %28 %29 - %31 = OpConstant %10 7 - %32 = OpConstant %10 8 - %33 = OpConstantComposite %11 %31 %32 - %34 = OpConstantComposite %12 %24 %27 %30 %33 - %35 = OpConstant %13 10 - %36 = OpConstant %7 100 - %37 = OpConstant %7 200 - %38 = OpConstantComposite %14 %36 %37 - %39 = OpConstantComposite %15 %35 %38 - %40 = OpConstantComposite %16 %21 %34 %39 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %18 = OpVariable %17 Function - OpStore %18 %40 - %100 = OpCompositeConstruct %9 %19 %20 %19 %20 %19 - %101 = OpCompositeConstruct %11 %22 %23 - %102 = OpCompositeConstruct %11 %25 %26 - %103 = OpCompositeConstruct %11 %28 %29 - %104 = OpCompositeConstruct %11 %31 %32 - %105 = OpCompositeConstruct %12 %101 %102 %103 %104 - %106 = OpCompositeConstruct %14 %36 %37 - %107 = OpCompositeConstruct %15 %35 %106 - %108 = OpCompositeConstruct %16 %100 %105 %107 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(24, {}), MakeDataDescriptor(101, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}), - MakeDataDescriptor(101, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}), - MakeDataDescriptor(101, {1}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}), - MakeDataDescriptor(101, {1}), - context.get())); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(24, {}), - MakeDataDescriptor(101, {}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(24, {}), MakeDataDescriptor(101, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}), - MakeDataDescriptor(101, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}), - MakeDataDescriptor(101, {1}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}), - MakeDataDescriptor(101, {1}), - context.get())); - - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}), - MakeDataDescriptor(102, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}), - MakeDataDescriptor(102, {1}), - context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {0}), - MakeDataDescriptor(102, {0}), context.get()); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}), - MakeDataDescriptor(102, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}), - MakeDataDescriptor(102, {1}), - context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {1}), - MakeDataDescriptor(102, {1}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}), - MakeDataDescriptor(102, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}), - MakeDataDescriptor(102, {1}), - context.get())); - - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(30, {}), MakeDataDescriptor(103, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}), - MakeDataDescriptor(103, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}), - MakeDataDescriptor(103, {1}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(33, {}), MakeDataDescriptor(104, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}), - MakeDataDescriptor(104, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}), - MakeDataDescriptor(104, {1}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(34, {}), MakeDataDescriptor(105, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}), - MakeDataDescriptor(105, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}), - MakeDataDescriptor(105, {1}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}), - MakeDataDescriptor(105, {2}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}), - MakeDataDescriptor(105, {3}), - context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(30, {}), - MakeDataDescriptor(103, {}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(33, {}), - MakeDataDescriptor(104, {}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {0}), - MakeDataDescriptor(105, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {1}), - MakeDataDescriptor(105, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {2}), - MakeDataDescriptor(105, {2}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(30, {}), MakeDataDescriptor(103, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}), - MakeDataDescriptor(103, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}), - MakeDataDescriptor(103, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(33, {}), MakeDataDescriptor(104, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}), - MakeDataDescriptor(104, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}), - MakeDataDescriptor(104, {1}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(34, {}), MakeDataDescriptor(105, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}), - MakeDataDescriptor(105, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}), - MakeDataDescriptor(105, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}), - MakeDataDescriptor(105, {2}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}), - MakeDataDescriptor(105, {3}), - context.get())); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {3}), - MakeDataDescriptor(105, {3}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}), - MakeDataDescriptor(104, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}), - MakeDataDescriptor(105, {3}), - context.get())); - - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(21, {}), MakeDataDescriptor(100, {}), context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {0}), - MakeDataDescriptor(100, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {1}), - MakeDataDescriptor(100, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {2}), - MakeDataDescriptor(100, {2}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {3}), - MakeDataDescriptor(100, {3}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {4}), - MakeDataDescriptor(100, {4}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(21, {}), MakeDataDescriptor(100, {}), context.get())); - - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}), - MakeDataDescriptor(107, {0}), - context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(35, {}), MakeDataDescriptor(39, {0}), context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(39, {0}), - MakeDataDescriptor(35, {}), context.get()); - ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}), - MakeDataDescriptor(107, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(35, {}), MakeDataDescriptor(39, {0}), context.get())); - - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {0}), MakeDataDescriptor(36, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {1}), MakeDataDescriptor(37, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(106, {0}), MakeDataDescriptor(36, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(106, {1}), MakeDataDescriptor(37, {}), context.get())); - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {}), MakeDataDescriptor(106, {}), context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {0}), - MakeDataDescriptor(36, {}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {0}), - MakeDataDescriptor(36, {}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {1}), - MakeDataDescriptor(37, {}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {1}), - MakeDataDescriptor(37, {}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {0}), MakeDataDescriptor(36, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {1}), MakeDataDescriptor(37, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(106, {0}), MakeDataDescriptor(36, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(106, {1}), MakeDataDescriptor(37, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {}), MakeDataDescriptor(106, {}), context.get())); - - ASSERT_FALSE(fact_manager.IsSynonymous( - MakeDataDescriptor(40, {}), MakeDataDescriptor(108, {}), context.get())); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(107, {0}), - MakeDataDescriptor(35, {}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {0}), - MakeDataDescriptor(108, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {1}), - MakeDataDescriptor(108, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {2}), - MakeDataDescriptor(108, {2}), context.get()); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(40, {}), MakeDataDescriptor(108, {}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0}), - MakeDataDescriptor(108, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1}), - MakeDataDescriptor(108, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2}), - MakeDataDescriptor(108, {2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 0}), - MakeDataDescriptor(108, {0, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 1}), - MakeDataDescriptor(108, {0, 1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 2}), - MakeDataDescriptor(108, {0, 2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 3}), - MakeDataDescriptor(108, {0, 3}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 4}), - MakeDataDescriptor(108, {0, 4}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0}), - MakeDataDescriptor(108, {1, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1}), - MakeDataDescriptor(108, {1, 1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2}), - MakeDataDescriptor(108, {1, 2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3}), - MakeDataDescriptor(108, {1, 3}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 0}), - MakeDataDescriptor(108, {1, 0, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 0}), - MakeDataDescriptor(108, {1, 1, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 0}), - MakeDataDescriptor(108, {1, 2, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 0}), - MakeDataDescriptor(108, {1, 3, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 1}), - MakeDataDescriptor(108, {1, 0, 1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 1}), - MakeDataDescriptor(108, {1, 1, 1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 1}), - MakeDataDescriptor(108, {1, 2, 1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 1}), - MakeDataDescriptor(108, {1, 3, 1}), - context.get())); - - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 0}), - MakeDataDescriptor(108, {2, 0}), - context.get())); - - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1}), - MakeDataDescriptor(108, {2, 1}), - context.get())); - - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 0}), - MakeDataDescriptor(108, {2, 1, 0}), - context.get())); - - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 1}), - MakeDataDescriptor(108, {2, 1, 1}), - context.get())); -} - -TEST(FactManagerTest, RecursiveAdditionOfFacts) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %12 "main" - OpExecutionMode %12 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeMatrix %7 4 - %9 = OpConstant %6 0 - %10 = OpConstantComposite %7 %9 %9 %9 %9 - %11 = OpConstantComposite %8 %10 %10 %10 %10 - %12 = OpFunction %2 None %3 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}), - MakeDataDescriptor(11, {2}), context.get()); - - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(10, {}), MakeDataDescriptor(11, {2}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {0}), - MakeDataDescriptor(11, {2, 0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {1}), - MakeDataDescriptor(11, {2, 1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {2}), - MakeDataDescriptor(11, {2, 2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {3}), - MakeDataDescriptor(11, {2, 3}), - context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/fuzz_test_util.cpp b/3rdparty/spirv-tools/test/fuzz/fuzz_test_util.cpp deleted file mode 100644 index 1d15ad624..000000000 --- a/3rdparty/spirv-tools/test/fuzz/fuzz_test_util.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "test/fuzz/fuzz_test_util.h" - -#include -#include - -#include "tools/io.h" - -namespace spvtools { -namespace fuzz { - -bool IsEqual(const spv_target_env env, - const std::vector& expected_binary, - const std::vector& actual_binary) { - if (expected_binary == actual_binary) { - return true; - } - SpirvTools t(env); - std::string expected_disassembled; - std::string actual_disassembled; - if (!t.Disassemble(expected_binary, &expected_disassembled, - kFuzzDisassembleOption)) { - return false; - } - if (!t.Disassemble(actual_binary, &actual_disassembled, - kFuzzDisassembleOption)) { - return false; - } - // Using expect gives us a string diff if the strings are not the same. - EXPECT_EQ(expected_disassembled, actual_disassembled); - // We then return the result of the equality comparison, to be used by an - // assertion in the test root function. - return expected_disassembled == actual_disassembled; -} - -bool IsEqual(const spv_target_env env, const std::string& expected_text, - const std::vector& actual_binary) { - std::vector expected_binary; - SpirvTools t(env); - if (!t.Assemble(expected_text, &expected_binary, kFuzzAssembleOption)) { - return false; - } - return IsEqual(env, expected_binary, actual_binary); -} - -bool IsEqual(const spv_target_env env, const std::string& expected_text, - const opt::IRContext* actual_ir) { - std::vector actual_binary; - actual_ir->module()->ToBinary(&actual_binary, false); - return IsEqual(env, expected_text, actual_binary); -} - -bool IsEqual(const spv_target_env env, const opt::IRContext* ir_1, - const opt::IRContext* ir_2) { - std::vector binary_1; - ir_1->module()->ToBinary(&binary_1, false); - std::vector binary_2; - ir_2->module()->ToBinary(&binary_2, false); - return IsEqual(env, binary_1, binary_2); -} - -bool IsValid(spv_target_env env, const opt::IRContext* ir) { - std::vector binary; - ir->module()->ToBinary(&binary, false); - SpirvTools t(env); - return t.Validate(binary); -} - -std::string ToString(spv_target_env env, const opt::IRContext* ir) { - std::vector binary; - ir->module()->ToBinary(&binary, false); - return ToString(env, binary); -} - -std::string ToString(spv_target_env env, const std::vector& binary) { - SpirvTools t(env); - std::string result; - t.Disassemble(binary, &result, kFuzzDisassembleOption); - return result; -} - -void DumpShader(opt::IRContext* context, const char* filename) { - std::vector binary; - context->module()->ToBinary(&binary, false); - DumpShader(binary, filename); -} - -void DumpShader(const std::vector& binary, const char* filename) { - auto write_file_succeeded = - WriteFile(filename, "wb", &binary[0], binary.size()); - if (!write_file_succeeded) { - std::cerr << "Failed to dump shader" << std::endl; - } -} - -void DumpTransformationsJson( - const protobufs::TransformationSequence& transformations, - const char* filename) { - std::string json_string; - auto json_options = google::protobuf::util::JsonOptions(); - json_options.add_whitespace = true; - auto json_generation_status = google::protobuf::util::MessageToJsonString( - transformations, &json_string, json_options); - if (json_generation_status == google::protobuf::util::Status::OK) { - std::ofstream transformations_json_file(filename); - transformations_json_file << json_string; - transformations_json_file.close(); - } -} - -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/fuzz_test_util.h b/3rdparty/spirv-tools/test/fuzz/fuzz_test_util.h deleted file mode 100644 index 9e08bf689..000000000 --- a/3rdparty/spirv-tools/test/fuzz/fuzz_test_util.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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. - -#ifndef TEST_FUZZ_FUZZ_TEST_UTIL_H_ -#define TEST_FUZZ_FUZZ_TEST_UTIL_H_ - -#include "gtest/gtest.h" - -#include - -#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" -#include "source/opt/build_module.h" -#include "source/opt/ir_context.h" -#include "spirv-tools/libspirv.h" - -namespace spvtools { -namespace fuzz { - -// Returns true if and only if the given binaries are bit-wise equal. -bool IsEqual(spv_target_env env, const std::vector& expected_binary, - const std::vector& actual_binary); - -// Assembles the given text and returns true if and only if the resulting binary -// is bit-wise equal to the given binary. -bool IsEqual(spv_target_env env, const std::string& expected_text, - const std::vector& actual_binary); - -// Assembles the given text and turns the given IR into binary, then returns -// true if and only if the resulting binaries are bit-wise equal. -bool IsEqual(spv_target_env env, const std::string& expected_text, - const opt::IRContext* actual_ir); - -// Turns the given IRs into binaries, then returns true if and only if the -// resulting binaries are bit-wise equal. -bool IsEqual(spv_target_env env, const opt::IRContext* ir_1, - const opt::IRContext* ir_2); - -// Assembles the given IR context and returns true if and only if -// the resulting binary is valid. -bool IsValid(spv_target_env env, const opt::IRContext* ir); - -// Assembles the given IR context, then returns its disassembly as a string. -// Useful for debugging. -std::string ToString(spv_target_env env, const opt::IRContext* ir); - -// Returns the disassembly of the given binary as a string. -// Useful for debugging. -std::string ToString(spv_target_env env, const std::vector& binary); - -// Assembly options for writing fuzzer tests. It simplifies matters if -// numeric ids do not change. -const uint32_t kFuzzAssembleOption = - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS; -// Disassembly options for writing fuzzer tests. -const uint32_t kFuzzDisassembleOption = - SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | SPV_BINARY_TO_TEXT_OPTION_INDENT; - -// A silent message consumer. -const spvtools::MessageConsumer kSilentConsumer = - [](spv_message_level_t, const char*, const spv_position_t&, - const char*) -> void {}; - -const spvtools::MessageConsumer kConsoleMessageConsumer = - [](spv_message_level_t level, const char*, const spv_position_t& position, - const char* message) -> void { - switch (level) { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - std::cerr << "error: line " << position.index << ": " << message - << std::endl; - break; - case SPV_MSG_WARNING: - std::cout << "warning: line " << position.index << ": " << message - << std::endl; - break; - case SPV_MSG_INFO: - std::cout << "info: line " << position.index << ": " << message - << std::endl; - break; - default: - break; - } -}; - -// Dumps the SPIRV-V module in |context| to file |filename|. Useful for -// interactive debugging. -void DumpShader(opt::IRContext* context, const char* filename); - -// Dumps |binary| to file |filename|. Useful for interactive debugging. -void DumpShader(const std::vector& binary, const char* filename); - -// Dumps |transformations| to file |filename| in JSON format. Useful for -// interactive debugging. -void DumpTransformationsJson( - const protobufs::TransformationSequence& transformations, - const char* filename); - -} // namespace fuzz -} // namespace spvtools - -#endif // TEST_FUZZ_FUZZ_TEST_UTIL_H_ diff --git a/3rdparty/spirv-tools/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp b/3rdparty/spirv-tools/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp deleted file mode 100644 index 89f006e07..000000000 --- a/3rdparty/spirv-tools/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/fuzzer_pass_add_useful_constructs.h" -#include "source/fuzz/pseudo_random_generator.h" -#include "source/fuzz/uniform_buffer_element_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -bool AddFactHelper( - FactManager* fact_manager, opt::IRContext* context, uint32_t word, - const protobufs::UniformBufferElementDescriptor& descriptor) { - protobufs::FactConstantUniform constant_uniform_fact; - constant_uniform_fact.add_constant_word(word); - *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() = - descriptor; - protobufs::Fact fact; - *fact.mutable_constant_uniform_fact() = constant_uniform_fact; - return fact_manager->AddFact(fact, context); -} - -TEST(FuzzerPassAddUsefulConstructsTest, CheckBasicStuffIsAdded) { - // The SPIR-V came from the following empty GLSL shader: - // - // #version 450 - // - // void main() - // { - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - FuzzerContext fuzzer_context(MakeUnique(0).get(), 100); - protobufs::TransformationSequence transformation_sequence; - - FuzzerPassAddUsefulConstructs pass(context.get(), &fact_manager, - &fuzzer_context, &transformation_sequence); - pass.Apply(); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %100 = OpTypeBool - %101 = OpTypeInt 32 1 - %102 = OpTypeInt 32 0 - %103 = OpTypeFloat 32 - %104 = OpConstantTrue %100 - %105 = OpConstantFalse %100 - %106 = OpConstant %101 0 - %107 = OpConstant %101 1 - %108 = OpConstant %102 0 - %109 = OpConstant %102 1 - %110 = OpConstant %103 0 - %111 = OpConstant %103 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after, context.get())); -} - -TEST(FuzzerPassAddUsefulConstructsTest, - CheckTypesIndicesAndConstantsAddedForUniformFacts) { - // The SPIR-V came from the following GLSL shader: - // - // #version 450 - // - // struct S { - // int x; - // float y; - // int z; - // int w; - // }; - // - // uniform buf { - // S s; - // uint w[10]; - // }; - // - // void main() { - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "S" - OpMemberName %8 0 "x" - OpMemberName %8 1 "y" - OpMemberName %8 2 "z" - OpMemberName %8 3 "w" - OpName %12 "buf" - OpMemberName %12 0 "s" - OpMemberName %12 1 "w" - OpName %14 "" - OpMemberDecorate %8 0 Offset 0 - OpMemberDecorate %8 1 Offset 4 - OpMemberDecorate %8 2 Offset 8 - OpMemberDecorate %8 3 Offset 12 - OpDecorate %11 ArrayStride 16 - OpMemberDecorate %12 0 Offset 0 - OpMemberDecorate %12 1 Offset 16 - OpDecorate %12 Block - OpDecorate %14 DescriptorSet 0 - OpDecorate %14 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFloat 32 - %8 = OpTypeStruct %6 %7 %6 %6 - %9 = OpTypeInt 32 0 - %10 = OpConstant %9 10 - %11 = OpTypeArray %9 %10 - %12 = OpTypeStruct %8 %11 - %13 = OpTypePointer Uniform %12 - %14 = OpVariable %13 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - FuzzerContext fuzzer_context(MakeUnique(0).get(), 100); - protobufs::TransformationSequence transformation_sequence; - - // Add some uniform facts. - - // buf.s.x == 200 - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 200, - MakeUniformBufferElementDescriptor(0, 0, {0, 0}))); - - // buf.s.y == 0.5 - const float float_value = 0.5; - uint32_t float_value_as_uint; - memcpy(&float_value_as_uint, &float_value, sizeof(float_value)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_value_as_uint, - MakeUniformBufferElementDescriptor(0, 0, {0, 1}))); - - // buf.s.z == 300 - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 300, - MakeUniformBufferElementDescriptor(0, 0, {0, 2}))); - - // buf.s.w == 400 - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 400, - MakeUniformBufferElementDescriptor(0, 0, {0, 3}))); - - // buf.w[6] = 22 - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 22, - MakeUniformBufferElementDescriptor(0, 0, {1, 6}))); - - // buf.w[8] = 23 - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 23, - MakeUniformBufferElementDescriptor(0, 0, {1, 8}))); - - // Assert some things about the module that are not true prior to adding the - // pass - - { - // No uniform int pointer - opt::analysis::Integer temp_type_signed_int(32, true); - opt::analysis::Integer* registered_type_signed_int = - context->get_type_mgr() - ->GetRegisteredType(&temp_type_signed_int) - ->AsInteger(); - opt::analysis::Pointer type_pointer_uniform_signed_int( - registered_type_signed_int, SpvStorageClassUniform); - ASSERT_EQ(0, - context->get_type_mgr()->GetId(&type_pointer_uniform_signed_int)); - - // No uniform uint pointer - opt::analysis::Integer temp_type_unsigned_int(32, false); - opt::analysis::Integer* registered_type_unsigned_int = - context->get_type_mgr() - ->GetRegisteredType(&temp_type_unsigned_int) - ->AsInteger(); - opt::analysis::Pointer type_pointer_uniform_unsigned_int( - registered_type_unsigned_int, SpvStorageClassUniform); - ASSERT_EQ( - 0, context->get_type_mgr()->GetId(&type_pointer_uniform_unsigned_int)); - - // No uniform float pointer - opt::analysis::Float temp_type_float(32); - opt::analysis::Float* registered_type_float = - context->get_type_mgr()->GetRegisteredType(&temp_type_float)->AsFloat(); - opt::analysis::Pointer type_pointer_uniform_float(registered_type_float, - SpvStorageClassUniform); - ASSERT_EQ(0, context->get_type_mgr()->GetId(&type_pointer_uniform_float)); - - // No int constants 200, 300 nor 400 - opt::analysis::IntConstant int_constant_200(registered_type_signed_int, - {200}); - opt::analysis::IntConstant int_constant_300(registered_type_signed_int, - {300}); - opt::analysis::IntConstant int_constant_400(registered_type_signed_int, - {400}); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_200)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_300)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_400)); - - // No float constant 0.5 - opt::analysis::FloatConstant float_constant_zero_point_five( - registered_type_float, {float_value_as_uint}); - ASSERT_EQ(nullptr, context->get_constant_mgr()->FindConstant( - &float_constant_zero_point_five)); - - // No uint constant 22 - opt::analysis::IntConstant uint_constant_22(registered_type_unsigned_int, - {22}); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&uint_constant_22)); - - // No uint constant 23 - opt::analysis::IntConstant uint_constant_23(registered_type_unsigned_int, - {23}); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&uint_constant_23)); - - // No int constants 0, 1, 2, 3, 6, 8 - opt::analysis::IntConstant int_constant_0(registered_type_signed_int, {0}); - opt::analysis::IntConstant int_constant_1(registered_type_signed_int, {1}); - opt::analysis::IntConstant int_constant_2(registered_type_signed_int, {2}); - opt::analysis::IntConstant int_constant_3(registered_type_signed_int, {3}); - opt::analysis::IntConstant int_constant_6(registered_type_signed_int, {6}); - opt::analysis::IntConstant int_constant_8(registered_type_signed_int, {8}); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_0)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_1)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_2)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_3)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_6)); - ASSERT_EQ(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_8)); - } - - FuzzerPassAddUsefulConstructs pass(context.get(), &fact_manager, - &fuzzer_context, &transformation_sequence); - pass.Apply(); - ASSERT_TRUE(IsValid(env, context.get())); - - // Now assert some things about the module that should be true following the - // pass. - - // We reconstruct all necessary types and constants to guard against the type - // and constant managers for the module having been invalidated. - - { - // Uniform int pointer now present - opt::analysis::Integer temp_type_signed_int(32, true); - opt::analysis::Integer* registered_type_signed_int = - context->get_type_mgr() - ->GetRegisteredType(&temp_type_signed_int) - ->AsInteger(); - opt::analysis::Pointer type_pointer_uniform_signed_int( - registered_type_signed_int, SpvStorageClassUniform); - ASSERT_NE(0, - context->get_type_mgr()->GetId(&type_pointer_uniform_signed_int)); - - // Uniform uint pointer now present - opt::analysis::Integer temp_type_unsigned_int(32, false); - opt::analysis::Integer* registered_type_unsigned_int = - context->get_type_mgr() - ->GetRegisteredType(&temp_type_unsigned_int) - ->AsInteger(); - opt::analysis::Pointer type_pointer_uniform_unsigned_int( - registered_type_unsigned_int, SpvStorageClassUniform); - ASSERT_NE( - 0, context->get_type_mgr()->GetId(&type_pointer_uniform_unsigned_int)); - - // Uniform float pointer now present - opt::analysis::Float temp_type_float(32); - opt::analysis::Float* registered_type_float = - context->get_type_mgr()->GetRegisteredType(&temp_type_float)->AsFloat(); - opt::analysis::Pointer type_pointer_uniform_float(registered_type_float, - SpvStorageClassUniform); - ASSERT_NE(0, context->get_type_mgr()->GetId(&type_pointer_uniform_float)); - - // int constants 200, 300, 400 now present - opt::analysis::IntConstant int_constant_200(registered_type_signed_int, - {200}); - opt::analysis::IntConstant int_constant_300(registered_type_signed_int, - {300}); - opt::analysis::IntConstant int_constant_400(registered_type_signed_int, - {400}); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_200)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_300)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_400)); - - // float constant 0.5 now present - opt::analysis::FloatConstant float_constant_zero_point_five( - registered_type_float, {float_value_as_uint}); - ASSERT_NE(nullptr, context->get_constant_mgr()->FindConstant( - &float_constant_zero_point_five)); - - // uint constant 22 now present - opt::analysis::IntConstant uint_constant_22(registered_type_unsigned_int, - {22}); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&uint_constant_22)); - - // uint constant 23 now present - opt::analysis::IntConstant uint_constant_23(registered_type_unsigned_int, - {23}); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&uint_constant_23)); - - // int constants 0, 1, 2, 3, 6, 8 now present - opt::analysis::IntConstant int_constant_0(registered_type_signed_int, {0}); - opt::analysis::IntConstant int_constant_1(registered_type_signed_int, {1}); - opt::analysis::IntConstant int_constant_2(registered_type_signed_int, {2}); - opt::analysis::IntConstant int_constant_3(registered_type_signed_int, {3}); - opt::analysis::IntConstant int_constant_6(registered_type_signed_int, {6}); - opt::analysis::IntConstant int_constant_8(registered_type_signed_int, {8}); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_0)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_1)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_2)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_3)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_6)); - ASSERT_NE(nullptr, - context->get_constant_mgr()->FindConstant(&int_constant_8)); - } -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/fuzzer_replayer_test.cpp b/3rdparty/spirv-tools/test/fuzz/fuzzer_replayer_test.cpp deleted file mode 100644 index fa1f09622..000000000 --- a/3rdparty/spirv-tools/test/fuzz/fuzzer_replayer_test.cpp +++ /dev/null @@ -1,1629 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/fuzzer.h" -#include "source/fuzz/replayer.h" -#include "source/fuzz/uniform_buffer_element_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -const uint32_t kNumFuzzerRuns = 20; - -void AddConstantUniformFact(protobufs::FactSequence* facts, - uint32_t descriptor_set, uint32_t binding, - std::vector&& indices, uint32_t value) { - protobufs::FactConstantUniform fact; - *fact.mutable_uniform_buffer_element_descriptor() = - MakeUniformBufferElementDescriptor(descriptor_set, binding, - std::move(indices)); - *fact.mutable_constant_word()->Add() = value; - protobufs::Fact temp; - *temp.mutable_constant_uniform_fact() = fact; - *facts->mutable_fact()->Add() = temp; -} - -// Reinterpret the bits of |value| as a 32-bit unsigned int -uint32_t FloatBitsAsUint(float value) { - uint32_t result; - memcpy(&result, &value, sizeof(float)); - return result; -} - -// Assembles the given |shader| text, and then runs the fuzzer |num_runs| -// times, using successive seeds starting from |initial_seed|. Checks that -// the binary produced after each fuzzer run is valid, and that replaying -// the transformations that were applied during fuzzing leads to an -// identical binary. -void RunFuzzerAndReplayer(const std::string& shader, - const protobufs::FactSequence& initial_facts, - uint32_t initial_seed, uint32_t num_runs) { - const auto env = SPV_ENV_UNIVERSAL_1_5; - - std::vector binary_in; - SpirvTools t(env); - t.SetMessageConsumer(kConsoleMessageConsumer); - ASSERT_TRUE(t.Assemble(shader, &binary_in, kFuzzAssembleOption)); - ASSERT_TRUE(t.Validate(binary_in)); - - for (uint32_t seed = initial_seed; seed < initial_seed + num_runs; seed++) { - std::vector fuzzer_binary_out; - protobufs::TransformationSequence fuzzer_transformation_sequence_out; - - Fuzzer fuzzer(env, seed, true); - fuzzer.SetMessageConsumer(kSilentConsumer); - auto fuzzer_result_status = - fuzzer.Run(binary_in, initial_facts, &fuzzer_binary_out, - &fuzzer_transformation_sequence_out); - ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result_status); - ASSERT_TRUE(t.Validate(fuzzer_binary_out)); - - std::vector replayer_binary_out; - protobufs::TransformationSequence replayer_transformation_sequence_out; - - Replayer replayer(env, false); - replayer.SetMessageConsumer(kSilentConsumer); - auto replayer_result_status = replayer.Run( - binary_in, initial_facts, fuzzer_transformation_sequence_out, - &replayer_binary_out, &replayer_transformation_sequence_out); - ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete, - replayer_result_status); - - // After replaying the transformations applied by the fuzzer, exactly those - // transformations should have been applied, and the binary resulting from - // replay should be identical to that which resulted from fuzzing. - std::string fuzzer_transformations_string; - std::string replayer_transformations_string; - fuzzer_transformation_sequence_out.SerializeToString( - &fuzzer_transformations_string); - replayer_transformation_sequence_out.SerializeToString( - &replayer_transformations_string); - ASSERT_EQ(fuzzer_transformations_string, replayer_transformations_string); - ASSERT_EQ(fuzzer_binary_out, replayer_binary_out); - } -} - -TEST(FuzzerReplayerTest, Miscellaneous1) { - // The SPIR-V came from this GLSL: - // - // #version 310 es - // - // void foo() { - // int x; - // x = 2; - // for (int i = 0; i < 100; i++) { - // x += i; - // x = x * 2; - // } - // return; - // } - // - // void main() { - // foo(); - // for (int i = 0; i < 10; i++) { - // int j = 20; - // while(j > 0) { - // foo(); - // j--; - // } - // do { - // i++; - // } while(i < 4); - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %6 "foo(" - OpName %10 "x" - OpName %12 "i" - OpName %33 "i" - OpName %42 "j" - OpDecorate %10 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %19 RelaxedPrecision - OpDecorate %23 RelaxedPrecision - OpDecorate %24 RelaxedPrecision - OpDecorate %25 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - OpDecorate %28 RelaxedPrecision - OpDecorate %30 RelaxedPrecision - OpDecorate %33 RelaxedPrecision - OpDecorate %39 RelaxedPrecision - OpDecorate %42 RelaxedPrecision - OpDecorate %49 RelaxedPrecision - OpDecorate %52 RelaxedPrecision - OpDecorate %53 RelaxedPrecision - OpDecorate %58 RelaxedPrecision - OpDecorate %59 RelaxedPrecision - OpDecorate %60 RelaxedPrecision - OpDecorate %63 RelaxedPrecision - OpDecorate %64 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %11 = OpConstant %8 2 - %13 = OpConstant %8 0 - %20 = OpConstant %8 100 - %21 = OpTypeBool - %29 = OpConstant %8 1 - %40 = OpConstant %8 10 - %43 = OpConstant %8 20 - %61 = OpConstant %8 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %33 = OpVariable %9 Function - %42 = OpVariable %9 Function - %32 = OpFunctionCall %2 %6 - OpStore %33 %13 - OpBranch %34 - %34 = OpLabel - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %39 = OpLoad %8 %33 - %41 = OpSLessThan %21 %39 %40 - OpBranchConditional %41 %35 %36 - %35 = OpLabel - OpStore %42 %43 - OpBranch %44 - %44 = OpLabel - OpLoopMerge %46 %47 None - OpBranch %48 - %48 = OpLabel - %49 = OpLoad %8 %42 - %50 = OpSGreaterThan %21 %49 %13 - OpBranchConditional %50 %45 %46 - %45 = OpLabel - %51 = OpFunctionCall %2 %6 - %52 = OpLoad %8 %42 - %53 = OpISub %8 %52 %29 - OpStore %42 %53 - OpBranch %47 - %47 = OpLabel - OpBranch %44 - %46 = OpLabel - OpBranch %54 - %54 = OpLabel - OpLoopMerge %56 %57 None - OpBranch %55 - %55 = OpLabel - %58 = OpLoad %8 %33 - %59 = OpIAdd %8 %58 %29 - OpStore %33 %59 - OpBranch %57 - %57 = OpLabel - %60 = OpLoad %8 %33 - %62 = OpSLessThan %21 %60 %61 - OpBranchConditional %62 %54 %56 - %56 = OpLabel - OpBranch %37 - %37 = OpLabel - %63 = OpLoad %8 %33 - %64 = OpIAdd %8 %63 %29 - OpStore %33 %64 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %10 = OpVariable %9 Function - %12 = OpVariable %9 Function - OpStore %10 %11 - OpStore %12 %13 - OpBranch %14 - %14 = OpLabel - OpLoopMerge %16 %17 None - OpBranch %18 - %18 = OpLabel - %19 = OpLoad %8 %12 - %22 = OpSLessThan %21 %19 %20 - OpBranchConditional %22 %15 %16 - %15 = OpLabel - %23 = OpLoad %8 %12 - %24 = OpLoad %8 %10 - %25 = OpIAdd %8 %24 %23 - OpStore %10 %25 - %26 = OpLoad %8 %10 - %27 = OpIMul %8 %26 %11 - OpStore %10 %27 - OpBranch %17 - %17 = OpLabel - %28 = OpLoad %8 %12 - %30 = OpIAdd %8 %28 %29 - OpStore %12 %30 - OpBranch %14 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Do some fuzzer runs, starting from an initial seed of 0 (seed value chosen - // arbitrarily). - RunFuzzerAndReplayer(shader, protobufs::FactSequence(), 0, kNumFuzzerRuns); -} - -TEST(FuzzerReplayerTest, Miscellaneous2) { - // The SPIR-V came from this GLSL, which was then optimized using spirv-opt - // with the -O argument: - // - // #version 310 es - // - // precision highp float; - // - // layout(location = 0) out vec4 _GLF_color; - // - // layout(set = 0, binding = 0) uniform buf0 { - // vec2 injectionSwitch; - // }; - // layout(set = 0, binding = 1) uniform buf1 { - // vec2 resolution; - // }; - // bool checkSwap(float a, float b) - // { - // return gl_FragCoord.y < resolution.y / 2.0 ? a > b : a < b; - // } - // void main() - // { - // float data[10]; - // for(int i = 0; i < 10; i++) - // { - // data[i] = float(10 - i) * injectionSwitch.y; - // } - // for(int i = 0; i < 9; i++) - // { - // for(int j = 0; j < 10; j++) - // { - // if(j < i + 1) - // { - // continue; - // } - // bool doSwap = checkSwap(data[i], data[j]); - // if(doSwap) - // { - // float temp = data[i]; - // data[i] = data[j]; - // data[j] = temp; - // } - // } - // } - // if(gl_FragCoord.x < resolution.x / 2.0) - // { - // _GLF_color = vec4(data[0] / 10.0, data[5] / 10.0, data[9] / 10.0, 1.0); - // } - // else - // { - // _GLF_color = vec4(data[5] / 10.0, data[9] / 10.0, data[0] / 10.0, 1.0); - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %16 %139 %25 %68 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %16 "gl_FragCoord" - OpName %23 "buf1" - OpMemberName %23 0 "resolution" - OpName %25 "" - OpName %61 "data" - OpName %66 "buf0" - OpMemberName %66 0 "injectionSwitch" - OpName %68 "" - OpName %139 "_GLF_color" - OpDecorate %16 BuiltIn FragCoord - OpMemberDecorate %23 0 Offset 0 - OpDecorate %23 Block - OpDecorate %25 DescriptorSet 0 - OpDecorate %25 Binding 1 - OpDecorate %64 RelaxedPrecision - OpMemberDecorate %66 0 Offset 0 - OpDecorate %66 Block - OpDecorate %68 DescriptorSet 0 - OpDecorate %68 Binding 0 - OpDecorate %75 RelaxedPrecision - OpDecorate %95 RelaxedPrecision - OpDecorate %126 RelaxedPrecision - OpDecorate %128 RelaxedPrecision - OpDecorate %139 Location 0 - OpDecorate %182 RelaxedPrecision - OpDecorate %183 RelaxedPrecision - OpDecorate %184 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %8 = OpTypeBool - %14 = OpTypeVector %6 4 - %15 = OpTypePointer Input %14 - %16 = OpVariable %15 Input - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 1 - %19 = OpTypePointer Input %6 - %22 = OpTypeVector %6 2 - %23 = OpTypeStruct %22 - %24 = OpTypePointer Uniform %23 - %25 = OpVariable %24 Uniform - %26 = OpTypeInt 32 1 - %27 = OpConstant %26 0 - %28 = OpTypePointer Uniform %6 - %56 = OpConstant %26 10 - %58 = OpConstant %17 10 - %59 = OpTypeArray %6 %58 - %60 = OpTypePointer Function %59 - %66 = OpTypeStruct %22 - %67 = OpTypePointer Uniform %66 - %68 = OpVariable %67 Uniform - %74 = OpConstant %26 1 - %83 = OpConstant %26 9 - %129 = OpConstant %17 0 - %138 = OpTypePointer Output %14 - %139 = OpVariable %138 Output - %144 = OpConstant %26 5 - %151 = OpConstant %6 1 - %194 = OpConstant %6 0.5 - %195 = OpConstant %6 0.100000001 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %61 = OpVariable %60 Function - OpBranch %50 - %50 = OpLabel - %182 = OpPhi %26 %27 %5 %75 %51 - %57 = OpSLessThan %8 %182 %56 - OpLoopMerge %52 %51 None - OpBranchConditional %57 %51 %52 - %51 = OpLabel - %64 = OpISub %26 %56 %182 - %65 = OpConvertSToF %6 %64 - %69 = OpAccessChain %28 %68 %27 %18 - %70 = OpLoad %6 %69 - %71 = OpFMul %6 %65 %70 - %72 = OpAccessChain %7 %61 %182 - OpStore %72 %71 - %75 = OpIAdd %26 %182 %74 - OpBranch %50 - %52 = OpLabel - OpBranch %77 - %77 = OpLabel - %183 = OpPhi %26 %27 %52 %128 %88 - %84 = OpSLessThan %8 %183 %83 - OpLoopMerge %79 %88 None - OpBranchConditional %84 %78 %79 - %78 = OpLabel - OpBranch %86 - %86 = OpLabel - %184 = OpPhi %26 %27 %78 %126 %89 - %92 = OpSLessThan %8 %184 %56 - OpLoopMerge %1000 %89 None - OpBranchConditional %92 %87 %1000 - %87 = OpLabel - %95 = OpIAdd %26 %183 %74 - %96 = OpSLessThan %8 %184 %95 - OpSelectionMerge %98 None - OpBranchConditional %96 %97 %98 - %97 = OpLabel - OpBranch %89 - %98 = OpLabel - %104 = OpAccessChain %7 %61 %183 - %105 = OpLoad %6 %104 - %107 = OpAccessChain %7 %61 %184 - %108 = OpLoad %6 %107 - %166 = OpAccessChain %19 %16 %18 - %167 = OpLoad %6 %166 - %168 = OpAccessChain %28 %25 %27 %18 - %169 = OpLoad %6 %168 - %170 = OpFMul %6 %169 %194 - %171 = OpFOrdLessThan %8 %167 %170 - OpSelectionMerge %172 None - OpBranchConditional %171 %173 %174 - %173 = OpLabel - %177 = OpFOrdGreaterThan %8 %105 %108 - OpBranch %172 - %174 = OpLabel - %180 = OpFOrdLessThan %8 %105 %108 - OpBranch %172 - %172 = OpLabel - %186 = OpPhi %8 %177 %173 %180 %174 - OpSelectionMerge %112 None - OpBranchConditional %186 %111 %112 - %111 = OpLabel - %116 = OpLoad %6 %104 - %120 = OpLoad %6 %107 - OpStore %104 %120 - OpStore %107 %116 - OpBranch %112 - %112 = OpLabel - OpBranch %89 - %89 = OpLabel - %126 = OpIAdd %26 %184 %74 - OpBranch %86 - %1000 = OpLabel - OpBranch %88 - %88 = OpLabel - %128 = OpIAdd %26 %183 %74 - OpBranch %77 - %79 = OpLabel - %130 = OpAccessChain %19 %16 %129 - %131 = OpLoad %6 %130 - %132 = OpAccessChain %28 %25 %27 %129 - %133 = OpLoad %6 %132 - %134 = OpFMul %6 %133 %194 - %135 = OpFOrdLessThan %8 %131 %134 - OpSelectionMerge %137 None - OpBranchConditional %135 %136 %153 - %136 = OpLabel - %140 = OpAccessChain %7 %61 %27 - %141 = OpLoad %6 %140 - %143 = OpFMul %6 %141 %195 - %145 = OpAccessChain %7 %61 %144 - %146 = OpLoad %6 %145 - %147 = OpFMul %6 %146 %195 - %148 = OpAccessChain %7 %61 %83 - %149 = OpLoad %6 %148 - %150 = OpFMul %6 %149 %195 - %152 = OpCompositeConstruct %14 %143 %147 %150 %151 - OpStore %139 %152 - OpBranch %137 - %153 = OpLabel - %154 = OpAccessChain %7 %61 %144 - %155 = OpLoad %6 %154 - %156 = OpFMul %6 %155 %195 - %157 = OpAccessChain %7 %61 %83 - %158 = OpLoad %6 %157 - %159 = OpFMul %6 %158 %195 - %160 = OpAccessChain %7 %61 %27 - %161 = OpLoad %6 %160 - %162 = OpFMul %6 %161 %195 - %163 = OpCompositeConstruct %14 %156 %159 %162 %151 - OpStore %139 %163 - OpBranch %137 - %137 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Do some fuzzer runs, starting from an initial seed of 10 (seed value chosen - // arbitrarily). - RunFuzzerAndReplayer(shader, protobufs::FactSequence(), 10, kNumFuzzerRuns); -} - -TEST(FuzzerReplayerTest, Miscellaneous3) { - // The SPIR-V came from this GLSL, which was then optimized using spirv-opt - // with the -O argument: - // - // #version 310 es - // - // precision highp float; - // - // layout(location = 0) out vec4 _GLF_color; - // - // layout(set = 0, binding = 0) uniform buf0 { - // vec2 resolution; - // }; - // void main(void) - // { - // float A[50]; - // for( - // int i = 0; - // i < 200; - // i ++ - // ) - // { - // if(i >= int(resolution.x)) - // { - // break; - // } - // if((4 * (i / 4)) == i) - // { - // A[i / 4] = float(i); - // } - // } - // for( - // int i = 0; - // i < 50; - // i ++ - // ) - // { - // if(i < int(gl_FragCoord.x)) - // { - // break; - // } - // if(i > 0) - // { - // A[i] += A[i - 1]; - // } - // } - // if(int(gl_FragCoord.x) < 20) - // { - // _GLF_color = vec4(A[0] / resolution.x, A[4] / resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 40) - // { - // _GLF_color = vec4(A[5] / resolution.x, A[9] / resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 60) - // { - // _GLF_color = vec4(A[10] / resolution.x, A[14] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 80) - // { - // _GLF_color = vec4(A[15] / resolution.x, A[19] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 100) - // { - // _GLF_color = vec4(A[20] / resolution.x, A[24] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 120) - // { - // _GLF_color = vec4(A[25] / resolution.x, A[29] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 140) - // { - // _GLF_color = vec4(A[30] / resolution.x, A[34] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 160) - // { - // _GLF_color = vec4(A[35] / resolution.x, A[39] / - // resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 180) - // { - // _GLF_color = vec4(A[40] / resolution.x, A[44] / - // resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 180) - // { - // _GLF_color = vec4(A[45] / resolution.x, A[49] / - // resolution.y, 1.0, 1.0); - // } - // else - // { - // discard; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %68 %100 %24 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %22 "buf0" - OpMemberName %22 0 "resolution" - OpName %24 "" - OpName %46 "A" - OpName %68 "gl_FragCoord" - OpName %100 "_GLF_color" - OpMemberDecorate %22 0 Offset 0 - OpDecorate %22 Block - OpDecorate %24 DescriptorSet 0 - OpDecorate %24 Binding 0 - OpDecorate %37 RelaxedPrecision - OpDecorate %38 RelaxedPrecision - OpDecorate %55 RelaxedPrecision - OpDecorate %68 BuiltIn FragCoord - OpDecorate %83 RelaxedPrecision - OpDecorate %91 RelaxedPrecision - OpDecorate %100 Location 0 - OpDecorate %302 RelaxedPrecision - OpDecorate %304 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpConstant %6 200 - %17 = OpTypeBool - %20 = OpTypeFloat 32 - %21 = OpTypeVector %20 2 - %22 = OpTypeStruct %21 - %23 = OpTypePointer Uniform %22 - %24 = OpVariable %23 Uniform - %25 = OpTypeInt 32 0 - %26 = OpConstant %25 0 - %27 = OpTypePointer Uniform %20 - %35 = OpConstant %6 4 - %43 = OpConstant %25 50 - %44 = OpTypeArray %20 %43 - %45 = OpTypePointer Function %44 - %51 = OpTypePointer Function %20 - %54 = OpConstant %6 1 - %63 = OpConstant %6 50 - %66 = OpTypeVector %20 4 - %67 = OpTypePointer Input %66 - %68 = OpVariable %67 Input - %69 = OpTypePointer Input %20 - %95 = OpConstant %6 20 - %99 = OpTypePointer Output %66 - %100 = OpVariable %99 Output - %108 = OpConstant %25 1 - %112 = OpConstant %20 1 - %118 = OpConstant %6 40 - %122 = OpConstant %6 5 - %128 = OpConstant %6 9 - %139 = OpConstant %6 60 - %143 = OpConstant %6 10 - %149 = OpConstant %6 14 - %160 = OpConstant %6 80 - %164 = OpConstant %6 15 - %170 = OpConstant %6 19 - %181 = OpConstant %6 100 - %190 = OpConstant %6 24 - %201 = OpConstant %6 120 - %205 = OpConstant %6 25 - %211 = OpConstant %6 29 - %222 = OpConstant %6 140 - %226 = OpConstant %6 30 - %232 = OpConstant %6 34 - %243 = OpConstant %6 160 - %247 = OpConstant %6 35 - %253 = OpConstant %6 39 - %264 = OpConstant %6 180 - %273 = OpConstant %6 44 - %287 = OpConstant %6 45 - %293 = OpConstant %6 49 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %46 = OpVariable %45 Function - OpBranch %10 - %10 = OpLabel - %302 = OpPhi %6 %9 %5 %55 %42 - %18 = OpSLessThan %17 %302 %16 - OpLoopMerge %12 %42 None - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %28 = OpAccessChain %27 %24 %9 %26 - %29 = OpLoad %20 %28 - %30 = OpConvertFToS %6 %29 - %31 = OpSGreaterThanEqual %17 %302 %30 - OpSelectionMerge %33 None - OpBranchConditional %31 %32 %33 - %32 = OpLabel - OpBranch %12 - %33 = OpLabel - %37 = OpSDiv %6 %302 %35 - %38 = OpIMul %6 %35 %37 - %40 = OpIEqual %17 %38 %302 - OpBranchConditional %40 %41 %42 - %41 = OpLabel - %50 = OpConvertSToF %20 %302 - %52 = OpAccessChain %51 %46 %37 - OpStore %52 %50 - OpBranch %42 - %42 = OpLabel - %55 = OpIAdd %6 %302 %54 - OpBranch %10 - %12 = OpLabel - OpBranch %57 - %57 = OpLabel - %304 = OpPhi %6 %9 %12 %91 %80 - %64 = OpSLessThan %17 %304 %63 - OpLoopMerge %59 %80 None - OpBranchConditional %64 %58 %59 - %58 = OpLabel - %70 = OpAccessChain %69 %68 %26 - %71 = OpLoad %20 %70 - %72 = OpConvertFToS %6 %71 - %73 = OpSLessThan %17 %304 %72 - OpSelectionMerge %75 None - OpBranchConditional %73 %74 %75 - %74 = OpLabel - OpBranch %59 - %75 = OpLabel - %78 = OpSGreaterThan %17 %304 %9 - OpBranchConditional %78 %79 %80 - %79 = OpLabel - %83 = OpISub %6 %304 %54 - %84 = OpAccessChain %51 %46 %83 - %85 = OpLoad %20 %84 - %86 = OpAccessChain %51 %46 %304 - %87 = OpLoad %20 %86 - %88 = OpFAdd %20 %87 %85 - OpStore %86 %88 - OpBranch %80 - %80 = OpLabel - %91 = OpIAdd %6 %304 %54 - OpBranch %57 - %59 = OpLabel - %92 = OpAccessChain %69 %68 %26 - %93 = OpLoad %20 %92 - %94 = OpConvertFToS %6 %93 - %96 = OpSLessThan %17 %94 %95 - OpSelectionMerge %98 None - OpBranchConditional %96 %97 %114 - %97 = OpLabel - %101 = OpAccessChain %51 %46 %9 - %102 = OpLoad %20 %101 - %103 = OpAccessChain %27 %24 %9 %26 - %104 = OpLoad %20 %103 - %105 = OpFDiv %20 %102 %104 - %106 = OpAccessChain %51 %46 %35 - %107 = OpLoad %20 %106 - %109 = OpAccessChain %27 %24 %9 %108 - %110 = OpLoad %20 %109 - %111 = OpFDiv %20 %107 %110 - %113 = OpCompositeConstruct %66 %105 %111 %112 %112 - OpStore %100 %113 - OpBranch %98 - %114 = OpLabel - %119 = OpSLessThan %17 %94 %118 - OpSelectionMerge %121 None - OpBranchConditional %119 %120 %135 - %120 = OpLabel - %123 = OpAccessChain %51 %46 %122 - %124 = OpLoad %20 %123 - %125 = OpAccessChain %27 %24 %9 %26 - %126 = OpLoad %20 %125 - %127 = OpFDiv %20 %124 %126 - %129 = OpAccessChain %51 %46 %128 - %130 = OpLoad %20 %129 - %131 = OpAccessChain %27 %24 %9 %108 - %132 = OpLoad %20 %131 - %133 = OpFDiv %20 %130 %132 - %134 = OpCompositeConstruct %66 %127 %133 %112 %112 - OpStore %100 %134 - OpBranch %121 - %135 = OpLabel - %140 = OpSLessThan %17 %94 %139 - OpSelectionMerge %142 None - OpBranchConditional %140 %141 %156 - %141 = OpLabel - %144 = OpAccessChain %51 %46 %143 - %145 = OpLoad %20 %144 - %146 = OpAccessChain %27 %24 %9 %26 - %147 = OpLoad %20 %146 - %148 = OpFDiv %20 %145 %147 - %150 = OpAccessChain %51 %46 %149 - %151 = OpLoad %20 %150 - %152 = OpAccessChain %27 %24 %9 %108 - %153 = OpLoad %20 %152 - %154 = OpFDiv %20 %151 %153 - %155 = OpCompositeConstruct %66 %148 %154 %112 %112 - OpStore %100 %155 - OpBranch %142 - %156 = OpLabel - %161 = OpSLessThan %17 %94 %160 - OpSelectionMerge %163 None - OpBranchConditional %161 %162 %177 - %162 = OpLabel - %165 = OpAccessChain %51 %46 %164 - %166 = OpLoad %20 %165 - %167 = OpAccessChain %27 %24 %9 %26 - %168 = OpLoad %20 %167 - %169 = OpFDiv %20 %166 %168 - %171 = OpAccessChain %51 %46 %170 - %172 = OpLoad %20 %171 - %173 = OpAccessChain %27 %24 %9 %108 - %174 = OpLoad %20 %173 - %175 = OpFDiv %20 %172 %174 - %176 = OpCompositeConstruct %66 %169 %175 %112 %112 - OpStore %100 %176 - OpBranch %163 - %177 = OpLabel - %182 = OpSLessThan %17 %94 %181 - OpSelectionMerge %184 None - OpBranchConditional %182 %183 %197 - %183 = OpLabel - %185 = OpAccessChain %51 %46 %95 - %186 = OpLoad %20 %185 - %187 = OpAccessChain %27 %24 %9 %26 - %188 = OpLoad %20 %187 - %189 = OpFDiv %20 %186 %188 - %191 = OpAccessChain %51 %46 %190 - %192 = OpLoad %20 %191 - %193 = OpAccessChain %27 %24 %9 %108 - %194 = OpLoad %20 %193 - %195 = OpFDiv %20 %192 %194 - %196 = OpCompositeConstruct %66 %189 %195 %112 %112 - OpStore %100 %196 - OpBranch %184 - %197 = OpLabel - %202 = OpSLessThan %17 %94 %201 - OpSelectionMerge %204 None - OpBranchConditional %202 %203 %218 - %203 = OpLabel - %206 = OpAccessChain %51 %46 %205 - %207 = OpLoad %20 %206 - %208 = OpAccessChain %27 %24 %9 %26 - %209 = OpLoad %20 %208 - %210 = OpFDiv %20 %207 %209 - %212 = OpAccessChain %51 %46 %211 - %213 = OpLoad %20 %212 - %214 = OpAccessChain %27 %24 %9 %108 - %215 = OpLoad %20 %214 - %216 = OpFDiv %20 %213 %215 - %217 = OpCompositeConstruct %66 %210 %216 %112 %112 - OpStore %100 %217 - OpBranch %204 - %218 = OpLabel - %223 = OpSLessThan %17 %94 %222 - OpSelectionMerge %225 None - OpBranchConditional %223 %224 %239 - %224 = OpLabel - %227 = OpAccessChain %51 %46 %226 - %228 = OpLoad %20 %227 - %229 = OpAccessChain %27 %24 %9 %26 - %230 = OpLoad %20 %229 - %231 = OpFDiv %20 %228 %230 - %233 = OpAccessChain %51 %46 %232 - %234 = OpLoad %20 %233 - %235 = OpAccessChain %27 %24 %9 %108 - %236 = OpLoad %20 %235 - %237 = OpFDiv %20 %234 %236 - %238 = OpCompositeConstruct %66 %231 %237 %112 %112 - OpStore %100 %238 - OpBranch %225 - %239 = OpLabel - %244 = OpSLessThan %17 %94 %243 - OpSelectionMerge %246 None - OpBranchConditional %244 %245 %260 - %245 = OpLabel - %248 = OpAccessChain %51 %46 %247 - %249 = OpLoad %20 %248 - %250 = OpAccessChain %27 %24 %9 %26 - %251 = OpLoad %20 %250 - %252 = OpFDiv %20 %249 %251 - %254 = OpAccessChain %51 %46 %253 - %255 = OpLoad %20 %254 - %256 = OpAccessChain %27 %24 %9 %108 - %257 = OpLoad %20 %256 - %258 = OpFDiv %20 %255 %257 - %259 = OpCompositeConstruct %66 %252 %258 %112 %112 - OpStore %100 %259 - OpBranch %246 - %260 = OpLabel - %265 = OpSLessThan %17 %94 %264 - OpSelectionMerge %267 None - OpBranchConditional %265 %266 %280 - %266 = OpLabel - %268 = OpAccessChain %51 %46 %118 - %269 = OpLoad %20 %268 - %270 = OpAccessChain %27 %24 %9 %26 - %271 = OpLoad %20 %270 - %272 = OpFDiv %20 %269 %271 - %274 = OpAccessChain %51 %46 %273 - %275 = OpLoad %20 %274 - %276 = OpAccessChain %27 %24 %9 %108 - %277 = OpLoad %20 %276 - %278 = OpFDiv %20 %275 %277 - %279 = OpCompositeConstruct %66 %272 %278 %112 %112 - OpStore %100 %279 - OpBranch %267 - %280 = OpLabel - OpSelectionMerge %285 None - OpBranchConditional %265 %285 %300 - %285 = OpLabel - %288 = OpAccessChain %51 %46 %287 - %289 = OpLoad %20 %288 - %290 = OpAccessChain %27 %24 %9 %26 - %291 = OpLoad %20 %290 - %292 = OpFDiv %20 %289 %291 - %294 = OpAccessChain %51 %46 %293 - %295 = OpLoad %20 %294 - %296 = OpAccessChain %27 %24 %9 %108 - %297 = OpLoad %20 %296 - %298 = OpFDiv %20 %295 %297 - %299 = OpCompositeConstruct %66 %292 %298 %112 %112 - OpStore %100 %299 - OpBranch %267 - %300 = OpLabel - OpKill - %267 = OpLabel - OpBranch %246 - %246 = OpLabel - OpBranch %225 - %225 = OpLabel - OpBranch %204 - %204 = OpLabel - OpBranch %184 - %184 = OpLabel - OpBranch %163 - %163 = OpLabel - OpBranch %142 - %142 = OpLabel - OpBranch %121 - %121 = OpLabel - OpBranch %98 - %98 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Add the facts "resolution.x == 250" and "resolution.y == 100". - protobufs::FactSequence facts; - AddConstantUniformFact(&facts, 0, 0, {0, 0}, 250); - AddConstantUniformFact(&facts, 0, 0, {0, 1}, 100); - - // Do some fuzzer runs, starting from an initial seed of 94 (seed value chosen - // arbitrarily). - RunFuzzerAndReplayer(shader, facts, 94, kNumFuzzerRuns); -} - -TEST(FuzzerReplayerTest, Miscellaneous4) { - // The SPIR-V comes from the 'matrices_smart_loops' GLSL shader that ships - // with GraphicsFuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %327 %363 %65 %70 %80 %90 %99 %108 %117 %126 %135 %144 %333 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "matrix_number" - OpName %12 "cols" - OpName %23 "rows" - OpName %31 "c" - OpName %41 "r" - OpName %65 "m22" - OpName %68 "buf0" - OpMemberName %68 0 "one" - OpName %70 "" - OpName %80 "m23" - OpName %90 "m24" - OpName %99 "m32" - OpName %108 "m33" - OpName %117 "m34" - OpName %126 "m42" - OpName %135 "m43" - OpName %144 "m44" - OpName %164 "sum_index" - OpName %165 "cols" - OpName %173 "rows" - OpName %184 "sums" - OpName %189 "c" - OpName %198 "r" - OpName %325 "region_x" - OpName %327 "gl_FragCoord" - OpName %331 "buf1" - OpMemberName %331 0 "resolution" - OpName %333 "" - OpName %340 "region_y" - OpName %348 "overall_region" - OpName %363 "_GLF_color" - OpDecorate %8 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %19 RelaxedPrecision - OpDecorate %23 RelaxedPrecision - OpDecorate %29 RelaxedPrecision - OpDecorate %31 RelaxedPrecision - OpDecorate %38 RelaxedPrecision - OpDecorate %39 RelaxedPrecision - OpDecorate %41 RelaxedPrecision - OpDecorate %47 RelaxedPrecision - OpDecorate %48 RelaxedPrecision - OpDecorate %50 RelaxedPrecision - OpDecorate %66 RelaxedPrecision - OpDecorate %67 RelaxedPrecision - OpMemberDecorate %68 0 Offset 0 - OpDecorate %68 Block - OpDecorate %70 DescriptorSet 0 - OpDecorate %70 Binding 0 - OpDecorate %81 RelaxedPrecision - OpDecorate %82 RelaxedPrecision - OpDecorate %91 RelaxedPrecision - OpDecorate %92 RelaxedPrecision - OpDecorate %100 RelaxedPrecision - OpDecorate %101 RelaxedPrecision - OpDecorate %109 RelaxedPrecision - OpDecorate %110 RelaxedPrecision - OpDecorate %118 RelaxedPrecision - OpDecorate %119 RelaxedPrecision - OpDecorate %127 RelaxedPrecision - OpDecorate %128 RelaxedPrecision - OpDecorate %136 RelaxedPrecision - OpDecorate %137 RelaxedPrecision - OpDecorate %145 RelaxedPrecision - OpDecorate %146 RelaxedPrecision - OpDecorate %152 RelaxedPrecision - OpDecorate %154 RelaxedPrecision - OpDecorate %155 RelaxedPrecision - OpDecorate %156 RelaxedPrecision - OpDecorate %157 RelaxedPrecision - OpDecorate %159 RelaxedPrecision - OpDecorate %160 RelaxedPrecision - OpDecorate %161 RelaxedPrecision - OpDecorate %162 RelaxedPrecision - OpDecorate %163 RelaxedPrecision - OpDecorate %164 RelaxedPrecision - OpDecorate %165 RelaxedPrecision - OpDecorate %171 RelaxedPrecision - OpDecorate %173 RelaxedPrecision - OpDecorate %179 RelaxedPrecision - OpDecorate %185 RelaxedPrecision - OpDecorate %189 RelaxedPrecision - OpDecorate %195 RelaxedPrecision - OpDecorate %196 RelaxedPrecision - OpDecorate %198 RelaxedPrecision - OpDecorate %204 RelaxedPrecision - OpDecorate %205 RelaxedPrecision - OpDecorate %207 RelaxedPrecision - OpDecorate %218 RelaxedPrecision - OpDecorate %219 RelaxedPrecision - OpDecorate %220 RelaxedPrecision - OpDecorate %228 RelaxedPrecision - OpDecorate %229 RelaxedPrecision - OpDecorate %230 RelaxedPrecision - OpDecorate %238 RelaxedPrecision - OpDecorate %239 RelaxedPrecision - OpDecorate %240 RelaxedPrecision - OpDecorate %248 RelaxedPrecision - OpDecorate %249 RelaxedPrecision - OpDecorate %250 RelaxedPrecision - OpDecorate %258 RelaxedPrecision - OpDecorate %259 RelaxedPrecision - OpDecorate %260 RelaxedPrecision - OpDecorate %268 RelaxedPrecision - OpDecorate %269 RelaxedPrecision - OpDecorate %270 RelaxedPrecision - OpDecorate %278 RelaxedPrecision - OpDecorate %279 RelaxedPrecision - OpDecorate %280 RelaxedPrecision - OpDecorate %288 RelaxedPrecision - OpDecorate %289 RelaxedPrecision - OpDecorate %290 RelaxedPrecision - OpDecorate %298 RelaxedPrecision - OpDecorate %299 RelaxedPrecision - OpDecorate %300 RelaxedPrecision - OpDecorate %309 RelaxedPrecision - OpDecorate %310 RelaxedPrecision - OpDecorate %311 RelaxedPrecision - OpDecorate %312 RelaxedPrecision - OpDecorate %313 RelaxedPrecision - OpDecorate %319 RelaxedPrecision - OpDecorate %320 RelaxedPrecision - OpDecorate %321 RelaxedPrecision - OpDecorate %322 RelaxedPrecision - OpDecorate %323 RelaxedPrecision - OpDecorate %324 RelaxedPrecision - OpDecorate %325 RelaxedPrecision - OpDecorate %327 BuiltIn FragCoord - OpMemberDecorate %331 0 Offset 0 - OpDecorate %331 Block - OpDecorate %333 DescriptorSet 0 - OpDecorate %333 Binding 1 - OpDecorate %339 RelaxedPrecision - OpDecorate %340 RelaxedPrecision - OpDecorate %347 RelaxedPrecision - OpDecorate %348 RelaxedPrecision - OpDecorate %349 RelaxedPrecision - OpDecorate %351 RelaxedPrecision - OpDecorate %352 RelaxedPrecision - OpDecorate %353 RelaxedPrecision - OpDecorate %354 RelaxedPrecision - OpDecorate %356 RelaxedPrecision - OpDecorate %363 Location 0 - OpDecorate %364 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 0 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 2 - %20 = OpConstant %10 4 - %21 = OpTypeBool - %32 = OpConstant %10 0 - %61 = OpTypeFloat 32 - %62 = OpTypeVector %61 2 - %63 = OpTypeMatrix %62 2 - %64 = OpTypePointer Private %63 - %65 = OpVariable %64 Private - %68 = OpTypeStruct %61 - %69 = OpTypePointer Uniform %68 - %70 = OpVariable %69 Uniform - %71 = OpTypePointer Uniform %61 - %74 = OpTypePointer Private %61 - %77 = OpTypeVector %61 3 - %78 = OpTypeMatrix %77 2 - %79 = OpTypePointer Private %78 - %80 = OpVariable %79 Private - %87 = OpTypeVector %61 4 - %88 = OpTypeMatrix %87 2 - %89 = OpTypePointer Private %88 - %90 = OpVariable %89 Private - %97 = OpTypeMatrix %62 3 - %98 = OpTypePointer Private %97 - %99 = OpVariable %98 Private - %106 = OpTypeMatrix %77 3 - %107 = OpTypePointer Private %106 - %108 = OpVariable %107 Private - %115 = OpTypeMatrix %87 3 - %116 = OpTypePointer Private %115 - %117 = OpVariable %116 Private - %124 = OpTypeMatrix %62 4 - %125 = OpTypePointer Private %124 - %126 = OpVariable %125 Private - %133 = OpTypeMatrix %77 4 - %134 = OpTypePointer Private %133 - %135 = OpVariable %134 Private - %142 = OpTypeMatrix %87 4 - %143 = OpTypePointer Private %142 - %144 = OpVariable %143 Private - %153 = OpConstant %10 1 - %158 = OpConstant %6 1 - %181 = OpConstant %6 9 - %182 = OpTypeArray %61 %181 - %183 = OpTypePointer Function %182 - %186 = OpConstant %61 0 - %187 = OpTypePointer Function %61 - %314 = OpConstant %61 16 - %326 = OpTypePointer Input %87 - %327 = OpVariable %326 Input - %328 = OpTypePointer Input %61 - %331 = OpTypeStruct %62 - %332 = OpTypePointer Uniform %331 - %333 = OpVariable %332 Uniform - %336 = OpConstant %61 3 - %350 = OpConstant %10 3 - %357 = OpConstant %10 9 - %362 = OpTypePointer Output %87 - %363 = OpVariable %362 Output - %368 = OpConstant %61 1 - %374 = OpConstantComposite %87 %186 %186 %186 %368 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %23 = OpVariable %11 Function - %31 = OpVariable %11 Function - %41 = OpVariable %11 Function - %164 = OpVariable %11 Function - %165 = OpVariable %11 Function - %173 = OpVariable %11 Function - %184 = OpVariable %183 Function - %189 = OpVariable %11 Function - %198 = OpVariable %11 Function - %325 = OpVariable %11 Function - %340 = OpVariable %11 Function - %348 = OpVariable %11 Function - OpStore %8 %9 - OpStore %12 %13 - OpBranch %14 - %14 = OpLabel - OpLoopMerge %16 %17 None - OpBranch %18 - %18 = OpLabel - %19 = OpLoad %10 %12 - %22 = OpSLessThanEqual %21 %19 %20 - OpBranchConditional %22 %15 %16 - %15 = OpLabel - OpStore %23 %13 - OpBranch %24 - %24 = OpLabel - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %29 = OpLoad %10 %23 - %30 = OpSLessThanEqual %21 %29 %20 - OpBranchConditional %30 %25 %26 - %25 = OpLabel - OpStore %31 %32 - OpBranch %33 - %33 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpLoad %10 %31 - %39 = OpLoad %10 %12 - %40 = OpSLessThan %21 %38 %39 - OpBranchConditional %40 %34 %35 - %34 = OpLabel - OpStore %41 %32 - OpBranch %42 - %42 = OpLabel - OpLoopMerge %44 %45 None - OpBranch %46 - %46 = OpLabel - %47 = OpLoad %10 %41 - %48 = OpLoad %10 %23 - %49 = OpSLessThan %21 %47 %48 - OpBranchConditional %49 %43 %44 - %43 = OpLabel - %50 = OpLoad %6 %8 - OpSelectionMerge %60 None - OpSwitch %50 %60 0 %51 1 %52 2 %53 3 %54 4 %55 5 %56 6 %57 7 %58 8 %59 - %51 = OpLabel - %66 = OpLoad %10 %31 - %67 = OpLoad %10 %41 - %72 = OpAccessChain %71 %70 %32 - %73 = OpLoad %61 %72 - %75 = OpAccessChain %74 %65 %66 %67 - OpStore %75 %73 - OpBranch %60 - %52 = OpLabel - %81 = OpLoad %10 %31 - %82 = OpLoad %10 %41 - %83 = OpAccessChain %71 %70 %32 - %84 = OpLoad %61 %83 - %85 = OpAccessChain %74 %80 %81 %82 - OpStore %85 %84 - OpBranch %60 - %53 = OpLabel - %91 = OpLoad %10 %31 - %92 = OpLoad %10 %41 - %93 = OpAccessChain %71 %70 %32 - %94 = OpLoad %61 %93 - %95 = OpAccessChain %74 %90 %91 %92 - OpStore %95 %94 - OpBranch %60 - %54 = OpLabel - %100 = OpLoad %10 %31 - %101 = OpLoad %10 %41 - %102 = OpAccessChain %71 %70 %32 - %103 = OpLoad %61 %102 - %104 = OpAccessChain %74 %99 %100 %101 - OpStore %104 %103 - OpBranch %60 - %55 = OpLabel - %109 = OpLoad %10 %31 - %110 = OpLoad %10 %41 - %111 = OpAccessChain %71 %70 %32 - %112 = OpLoad %61 %111 - %113 = OpAccessChain %74 %108 %109 %110 - OpStore %113 %112 - OpBranch %60 - %56 = OpLabel - %118 = OpLoad %10 %31 - %119 = OpLoad %10 %41 - %120 = OpAccessChain %71 %70 %32 - %121 = OpLoad %61 %120 - %122 = OpAccessChain %74 %117 %118 %119 - OpStore %122 %121 - OpBranch %60 - %57 = OpLabel - %127 = OpLoad %10 %31 - %128 = OpLoad %10 %41 - %129 = OpAccessChain %71 %70 %32 - %130 = OpLoad %61 %129 - %131 = OpAccessChain %74 %126 %127 %128 - OpStore %131 %130 - OpBranch %60 - %58 = OpLabel - %136 = OpLoad %10 %31 - %137 = OpLoad %10 %41 - %138 = OpAccessChain %71 %70 %32 - %139 = OpLoad %61 %138 - %140 = OpAccessChain %74 %135 %136 %137 - OpStore %140 %139 - OpBranch %60 - %59 = OpLabel - %145 = OpLoad %10 %31 - %146 = OpLoad %10 %41 - %147 = OpAccessChain %71 %70 %32 - %148 = OpLoad %61 %147 - %149 = OpAccessChain %74 %144 %145 %146 - OpStore %149 %148 - OpBranch %60 - %60 = OpLabel - OpBranch %45 - %45 = OpLabel - %152 = OpLoad %10 %41 - %154 = OpIAdd %10 %152 %153 - OpStore %41 %154 - OpBranch %42 - %44 = OpLabel - OpBranch %36 - %36 = OpLabel - %155 = OpLoad %10 %31 - %156 = OpIAdd %10 %155 %153 - OpStore %31 %156 - OpBranch %33 - %35 = OpLabel - %157 = OpLoad %6 %8 - %159 = OpIAdd %6 %157 %158 - OpStore %8 %159 - OpBranch %27 - %27 = OpLabel - %160 = OpLoad %10 %23 - %161 = OpIAdd %10 %160 %153 - OpStore %23 %161 - OpBranch %24 - %26 = OpLabel - OpBranch %17 - %17 = OpLabel - %162 = OpLoad %10 %12 - %163 = OpIAdd %10 %162 %153 - OpStore %12 %163 - OpBranch %14 - %16 = OpLabel - OpStore %164 %32 - OpStore %165 %13 - OpBranch %166 - %166 = OpLabel - OpLoopMerge %168 %169 None - OpBranch %170 - %170 = OpLabel - %171 = OpLoad %10 %165 - %172 = OpSLessThanEqual %21 %171 %20 - OpBranchConditional %172 %167 %168 - %167 = OpLabel - OpStore %173 %13 - OpBranch %174 - %174 = OpLabel - OpLoopMerge %176 %177 None - OpBranch %178 - %178 = OpLabel - %179 = OpLoad %10 %173 - %180 = OpSLessThanEqual %21 %179 %20 - OpBranchConditional %180 %175 %176 - %175 = OpLabel - %185 = OpLoad %10 %164 - %188 = OpAccessChain %187 %184 %185 - OpStore %188 %186 - OpStore %189 %32 - OpBranch %190 - %190 = OpLabel - OpLoopMerge %192 %193 None - OpBranch %194 - %194 = OpLabel - %195 = OpLoad %10 %189 - %196 = OpLoad %10 %165 - %197 = OpSLessThan %21 %195 %196 - OpBranchConditional %197 %191 %192 - %191 = OpLabel - OpStore %198 %32 - OpBranch %199 - %199 = OpLabel - OpLoopMerge %201 %202 None - OpBranch %203 - %203 = OpLabel - %204 = OpLoad %10 %198 - %205 = OpLoad %10 %173 - %206 = OpSLessThan %21 %204 %205 - OpBranchConditional %206 %200 %201 - %200 = OpLabel - %207 = OpLoad %10 %164 - OpSelectionMerge %217 None - OpSwitch %207 %217 0 %208 1 %209 2 %210 3 %211 4 %212 5 %213 6 %214 7 %215 8 %216 - %208 = OpLabel - %218 = OpLoad %10 %164 - %219 = OpLoad %10 %189 - %220 = OpLoad %10 %198 - %221 = OpAccessChain %74 %65 %219 %220 - %222 = OpLoad %61 %221 - %223 = OpAccessChain %187 %184 %218 - %224 = OpLoad %61 %223 - %225 = OpFAdd %61 %224 %222 - %226 = OpAccessChain %187 %184 %218 - OpStore %226 %225 - OpBranch %217 - %209 = OpLabel - %228 = OpLoad %10 %164 - %229 = OpLoad %10 %189 - %230 = OpLoad %10 %198 - %231 = OpAccessChain %74 %80 %229 %230 - %232 = OpLoad %61 %231 - %233 = OpAccessChain %187 %184 %228 - %234 = OpLoad %61 %233 - %235 = OpFAdd %61 %234 %232 - %236 = OpAccessChain %187 %184 %228 - OpStore %236 %235 - OpBranch %217 - %210 = OpLabel - %238 = OpLoad %10 %164 - %239 = OpLoad %10 %189 - %240 = OpLoad %10 %198 - %241 = OpAccessChain %74 %90 %239 %240 - %242 = OpLoad %61 %241 - %243 = OpAccessChain %187 %184 %238 - %244 = OpLoad %61 %243 - %245 = OpFAdd %61 %244 %242 - %246 = OpAccessChain %187 %184 %238 - OpStore %246 %245 - OpBranch %217 - %211 = OpLabel - %248 = OpLoad %10 %164 - %249 = OpLoad %10 %189 - %250 = OpLoad %10 %198 - %251 = OpAccessChain %74 %99 %249 %250 - %252 = OpLoad %61 %251 - %253 = OpAccessChain %187 %184 %248 - %254 = OpLoad %61 %253 - %255 = OpFAdd %61 %254 %252 - %256 = OpAccessChain %187 %184 %248 - OpStore %256 %255 - OpBranch %217 - %212 = OpLabel - %258 = OpLoad %10 %164 - %259 = OpLoad %10 %189 - %260 = OpLoad %10 %198 - %261 = OpAccessChain %74 %108 %259 %260 - %262 = OpLoad %61 %261 - %263 = OpAccessChain %187 %184 %258 - %264 = OpLoad %61 %263 - %265 = OpFAdd %61 %264 %262 - %266 = OpAccessChain %187 %184 %258 - OpStore %266 %265 - OpBranch %217 - %213 = OpLabel - %268 = OpLoad %10 %164 - %269 = OpLoad %10 %189 - %270 = OpLoad %10 %198 - %271 = OpAccessChain %74 %117 %269 %270 - %272 = OpLoad %61 %271 - %273 = OpAccessChain %187 %184 %268 - %274 = OpLoad %61 %273 - %275 = OpFAdd %61 %274 %272 - %276 = OpAccessChain %187 %184 %268 - OpStore %276 %275 - OpBranch %217 - %214 = OpLabel - %278 = OpLoad %10 %164 - %279 = OpLoad %10 %189 - %280 = OpLoad %10 %198 - %281 = OpAccessChain %74 %126 %279 %280 - %282 = OpLoad %61 %281 - %283 = OpAccessChain %187 %184 %278 - %284 = OpLoad %61 %283 - %285 = OpFAdd %61 %284 %282 - %286 = OpAccessChain %187 %184 %278 - OpStore %286 %285 - OpBranch %217 - %215 = OpLabel - %288 = OpLoad %10 %164 - %289 = OpLoad %10 %189 - %290 = OpLoad %10 %198 - %291 = OpAccessChain %74 %135 %289 %290 - %292 = OpLoad %61 %291 - %293 = OpAccessChain %187 %184 %288 - %294 = OpLoad %61 %293 - %295 = OpFAdd %61 %294 %292 - %296 = OpAccessChain %187 %184 %288 - OpStore %296 %295 - OpBranch %217 - %216 = OpLabel - %298 = OpLoad %10 %164 - %299 = OpLoad %10 %189 - %300 = OpLoad %10 %198 - %301 = OpAccessChain %74 %144 %299 %300 - %302 = OpLoad %61 %301 - %303 = OpAccessChain %187 %184 %298 - %304 = OpLoad %61 %303 - %305 = OpFAdd %61 %304 %302 - %306 = OpAccessChain %187 %184 %298 - OpStore %306 %305 - OpBranch %217 - %217 = OpLabel - OpBranch %202 - %202 = OpLabel - %309 = OpLoad %10 %198 - %310 = OpIAdd %10 %309 %153 - OpStore %198 %310 - OpBranch %199 - %201 = OpLabel - OpBranch %193 - %193 = OpLabel - %311 = OpLoad %10 %189 - %312 = OpIAdd %10 %311 %153 - OpStore %189 %312 - OpBranch %190 - %192 = OpLabel - %313 = OpLoad %10 %164 - %315 = OpAccessChain %187 %184 %313 - %316 = OpLoad %61 %315 - %317 = OpFDiv %61 %316 %314 - %318 = OpAccessChain %187 %184 %313 - OpStore %318 %317 - %319 = OpLoad %10 %164 - %320 = OpIAdd %10 %319 %153 - OpStore %164 %320 - OpBranch %177 - %177 = OpLabel - %321 = OpLoad %10 %173 - %322 = OpIAdd %10 %321 %153 - OpStore %173 %322 - OpBranch %174 - %176 = OpLabel - OpBranch %169 - %169 = OpLabel - %323 = OpLoad %10 %165 - %324 = OpIAdd %10 %323 %153 - OpStore %165 %324 - OpBranch %166 - %168 = OpLabel - %329 = OpAccessChain %328 %327 %9 - %330 = OpLoad %61 %329 - %334 = OpAccessChain %71 %333 %32 %9 - %335 = OpLoad %61 %334 - %337 = OpFDiv %61 %335 %336 - %338 = OpFDiv %61 %330 %337 - %339 = OpConvertFToS %10 %338 - OpStore %325 %339 - %341 = OpAccessChain %328 %327 %158 - %342 = OpLoad %61 %341 - %343 = OpAccessChain %71 %333 %32 %9 - %344 = OpLoad %61 %343 - %345 = OpFDiv %61 %344 %336 - %346 = OpFDiv %61 %342 %345 - %347 = OpConvertFToS %10 %346 - OpStore %340 %347 - %349 = OpLoad %10 %340 - %351 = OpIMul %10 %349 %350 - %352 = OpLoad %10 %325 - %353 = OpIAdd %10 %351 %352 - OpStore %348 %353 - %354 = OpLoad %10 %348 - %355 = OpSGreaterThan %21 %354 %32 - %356 = OpLoad %10 %348 - %358 = OpSLessThan %21 %356 %357 - %359 = OpLogicalAnd %21 %355 %358 - OpSelectionMerge %361 None - OpBranchConditional %359 %360 %373 - %360 = OpLabel - %364 = OpLoad %10 %348 - %365 = OpAccessChain %187 %184 %364 - %366 = OpLoad %61 %365 - %367 = OpCompositeConstruct %77 %366 %366 %366 - %369 = OpCompositeExtract %61 %367 0 - %370 = OpCompositeExtract %61 %367 1 - %371 = OpCompositeExtract %61 %367 2 - %372 = OpCompositeConstruct %87 %369 %370 %371 %368 - OpStore %363 %372 - OpBranch %361 - %373 = OpLabel - OpStore %363 %374 - OpBranch %361 - %361 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Add the facts: - // - "one == 1.0" - // - "resolution.y == 256.0", - protobufs::FactSequence facts; - AddConstantUniformFact(&facts, 0, 0, {0}, FloatBitsAsUint(1.0)); - AddConstantUniformFact(&facts, 0, 1, {0, 0}, FloatBitsAsUint(256.0)); - AddConstantUniformFact(&facts, 0, 1, {0, 1}, FloatBitsAsUint(256.0)); - - // Do some fuzzer runs, starting from an initial seed of 14 (seed value chosen - // arbitrarily). - RunFuzzerAndReplayer(shader, facts, 14, kNumFuzzerRuns); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/fuzzer_shrinker_test.cpp b/3rdparty/spirv-tools/test/fuzz/fuzzer_shrinker_test.cpp deleted file mode 100644 index 9af863e24..000000000 --- a/3rdparty/spirv-tools/test/fuzz/fuzzer_shrinker_test.cpp +++ /dev/null @@ -1,1107 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/fuzzer.h" -#include "source/fuzz/pseudo_random_generator.h" -#include "source/fuzz/shrinker.h" -#include "source/fuzz/uniform_buffer_element_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -// Abstract class exposing an interestingness function as a virtual method. -class InterestingnessTest { - public: - virtual ~InterestingnessTest() = default; - - // Abstract method that subclasses should implement for specific notions of - // interestingness. Its signature matches Shrinker::InterestingnessFunction. - // Argument |binary| is the SPIR-V binary to be checked; |counter| is used for - // debugging purposes. - virtual bool Interesting(const std::vector& binary, - uint32_t counter) = 0; - - // Yields the Interesting instance method wrapped in a function object. - Shrinker::InterestingnessFunction AsFunction() { - return std::bind(&InterestingnessTest::Interesting, this, - std::placeholders::_1, std::placeholders::_2); - } -}; - -// A test that says all binaries are interesting. -class AlwaysInteresting : public InterestingnessTest { - public: - bool Interesting(const std::vector&, uint32_t) override { - return true; - } -}; - -// A test that says a binary is interesting first time round, and uninteresting -// thereafter. -class OnlyInterestingFirstTime : public InterestingnessTest { - public: - explicit OnlyInterestingFirstTime() : first_time_(true) {} - - bool Interesting(const std::vector&, uint32_t) override { - if (first_time_) { - first_time_ = false; - return true; - } - return false; - } - - private: - bool first_time_; -}; - -// A test that says a binary is interesting first time round, after which -// interestingness ping pongs between false and true. -class PingPong : public InterestingnessTest { - public: - explicit PingPong() : interesting_(false) {} - - bool Interesting(const std::vector&, uint32_t) override { - interesting_ = !interesting_; - return interesting_; - } - - private: - bool interesting_; -}; - -// A test that says a binary is interesting first time round, thereafter -// decides at random whether it is interesting. This allows the logic of the -// shrinker to be exercised quite a bit. -class InterestingThenRandom : public InterestingnessTest { - public: - InterestingThenRandom(const PseudoRandomGenerator& random_generator) - : first_time_(true), random_generator_(random_generator) {} - - bool Interesting(const std::vector&, uint32_t) override { - if (first_time_) { - first_time_ = false; - return true; - } - return random_generator_.RandomBool(); - } - - private: - bool first_time_; - PseudoRandomGenerator random_generator_; -}; - -// |binary_in| and |initial_facts| are a SPIR-V binary and sequence of facts to -// which |transformation_sequence_in| can be applied. Shrinking of -// |transformation_sequence_in| gets performed with respect to -// |interestingness_function|. If |expected_binary_out| is non-empty, it must -// match the binary obtained by applying the final shrunk set of -// transformations, in which case the number of such transformations should -// equal |expected_transformations_out_size|. -// -// The |step_limit| parameter restricts the number of steps that the shrinker -// will try; it can be set to something small for a faster (but less thorough) -// test. -void RunAndCheckShrinker( - const spv_target_env& target_env, const std::vector& binary_in, - const protobufs::FactSequence& initial_facts, - const protobufs::TransformationSequence& transformation_sequence_in, - const Shrinker::InterestingnessFunction& interestingness_function, - const std::vector& expected_binary_out, - uint32_t expected_transformations_out_size, uint32_t step_limit) { - // Run the shrinker. - Shrinker shrinker(target_env, step_limit, false); - shrinker.SetMessageConsumer(kSilentConsumer); - - std::vector binary_out; - protobufs::TransformationSequence transformations_out; - Shrinker::ShrinkerResultStatus shrinker_result_status = - shrinker.Run(binary_in, initial_facts, transformation_sequence_in, - interestingness_function, &binary_out, &transformations_out); - ASSERT_TRUE(Shrinker::ShrinkerResultStatus::kComplete == - shrinker_result_status || - Shrinker::ShrinkerResultStatus::kStepLimitReached == - shrinker_result_status); - - // If a non-empty expected binary was provided, check that it matches the - // result of shrinking and that the expected number of transformations remain. - if (!expected_binary_out.empty()) { - ASSERT_EQ(expected_binary_out, binary_out); - ASSERT_EQ(expected_transformations_out_size, - static_cast(transformations_out.transformation_size())); - } -} - -// Assembles the given |shader| text, and then: -// - Runs the fuzzer with |seed| to yield a set of transformations -// - Shrinks the transformation with various interestingness functions, -// asserting some properties about the result each time -void RunFuzzerAndShrinker(const std::string& shader, - const protobufs::FactSequence& initial_facts, - uint32_t seed) { - const auto env = SPV_ENV_UNIVERSAL_1_5; - - std::vector binary_in; - SpirvTools t(env); - t.SetMessageConsumer(kConsoleMessageConsumer); - ASSERT_TRUE(t.Assemble(shader, &binary_in, kFuzzAssembleOption)); - ASSERT_TRUE(t.Validate(binary_in)); - - // Run the fuzzer and check that it successfully yields a valid binary. - std::vector fuzzer_binary_out; - protobufs::TransformationSequence fuzzer_transformation_sequence_out; - Fuzzer fuzzer(env, seed, true); - fuzzer.SetMessageConsumer(kSilentConsumer); - auto fuzzer_result_status = - fuzzer.Run(binary_in, initial_facts, &fuzzer_binary_out, - &fuzzer_transformation_sequence_out); - ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result_status); - ASSERT_TRUE(t.Validate(fuzzer_binary_out)); - - const uint32_t kReasonableStepLimit = 50; - const uint32_t kSmallStepLimit = 20; - - // With the AlwaysInteresting test, we should quickly shrink to the original - // binary with no transformations remaining. - RunAndCheckShrinker( - env, binary_in, initial_facts, fuzzer_transformation_sequence_out, - AlwaysInteresting().AsFunction(), binary_in, 0, kReasonableStepLimit); - - // With the OnlyInterestingFirstTime test, no shrinking should be achieved. - RunAndCheckShrinker( - env, binary_in, initial_facts, fuzzer_transformation_sequence_out, - OnlyInterestingFirstTime().AsFunction(), fuzzer_binary_out, - static_cast( - fuzzer_transformation_sequence_out.transformation_size()), - kReasonableStepLimit); - - // The PingPong test is unpredictable; passing an empty expected binary - // means that we don't check anything beyond that shrinking completes - // successfully. - RunAndCheckShrinker(env, binary_in, initial_facts, - fuzzer_transformation_sequence_out, - PingPong().AsFunction(), {}, 0, kSmallStepLimit); - - // The InterestingThenRandom test is unpredictable; passing an empty - // expected binary means that we do not check anything about shrinking - // results. - RunAndCheckShrinker( - env, binary_in, initial_facts, fuzzer_transformation_sequence_out, - InterestingThenRandom(PseudoRandomGenerator(seed)).AsFunction(), {}, 0, - kSmallStepLimit); -} - -TEST(FuzzerShrinkerTest, Miscellaneous1) { - // The following SPIR-V came from this GLSL: - // - // #version 310 es - // - // void foo() { - // int x; - // x = 2; - // for (int i = 0; i < 100; i++) { - // x += i; - // x = x * 2; - // } - // return; - // } - // - // void main() { - // foo(); - // for (int i = 0; i < 10; i++) { - // int j = 20; - // while(j > 0) { - // foo(); - // j--; - // } - // do { - // i++; - // } while(i < 4); - // } - // } - - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %6 "foo(" - OpName %10 "x" - OpName %12 "i" - OpName %33 "i" - OpName %42 "j" - OpDecorate %10 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %19 RelaxedPrecision - OpDecorate %23 RelaxedPrecision - OpDecorate %24 RelaxedPrecision - OpDecorate %25 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - OpDecorate %28 RelaxedPrecision - OpDecorate %30 RelaxedPrecision - OpDecorate %33 RelaxedPrecision - OpDecorate %39 RelaxedPrecision - OpDecorate %42 RelaxedPrecision - OpDecorate %49 RelaxedPrecision - OpDecorate %52 RelaxedPrecision - OpDecorate %53 RelaxedPrecision - OpDecorate %58 RelaxedPrecision - OpDecorate %59 RelaxedPrecision - OpDecorate %60 RelaxedPrecision - OpDecorate %63 RelaxedPrecision - OpDecorate %64 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %11 = OpConstant %8 2 - %13 = OpConstant %8 0 - %20 = OpConstant %8 100 - %21 = OpTypeBool - %29 = OpConstant %8 1 - %40 = OpConstant %8 10 - %43 = OpConstant %8 20 - %61 = OpConstant %8 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %33 = OpVariable %9 Function - %42 = OpVariable %9 Function - %32 = OpFunctionCall %2 %6 - OpStore %33 %13 - OpBranch %34 - %34 = OpLabel - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %39 = OpLoad %8 %33 - %41 = OpSLessThan %21 %39 %40 - OpBranchConditional %41 %35 %36 - %35 = OpLabel - OpStore %42 %43 - OpBranch %44 - %44 = OpLabel - OpLoopMerge %46 %47 None - OpBranch %48 - %48 = OpLabel - %49 = OpLoad %8 %42 - %50 = OpSGreaterThan %21 %49 %13 - OpBranchConditional %50 %45 %46 - %45 = OpLabel - %51 = OpFunctionCall %2 %6 - %52 = OpLoad %8 %42 - %53 = OpISub %8 %52 %29 - OpStore %42 %53 - OpBranch %47 - %47 = OpLabel - OpBranch %44 - %46 = OpLabel - OpBranch %54 - %54 = OpLabel - OpLoopMerge %56 %57 None - OpBranch %55 - %55 = OpLabel - %58 = OpLoad %8 %33 - %59 = OpIAdd %8 %58 %29 - OpStore %33 %59 - OpBranch %57 - %57 = OpLabel - %60 = OpLoad %8 %33 - %62 = OpSLessThan %21 %60 %61 - OpBranchConditional %62 %54 %56 - %56 = OpLabel - OpBranch %37 - %37 = OpLabel - %63 = OpLoad %8 %33 - %64 = OpIAdd %8 %63 %29 - OpStore %33 %64 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %10 = OpVariable %9 Function - %12 = OpVariable %9 Function - OpStore %10 %11 - OpStore %12 %13 - OpBranch %14 - %14 = OpLabel - OpLoopMerge %16 %17 None - OpBranch %18 - %18 = OpLabel - %19 = OpLoad %8 %12 - %22 = OpSLessThan %21 %19 %20 - OpBranchConditional %22 %15 %16 - %15 = OpLabel - %23 = OpLoad %8 %12 - %24 = OpLoad %8 %10 - %25 = OpIAdd %8 %24 %23 - OpStore %10 %25 - %26 = OpLoad %8 %10 - %27 = OpIMul %8 %26 %11 - OpStore %10 %27 - OpBranch %17 - %17 = OpLabel - %28 = OpLoad %8 %12 - %30 = OpIAdd %8 %28 %29 - OpStore %12 %30 - OpBranch %14 - %16 = OpLabel - OpReturn - OpFunctionEnd - - )"; - - RunFuzzerAndShrinker(shader, protobufs::FactSequence(), 2); -} - -TEST(FuzzerShrinkerTest, Miscellaneous2) { - // The following SPIR-V came from this GLSL, which was then optimized using - // spirv-opt with the -O argument: - // - // #version 310 es - // - // precision highp float; - // - // layout(location = 0) out vec4 _GLF_color; - // - // layout(set = 0, binding = 0) uniform buf0 { - // vec2 injectionSwitch; - // }; - // layout(set = 0, binding = 1) uniform buf1 { - // vec2 resolution; - // }; - // bool checkSwap(float a, float b) - // { - // return gl_FragCoord.y < resolution.y / 2.0 ? a > b : a < b; - // } - // void main() - // { - // float data[10]; - // for(int i = 0; i < 10; i++) - // { - // data[i] = float(10 - i) * injectionSwitch.y; - // } - // for(int i = 0; i < 9; i++) - // { - // for(int j = 0; j < 10; j++) - // { - // if(j < i + 1) - // { - // continue; - // } - // bool doSwap = checkSwap(data[i], data[j]); - // if(doSwap) - // { - // float temp = data[i]; - // data[i] = data[j]; - // data[j] = temp; - // } - // } - // } - // if(gl_FragCoord.x < resolution.x / 2.0) - // { - // _GLF_color = vec4(data[0] / 10.0, data[5] / 10.0, data[9] / 10.0, 1.0); - // } - // else - // { - // _GLF_color = vec4(data[5] / 10.0, data[9] / 10.0, data[0] / 10.0, 1.0); - // } - // } - - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %16 %139 %25 %68 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %16 "gl_FragCoord" - OpName %23 "buf1" - OpMemberName %23 0 "resolution" - OpName %25 "" - OpName %61 "data" - OpName %66 "buf0" - OpMemberName %66 0 "injectionSwitch" - OpName %68 "" - OpName %139 "_GLF_color" - OpDecorate %16 BuiltIn FragCoord - OpMemberDecorate %23 0 Offset 0 - OpDecorate %23 Block - OpDecorate %25 DescriptorSet 0 - OpDecorate %25 Binding 1 - OpDecorate %64 RelaxedPrecision - OpMemberDecorate %66 0 Offset 0 - OpDecorate %66 Block - OpDecorate %68 DescriptorSet 0 - OpDecorate %68 Binding 0 - OpDecorate %75 RelaxedPrecision - OpDecorate %95 RelaxedPrecision - OpDecorate %126 RelaxedPrecision - OpDecorate %128 RelaxedPrecision - OpDecorate %139 Location 0 - OpDecorate %182 RelaxedPrecision - OpDecorate %183 RelaxedPrecision - OpDecorate %184 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %8 = OpTypeBool - %14 = OpTypeVector %6 4 - %15 = OpTypePointer Input %14 - %16 = OpVariable %15 Input - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 1 - %19 = OpTypePointer Input %6 - %22 = OpTypeVector %6 2 - %23 = OpTypeStruct %22 - %24 = OpTypePointer Uniform %23 - %25 = OpVariable %24 Uniform - %26 = OpTypeInt 32 1 - %27 = OpConstant %26 0 - %28 = OpTypePointer Uniform %6 - %56 = OpConstant %26 10 - %58 = OpConstant %17 10 - %59 = OpTypeArray %6 %58 - %60 = OpTypePointer Function %59 - %66 = OpTypeStruct %22 - %67 = OpTypePointer Uniform %66 - %68 = OpVariable %67 Uniform - %74 = OpConstant %26 1 - %83 = OpConstant %26 9 - %129 = OpConstant %17 0 - %138 = OpTypePointer Output %14 - %139 = OpVariable %138 Output - %144 = OpConstant %26 5 - %151 = OpConstant %6 1 - %194 = OpConstant %6 0.5 - %195 = OpConstant %6 0.100000001 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %61 = OpVariable %60 Function - OpBranch %50 - %50 = OpLabel - %182 = OpPhi %26 %27 %5 %75 %51 - %57 = OpSLessThan %8 %182 %56 - OpLoopMerge %52 %51 None - OpBranchConditional %57 %51 %52 - %51 = OpLabel - %64 = OpISub %26 %56 %182 - %65 = OpConvertSToF %6 %64 - %69 = OpAccessChain %28 %68 %27 %18 - %70 = OpLoad %6 %69 - %71 = OpFMul %6 %65 %70 - %72 = OpAccessChain %7 %61 %182 - OpStore %72 %71 - %75 = OpIAdd %26 %182 %74 - OpBranch %50 - %52 = OpLabel - OpBranch %77 - %77 = OpLabel - %183 = OpPhi %26 %27 %52 %128 %88 - %84 = OpSLessThan %8 %183 %83 - OpLoopMerge %79 %88 None - OpBranchConditional %84 %78 %79 - %78 = OpLabel - OpBranch %86 - %86 = OpLabel - %184 = OpPhi %26 %27 %78 %126 %89 - %92 = OpSLessThan %8 %184 %56 - OpLoopMerge %1000 %89 None - OpBranchConditional %92 %87 %1000 - %87 = OpLabel - %95 = OpIAdd %26 %183 %74 - %96 = OpSLessThan %8 %184 %95 - OpSelectionMerge %98 None - OpBranchConditional %96 %97 %98 - %97 = OpLabel - OpBranch %89 - %98 = OpLabel - %104 = OpAccessChain %7 %61 %183 - %105 = OpLoad %6 %104 - %107 = OpAccessChain %7 %61 %184 - %108 = OpLoad %6 %107 - %166 = OpAccessChain %19 %16 %18 - %167 = OpLoad %6 %166 - %168 = OpAccessChain %28 %25 %27 %18 - %169 = OpLoad %6 %168 - %170 = OpFMul %6 %169 %194 - %171 = OpFOrdLessThan %8 %167 %170 - OpSelectionMerge %172 None - OpBranchConditional %171 %173 %174 - %173 = OpLabel - %177 = OpFOrdGreaterThan %8 %105 %108 - OpBranch %172 - %174 = OpLabel - %180 = OpFOrdLessThan %8 %105 %108 - OpBranch %172 - %172 = OpLabel - %186 = OpPhi %8 %177 %173 %180 %174 - OpSelectionMerge %112 None - OpBranchConditional %186 %111 %112 - %111 = OpLabel - %116 = OpLoad %6 %104 - %120 = OpLoad %6 %107 - OpStore %104 %120 - OpStore %107 %116 - OpBranch %112 - %112 = OpLabel - OpBranch %89 - %89 = OpLabel - %126 = OpIAdd %26 %184 %74 - OpBranch %86 - %1000 = OpLabel - OpBranch %88 - %88 = OpLabel - %128 = OpIAdd %26 %183 %74 - OpBranch %77 - %79 = OpLabel - %130 = OpAccessChain %19 %16 %129 - %131 = OpLoad %6 %130 - %132 = OpAccessChain %28 %25 %27 %129 - %133 = OpLoad %6 %132 - %134 = OpFMul %6 %133 %194 - %135 = OpFOrdLessThan %8 %131 %134 - OpSelectionMerge %137 None - OpBranchConditional %135 %136 %153 - %136 = OpLabel - %140 = OpAccessChain %7 %61 %27 - %141 = OpLoad %6 %140 - %143 = OpFMul %6 %141 %195 - %145 = OpAccessChain %7 %61 %144 - %146 = OpLoad %6 %145 - %147 = OpFMul %6 %146 %195 - %148 = OpAccessChain %7 %61 %83 - %149 = OpLoad %6 %148 - %150 = OpFMul %6 %149 %195 - %152 = OpCompositeConstruct %14 %143 %147 %150 %151 - OpStore %139 %152 - OpBranch %137 - %153 = OpLabel - %154 = OpAccessChain %7 %61 %144 - %155 = OpLoad %6 %154 - %156 = OpFMul %6 %155 %195 - %157 = OpAccessChain %7 %61 %83 - %158 = OpLoad %6 %157 - %159 = OpFMul %6 %158 %195 - %160 = OpAccessChain %7 %61 %27 - %161 = OpLoad %6 %160 - %162 = OpFMul %6 %161 %195 - %163 = OpCompositeConstruct %14 %156 %159 %162 %151 - OpStore %139 %163 - OpBranch %137 - %137 = OpLabel - OpReturn - OpFunctionEnd - )"; - - RunFuzzerAndShrinker(shader, protobufs::FactSequence(), 19); -} - -TEST(FuzzerShrinkerTest, Miscellaneous3) { - // The following SPIR-V came from this GLSL, which was then optimized using - // spirv-opt with the -O argument: - // - // #version 310 es - // - // precision highp float; - // - // layout(location = 0) out vec4 _GLF_color; - // - // layout(set = 0, binding = 0) uniform buf0 { - // vec2 resolution; - // }; - // void main(void) - // { - // float A[50]; - // for( - // int i = 0; - // i < 200; - // i ++ - // ) - // { - // if(i >= int(resolution.x)) - // { - // break; - // } - // if((4 * (i / 4)) == i) - // { - // A[i / 4] = float(i); - // } - // } - // for( - // int i = 0; - // i < 50; - // i ++ - // ) - // { - // if(i < int(gl_FragCoord.x)) - // { - // break; - // } - // if(i > 0) - // { - // A[i] += A[i - 1]; - // } - // } - // if(int(gl_FragCoord.x) < 20) - // { - // _GLF_color = vec4(A[0] / resolution.x, A[4] / resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 40) - // { - // _GLF_color = vec4(A[5] / resolution.x, A[9] / resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 60) - // { - // _GLF_color = vec4(A[10] / resolution.x, A[14] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 80) - // { - // _GLF_color = vec4(A[15] / resolution.x, A[19] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 100) - // { - // _GLF_color = vec4(A[20] / resolution.x, A[24] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 120) - // { - // _GLF_color = vec4(A[25] / resolution.x, A[29] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 140) - // { - // _GLF_color = vec4(A[30] / resolution.x, A[34] / resolution.y, - // 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 160) - // { - // _GLF_color = vec4(A[35] / resolution.x, A[39] / - // resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 180) - // { - // _GLF_color = vec4(A[40] / resolution.x, A[44] / - // resolution.y, 1.0, 1.0); - // } - // else - // if(int(gl_FragCoord.x) < 180) - // { - // _GLF_color = vec4(A[45] / resolution.x, A[49] / - // resolution.y, 1.0, 1.0); - // } - // else - // { - // discard; - // } - // } - - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %68 %100 %24 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %22 "buf0" - OpMemberName %22 0 "resolution" - OpName %24 "" - OpName %46 "A" - OpName %68 "gl_FragCoord" - OpName %100 "_GLF_color" - OpMemberDecorate %22 0 Offset 0 - OpDecorate %22 Block - OpDecorate %24 DescriptorSet 0 - OpDecorate %24 Binding 0 - OpDecorate %37 RelaxedPrecision - OpDecorate %38 RelaxedPrecision - OpDecorate %55 RelaxedPrecision - OpDecorate %68 BuiltIn FragCoord - OpDecorate %83 RelaxedPrecision - OpDecorate %91 RelaxedPrecision - OpDecorate %100 Location 0 - OpDecorate %302 RelaxedPrecision - OpDecorate %304 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpConstant %6 200 - %17 = OpTypeBool - %20 = OpTypeFloat 32 - %21 = OpTypeVector %20 2 - %22 = OpTypeStruct %21 - %23 = OpTypePointer Uniform %22 - %24 = OpVariable %23 Uniform - %25 = OpTypeInt 32 0 - %26 = OpConstant %25 0 - %27 = OpTypePointer Uniform %20 - %35 = OpConstant %6 4 - %43 = OpConstant %25 50 - %44 = OpTypeArray %20 %43 - %45 = OpTypePointer Function %44 - %51 = OpTypePointer Function %20 - %54 = OpConstant %6 1 - %63 = OpConstant %6 50 - %66 = OpTypeVector %20 4 - %67 = OpTypePointer Input %66 - %68 = OpVariable %67 Input - %69 = OpTypePointer Input %20 - %95 = OpConstant %6 20 - %99 = OpTypePointer Output %66 - %100 = OpVariable %99 Output - %108 = OpConstant %25 1 - %112 = OpConstant %20 1 - %118 = OpConstant %6 40 - %122 = OpConstant %6 5 - %128 = OpConstant %6 9 - %139 = OpConstant %6 60 - %143 = OpConstant %6 10 - %149 = OpConstant %6 14 - %160 = OpConstant %6 80 - %164 = OpConstant %6 15 - %170 = OpConstant %6 19 - %181 = OpConstant %6 100 - %190 = OpConstant %6 24 - %201 = OpConstant %6 120 - %205 = OpConstant %6 25 - %211 = OpConstant %6 29 - %222 = OpConstant %6 140 - %226 = OpConstant %6 30 - %232 = OpConstant %6 34 - %243 = OpConstant %6 160 - %247 = OpConstant %6 35 - %253 = OpConstant %6 39 - %264 = OpConstant %6 180 - %273 = OpConstant %6 44 - %287 = OpConstant %6 45 - %293 = OpConstant %6 49 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %46 = OpVariable %45 Function - OpBranch %10 - %10 = OpLabel - %302 = OpPhi %6 %9 %5 %55 %42 - %18 = OpSLessThan %17 %302 %16 - OpLoopMerge %12 %42 None - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %28 = OpAccessChain %27 %24 %9 %26 - %29 = OpLoad %20 %28 - %30 = OpConvertFToS %6 %29 - %31 = OpSGreaterThanEqual %17 %302 %30 - OpSelectionMerge %33 None - OpBranchConditional %31 %32 %33 - %32 = OpLabel - OpBranch %12 - %33 = OpLabel - %37 = OpSDiv %6 %302 %35 - %38 = OpIMul %6 %35 %37 - %40 = OpIEqual %17 %38 %302 - OpBranchConditional %40 %41 %42 - %41 = OpLabel - %50 = OpConvertSToF %20 %302 - %52 = OpAccessChain %51 %46 %37 - OpStore %52 %50 - OpBranch %42 - %42 = OpLabel - %55 = OpIAdd %6 %302 %54 - OpBranch %10 - %12 = OpLabel - OpBranch %57 - %57 = OpLabel - %304 = OpPhi %6 %9 %12 %91 %80 - %64 = OpSLessThan %17 %304 %63 - OpLoopMerge %59 %80 None - OpBranchConditional %64 %58 %59 - %58 = OpLabel - %70 = OpAccessChain %69 %68 %26 - %71 = OpLoad %20 %70 - %72 = OpConvertFToS %6 %71 - %73 = OpSLessThan %17 %304 %72 - OpSelectionMerge %75 None - OpBranchConditional %73 %74 %75 - %74 = OpLabel - OpBranch %59 - %75 = OpLabel - %78 = OpSGreaterThan %17 %304 %9 - OpBranchConditional %78 %79 %80 - %79 = OpLabel - %83 = OpISub %6 %304 %54 - %84 = OpAccessChain %51 %46 %83 - %85 = OpLoad %20 %84 - %86 = OpAccessChain %51 %46 %304 - %87 = OpLoad %20 %86 - %88 = OpFAdd %20 %87 %85 - OpStore %86 %88 - OpBranch %80 - %80 = OpLabel - %91 = OpIAdd %6 %304 %54 - OpBranch %57 - %59 = OpLabel - %92 = OpAccessChain %69 %68 %26 - %93 = OpLoad %20 %92 - %94 = OpConvertFToS %6 %93 - %96 = OpSLessThan %17 %94 %95 - OpSelectionMerge %98 None - OpBranchConditional %96 %97 %114 - %97 = OpLabel - %101 = OpAccessChain %51 %46 %9 - %102 = OpLoad %20 %101 - %103 = OpAccessChain %27 %24 %9 %26 - %104 = OpLoad %20 %103 - %105 = OpFDiv %20 %102 %104 - %106 = OpAccessChain %51 %46 %35 - %107 = OpLoad %20 %106 - %109 = OpAccessChain %27 %24 %9 %108 - %110 = OpLoad %20 %109 - %111 = OpFDiv %20 %107 %110 - %113 = OpCompositeConstruct %66 %105 %111 %112 %112 - OpStore %100 %113 - OpBranch %98 - %114 = OpLabel - %119 = OpSLessThan %17 %94 %118 - OpSelectionMerge %121 None - OpBranchConditional %119 %120 %135 - %120 = OpLabel - %123 = OpAccessChain %51 %46 %122 - %124 = OpLoad %20 %123 - %125 = OpAccessChain %27 %24 %9 %26 - %126 = OpLoad %20 %125 - %127 = OpFDiv %20 %124 %126 - %129 = OpAccessChain %51 %46 %128 - %130 = OpLoad %20 %129 - %131 = OpAccessChain %27 %24 %9 %108 - %132 = OpLoad %20 %131 - %133 = OpFDiv %20 %130 %132 - %134 = OpCompositeConstruct %66 %127 %133 %112 %112 - OpStore %100 %134 - OpBranch %121 - %135 = OpLabel - %140 = OpSLessThan %17 %94 %139 - OpSelectionMerge %142 None - OpBranchConditional %140 %141 %156 - %141 = OpLabel - %144 = OpAccessChain %51 %46 %143 - %145 = OpLoad %20 %144 - %146 = OpAccessChain %27 %24 %9 %26 - %147 = OpLoad %20 %146 - %148 = OpFDiv %20 %145 %147 - %150 = OpAccessChain %51 %46 %149 - %151 = OpLoad %20 %150 - %152 = OpAccessChain %27 %24 %9 %108 - %153 = OpLoad %20 %152 - %154 = OpFDiv %20 %151 %153 - %155 = OpCompositeConstruct %66 %148 %154 %112 %112 - OpStore %100 %155 - OpBranch %142 - %156 = OpLabel - %161 = OpSLessThan %17 %94 %160 - OpSelectionMerge %163 None - OpBranchConditional %161 %162 %177 - %162 = OpLabel - %165 = OpAccessChain %51 %46 %164 - %166 = OpLoad %20 %165 - %167 = OpAccessChain %27 %24 %9 %26 - %168 = OpLoad %20 %167 - %169 = OpFDiv %20 %166 %168 - %171 = OpAccessChain %51 %46 %170 - %172 = OpLoad %20 %171 - %173 = OpAccessChain %27 %24 %9 %108 - %174 = OpLoad %20 %173 - %175 = OpFDiv %20 %172 %174 - %176 = OpCompositeConstruct %66 %169 %175 %112 %112 - OpStore %100 %176 - OpBranch %163 - %177 = OpLabel - %182 = OpSLessThan %17 %94 %181 - OpSelectionMerge %184 None - OpBranchConditional %182 %183 %197 - %183 = OpLabel - %185 = OpAccessChain %51 %46 %95 - %186 = OpLoad %20 %185 - %187 = OpAccessChain %27 %24 %9 %26 - %188 = OpLoad %20 %187 - %189 = OpFDiv %20 %186 %188 - %191 = OpAccessChain %51 %46 %190 - %192 = OpLoad %20 %191 - %193 = OpAccessChain %27 %24 %9 %108 - %194 = OpLoad %20 %193 - %195 = OpFDiv %20 %192 %194 - %196 = OpCompositeConstruct %66 %189 %195 %112 %112 - OpStore %100 %196 - OpBranch %184 - %197 = OpLabel - %202 = OpSLessThan %17 %94 %201 - OpSelectionMerge %204 None - OpBranchConditional %202 %203 %218 - %203 = OpLabel - %206 = OpAccessChain %51 %46 %205 - %207 = OpLoad %20 %206 - %208 = OpAccessChain %27 %24 %9 %26 - %209 = OpLoad %20 %208 - %210 = OpFDiv %20 %207 %209 - %212 = OpAccessChain %51 %46 %211 - %213 = OpLoad %20 %212 - %214 = OpAccessChain %27 %24 %9 %108 - %215 = OpLoad %20 %214 - %216 = OpFDiv %20 %213 %215 - %217 = OpCompositeConstruct %66 %210 %216 %112 %112 - OpStore %100 %217 - OpBranch %204 - %218 = OpLabel - %223 = OpSLessThan %17 %94 %222 - OpSelectionMerge %225 None - OpBranchConditional %223 %224 %239 - %224 = OpLabel - %227 = OpAccessChain %51 %46 %226 - %228 = OpLoad %20 %227 - %229 = OpAccessChain %27 %24 %9 %26 - %230 = OpLoad %20 %229 - %231 = OpFDiv %20 %228 %230 - %233 = OpAccessChain %51 %46 %232 - %234 = OpLoad %20 %233 - %235 = OpAccessChain %27 %24 %9 %108 - %236 = OpLoad %20 %235 - %237 = OpFDiv %20 %234 %236 - %238 = OpCompositeConstruct %66 %231 %237 %112 %112 - OpStore %100 %238 - OpBranch %225 - %239 = OpLabel - %244 = OpSLessThan %17 %94 %243 - OpSelectionMerge %246 None - OpBranchConditional %244 %245 %260 - %245 = OpLabel - %248 = OpAccessChain %51 %46 %247 - %249 = OpLoad %20 %248 - %250 = OpAccessChain %27 %24 %9 %26 - %251 = OpLoad %20 %250 - %252 = OpFDiv %20 %249 %251 - %254 = OpAccessChain %51 %46 %253 - %255 = OpLoad %20 %254 - %256 = OpAccessChain %27 %24 %9 %108 - %257 = OpLoad %20 %256 - %258 = OpFDiv %20 %255 %257 - %259 = OpCompositeConstruct %66 %252 %258 %112 %112 - OpStore %100 %259 - OpBranch %246 - %260 = OpLabel - %265 = OpSLessThan %17 %94 %264 - OpSelectionMerge %267 None - OpBranchConditional %265 %266 %280 - %266 = OpLabel - %268 = OpAccessChain %51 %46 %118 - %269 = OpLoad %20 %268 - %270 = OpAccessChain %27 %24 %9 %26 - %271 = OpLoad %20 %270 - %272 = OpFDiv %20 %269 %271 - %274 = OpAccessChain %51 %46 %273 - %275 = OpLoad %20 %274 - %276 = OpAccessChain %27 %24 %9 %108 - %277 = OpLoad %20 %276 - %278 = OpFDiv %20 %275 %277 - %279 = OpCompositeConstruct %66 %272 %278 %112 %112 - OpStore %100 %279 - OpBranch %267 - %280 = OpLabel - OpSelectionMerge %285 None - OpBranchConditional %265 %285 %300 - %285 = OpLabel - %288 = OpAccessChain %51 %46 %287 - %289 = OpLoad %20 %288 - %290 = OpAccessChain %27 %24 %9 %26 - %291 = OpLoad %20 %290 - %292 = OpFDiv %20 %289 %291 - %294 = OpAccessChain %51 %46 %293 - %295 = OpLoad %20 %294 - %296 = OpAccessChain %27 %24 %9 %108 - %297 = OpLoad %20 %296 - %298 = OpFDiv %20 %295 %297 - %299 = OpCompositeConstruct %66 %292 %298 %112 %112 - OpStore %100 %299 - OpBranch %267 - %300 = OpLabel - OpKill - %267 = OpLabel - OpBranch %246 - %246 = OpLabel - OpBranch %225 - %225 = OpLabel - OpBranch %204 - %204 = OpLabel - OpBranch %184 - %184 = OpLabel - OpBranch %163 - %163 = OpLabel - OpBranch %142 - %142 = OpLabel - OpBranch %121 - %121 = OpLabel - OpBranch %98 - %98 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Add the facts "resolution.x == 250" and "resolution.y == 100". - protobufs::FactSequence facts; - { - protobufs::FactConstantUniform resolution_x_eq_250; - *resolution_x_eq_250.mutable_uniform_buffer_element_descriptor() = - MakeUniformBufferElementDescriptor(0, 0, {0, 0}); - *resolution_x_eq_250.mutable_constant_word()->Add() = 250; - protobufs::Fact temp; - *temp.mutable_constant_uniform_fact() = resolution_x_eq_250; - *facts.mutable_fact()->Add() = temp; - } - { - protobufs::FactConstantUniform resolution_y_eq_100; - *resolution_y_eq_100.mutable_uniform_buffer_element_descriptor() = - MakeUniformBufferElementDescriptor(0, 0, {0, 1}); - *resolution_y_eq_100.mutable_constant_word()->Add() = 100; - protobufs::Fact temp; - *temp.mutable_constant_uniform_fact() = resolution_y_eq_100; - *facts.mutable_fact()->Add() = temp; - } - - // Do 2 fuzzer runs, starting from an initial seed of 194 (seed value chosen - // arbitrarily). - RunFuzzerAndShrinker(shader, facts, 194); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/instruction_descriptor_test.cpp b/3rdparty/spirv-tools/test/fuzz/instruction_descriptor_test.cpp deleted file mode 100644 index 5165cfb07..000000000 --- a/3rdparty/spirv-tools/test/fuzz/instruction_descriptor_test.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(InstructionDescriptorTest, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 0 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 2 - %32 = OpConstant %10 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %164 = OpVariable %11 Function - %165 = OpVariable %11 Function - OpBranch %16 - %16 = OpLabel - OpStore %164 %32 - OpStore %165 %13 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - for (auto& function : *context->module()) { - for (auto& block : function) { - for (auto inst_it = block.cbegin(); inst_it != block.cend(); ++inst_it) { - ASSERT_EQ(&*inst_it, - FindInstruction(MakeInstructionDescriptor(block, inst_it), - context.get())); - } - } - } -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_constant_boolean_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_constant_boolean_test.cpp deleted file mode 100644 index f51c46bf4..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_constant_boolean_test.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_constant_boolean.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddConstantBooleanTest, NeitherPresentInitiallyAddBoth) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %6 = OpTypeBool - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // True and false can both be added as neither is present. - ASSERT_TRUE(TransformationAddConstantBoolean(7, true).IsApplicable( - context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddConstantBoolean(7, false).IsApplicable( - context.get(), fact_manager)); - - // Id 5 is already taken. - ASSERT_FALSE(TransformationAddConstantBoolean(5, true).IsApplicable( - context.get(), fact_manager)); - - auto add_true = TransformationAddConstantBoolean(7, true); - auto add_false = TransformationAddConstantBoolean(8, false); - - ASSERT_TRUE(add_true.IsApplicable(context.get(), fact_manager)); - add_true.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Having added true, we cannot add it again with the same id. - ASSERT_FALSE(add_true.IsApplicable(context.get(), fact_manager)); - // But we can add it with a different id. - auto add_true_again = TransformationAddConstantBoolean(100, true); - ASSERT_TRUE(add_true_again.IsApplicable(context.get(), fact_manager)); - add_true_again.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(add_false.IsApplicable(context.get(), fact_manager)); - add_false.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Having added false, we cannot add it again with the same id. - ASSERT_FALSE(add_false.IsApplicable(context.get(), fact_manager)); - // But we can add it with a different id. - auto add_false_again = TransformationAddConstantBoolean(101, false); - ASSERT_TRUE(add_false_again.IsApplicable(context.get(), fact_manager)); - add_false_again.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %6 = OpTypeBool - %3 = OpTypeFunction %2 - %7 = OpConstantTrue %6 - %100 = OpConstantTrue %6 - %8 = OpConstantFalse %6 - %101 = OpConstantFalse %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddConstantBooleanTest, NoOpTypeBoolPresent) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Neither true nor false can be added as OpTypeBool is not present. - ASSERT_FALSE(TransformationAddConstantBoolean(6, true).IsApplicable( - context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddConstantBoolean(6, false).IsApplicable( - context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_constant_scalar_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_constant_scalar_test.cpp deleted file mode 100644 index b15611124..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_constant_scalar_test.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_constant_scalar.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddConstantScalarTest, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %12 "y" - OpName %16 "z" - OpDecorate %8 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpTypeInt 32 0 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 2 - %14 = OpTypeFloat 32 - %15 = OpTypePointer Function %14 - %17 = OpConstant %14 3 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %16 = OpVariable %15 Function - OpStore %8 %9 - OpStore %12 %13 - OpStore %16 %17 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - const float float_values[2] = {3.0, 30.0}; - uint32_t uint_for_float[2]; - memcpy(uint_for_float, float_values, sizeof(float_values)); - - auto add_signed_int_1 = TransformationAddConstantScalar(100, 6, {1}); - auto add_signed_int_10 = TransformationAddConstantScalar(101, 6, {10}); - auto add_unsigned_int_2 = TransformationAddConstantScalar(102, 10, {2}); - auto add_unsigned_int_20 = TransformationAddConstantScalar(103, 10, {20}); - auto add_float_3 = - TransformationAddConstantScalar(104, 14, {uint_for_float[0]}); - auto add_float_30 = - TransformationAddConstantScalar(105, 14, {uint_for_float[1]}); - auto bad_add_float_30_id_already_used = - TransformationAddConstantScalar(104, 14, {uint_for_float[1]}); - auto bad_id_already_used = TransformationAddConstantScalar(1, 6, {1}); - auto bad_no_data = TransformationAddConstantScalar(100, 6, {}); - auto bad_too_much_data = TransformationAddConstantScalar(100, 6, {1, 2}); - auto bad_type_id_does_not_exist = - TransformationAddConstantScalar(108, 2020, {uint_for_float[0]}); - auto bad_type_id_is_not_a_type = TransformationAddConstantScalar(109, 9, {0}); - auto bad_type_id_is_void = TransformationAddConstantScalar(110, 2, {0}); - auto bad_type_id_is_pointer = TransformationAddConstantScalar(111, 11, {0}); - - // Id is already in use. - ASSERT_FALSE(bad_id_already_used.IsApplicable(context.get(), fact_manager)); - - // At least one word of data must be provided. - ASSERT_FALSE(bad_no_data.IsApplicable(context.get(), fact_manager)); - - // Cannot give two data words for a 32-bit type. - ASSERT_FALSE(bad_too_much_data.IsApplicable(context.get(), fact_manager)); - - // Type id does not exist - ASSERT_FALSE( - bad_type_id_does_not_exist.IsApplicable(context.get(), fact_manager)); - - // Type id is not a type - ASSERT_FALSE( - bad_type_id_is_not_a_type.IsApplicable(context.get(), fact_manager)); - - // Type id is void - ASSERT_FALSE(bad_type_id_is_void.IsApplicable(context.get(), fact_manager)); - - // Type id is pointer - ASSERT_FALSE( - bad_type_id_is_pointer.IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(add_signed_int_1.IsApplicable(context.get(), fact_manager)); - add_signed_int_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(add_signed_int_10.IsApplicable(context.get(), fact_manager)); - add_signed_int_10.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(add_unsigned_int_2.IsApplicable(context.get(), fact_manager)); - add_unsigned_int_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(add_unsigned_int_20.IsApplicable(context.get(), fact_manager)); - add_unsigned_int_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(add_float_3.IsApplicable(context.get(), fact_manager)); - add_float_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(add_float_30.IsApplicable(context.get(), fact_manager)); - add_float_30.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_FALSE(bad_add_float_30_id_already_used.IsApplicable(context.get(), - fact_manager)); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %12 "y" - OpName %16 "z" - OpDecorate %8 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpTypeInt 32 0 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 2 - %14 = OpTypeFloat 32 - %15 = OpTypePointer Function %14 - %17 = OpConstant %14 3 - %100 = OpConstant %6 1 - %101 = OpConstant %6 10 - %102 = OpConstant %10 2 - %103 = OpConstant %10 20 - %104 = OpConstant %14 3 - %105 = OpConstant %14 30 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %16 = OpVariable %15 Function - OpStore %8 %9 - OpStore %12 %13 - OpStore %16 %17 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_dead_break_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_dead_break_test.cpp deleted file mode 100644 index 1dd0c9d4e..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_dead_break_test.cpp +++ /dev/null @@ -1,2613 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_dead_break.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddDeadBreakTest, BreaksOutOfSimpleIf) { - // For a simple if-then-else, checks that some dead break scenarios are - // possible, and sanity-checks that some illegal scenarios are indeed not - // allowed. - - // The SPIR-V for this test is adapted from the following GLSL, by separating - // some assignments into their own basic blocks, and adding constants for true - // and false: - // - // void main() { - // int x; - // int y; - // x = 1; - // if (x < y) { - // x = 2; - // x = 3; - // } else { - // y = 2; - // y = 3; - // } - // x = y; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpTypeBool - %17 = OpConstant %6 2 - %18 = OpConstant %6 3 - %25 = OpConstantTrue %13 - %26 = OpConstantFalse %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %19 - %15 = OpLabel - OpStore %8 %17 - OpBranch %21 - %21 = OpLabel - OpStore %8 %18 - OpBranch %22 - %22 = OpLabel - OpBranch %16 - %19 = OpLabel - OpStore %11 %17 - OpBranch %23 - %23 = OpLabel - OpStore %11 %18 - OpBranch %24 - %24 = OpLabel - OpBranch %16 - %16 = OpLabel - %20 = OpLoad %6 %11 - OpStore %8 %20 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - FactManager fact_manager; - - const uint32_t merge_block = 16; - - // These are all possibilities. - ASSERT_TRUE(TransformationAddDeadBreak(15, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(15, merge_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(21, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(21, merge_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(22, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(22, merge_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(19, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(19, merge_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(23, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(23, merge_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(24, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(24, merge_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 100 is not a block id. - ASSERT_FALSE(TransformationAddDeadBreak(100, merge_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(15, 100, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 24 is not a merge block. - ASSERT_FALSE(TransformationAddDeadBreak(15, 24, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // These are the transformations we will apply. - auto transformation1 = TransformationAddDeadBreak(15, merge_block, true, {}); - auto transformation2 = TransformationAddDeadBreak(21, merge_block, false, {}); - auto transformation3 = TransformationAddDeadBreak(22, merge_block, true, {}); - auto transformation4 = TransformationAddDeadBreak(19, merge_block, false, {}); - auto transformation5 = TransformationAddDeadBreak(23, merge_block, true, {}); - auto transformation6 = TransformationAddDeadBreak(24, merge_block, false, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager)); - transformation6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpTypeBool - %17 = OpConstant %6 2 - %18 = OpConstant %6 3 - %25 = OpConstantTrue %13 - %26 = OpConstantFalse %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %19 - %15 = OpLabel - OpStore %8 %17 - OpBranchConditional %25 %21 %16 - %21 = OpLabel - OpStore %8 %18 - OpBranchConditional %26 %16 %22 - %22 = OpLabel - OpBranchConditional %25 %16 %16 - %19 = OpLabel - OpStore %11 %17 - OpBranchConditional %26 %16 %23 - %23 = OpLabel - OpStore %11 %18 - OpBranchConditional %25 %24 %16 - %24 = OpLabel - OpBranchConditional %26 %16 %16 - %16 = OpLabel - %20 = OpLoad %6 %11 - OpStore %8 %20 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, BreakOutOfNestedIfs) { - // Checks some allowed and disallowed scenarios for nests of ifs. - - // The SPIR-V for this test is adapted from the following GLSL: - // - // void main() { - // int x; - // int y; - // x = 1; - // if (x < y) { - // x = 2; - // x = 3; - // if (x == y) { - // y = 3; - // } - // } else { - // y = 2; - // y = 3; - // } - // if (x == y) { - // x = 2; - // } - // x = y; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpTypeBool - %17 = OpConstant %6 2 - %18 = OpConstant %6 3 - %31 = OpConstantTrue %13 - %32 = OpConstantFalse %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %24 - %15 = OpLabel - OpStore %8 %17 - OpBranch %33 - %33 = OpLabel - OpStore %8 %18 - %19 = OpLoad %6 %8 - OpBranch %34 - %34 = OpLabel - %20 = OpLoad %6 %11 - %21 = OpIEqual %13 %19 %20 - OpSelectionMerge %23 None - OpBranchConditional %21 %22 %23 - %22 = OpLabel - OpStore %11 %18 - OpBranch %35 - %35 = OpLabel - OpBranch %23 - %23 = OpLabel - OpBranch %16 - %24 = OpLabel - OpStore %11 %17 - OpBranch %36 - %36 = OpLabel - OpStore %11 %18 - OpBranch %16 - %16 = OpLabel - %25 = OpLoad %6 %8 - OpBranch %37 - %37 = OpLabel - %26 = OpLoad %6 %11 - %27 = OpIEqual %13 %25 %26 - OpSelectionMerge %29 None - OpBranchConditional %27 %28 %29 - %28 = OpLabel - OpStore %8 %17 - OpBranch %38 - %38 = OpLabel - OpBranch %29 - %29 = OpLabel - %30 = OpLoad %6 %11 - OpStore %8 %30 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // The header and merge blocks - const uint32_t header_inner = 34; - const uint32_t merge_inner = 23; - const uint32_t header_outer = 5; - const uint32_t merge_outer = 16; - const uint32_t header_after = 37; - const uint32_t merge_after = 29; - - // The non-merge-nor-header blocks in each construct - const uint32_t inner_block_1 = 22; - const uint32_t inner_block_2 = 35; - const uint32_t outer_block_1 = 15; - const uint32_t outer_block_2 = 33; - const uint32_t outer_block_3 = 24; - const uint32_t outer_block_4 = 36; - const uint32_t after_block_1 = 28; - const uint32_t after_block_2 = 38; - - // Fine to break from a construct to its merge - ASSERT_TRUE(TransformationAddDeadBreak(inner_block_1, merge_inner, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(inner_block_2, merge_inner, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(outer_block_1, merge_outer, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(outer_block_2, merge_outer, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(outer_block_3, merge_outer, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(outer_block_4, merge_outer, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(after_block_1, merge_after, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(after_block_2, merge_after, false, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break to the wrong merge (whether enclosing or not) - ASSERT_FALSE(TransformationAddDeadBreak(inner_block_1, merge_outer, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(inner_block_2, merge_after, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(outer_block_1, merge_inner, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(outer_block_2, merge_after, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(after_block_1, merge_inner, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(after_block_2, merge_outer, false, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break from header (as it does not branch unconditionally) - ASSERT_FALSE(TransformationAddDeadBreak(header_inner, merge_inner, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(header_outer, merge_outer, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(header_after, merge_after, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break to non-merge - ASSERT_FALSE( - TransformationAddDeadBreak(inner_block_1, inner_block_2, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(outer_block_2, after_block_1, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(outer_block_1, header_after, true, {}) - .IsApplicable(context.get(), fact_manager)); - - auto transformation1 = - TransformationAddDeadBreak(inner_block_1, merge_inner, true, {}); - auto transformation2 = - TransformationAddDeadBreak(inner_block_2, merge_inner, false, {}); - auto transformation3 = - TransformationAddDeadBreak(outer_block_1, merge_outer, true, {}); - auto transformation4 = - TransformationAddDeadBreak(outer_block_2, merge_outer, false, {}); - auto transformation5 = - TransformationAddDeadBreak(outer_block_3, merge_outer, true, {}); - auto transformation6 = - TransformationAddDeadBreak(outer_block_4, merge_outer, false, {}); - auto transformation7 = - TransformationAddDeadBreak(after_block_1, merge_after, true, {}); - auto transformation8 = - TransformationAddDeadBreak(after_block_2, merge_after, false, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager)); - transformation6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager)); - transformation7.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation8.IsApplicable(context.get(), fact_manager)); - transformation8.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpTypeBool - %17 = OpConstant %6 2 - %18 = OpConstant %6 3 - %31 = OpConstantTrue %13 - %32 = OpConstantFalse %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %24 - %15 = OpLabel - OpStore %8 %17 - OpBranchConditional %31 %33 %16 - %33 = OpLabel - OpStore %8 %18 - %19 = OpLoad %6 %8 - OpBranchConditional %32 %16 %34 - %34 = OpLabel - %20 = OpLoad %6 %11 - %21 = OpIEqual %13 %19 %20 - OpSelectionMerge %23 None - OpBranchConditional %21 %22 %23 - %22 = OpLabel - OpStore %11 %18 - OpBranchConditional %31 %35 %23 - %35 = OpLabel - OpBranchConditional %32 %23 %23 - %23 = OpLabel - OpBranch %16 - %24 = OpLabel - OpStore %11 %17 - OpBranchConditional %31 %36 %16 - %36 = OpLabel - OpStore %11 %18 - OpBranchConditional %32 %16 %16 - %16 = OpLabel - %25 = OpLoad %6 %8 - OpBranch %37 - %37 = OpLabel - %26 = OpLoad %6 %11 - %27 = OpIEqual %13 %25 %26 - OpSelectionMerge %29 None - OpBranchConditional %27 %28 %29 - %28 = OpLabel - OpStore %8 %17 - OpBranchConditional %31 %38 %29 - %38 = OpLabel - OpBranchConditional %32 %29 %29 - %29 = OpLabel - %30 = OpLoad %6 %11 - OpStore %8 %30 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, BreakOutOfNestedSwitches) { - // Checks some allowed and disallowed scenarios for nests of switches. - - // The SPIR-V for this test is adapted from the following GLSL: - // - // void main() { - // int x; - // int y; - // x = 1; - // if (x < y) { - // switch (x) { - // case 0: - // case 1: - // if (x == y) { - // } - // x = 2; - // break; - // case 3: - // if (y == 4) { - // y = 2; - // x = 3; - // } - // case 10: - // break; - // default: - // switch (y) { - // case 1: - // break; - // case 2: - // x = 4; - // y = 2; - // default: - // x = 3; - // break; - // } - // } - // } else { - // switch (y) { - // case 1: - // x = 4; - // case 2: - // y = 3; - // default: - // x = y; - // break; - // } - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpTypeBool - %29 = OpConstant %6 2 - %32 = OpConstant %6 4 - %36 = OpConstant %6 3 - %60 = OpConstantTrue %13 - %61 = OpConstantFalse %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %47 - %15 = OpLabel - %17 = OpLoad %6 %8 - OpSelectionMerge %22 None - OpSwitch %17 %21 0 %18 1 %18 3 %19 10 %20 - %21 = OpLabel - %38 = OpLoad %6 %11 - OpSelectionMerge %42 None - OpSwitch %38 %41 1 %39 2 %40 - %41 = OpLabel - OpStore %8 %36 - OpBranch %42 - %39 = OpLabel - OpBranch %42 - %40 = OpLabel - OpStore %8 %32 - OpStore %11 %29 - OpBranch %41 - %42 = OpLabel - OpBranch %22 - %18 = OpLabel - %23 = OpLoad %6 %8 - OpBranch %63 - %63 = OpLabel - %24 = OpLoad %6 %11 - %25 = OpIEqual %13 %23 %24 - OpSelectionMerge %27 None - OpBranchConditional %25 %26 %27 - %26 = OpLabel - OpBranch %27 - %27 = OpLabel - OpStore %8 %29 - OpBranch %22 - %19 = OpLabel - %31 = OpLoad %6 %11 - %33 = OpIEqual %13 %31 %32 - OpSelectionMerge %35 None - OpBranchConditional %33 %34 %35 - %34 = OpLabel - OpStore %11 %29 - OpBranch %62 - %62 = OpLabel - OpStore %8 %36 - OpBranch %35 - %35 = OpLabel - OpBranch %20 - %20 = OpLabel - OpBranch %22 - %22 = OpLabel - OpBranch %16 - %47 = OpLabel - %48 = OpLoad %6 %11 - OpSelectionMerge %52 None - OpSwitch %48 %51 1 %49 2 %50 - %51 = OpLabel - %53 = OpLoad %6 %11 - OpStore %8 %53 - OpBranch %52 - %49 = OpLabel - OpStore %8 %32 - OpBranch %50 - %50 = OpLabel - OpStore %11 %36 - OpBranch %51 - %52 = OpLabel - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // The header and merge blocks - const uint32_t header_outer_if = 5; - const uint32_t merge_outer_if = 16; - const uint32_t header_then_outer_switch = 15; - const uint32_t merge_then_outer_switch = 22; - const uint32_t header_then_inner_switch = 21; - const uint32_t merge_then_inner_switch = 42; - const uint32_t header_else_switch = 47; - const uint32_t merge_else_switch = 52; - const uint32_t header_inner_if_1 = 19; - const uint32_t merge_inner_if_1 = 35; - const uint32_t header_inner_if_2 = 63; - const uint32_t merge_inner_if_2 = 27; - - // The non-merge-nor-header blocks in each construct - const uint32_t then_outer_switch_block_1 = 18; - const uint32_t then_inner_switch_block_1 = 39; - const uint32_t then_inner_switch_block_2 = 40; - const uint32_t then_inner_switch_block_3 = 41; - const uint32_t else_switch_block_1 = 49; - const uint32_t else_switch_block_2 = 50; - const uint32_t else_switch_block_3 = 51; - const uint32_t inner_if_1_block_1 = 34; - const uint32_t inner_if_1_block_2 = 62; - const uint32_t inner_if_2_block_1 = 26; - - // Fine to branch straight to direct merge block for a construct - ASSERT_TRUE(TransformationAddDeadBreak(then_outer_switch_block_1, - merge_then_outer_switch, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(then_inner_switch_block_1, - merge_then_inner_switch, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(then_inner_switch_block_2, - merge_then_inner_switch, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(then_inner_switch_block_3, - merge_then_inner_switch, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(else_switch_block_1, merge_else_switch, - false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(else_switch_block_2, merge_else_switch, - true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(else_switch_block_3, merge_else_switch, - false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationAddDeadBreak(inner_if_1_block_1, merge_inner_if_1, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(inner_if_1_block_2, merge_inner_if_1, - false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationAddDeadBreak(inner_if_2_block_1, merge_inner_if_2, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break out of a switch from a selection construct inside the - // switch. - ASSERT_FALSE(TransformationAddDeadBreak(inner_if_1_block_1, - merge_then_outer_switch, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(inner_if_1_block_2, - merge_then_outer_switch, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(inner_if_2_block_1, - merge_then_outer_switch, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Some miscellaneous inapplicable cases. - ASSERT_FALSE( - TransformationAddDeadBreak(header_outer_if, merge_outer_if, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(header_inner_if_1, inner_if_1_block_2, - false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(header_then_inner_switch, - header_then_outer_switch, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(header_else_switch, - then_inner_switch_block_3, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(header_inner_if_2, header_inner_if_2, - false, {}) - .IsApplicable(context.get(), fact_manager)); - - auto transformation1 = TransformationAddDeadBreak( - then_outer_switch_block_1, merge_then_outer_switch, true, {}); - auto transformation2 = TransformationAddDeadBreak( - then_inner_switch_block_1, merge_then_inner_switch, false, {}); - auto transformation3 = TransformationAddDeadBreak( - then_inner_switch_block_2, merge_then_inner_switch, true, {}); - auto transformation4 = TransformationAddDeadBreak( - then_inner_switch_block_3, merge_then_inner_switch, true, {}); - auto transformation5 = TransformationAddDeadBreak( - else_switch_block_1, merge_else_switch, false, {}); - auto transformation6 = TransformationAddDeadBreak( - else_switch_block_2, merge_else_switch, true, {}); - auto transformation7 = TransformationAddDeadBreak( - else_switch_block_3, merge_else_switch, false, {}); - auto transformation8 = TransformationAddDeadBreak(inner_if_1_block_1, - merge_inner_if_1, true, {}); - auto transformation9 = TransformationAddDeadBreak( - inner_if_1_block_2, merge_inner_if_1, false, {}); - auto transformation10 = TransformationAddDeadBreak( - inner_if_2_block_1, merge_inner_if_2, true, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager)); - transformation6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager)); - transformation7.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation8.IsApplicable(context.get(), fact_manager)); - transformation8.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation9.IsApplicable(context.get(), fact_manager)); - transformation9.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation10.IsApplicable(context.get(), fact_manager)); - transformation10.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpTypeBool - %29 = OpConstant %6 2 - %32 = OpConstant %6 4 - %36 = OpConstant %6 3 - %60 = OpConstantTrue %13 - %61 = OpConstantFalse %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %47 - %15 = OpLabel - %17 = OpLoad %6 %8 - OpSelectionMerge %22 None - OpSwitch %17 %21 0 %18 1 %18 3 %19 10 %20 - %21 = OpLabel - %38 = OpLoad %6 %11 - OpSelectionMerge %42 None - OpSwitch %38 %41 1 %39 2 %40 - %41 = OpLabel - OpStore %8 %36 - OpBranchConditional %60 %42 %42 - %39 = OpLabel - OpBranchConditional %61 %42 %42 - %40 = OpLabel - OpStore %8 %32 - OpStore %11 %29 - OpBranchConditional %60 %41 %42 - %42 = OpLabel - OpBranch %22 - %18 = OpLabel - %23 = OpLoad %6 %8 - OpBranchConditional %60 %63 %22 - %63 = OpLabel - %24 = OpLoad %6 %11 - %25 = OpIEqual %13 %23 %24 - OpSelectionMerge %27 None - OpBranchConditional %25 %26 %27 - %26 = OpLabel - OpBranchConditional %60 %27 %27 - %27 = OpLabel - OpStore %8 %29 - OpBranch %22 - %19 = OpLabel - %31 = OpLoad %6 %11 - %33 = OpIEqual %13 %31 %32 - OpSelectionMerge %35 None - OpBranchConditional %33 %34 %35 - %34 = OpLabel - OpStore %11 %29 - OpBranchConditional %60 %62 %35 - %62 = OpLabel - OpStore %8 %36 - OpBranchConditional %61 %35 %35 - %35 = OpLabel - OpBranch %20 - %20 = OpLabel - OpBranch %22 - %22 = OpLabel - OpBranch %16 - %47 = OpLabel - %48 = OpLoad %6 %11 - OpSelectionMerge %52 None - OpSwitch %48 %51 1 %49 2 %50 - %51 = OpLabel - %53 = OpLoad %6 %11 - OpStore %8 %53 - OpBranchConditional %61 %52 %52 - %49 = OpLabel - OpStore %8 %32 - OpBranchConditional %61 %52 %50 - %50 = OpLabel - OpStore %11 %36 - OpBranchConditional %60 %51 %52 - %52 = OpLabel - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, BreakOutOfLoopNest) { - // Checks some allowed and disallowed scenarios for a nest of loops, including - // breaking from an if or switch right out of a loop. - - // The SPIR-V for this test is adapted from the following GLSL: - // - // void main() { - // int x, y; - // do { - // x++; - // for (int j = 0; j < 100; j++) { - // y++; - // if (x == y) { - // x++; - // if (x == 2) { - // y++; - // } - // switch (x) { - // case 0: - // x = 2; - // default: - // break; - // } - // } - // } - // } while (x > y); - // - // for (int i = 0; i < 100; i++) { - // x++; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %12 "x" - OpName %16 "j" - OpName %27 "y" - OpName %55 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %14 = OpConstant %10 1 - %17 = OpConstant %10 0 - %24 = OpConstant %10 100 - %25 = OpTypeBool - %38 = OpConstant %10 2 - %67 = OpConstantTrue %25 - %68 = OpConstantFalse %25 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %11 Function - %16 = OpVariable %11 Function - %27 = OpVariable %11 Function - %55 = OpVariable %11 Function - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - %13 = OpLoad %10 %12 - %15 = OpIAdd %10 %13 %14 - OpStore %12 %15 - OpStore %16 %17 - OpBranch %18 - %18 = OpLabel - OpLoopMerge %20 %21 None - OpBranch %22 - %22 = OpLabel - %23 = OpLoad %10 %16 - %26 = OpSLessThan %25 %23 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %28 = OpLoad %10 %27 - %29 = OpIAdd %10 %28 %14 - OpStore %27 %29 - %30 = OpLoad %10 %12 - %31 = OpLoad %10 %27 - %32 = OpIEqual %25 %30 %31 - OpSelectionMerge %34 None - OpBranchConditional %32 %33 %34 - %33 = OpLabel - %35 = OpLoad %10 %12 - %36 = OpIAdd %10 %35 %14 - OpStore %12 %36 - %37 = OpLoad %10 %12 - %39 = OpIEqual %25 %37 %38 - OpSelectionMerge %41 None - OpBranchConditional %39 %40 %41 - %40 = OpLabel - %42 = OpLoad %10 %27 - %43 = OpIAdd %10 %42 %14 - OpStore %27 %43 - OpBranch %41 - %41 = OpLabel - %44 = OpLoad %10 %12 - OpSelectionMerge %47 None - OpSwitch %44 %46 0 %45 - %46 = OpLabel - OpBranch %47 - %45 = OpLabel - OpStore %12 %38 - OpBranch %46 - %47 = OpLabel - OpBranch %34 - %34 = OpLabel - OpBranch %21 - %21 = OpLabel - %50 = OpLoad %10 %16 - %51 = OpIAdd %10 %50 %14 - OpStore %16 %51 - OpBranch %18 - %20 = OpLabel - OpBranch %9 - %9 = OpLabel - %52 = OpLoad %10 %12 - %53 = OpLoad %10 %27 - %54 = OpSGreaterThan %25 %52 %53 - OpBranchConditional %54 %6 %8 - %8 = OpLabel - OpStore %55 %17 - OpBranch %56 - %56 = OpLabel - OpLoopMerge %58 %59 None - OpBranch %60 - %60 = OpLabel - %61 = OpLoad %10 %55 - %62 = OpSLessThan %25 %61 %24 - OpBranchConditional %62 %57 %58 - %57 = OpLabel - %63 = OpLoad %10 %12 - %64 = OpIAdd %10 %63 %14 - OpStore %12 %64 - OpBranch %59 - %59 = OpLabel - %65 = OpLoad %10 %55 - %66 = OpIAdd %10 %65 %14 - OpStore %55 %66 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // The header and merge blocks - const uint32_t header_do_while = 6; - const uint32_t merge_do_while = 8; - const uint32_t header_for_j = 18; - const uint32_t merge_for_j = 20; - const uint32_t header_for_i = 56; - const uint32_t merge_for_i = 58; - const uint32_t header_switch = 41; - const uint32_t merge_switch = 47; - const uint32_t header_if_x_eq_y = 19; - const uint32_t merge_if_x_eq_y = 34; - const uint32_t header_if_x_eq_2 = 33; - const uint32_t merge_if_x_eq_2 = 41; - - // Loop continue targets - const uint32_t continue_do_while = 9; - const uint32_t continue_for_j = 21; - const uint32_t continue_for_i = 59; - - // Some blocks in these constructs - const uint32_t block_in_inner_if = 40; - const uint32_t block_switch_case = 46; - const uint32_t block_switch_default = 45; - const uint32_t block_in_for_i_loop = 57; - - // Fine to break from any loop header to its merge - ASSERT_TRUE( - TransformationAddDeadBreak(header_do_while, merge_do_while, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(header_for_i, merge_for_i, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadBreak(header_for_j, merge_for_j, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Fine to break from any of the blocks in constructs in the "for j" loop to - // that loop's merge - ASSERT_TRUE( - TransformationAddDeadBreak(block_in_inner_if, merge_for_j, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationAddDeadBreak(block_switch_case, merge_for_j, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationAddDeadBreak(block_switch_default, merge_for_j, false, {}) - .IsApplicable(context.get(), fact_manager)); - - // Fine to break from the body of the "for i" loop to that loop's merge - ASSERT_TRUE( - TransformationAddDeadBreak(block_in_for_i_loop, merge_for_i, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break from multiple loops - ASSERT_FALSE( - TransformationAddDeadBreak(block_in_inner_if, merge_do_while, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(block_switch_case, merge_do_while, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(block_switch_default, merge_do_while, - false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(header_for_j, merge_do_while, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break loop from its continue construct - ASSERT_FALSE( - TransformationAddDeadBreak(continue_do_while, merge_do_while, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(continue_for_j, merge_for_j, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(continue_for_i, merge_for_i, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to break out of multiple non-loop constructs if not breaking to a - // loop merge - ASSERT_FALSE( - TransformationAddDeadBreak(block_in_inner_if, merge_if_x_eq_y, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(block_switch_case, merge_if_x_eq_y, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(block_switch_default, merge_if_x_eq_y, - false, {}) - .IsApplicable(context.get(), fact_manager)); - - // Some miscellaneous inapplicable transformations - ASSERT_FALSE( - TransformationAddDeadBreak(header_if_x_eq_2, header_if_x_eq_y, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(merge_if_x_eq_2, merge_switch, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(header_switch, header_switch, false, {}) - .IsApplicable(context.get(), fact_manager)); - - auto transformation1 = - TransformationAddDeadBreak(header_do_while, merge_do_while, true, {}); - auto transformation2 = - TransformationAddDeadBreak(header_for_i, merge_for_i, false, {}); - auto transformation3 = - TransformationAddDeadBreak(header_for_j, merge_for_j, true, {}); - auto transformation4 = - TransformationAddDeadBreak(block_in_inner_if, merge_for_j, false, {}); - auto transformation5 = - TransformationAddDeadBreak(block_switch_case, merge_for_j, true, {}); - auto transformation6 = - TransformationAddDeadBreak(block_switch_default, merge_for_j, false, {}); - auto transformation7 = - TransformationAddDeadBreak(block_in_for_i_loop, merge_for_i, true, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager)); - transformation6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager)); - transformation7.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %12 "x" - OpName %16 "j" - OpName %27 "y" - OpName %55 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %14 = OpConstant %10 1 - %17 = OpConstant %10 0 - %24 = OpConstant %10 100 - %25 = OpTypeBool - %38 = OpConstant %10 2 - %67 = OpConstantTrue %25 - %68 = OpConstantFalse %25 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %11 Function - %16 = OpVariable %11 Function - %27 = OpVariable %11 Function - %55 = OpVariable %11 Function - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranchConditional %67 %7 %8 - %7 = OpLabel - %13 = OpLoad %10 %12 - %15 = OpIAdd %10 %13 %14 - OpStore %12 %15 - OpStore %16 %17 - OpBranch %18 - %18 = OpLabel - OpLoopMerge %20 %21 None - OpBranchConditional %67 %22 %20 - %22 = OpLabel - %23 = OpLoad %10 %16 - %26 = OpSLessThan %25 %23 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %28 = OpLoad %10 %27 - %29 = OpIAdd %10 %28 %14 - OpStore %27 %29 - %30 = OpLoad %10 %12 - %31 = OpLoad %10 %27 - %32 = OpIEqual %25 %30 %31 - OpSelectionMerge %34 None - OpBranchConditional %32 %33 %34 - %33 = OpLabel - %35 = OpLoad %10 %12 - %36 = OpIAdd %10 %35 %14 - OpStore %12 %36 - %37 = OpLoad %10 %12 - %39 = OpIEqual %25 %37 %38 - OpSelectionMerge %41 None - OpBranchConditional %39 %40 %41 - %40 = OpLabel - %42 = OpLoad %10 %27 - %43 = OpIAdd %10 %42 %14 - OpStore %27 %43 - OpBranchConditional %68 %20 %41 - %41 = OpLabel - %44 = OpLoad %10 %12 - OpSelectionMerge %47 None - OpSwitch %44 %46 0 %45 - %46 = OpLabel - OpBranchConditional %67 %47 %20 - %45 = OpLabel - OpStore %12 %38 - OpBranchConditional %68 %20 %46 - %47 = OpLabel - OpBranch %34 - %34 = OpLabel - OpBranch %21 - %21 = OpLabel - %50 = OpLoad %10 %16 - %51 = OpIAdd %10 %50 %14 - OpStore %16 %51 - OpBranch %18 - %20 = OpLabel - OpBranch %9 - %9 = OpLabel - %52 = OpLoad %10 %12 - %53 = OpLoad %10 %27 - %54 = OpSGreaterThan %25 %52 %53 - OpBranchConditional %54 %6 %8 - %8 = OpLabel - OpStore %55 %17 - OpBranch %56 - %56 = OpLabel - OpLoopMerge %58 %59 None - OpBranchConditional %68 %58 %60 - %60 = OpLabel - %61 = OpLoad %10 %55 - %62 = OpSLessThan %25 %61 %24 - OpBranchConditional %62 %57 %58 - %57 = OpLabel - %63 = OpLoad %10 %12 - %64 = OpIAdd %10 %63 %14 - OpStore %12 %64 - OpBranchConditional %67 %59 %58 - %59 = OpLabel - %65 = OpLoad %10 %55 - %66 = OpIAdd %10 %65 %14 - OpStore %55 %66 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, NoBreakFromContinueConstruct) { - // Checks that it is illegal to break straight from a continue construct. - - // The SPIR-V for this test is adapted from the following GLSL: - // - // void main() { - // for (int i = 0; i < 100; i++) { - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - OpDecorate %8 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - OpDecorate %19 RelaxedPrecision - OpDecorate %21 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %22 = OpConstantTrue %17 - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpIAdd %6 %19 %20 - OpBranch %23 - %23 = OpLabel - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Not OK to break loop from its continue construct - ASSERT_FALSE(TransformationAddDeadBreak(13, 12, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(23, 12, true, {}) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, SelectionInContinueConstruct) { - // Considers some scenarios where there is a selection construct in a loop's - // continue construct. - - // The SPIR-V for this test is adapted from the following GLSL: - // - // void main() { - // for (int i = 0; i < 100; i = (i < 50 ? i + 2 : i + 1)) { - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %99 = OpConstantTrue %17 - %20 = OpConstant %6 50 - %26 = OpConstant %6 2 - %30 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpSLessThan %17 %19 %20 - OpSelectionMerge %24 None - OpBranchConditional %21 %23 %28 - %23 = OpLabel - %25 = OpLoad %6 %8 - OpBranch %100 - %100 = OpLabel - %27 = OpIAdd %6 %25 %26 - OpStore %22 %27 - OpBranch %24 - %28 = OpLabel - %29 = OpLoad %6 %8 - OpBranch %101 - %101 = OpLabel - %31 = OpIAdd %6 %29 %30 - OpStore %22 %31 - OpBranch %24 - %24 = OpLabel - %32 = OpLoad %6 %22 - OpStore %8 %32 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - const uint32_t loop_merge = 12; - const uint32_t selection_merge = 24; - const uint32_t in_selection_1 = 23; - const uint32_t in_selection_2 = 100; - const uint32_t in_selection_3 = 28; - const uint32_t in_selection_4 = 101; - - // Not OK to jump from the selection to the loop merge, as this would break - // from the loop's continue construct. - ASSERT_FALSE(TransformationAddDeadBreak(in_selection_1, loop_merge, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(in_selection_2, loop_merge, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(in_selection_3, loop_merge, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationAddDeadBreak(in_selection_4, loop_merge, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // But fine to jump from the selection to its merge. - - auto transformation1 = - TransformationAddDeadBreak(in_selection_1, selection_merge, true, {}); - auto transformation2 = - TransformationAddDeadBreak(in_selection_2, selection_merge, true, {}); - auto transformation3 = - TransformationAddDeadBreak(in_selection_3, selection_merge, true, {}); - auto transformation4 = - TransformationAddDeadBreak(in_selection_4, selection_merge, true, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %99 = OpConstantTrue %17 - %20 = OpConstant %6 50 - %26 = OpConstant %6 2 - %30 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpSLessThan %17 %19 %20 - OpSelectionMerge %24 None - OpBranchConditional %21 %23 %28 - %23 = OpLabel - %25 = OpLoad %6 %8 - OpBranchConditional %99 %100 %24 - %100 = OpLabel - %27 = OpIAdd %6 %25 %26 - OpStore %22 %27 - OpBranchConditional %99 %24 %24 - %28 = OpLabel - %29 = OpLoad %6 %8 - OpBranchConditional %99 %101 %24 - %101 = OpLabel - %31 = OpIAdd %6 %29 %30 - OpStore %22 %31 - OpBranchConditional %99 %24 %24 - %24 = OpLabel - %32 = OpLoad %6 %22 - OpStore %8 %32 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, LoopInContinueConstruct) { - // Considers some scenarios where there is a loop in a loop's continue - // construct. - - // The SPIR-V for this test is adapted from the following GLSL, with inlining - // applied so that the loop from foo is in the main loop's continue construct: - // - // int foo() { - // int result = 0; - // for (int j = 0; j < 10; j++) { - // result++; - // } - // return result; - // } - // - // void main() { - // for (int i = 0; i < 100; i += foo()) { - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %31 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFunction %6 - %10 = OpTypePointer Function %6 - %12 = OpConstant %6 0 - %20 = OpConstant %6 10 - %21 = OpTypeBool - %100 = OpConstantTrue %21 - %24 = OpConstant %6 1 - %38 = OpConstant %6 100 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %43 = OpVariable %10 Function - %44 = OpVariable %10 Function - %45 = OpVariable %10 Function - %31 = OpVariable %10 Function - OpStore %31 %12 - OpBranch %32 - %32 = OpLabel - OpLoopMerge %34 %35 None - OpBranch %36 - %36 = OpLabel - %37 = OpLoad %6 %31 - %39 = OpSLessThan %21 %37 %38 - OpBranchConditional %39 %33 %34 - %33 = OpLabel - OpBranch %35 - %35 = OpLabel - OpStore %43 %12 - OpStore %44 %12 - OpBranch %46 - %46 = OpLabel - OpLoopMerge %47 %48 None - OpBranch %49 - %49 = OpLabel - %50 = OpLoad %6 %44 - %51 = OpSLessThan %21 %50 %20 - OpBranchConditional %51 %52 %47 - %52 = OpLabel - %53 = OpLoad %6 %43 - OpBranch %101 - %101 = OpLabel - %54 = OpIAdd %6 %53 %24 - OpStore %43 %54 - OpBranch %48 - %48 = OpLabel - %55 = OpLoad %6 %44 - %56 = OpIAdd %6 %55 %24 - OpStore %44 %56 - OpBranch %46 - %47 = OpLabel - %57 = OpLoad %6 %43 - OpStore %45 %57 - %40 = OpLoad %6 %45 - %41 = OpLoad %6 %31 - %42 = OpIAdd %6 %41 %40 - OpStore %31 %42 - OpBranch %32 - %34 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - const uint32_t outer_loop_merge = 34; - const uint32_t outer_loop_block = 33; - const uint32_t inner_loop_merge = 47; - const uint32_t inner_loop_block = 52; - - // Some inapplicable cases - ASSERT_FALSE( - TransformationAddDeadBreak(inner_loop_block, outer_loop_merge, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationAddDeadBreak(outer_loop_block, inner_loop_merge, true, {}) - .IsApplicable(context.get(), fact_manager)); - - auto transformation1 = - TransformationAddDeadBreak(inner_loop_block, inner_loop_merge, true, {}); - auto transformation2 = - TransformationAddDeadBreak(outer_loop_block, outer_loop_merge, true, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %31 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFunction %6 - %10 = OpTypePointer Function %6 - %12 = OpConstant %6 0 - %20 = OpConstant %6 10 - %21 = OpTypeBool - %100 = OpConstantTrue %21 - %24 = OpConstant %6 1 - %38 = OpConstant %6 100 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %43 = OpVariable %10 Function - %44 = OpVariable %10 Function - %45 = OpVariable %10 Function - %31 = OpVariable %10 Function - OpStore %31 %12 - OpBranch %32 - %32 = OpLabel - OpLoopMerge %34 %35 None - OpBranch %36 - %36 = OpLabel - %37 = OpLoad %6 %31 - %39 = OpSLessThan %21 %37 %38 - OpBranchConditional %39 %33 %34 - %33 = OpLabel - OpBranchConditional %100 %35 %34 - %35 = OpLabel - OpStore %43 %12 - OpStore %44 %12 - OpBranch %46 - %46 = OpLabel - OpLoopMerge %47 %48 None - OpBranch %49 - %49 = OpLabel - %50 = OpLoad %6 %44 - %51 = OpSLessThan %21 %50 %20 - OpBranchConditional %51 %52 %47 - %52 = OpLabel - %53 = OpLoad %6 %43 - OpBranchConditional %100 %101 %47 - %101 = OpLabel - %54 = OpIAdd %6 %53 %24 - OpStore %43 %54 - OpBranch %48 - %48 = OpLabel - %55 = OpLoad %6 %44 - %56 = OpIAdd %6 %55 %24 - OpStore %44 %56 - OpBranch %46 - %47 = OpLabel - %57 = OpLoad %6 %43 - OpStore %45 %57 - %40 = OpLoad %6 %45 - %41 = OpLoad %6 %31 - %42 = OpIAdd %6 %41 %40 - OpStore %31 %42 - OpBranch %32 - %34 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, PhiInstructions) { - // Checks that the transformation works in the presence of phi instructions. - - // The SPIR-V for this test is adapted from the following GLSL, with a bit of - // extra and artificial work to get some interesting uses of OpPhi: - // - // void main() { - // int x; int y; - // float f; - // x = 2; - // f = 3.0; - // if (x > y) { - // x = 3; - // f = 4.0; - // } else { - // x = x + 2; - // f = f + 10.0; - // } - // while (x < y) { - // x = x + 1; - // f = f + 1.0; - // } - // y = x; - // f = f + 3.0; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %12 "f" - OpName %15 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %10 = OpTypeFloat 32 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 3 - %17 = OpTypeBool - %80 = OpConstantTrue %17 - %21 = OpConstant %6 3 - %22 = OpConstant %10 4 - %27 = OpConstant %10 10 - %38 = OpConstant %6 1 - %41 = OpConstant %10 1 - %46 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %15 = OpVariable %7 Function - OpStore %8 %9 - OpStore %12 %13 - %18 = OpSGreaterThan %17 %9 %46 - OpSelectionMerge %20 None - OpBranchConditional %18 %19 %23 - %19 = OpLabel - OpStore %8 %21 - OpStore %12 %22 - OpBranch %20 - %23 = OpLabel - %25 = OpIAdd %6 %9 %9 - OpStore %8 %25 - OpBranch %70 - %70 = OpLabel - %28 = OpFAdd %10 %13 %27 - OpStore %12 %28 - OpBranch %20 - %20 = OpLabel - %52 = OpPhi %10 %22 %19 %28 %70 - %48 = OpPhi %6 %21 %19 %25 %70 - OpBranch %29 - %29 = OpLabel - %51 = OpPhi %10 %52 %20 %42 %32 - %47 = OpPhi %6 %48 %20 %39 %32 - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %36 = OpSLessThan %17 %47 %46 - OpBranchConditional %36 %30 %31 - %30 = OpLabel - %39 = OpIAdd %6 %47 %38 - OpStore %8 %39 - OpBranch %75 - %75 = OpLabel - %42 = OpFAdd %10 %51 %41 - OpStore %12 %42 - OpBranch %32 - %32 = OpLabel - OpBranch %29 - %31 = OpLabel - %71 = OpPhi %6 %47 %33 - %72 = OpPhi %10 %51 %33 - OpStore %15 %71 - %45 = OpFAdd %10 %72 %13 - OpStore %12 %45 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Some inapplicable transformations - // Not applicable because there is already an edge 19->20, so the OpPhis at 20 - // do not need to be updated - ASSERT_FALSE(TransformationAddDeadBreak(19, 20, true, {13, 21}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because two OpPhis (not zero) need to be updated at 20 - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because two OpPhis (not just one) need to be updated at 20 - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {13}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because only two OpPhis (not three) need to be updated at 20 - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {13, 21, 22}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because the given ids do not have types that match the - // OpPhis at 20, in order - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {21, 13}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because id 23 is a label - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {21, 23}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because 101 is not an id - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {21, 101}) - .IsApplicable(context.get(), fact_manager)); - // Not applicable because ids 51 and 47 are not available at the end of block - // 23 - ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {51, 47}) - .IsApplicable(context.get(), fact_manager)); - - // Not applicable because OpConstantFalse is not present in the module - ASSERT_FALSE(TransformationAddDeadBreak(19, 20, false, {}) - .IsApplicable(context.get(), fact_manager)); - - auto transformation1 = TransformationAddDeadBreak(19, 20, true, {}); - auto transformation2 = TransformationAddDeadBreak(23, 20, true, {13, 21}); - auto transformation3 = TransformationAddDeadBreak(70, 20, true, {}); - auto transformation4 = TransformationAddDeadBreak(30, 31, true, {21, 13}); - auto transformation5 = TransformationAddDeadBreak(75, 31, true, {47, 51}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %12 "f" - OpName %15 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %10 = OpTypeFloat 32 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 3 - %17 = OpTypeBool - %80 = OpConstantTrue %17 - %21 = OpConstant %6 3 - %22 = OpConstant %10 4 - %27 = OpConstant %10 10 - %38 = OpConstant %6 1 - %41 = OpConstant %10 1 - %46 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %15 = OpVariable %7 Function - OpStore %8 %9 - OpStore %12 %13 - %18 = OpSGreaterThan %17 %9 %46 - OpSelectionMerge %20 None - OpBranchConditional %18 %19 %23 - %19 = OpLabel - OpStore %8 %21 - OpStore %12 %22 - OpBranchConditional %80 %20 %20 - %23 = OpLabel - %25 = OpIAdd %6 %9 %9 - OpStore %8 %25 - OpBranchConditional %80 %70 %20 - %70 = OpLabel - %28 = OpFAdd %10 %13 %27 - OpStore %12 %28 - OpBranchConditional %80 %20 %20 - %20 = OpLabel - %52 = OpPhi %10 %22 %19 %28 %70 %13 %23 - %48 = OpPhi %6 %21 %19 %25 %70 %21 %23 - OpBranch %29 - %29 = OpLabel - %51 = OpPhi %10 %52 %20 %42 %32 - %47 = OpPhi %6 %48 %20 %39 %32 - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %36 = OpSLessThan %17 %47 %46 - OpBranchConditional %36 %30 %31 - %30 = OpLabel - %39 = OpIAdd %6 %47 %38 - OpStore %8 %39 - OpBranchConditional %80 %75 %31 - %75 = OpLabel - %42 = OpFAdd %10 %51 %41 - OpStore %12 %42 - OpBranchConditional %80 %32 %31 - %32 = OpLabel - OpBranch %29 - %31 = OpLabel - %71 = OpPhi %6 %47 %33 %21 %30 %47 %75 - %72 = OpPhi %10 %51 %33 %13 %30 %51 %75 - OpStore %15 %71 - %45 = OpFAdd %10 %72 %13 - OpStore %12 %45 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules1) { - // Right after the loop, an OpCopyObject defined by the loop is used. Adding - // a dead break would prevent that use from being dominated by its definition, - // so is not allowed. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %102 None - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %104 - %104 = OpLabel - OpBranch %102 - %102 = OpLabel - OpBranchConditional %11 %100 %101 - %101 = OpLabel - %201 = OpCopyObject %10 %200 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadBreak(100, 101, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules2) { - // This example captures the following idiom: - // - // if { - // L1: - // } - // definition; - // L2: - // use; - // - // Adding a dead jump from L1 to L2 would lead to 'definition' no longer - // dominating 'use', and so is not allowed. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpSelectionMerge %101 None - OpBranchConditional %11 %102 %103 - %102 = OpLabel - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %101 - %101 = OpLabel - %201 = OpCopyObject %10 %200 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules3) { - // Right after the loop, an OpCopyObject defined by the loop is used in an - // OpPhi. Adding a dead break is OK in this case, due to the use being in an - // OpPhi. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %102 None - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %104 - %104 = OpLabel - OpBranch %102 - %102 = OpLabel - OpBranchConditional %11 %100 %101 - %101 = OpLabel - %201 = OpPhi %10 %200 %102 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto good_transformation = TransformationAddDeadBreak(100, 101, false, {11}); - ASSERT_TRUE(good_transformation.IsApplicable(context.get(), fact_manager)); - - good_transformation.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %102 None - OpBranchConditional %11 %101 %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %104 - %104 = OpLabel - OpBranch %102 - %102 = OpLabel - OpBranchConditional %11 %100 %101 - %101 = OpLabel - %201 = OpPhi %10 %200 %102 %11 %100 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules4) { - // This example captures the following idiom: - // - // if { - // L1: - // } - // definition; - // L2: - // use in OpPhi; - // - // Adding a dead jump from L1 to L2 is OK, due to 'use' being in an OpPhi. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpSelectionMerge %101 None - OpBranchConditional %11 %102 %103 - %102 = OpLabel - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %101 - %101 = OpLabel - %201 = OpPhi %10 %200 %103 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto good_transformation = TransformationAddDeadBreak(102, 101, false, {11}); - ASSERT_TRUE(good_transformation.IsApplicable(context.get(), fact_manager)); - - good_transformation.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpSelectionMerge %101 None - OpBranchConditional %11 %102 %103 - %102 = OpLabel - OpBranchConditional %11 %101 %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %101 - %101 = OpLabel - %201 = OpPhi %10 %200 %103 %11 %102 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules5) { - // After, but not right after, the loop, an OpCopyObject defined by the loop - // is used in an OpPhi. Adding a dead break is not OK in this case. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %102 None - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %104 - %104 = OpLabel - OpBranch %102 - %102 = OpLabel - OpBranchConditional %11 %100 %101 - %101 = OpLabel - OpBranch %105 - %105 = OpLabel - %201 = OpPhi %10 %200 %101 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadBreak(100, 101, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules6) { - // This example captures the following idiom: - // - // if { - // L1: - // } - // definition; - // L2: - // goto L3; - // L3: - // use in OpPhi; - // - // Adding a dead jump from L1 to L2 not OK, due to the use in an OpPhi being - // in L3. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpSelectionMerge %101 None - OpBranchConditional %11 %102 %103 - %102 = OpLabel - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %101 - %101 = OpLabel - OpBranch %150 - %150 = OpLabel - %201 = OpPhi %10 %200 %101 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules7) { - // This example - a variation on an earlier test - captures the following - // idiom: - // - // loop { - // L1: - // } - // definition; - // L2: - // use; - // - // Adding a dead jump from L1 to L2 would lead to 'definition' no longer - // dominating 'use', and so is not allowed. - // - // This version of the test captures the case where L1 appears after the - // loop merge (which SPIR-V dominance rules allow). - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %104 None - OpBranchConditional %11 %102 %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %101 - %101 = OpLabel - %201 = OpCopyObject %10 %200 - OpReturn - %102 = OpLabel - OpBranch %103 - %104 = OpLabel - OpBranch %100 - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, RespectDominanceRules8) { - // A variation of RespectDominanceRules8 where the defining block appears - // in the loop, but after the definition of interest. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %104 None - OpBranchConditional %11 %102 %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %101 - %102 = OpLabel - OpBranch %103 - %101 = OpLabel - %201 = OpCopyObject %10 %200 - OpReturn - %104 = OpLabel - OpBranch %100 - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadBreakTest, - BreakWouldDisobeyDominanceBlockOrderingRules) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %9 = OpConstantTrue %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %16 %15 None - OpBranch %11 - %11 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %9 %12 %13 - %14 = OpLabel - OpBranch %15 - %12 = OpLabel - OpBranch %16 - %13 = OpLabel - OpBranch %16 - %15 = OpLabel - OpBranch %10 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Bad because 14 comes before 12 in the module, and 14 has no predecessors. - // This means that an edge from 12 to 14 will lead to 12 dominating 14, which - // is illegal if 12 appears after 14. - auto bad_transformation = TransformationAddDeadBreak(12, 14, true, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_dead_continue_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_dead_continue_test.cpp deleted file mode 100644 index ff93da8a9..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_dead_continue_test.cpp +++ /dev/null @@ -1,1562 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_dead_continue.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddDeadContinueTest, SimpleExample) { - // For a simple loop, checks that some dead continue scenarios are possible, - // sanity-checks that some illegal scenarios are indeed not allowed, and then - // applies a transformation. - - // The SPIR-V for this test is adapted from the following GLSL, by separating - // some assignments into their own basic blocks, and adding constants for true - // and false: - // - // void main() { - // int x = 0; - // for (int i = 0; i < 10; i++) { - // x = x + i; - // x = x + i; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %41 = OpConstantTrue %18 - %42 = OpConstantFalse %18 - %27 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %16 = OpLoad %6 %10 - %19 = OpSLessThan %18 %16 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %20 = OpLoad %6 %8 - %21 = OpLoad %6 %10 - %22 = OpIAdd %6 %20 %21 - OpStore %8 %22 - OpBranch %40 - %40 = OpLabel - %23 = OpLoad %6 %8 - %24 = OpLoad %6 %10 - %25 = OpIAdd %6 %23 %24 - OpStore %8 %25 - OpBranch %14 - %14 = OpLabel - %26 = OpLoad %6 %10 - %28 = OpIAdd %6 %26 %27 - OpStore %10 %28 - OpBranch %11 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - FactManager fact_manager; - - // These are all possibilities. - ASSERT_TRUE(TransformationAddDeadContinue(11, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadContinue(11, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadContinue(12, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadContinue(12, false, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadContinue(40, true, {}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationAddDeadContinue(40, false, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 100 is not a block id. - ASSERT_FALSE(TransformationAddDeadContinue(100, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 10 is not in a loop. - ASSERT_FALSE(TransformationAddDeadContinue(10, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 15 does not branch unconditionally to a single successor. - ASSERT_FALSE(TransformationAddDeadContinue(15, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 13 is not in a loop and has no successor. - ASSERT_FALSE(TransformationAddDeadContinue(13, true, {}) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable: 14 is the loop continue target, so it's not OK to jump to - // the loop continue from there. - ASSERT_FALSE(TransformationAddDeadContinue(14, false, {}) - .IsApplicable(context.get(), fact_manager)); - - // These are the transformations we will apply. - auto transformation1 = TransformationAddDeadContinue(11, true, {}); - auto transformation2 = TransformationAddDeadContinue(12, false, {}); - auto transformation3 = TransformationAddDeadContinue(40, true, {}); - - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %41 = OpConstantTrue %18 - %42 = OpConstantFalse %18 - %27 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - OpLoopMerge %13 %14 None - OpBranchConditional %41 %15 %14 - %15 = OpLabel - %16 = OpLoad %6 %10 - %19 = OpSLessThan %18 %16 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %20 = OpLoad %6 %8 - %21 = OpLoad %6 %10 - %22 = OpIAdd %6 %20 %21 - OpStore %8 %22 - OpBranchConditional %42 %14 %40 - %40 = OpLabel - %23 = OpLoad %6 %8 - %24 = OpLoad %6 %10 - %25 = OpIAdd %6 %23 %24 - OpStore %8 %25 - OpBranchConditional %41 %14 %14 - %14 = OpLabel - %26 = OpLoad %6 %10 - %28 = OpIAdd %6 %26 %27 - OpStore %10 %28 - OpBranch %11 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadContinueTest, LoopNest) { - // Checks some allowed and disallowed scenarios for a nest of loops, including - // continuing a loop from an if or switch. - - // The SPIR-V for this test is adapted from the following GLSL: - // - // void main() { - // int x, y; - // do { - // x++; - // for (int j = 0; j < 100; j++) { - // y++; - // if (x == y) { - // x++; - // if (x == 2) { - // y++; - // } - // switch (x) { - // case 0: - // x = 2; - // default: - // break; - // } - // } - // } - // } while (x > y); - // - // for (int i = 0; i < 100; i++) { - // x++; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %12 "x" - OpName %16 "j" - OpName %27 "y" - OpName %55 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %14 = OpConstant %10 1 - %17 = OpConstant %10 0 - %24 = OpConstant %10 100 - %25 = OpTypeBool - %38 = OpConstant %10 2 - %67 = OpConstantTrue %25 - %68 = OpConstantFalse %25 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %11 Function - %16 = OpVariable %11 Function - %27 = OpVariable %11 Function - %55 = OpVariable %11 Function - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - %13 = OpLoad %10 %12 - %15 = OpIAdd %10 %13 %14 - OpStore %12 %15 - OpStore %16 %17 - OpBranch %18 - %18 = OpLabel - OpLoopMerge %20 %21 None - OpBranch %22 - %22 = OpLabel - %23 = OpLoad %10 %16 - %26 = OpSLessThan %25 %23 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %28 = OpLoad %10 %27 - %29 = OpIAdd %10 %28 %14 - OpStore %27 %29 - %30 = OpLoad %10 %12 - %31 = OpLoad %10 %27 - %32 = OpIEqual %25 %30 %31 - OpSelectionMerge %34 None - OpBranchConditional %32 %33 %34 - %33 = OpLabel - %35 = OpLoad %10 %12 - %36 = OpIAdd %10 %35 %14 - OpStore %12 %36 - %37 = OpLoad %10 %12 - %39 = OpIEqual %25 %37 %38 - OpSelectionMerge %41 None - OpBranchConditional %39 %40 %41 - %40 = OpLabel - %42 = OpLoad %10 %27 - %43 = OpIAdd %10 %42 %14 - OpStore %27 %43 - OpBranch %41 - %41 = OpLabel - %44 = OpLoad %10 %12 - OpSelectionMerge %47 None - OpSwitch %44 %46 0 %45 - %46 = OpLabel - OpBranch %47 - %45 = OpLabel - OpStore %12 %38 - OpBranch %46 - %47 = OpLabel - OpBranch %34 - %34 = OpLabel - OpBranch %21 - %21 = OpLabel - %50 = OpLoad %10 %16 - %51 = OpIAdd %10 %50 %14 - OpStore %16 %51 - OpBranch %18 - %20 = OpLabel - OpBranch %9 - %9 = OpLabel - %52 = OpLoad %10 %12 - %53 = OpLoad %10 %27 - %54 = OpSGreaterThan %25 %52 %53 - OpBranchConditional %54 %6 %8 - %8 = OpLabel - OpStore %55 %17 - OpBranch %56 - %56 = OpLabel - OpLoopMerge %58 %59 None - OpBranch %60 - %60 = OpLabel - %61 = OpLoad %10 %55 - %62 = OpSLessThan %25 %61 %24 - OpBranchConditional %62 %57 %58 - %57 = OpLabel - %63 = OpLoad %10 %12 - %64 = OpIAdd %10 %63 %14 - OpStore %12 %64 - OpBranch %59 - %59 = OpLabel - %65 = OpLoad %10 %55 - %66 = OpIAdd %10 %65 %14 - OpStore %55 %66 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - std::vector good = {6, 7, 18, 20, 34, 40, 45, 46, 47, 56, 57}; - std::vector bad = {5, 8, 9, 19, 21, 22, 33, 41, 58, 59, 60}; - - for (uint32_t from_block : bad) { - ASSERT_FALSE(TransformationAddDeadContinue(from_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - } - for (uint32_t from_block : good) { - const TransformationAddDeadContinue transformation(from_block, true, {}); - ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager)); - transformation.Apply(context.get(), &fact_manager); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); - } - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %12 "x" - OpName %16 "j" - OpName %27 "y" - OpName %55 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %14 = OpConstant %10 1 - %17 = OpConstant %10 0 - %24 = OpConstant %10 100 - %25 = OpTypeBool - %38 = OpConstant %10 2 - %67 = OpConstantTrue %25 - %68 = OpConstantFalse %25 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %11 Function - %16 = OpVariable %11 Function - %27 = OpVariable %11 Function - %55 = OpVariable %11 Function - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranchConditional %67 %7 %9 - %7 = OpLabel - %13 = OpLoad %10 %12 - %15 = OpIAdd %10 %13 %14 - OpStore %12 %15 - OpStore %16 %17 - OpBranchConditional %67 %18 %9 - %18 = OpLabel - OpLoopMerge %20 %21 None - OpBranchConditional %67 %22 %21 - %22 = OpLabel - %23 = OpLoad %10 %16 - %26 = OpSLessThan %25 %23 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %28 = OpLoad %10 %27 - %29 = OpIAdd %10 %28 %14 - OpStore %27 %29 - %30 = OpLoad %10 %12 - %31 = OpLoad %10 %27 - %32 = OpIEqual %25 %30 %31 - OpSelectionMerge %34 None - OpBranchConditional %32 %33 %34 - %33 = OpLabel - %35 = OpLoad %10 %12 - %36 = OpIAdd %10 %35 %14 - OpStore %12 %36 - %37 = OpLoad %10 %12 - %39 = OpIEqual %25 %37 %38 - OpSelectionMerge %41 None - OpBranchConditional %39 %40 %41 - %40 = OpLabel - %42 = OpLoad %10 %27 - %43 = OpIAdd %10 %42 %14 - OpStore %27 %43 - OpBranchConditional %67 %41 %21 - %41 = OpLabel - %44 = OpLoad %10 %12 - OpSelectionMerge %47 None - OpSwitch %44 %46 0 %45 - %46 = OpLabel - OpBranchConditional %67 %47 %21 - %45 = OpLabel - OpStore %12 %38 - OpBranchConditional %67 %46 %21 - %47 = OpLabel - OpBranchConditional %67 %34 %21 - %34 = OpLabel - OpBranchConditional %67 %21 %21 - %21 = OpLabel - %50 = OpLoad %10 %16 - %51 = OpIAdd %10 %50 %14 - OpStore %16 %51 - OpBranch %18 - %20 = OpLabel - OpBranchConditional %67 %9 %9 - %9 = OpLabel - %52 = OpLoad %10 %12 - %53 = OpLoad %10 %27 - %54 = OpSGreaterThan %25 %52 %53 - OpBranchConditional %54 %6 %8 - %8 = OpLabel - OpStore %55 %17 - OpBranch %56 - %56 = OpLabel - OpLoopMerge %58 %59 None - OpBranchConditional %67 %60 %59 - %60 = OpLabel - %61 = OpLoad %10 %55 - %62 = OpSLessThan %25 %61 %24 - OpBranchConditional %62 %57 %58 - %57 = OpLabel - %63 = OpLoad %10 %12 - %64 = OpIAdd %10 %63 %14 - OpStore %12 %64 - OpBranchConditional %67 %59 %59 - %59 = OpLabel - %65 = OpLoad %10 %55 - %66 = OpIAdd %10 %65 %14 - OpStore %55 %66 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadConditionalTest, LoopInContinueConstruct) { - // Considers some scenarios where there is a loop in a loop's continue - // construct. - - // The SPIR-V for this test is adapted from the following GLSL, with inlining - // applied so that the loop from foo is in the main loop's continue construct: - // - // int foo() { - // int result = 0; - // for (int j = 0; j < 10; j++) { - // result++; - // } - // return result; - // } - // - // void main() { - // for (int i = 0; i < 100; i += foo()) { - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %31 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFunction %6 - %10 = OpTypePointer Function %6 - %12 = OpConstant %6 0 - %20 = OpConstant %6 10 - %21 = OpTypeBool - %100 = OpConstantFalse %21 - %24 = OpConstant %6 1 - %38 = OpConstant %6 100 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %43 = OpVariable %10 Function - %44 = OpVariable %10 Function - %45 = OpVariable %10 Function - %31 = OpVariable %10 Function - OpStore %31 %12 - OpBranch %32 - %32 = OpLabel - OpLoopMerge %34 %35 None - OpBranch %36 - %36 = OpLabel - %37 = OpLoad %6 %31 - %39 = OpSLessThan %21 %37 %38 - OpBranchConditional %39 %33 %34 - %33 = OpLabel - OpBranch %35 - %35 = OpLabel - OpStore %43 %12 - OpStore %44 %12 - OpBranch %46 - %46 = OpLabel - OpLoopMerge %47 %48 None - OpBranch %49 - %49 = OpLabel - %50 = OpLoad %6 %44 - %51 = OpSLessThan %21 %50 %20 - OpBranchConditional %51 %52 %47 - %52 = OpLabel - %53 = OpLoad %6 %43 - OpBranch %101 - %101 = OpLabel - %54 = OpIAdd %6 %53 %24 - OpStore %43 %54 - OpBranch %48 - %48 = OpLabel - %55 = OpLoad %6 %44 - %56 = OpIAdd %6 %55 %24 - OpStore %44 %56 - OpBranch %46 - %47 = OpLabel - %57 = OpLoad %6 %43 - OpStore %45 %57 - %40 = OpLoad %6 %45 - %41 = OpLoad %6 %31 - %42 = OpIAdd %6 %41 %40 - OpStore %31 %42 - OpBranch %32 - %34 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - std::vector good = {32, 33, 46, 52, 101}; - std::vector bad = {5, 34, 36, 35, 47, 49, 48}; - - for (uint32_t from_block : bad) { - ASSERT_FALSE(TransformationAddDeadContinue(from_block, false, {}) - .IsApplicable(context.get(), fact_manager)); - } - for (uint32_t from_block : good) { - const TransformationAddDeadContinue transformation(from_block, false, {}); - ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager)); - transformation.Apply(context.get(), &fact_manager); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); - } - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %31 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFunction %6 - %10 = OpTypePointer Function %6 - %12 = OpConstant %6 0 - %20 = OpConstant %6 10 - %21 = OpTypeBool - %100 = OpConstantFalse %21 - %24 = OpConstant %6 1 - %38 = OpConstant %6 100 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %43 = OpVariable %10 Function - %44 = OpVariable %10 Function - %45 = OpVariable %10 Function - %31 = OpVariable %10 Function - OpStore %31 %12 - OpBranch %32 - %32 = OpLabel - OpLoopMerge %34 %35 None - OpBranchConditional %100 %35 %36 - %36 = OpLabel - %37 = OpLoad %6 %31 - %39 = OpSLessThan %21 %37 %38 - OpBranchConditional %39 %33 %34 - %33 = OpLabel - OpBranchConditional %100 %35 %35 - %35 = OpLabel - OpStore %43 %12 - OpStore %44 %12 - OpBranch %46 - %46 = OpLabel - OpLoopMerge %47 %48 None - OpBranchConditional %100 %48 %49 - %49 = OpLabel - %50 = OpLoad %6 %44 - %51 = OpSLessThan %21 %50 %20 - OpBranchConditional %51 %52 %47 - %52 = OpLabel - %53 = OpLoad %6 %43 - OpBranchConditional %100 %48 %101 - %101 = OpLabel - %54 = OpIAdd %6 %53 %24 - OpStore %43 %54 - OpBranchConditional %100 %48 %48 - %48 = OpLabel - %55 = OpLoad %6 %44 - %56 = OpIAdd %6 %55 %24 - OpStore %44 %56 - OpBranch %46 - %47 = OpLabel - %57 = OpLoad %6 %43 - OpStore %45 %57 - %40 = OpLoad %6 %45 - %41 = OpLoad %6 %31 - %42 = OpIAdd %6 %41 %40 - OpStore %31 %42 - OpBranch %32 - %34 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadContinueTest, PhiInstructions) { - // Checks that the transformation works in the presence of phi instructions. - - // The SPIR-V for this test is adapted from the following GLSL, with a bit of - // extra and artificial work to get some interesting uses of OpPhi: - // - // void main() { - // int x; int y; - // float f; - // x = 2; - // f = 3.0; - // if (x > y) { - // x = 3; - // f = 4.0; - // } else { - // x = x + 2; - // f = f + 10.0; - // } - // while (x < y) { - // x = x + 1; - // f = f + 1.0; - // } - // y = x; - // f = f + 3.0; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %12 "f" - OpName %15 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %10 = OpTypeFloat 32 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 3 - %17 = OpTypeBool - %80 = OpConstantTrue %17 - %21 = OpConstant %6 3 - %22 = OpConstant %10 4 - %27 = OpConstant %10 10 - %38 = OpConstant %6 1 - %41 = OpConstant %10 1 - %46 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %15 = OpVariable %7 Function - OpStore %8 %9 - OpStore %12 %13 - %18 = OpSGreaterThan %17 %9 %46 - OpSelectionMerge %20 None - OpBranchConditional %18 %19 %23 - %19 = OpLabel - OpStore %8 %21 - OpStore %12 %22 - OpBranch %20 - %23 = OpLabel - %25 = OpIAdd %6 %9 %9 - OpStore %8 %25 - OpBranch %70 - %70 = OpLabel - %28 = OpFAdd %10 %13 %27 - OpStore %12 %28 - OpBranch %20 - %20 = OpLabel - %52 = OpPhi %10 %22 %19 %28 %70 - %48 = OpPhi %6 %21 %19 %25 %70 - OpBranch %29 - %29 = OpLabel - %51 = OpPhi %10 %52 %20 %100 %32 - %47 = OpPhi %6 %48 %20 %101 %32 - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %36 = OpSLessThan %17 %47 %46 - OpBranchConditional %36 %30 %31 - %30 = OpLabel - %39 = OpIAdd %6 %47 %38 - OpStore %8 %39 - OpBranch %75 - %75 = OpLabel - %42 = OpFAdd %10 %51 %41 - OpStore %12 %42 - OpBranch %32 - %32 = OpLabel - %100 = OpPhi %10 %42 %75 - %101 = OpPhi %6 %39 %75 - OpBranch %29 - %31 = OpLabel - %71 = OpPhi %6 %47 %33 - %72 = OpPhi %10 %51 %33 - OpStore %15 %71 - %45 = OpFAdd %10 %72 %13 - OpStore %12 %45 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - std::vector bad = {5, 19, 20, 23, 31, 32, 33, 70}; - - std::vector good = {29, 30, 75}; - - for (uint32_t from_block : bad) { - ASSERT_FALSE(TransformationAddDeadContinue(from_block, true, {}) - .IsApplicable(context.get(), fact_manager)); - } - auto transformation1 = TransformationAddDeadContinue(29, true, {13, 21}); - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - - auto transformation2 = TransformationAddDeadContinue(30, true, {22, 46}); - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - - // 75 already has the continue block as a successor, so we should not provide - // phi ids. - auto transformationBad = TransformationAddDeadContinue(75, true, {27, 46}); - ASSERT_FALSE(transformationBad.IsApplicable(context.get(), fact_manager)); - - auto transformation3 = TransformationAddDeadContinue(75, true, {}); - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %12 "f" - OpName %15 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %10 = OpTypeFloat 32 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 3 - %17 = OpTypeBool - %80 = OpConstantTrue %17 - %21 = OpConstant %6 3 - %22 = OpConstant %10 4 - %27 = OpConstant %10 10 - %38 = OpConstant %6 1 - %41 = OpConstant %10 1 - %46 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %12 = OpVariable %11 Function - %15 = OpVariable %7 Function - OpStore %8 %9 - OpStore %12 %13 - %18 = OpSGreaterThan %17 %9 %46 - OpSelectionMerge %20 None - OpBranchConditional %18 %19 %23 - %19 = OpLabel - OpStore %8 %21 - OpStore %12 %22 - OpBranch %20 - %23 = OpLabel - %25 = OpIAdd %6 %9 %9 - OpStore %8 %25 - OpBranch %70 - %70 = OpLabel - %28 = OpFAdd %10 %13 %27 - OpStore %12 %28 - OpBranch %20 - %20 = OpLabel - %52 = OpPhi %10 %22 %19 %28 %70 - %48 = OpPhi %6 %21 %19 %25 %70 - OpBranch %29 - %29 = OpLabel - %51 = OpPhi %10 %52 %20 %100 %32 - %47 = OpPhi %6 %48 %20 %101 %32 - OpLoopMerge %31 %32 None - OpBranchConditional %80 %33 %32 - %33 = OpLabel - %36 = OpSLessThan %17 %47 %46 - OpBranchConditional %36 %30 %31 - %30 = OpLabel - %39 = OpIAdd %6 %47 %38 - OpStore %8 %39 - OpBranchConditional %80 %75 %32 - %75 = OpLabel - %42 = OpFAdd %10 %51 %41 - OpStore %12 %42 - OpBranchConditional %80 %32 %32 - %32 = OpLabel - %100 = OpPhi %10 %42 %75 %13 %29 %22 %30 - %101 = OpPhi %6 %39 %75 %21 %29 %46 %30 - OpBranch %29 - %31 = OpLabel - %71 = OpPhi %6 %47 %33 - %72 = OpPhi %10 %51 %33 - OpStore %15 %71 - %45 = OpFAdd %10 %72 %13 - OpStore %12 %45 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationAddDeadContinueTest, RespectDominanceRules1) { - // Checks that a dead continue cannot be added if it would prevent a block - // later in the loop from dominating the loop's continue construct, in the - // case where said block defines and id that is used in the loop's continue - // construct. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - %21 = OpCopyObject %10 %11 - OpBranch %9 - %9 = OpLabel - %20 = OpPhi %10 %21 %7 - OpBranchConditional %11 %6 %8 - %8 = OpLabel - OpBranch %12 - %12 = OpLabel - OpLoopMerge %14 %15 None - OpBranch %13 - %13 = OpLabel - OpBranch %22 - %22 = OpLabel - %23 = OpCopyObject %10 %11 - OpBranch %25 - %25 = OpLabel - OpBranch %15 - %15 = OpLabel - %26 = OpCopyObject %10 %23 - OpBranchConditional %11 %12 %14 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // This transformation is not applicable because the dead continue from the - // loop body prevents the definition of %23 later in the loop body from - // dominating its use in the loop's continue target. - auto bad_transformation = TransformationAddDeadContinue(13, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); - - auto good_transformation_1 = TransformationAddDeadContinue(7, false, {}); - ASSERT_TRUE(good_transformation_1.IsApplicable(context.get(), fact_manager)); - good_transformation_1.Apply(context.get(), &fact_manager); - - auto good_transformation_2 = TransformationAddDeadContinue(22, false, {}); - ASSERT_TRUE(good_transformation_2.IsApplicable(context.get(), fact_manager)); - good_transformation_2.Apply(context.get(), &fact_manager); - - // This transformation is OK, because the definition of %21 in the loop body - // is only used in an OpPhi in the loop's continue target. - auto good_transformation_3 = TransformationAddDeadContinue(6, false, {11}); - ASSERT_TRUE(good_transformation_3.IsApplicable(context.get(), fact_manager)); - good_transformation_3.Apply(context.get(), &fact_manager); - - std::string after_transformations = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranchConditional %11 %9 %7 - %7 = OpLabel - %21 = OpCopyObject %10 %11 - OpBranchConditional %11 %9 %9 - %9 = OpLabel - %20 = OpPhi %10 %21 %7 %11 %6 - OpBranchConditional %11 %6 %8 - %8 = OpLabel - OpBranch %12 - %12 = OpLabel - OpLoopMerge %14 %15 None - OpBranch %13 - %13 = OpLabel - OpBranch %22 - %22 = OpLabel - %23 = OpCopyObject %10 %11 - OpBranchConditional %11 %15 %25 - %25 = OpLabel - OpBranch %15 - %15 = OpLabel - %26 = OpCopyObject %10 %23 - OpBranchConditional %11 %12 %14 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformations, context.get())); -} - -TEST(TransformationAddDeadContinueTest, RespectDominanceRules2) { - // Checks that a dead continue cannot be added if it would lead to a use after - // the loop failing to be dominated by its definition. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %102 None - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %104 - %104 = OpLabel - OpBranch %102 - %102 = OpLabel - OpBranchConditional %11 %100 %101 - %101 = OpLabel - %201 = OpCopyObject %10 %200 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // This transformation would shortcut the part of the loop body that defines - // an id used after the loop. - auto bad_transformation = TransformationAddDeadContinue(100, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, RespectDominanceRules3) { - // Checks that a dead continue cannot be added if it would lead to a dominance - // problem with an id used in an OpPhi after the loop. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %100 - %100 = OpLabel - OpLoopMerge %101 %102 None - OpBranch %103 - %103 = OpLabel - %200 = OpCopyObject %10 %11 - OpBranch %104 - %104 = OpLabel - OpBranch %102 - %102 = OpLabel - OpBranchConditional %11 %100 %101 - %101 = OpLabel - %201 = OpPhi %10 %200 %102 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // This transformation would shortcut the part of the loop body that defines - // an id used after the loop. - auto bad_transformation = TransformationAddDeadContinue(100, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, Miscellaneous1) { - // A miscellaneous test that exposed a bug in spirv-fuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %586 %623 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %34 0 Offset 0 - OpDecorate %34 Block - OpDecorate %36 DescriptorSet 0 - OpDecorate %36 Binding 0 - OpDecorate %586 BuiltIn FragCoord - OpMemberDecorate %591 0 Offset 0 - OpDecorate %591 Block - OpDecorate %593 DescriptorSet 0 - OpDecorate %593 Binding 1 - OpDecorate %623 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 2 - %17 = OpTypeBool - %27 = OpTypeFloat 32 - %28 = OpTypeVector %27 2 - %29 = OpTypeMatrix %28 2 - %30 = OpTypePointer Private %29 - %31 = OpVariable %30 Private - %34 = OpTypeStruct %27 - %35 = OpTypePointer Uniform %34 - %36 = OpVariable %35 Uniform - %37 = OpTypePointer Uniform %27 - %40 = OpTypePointer Private %27 - %43 = OpConstant %6 1 - %62 = OpConstant %6 3 - %64 = OpTypeVector %27 3 - %65 = OpTypeMatrix %64 2 - %66 = OpTypePointer Private %65 - %67 = OpVariable %66 Private - %92 = OpConstant %6 4 - %94 = OpTypeVector %27 4 - %95 = OpTypeMatrix %94 2 - %96 = OpTypePointer Private %95 - %97 = OpVariable %96 Private - %123 = OpTypeMatrix %28 3 - %124 = OpTypePointer Private %123 - %125 = OpVariable %124 Private - %151 = OpTypeMatrix %64 3 - %152 = OpTypePointer Private %151 - %153 = OpVariable %152 Private - %179 = OpTypeMatrix %94 3 - %180 = OpTypePointer Private %179 - %181 = OpVariable %180 Private - %207 = OpTypeMatrix %28 4 - %208 = OpTypePointer Private %207 - %209 = OpVariable %208 Private - %235 = OpTypeMatrix %64 4 - %236 = OpTypePointer Private %235 - %237 = OpVariable %236 Private - %263 = OpTypeMatrix %94 4 - %264 = OpTypePointer Private %263 - %265 = OpVariable %264 Private - %275 = OpTypeInt 32 0 - %276 = OpConstant %275 9 - %277 = OpTypeArray %27 %276 - %278 = OpTypePointer Function %277 - %280 = OpConstant %27 0 - %281 = OpTypePointer Function %27 - %311 = OpConstant %27 16 - %448 = OpConstant %6 5 - %482 = OpConstant %6 6 - %516 = OpConstant %6 7 - %550 = OpConstant %6 8 - %585 = OpTypePointer Input %94 - %586 = OpVariable %585 Input - %587 = OpConstant %275 0 - %588 = OpTypePointer Input %27 - %591 = OpTypeStruct %28 - %592 = OpTypePointer Uniform %591 - %593 = OpVariable %592 Uniform - %596 = OpConstant %27 3 - %601 = OpConstant %275 1 - %617 = OpConstant %6 9 - %622 = OpTypePointer Output %94 - %623 = OpVariable %622 Output - %628 = OpConstant %27 1 - %634 = OpConstantComposite %94 %280 %280 %280 %628 - %635 = OpUndef %6 - %636 = OpUndef %17 - %637 = OpUndef %27 - %638 = OpUndef %64 - %639 = OpUndef %94 - %640 = OpConstantTrue %17 - %736 = OpConstantFalse %17 - %642 = OpVariable %37 Uniform - %643 = OpVariable %40 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %164 - %164 = OpLabel - OpLoopMerge %166 %167 None - OpBranch %165 - %165 = OpLabel - OpBranch %172 - %172 = OpLabel - OpSelectionMerge %174 None - OpBranchConditional %640 %174 %174 - %174 = OpLabel - %785 = OpCopyObject %6 %43 - OpBranch %167 - %167 = OpLabel - %190 = OpIAdd %6 %9 %785 - OpBranchConditional %640 %164 %166 - %166 = OpLabel - OpBranch %196 - %196 = OpLabel - OpBranch %194 - %194 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // This transformation would shortcut the part of the loop body that defines - // an id used in the continue target. - auto bad_transformation = TransformationAddDeadContinue(165, false, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, Miscellaneous2) { - // A miscellaneous test that exposed a bug in spirv-fuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %51 = OpTypeBool - %395 = OpConstantTrue %51 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %389 - %389 = OpLabel - OpLoopMerge %388 %391 None - OpBranch %339 - %339 = OpLabel - OpSelectionMerge %396 None - OpBranchConditional %395 %388 %396 - %396 = OpLabel - OpBranch %1552 - %1552 = OpLabel - OpLoopMerge %1553 %1554 None - OpBranch %1556 - %1556 = OpLabel - OpLoopMerge %1557 %1570 None - OpBranchConditional %395 %1562 %1557 - %1562 = OpLabel - OpBranchConditional %395 %1571 %1570 - %1571 = OpLabel - OpBranch %1557 - %1570 = OpLabel - OpBranch %1556 - %1557 = OpLabel - OpSelectionMerge %1586 None - OpBranchConditional %395 %1553 %1586 - %1586 = OpLabel - OpBranch %1553 - %1554 = OpLabel - OpBranch %1552 - %1553 = OpLabel - OpBranch %388 - %391 = OpLabel - OpBranch %389 - %388 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // This transformation would introduce a branch from a continue target to - // itself. - auto bad_transformation = TransformationAddDeadContinue(1554, true, {}); - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, Miscellaneous3) { - // A miscellaneous test that exposed a bug in spirv-fuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %85 = OpTypeBool - %434 = OpConstantFalse %85 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %234 - %234 = OpLabel - OpLoopMerge %235 %236 None - OpBranch %259 - %259 = OpLabel - OpLoopMerge %260 %274 None - OpBranchConditional %434 %265 %260 - %265 = OpLabel - OpBranch %275 - %275 = OpLabel - OpBranch %260 - %274 = OpLabel - OpBranch %259 - %260 = OpLabel - OpSelectionMerge %298 None - OpBranchConditional %434 %299 %300 - %300 = OpLabel - OpBranch %235 - %298 = OpLabel - OpUnreachable - %236 = OpLabel - OpBranch %234 - %299 = OpLabel - OpBranch %235 - %235 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadContinue(299, false, {}); - - // The continue edge would connect %299 to the previously-unreachable %236, - // making %299 dominate %236, and breaking the rule that block ordering must - // respect dominance. - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, Miscellaneous4) { - // A miscellaneous test that exposed a bug in spirv-fuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %100 = OpConstantFalse %17 - %21 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %13 = OpLabel - %20 = OpLoad %6 %8 - %22 = OpIAdd %6 %20 %21 - OpStore %8 %22 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %12 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadContinue(10, false, {}); - - // The continue edge would connect %10 to the previously-unreachable %13, - // making %10 dominate %13, and breaking the rule that block ordering must - // respect dominance. - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, Miscellaneous5) { - // A miscellaneous test that exposed a bug in spirv-fuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpTypePointer Function %6 - %9 = OpConstantTrue %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %98 - %98 = OpLabel - OpLoopMerge %100 %101 None - OpBranch %99 - %99 = OpLabel - OpSelectionMerge %111 None - OpBranchConditional %9 %110 %111 - %110 = OpLabel - OpBranch %100 - %111 = OpLabel - %200 = OpCopyObject %6 %9 - OpBranch %101 - %101 = OpLabel - %201 = OpCopyObject %6 %200 - OpBranchConditional %9 %98 %100 - %100 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadContinue(110, true, {}); - - // The continue edge would lead to the use of %200 in block %101 no longer - // being dominated by its definition in block %111. - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationAddDeadContinueTest, Miscellaneous6) { - // A miscellaneous test that exposed a bug in spirv-fuzz. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %9 = OpConstantTrue %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %13 %12 None - OpBranch %11 - %11 = OpLabel - %20 = OpCopyObject %6 %9 - OpBranch %12 - %12 = OpLabel - OpBranchConditional %9 %10 %13 - %13 = OpLabel - %21 = OpCopyObject %6 %20 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_transformation = TransformationAddDeadContinue(10, true, {}); - - ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_no_contraction_decoration_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_no_contraction_decoration_test.cpp deleted file mode 100644 index b1a87ead3..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_no_contraction_decoration_test.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_no_contraction_decoration.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddNoContractionDecorationTest, BasicScenarios) { - // This is a simple transformation and this test handles the main cases. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpName %14 "i" - OpDecorate %32 NoContraction - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %11 = OpConstant %6 2 - %12 = OpTypeInt 32 1 - %13 = OpTypePointer Function %12 - %15 = OpConstant %12 0 - %22 = OpConstant %12 10 - %23 = OpTypeBool - %31 = OpConstant %6 3.5999999 - %38 = OpConstant %12 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %13 Function - OpStore %8 %9 - OpStore %10 %11 - OpStore %14 %15 - OpBranch %16 - %16 = OpLabel - OpLoopMerge %18 %19 None - OpBranch %20 - %20 = OpLabel - %21 = OpLoad %12 %14 - %24 = OpSLessThan %23 %21 %22 - OpBranchConditional %24 %17 %18 - %17 = OpLabel - %25 = OpLoad %6 %10 - %26 = OpLoad %6 %10 - %27 = OpFMul %6 %25 %26 - %28 = OpLoad %6 %8 - %29 = OpFAdd %6 %28 %27 - OpStore %8 %29 - %30 = OpLoad %6 %10 - %32 = OpFDiv %6 %30 %31 - OpStore %10 %32 - %33 = OpLoad %12 %14 - %34 = OpConvertSToF %6 %33 - %35 = OpLoad %6 %8 - %36 = OpFAdd %6 %35 %34 - OpStore %8 %36 - OpBranch %19 - %19 = OpLabel - %37 = OpLoad %12 %14 - %39 = OpIAdd %12 %37 %38 - OpStore %14 %39 - OpBranch %16 - %18 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - FactManager fact_manager; - - // Invalid: 200 is not an id - ASSERT_FALSE(TransformationAddNoContractionDecoration(200).IsApplicable( - context.get(), fact_manager)); - // Invalid: 17 is a block id - ASSERT_FALSE(TransformationAddNoContractionDecoration(17).IsApplicable( - context.get(), fact_manager)); - // Invalid: 24 is not arithmetic - ASSERT_FALSE(TransformationAddNoContractionDecoration(24).IsApplicable( - context.get(), fact_manager)); - - // It is valid to add NoContraction to each of these ids (and it's fine to - // have duplicates of the decoration, in the case of 32). - for (uint32_t result_id : {32u, 32u, 27u, 29u, 39u}) { - TransformationAddNoContractionDecoration transformation(result_id); - ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager)); - transformation.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - } - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpName %14 "i" - OpDecorate %32 NoContraction - OpDecorate %32 NoContraction - OpDecorate %32 NoContraction - OpDecorate %27 NoContraction - OpDecorate %29 NoContraction - OpDecorate %39 NoContraction - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %11 = OpConstant %6 2 - %12 = OpTypeInt 32 1 - %13 = OpTypePointer Function %12 - %15 = OpConstant %12 0 - %22 = OpConstant %12 10 - %23 = OpTypeBool - %31 = OpConstant %6 3.5999999 - %38 = OpConstant %12 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %13 Function - OpStore %8 %9 - OpStore %10 %11 - OpStore %14 %15 - OpBranch %16 - %16 = OpLabel - OpLoopMerge %18 %19 None - OpBranch %20 - %20 = OpLabel - %21 = OpLoad %12 %14 - %24 = OpSLessThan %23 %21 %22 - OpBranchConditional %24 %17 %18 - %17 = OpLabel - %25 = OpLoad %6 %10 - %26 = OpLoad %6 %10 - %27 = OpFMul %6 %25 %26 - %28 = OpLoad %6 %8 - %29 = OpFAdd %6 %28 %27 - OpStore %8 %29 - %30 = OpLoad %6 %10 - %32 = OpFDiv %6 %30 %31 - OpStore %10 %32 - %33 = OpLoad %12 %14 - %34 = OpConvertSToF %6 %33 - %35 = OpLoad %6 %8 - %36 = OpFAdd %6 %35 %34 - OpStore %8 %36 - OpBranch %19 - %19 = OpLabel - %37 = OpLoad %12 %14 - %39 = OpIAdd %12 %37 %38 - OpStore %14 %39 - OpBranch %16 - %18 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_boolean_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_type_boolean_test.cpp deleted file mode 100644 index 9975953ba..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_boolean_test.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_type_boolean.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddTypeBooleanTest, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Not applicable because id 1 is already in use. - ASSERT_FALSE(TransformationAddTypeBoolean(1).IsApplicable(context.get(), - fact_manager)); - - auto add_type_bool = TransformationAddTypeBoolean(100); - ASSERT_TRUE(add_type_bool.IsApplicable(context.get(), fact_manager)); - add_type_bool.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Not applicable as we already have this type now. - ASSERT_FALSE(TransformationAddTypeBoolean(101).IsApplicable(context.get(), - fact_manager)); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %100 = OpTypeBool - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_float_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_type_float_test.cpp deleted file mode 100644 index 67408da5a..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_float_test.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_type_float.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddTypeFloatTest, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Not applicable because id 1 is already in use. - ASSERT_FALSE(TransformationAddTypeFloat(1, 32).IsApplicable(context.get(), - fact_manager)); - - auto add_type_float_32 = TransformationAddTypeFloat(100, 32); - ASSERT_TRUE(add_type_float_32.IsApplicable(context.get(), fact_manager)); - add_type_float_32.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Not applicable as we already have this type now. - ASSERT_FALSE(TransformationAddTypeFloat(101, 32).IsApplicable(context.get(), - fact_manager)); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %100 = OpTypeFloat 32 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_int_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_type_int_test.cpp deleted file mode 100644 index c6f884c20..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_int_test.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_type_int.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddTypeIntTest, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Not applicable because id 1 is already in use. - ASSERT_FALSE(TransformationAddTypeInt(1, 32, false) - .IsApplicable(context.get(), fact_manager)); - - auto add_type_signed_int_32 = TransformationAddTypeInt(100, 32, true); - auto add_type_unsigned_int_32 = TransformationAddTypeInt(101, 32, false); - auto add_type_signed_int_32_again = TransformationAddTypeInt(102, 32, true); - auto add_type_unsigned_int_32_again = - TransformationAddTypeInt(103, 32, false); - - ASSERT_TRUE(add_type_signed_int_32.IsApplicable(context.get(), fact_manager)); - add_type_signed_int_32.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE( - add_type_unsigned_int_32.IsApplicable(context.get(), fact_manager)); - add_type_unsigned_int_32.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Not applicable as we already have these types now. - ASSERT_FALSE( - add_type_signed_int_32_again.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - add_type_unsigned_int_32_again.IsApplicable(context.get(), fact_manager)); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %100 = OpTypeInt 32 1 - %101 = OpTypeInt 32 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_pointer_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_add_type_pointer_test.cpp deleted file mode 100644 index e36707f54..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_add_type_pointer_test.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_add_type_pointer.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationAddTypePointerTest, BasicTest) { - // The SPIR-V was obtained from this GLSL: - // - // #version 450 - // - // int x; - // float y; - // vec2 z; - // - // struct T { - // int a, b; - // }; - // - // struct S { - // T t; - // int u; - // }; - // - // void main() { - // S myS = S(T(1, 2), 3); - // myS.u = x; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %7 "T" - OpMemberName %7 0 "a" - OpMemberName %7 1 "b" - OpName %8 "S" - OpMemberName %8 0 "t" - OpMemberName %8 1 "u" - OpName %10 "myS" - OpName %17 "x" - OpName %23 "y" - OpName %26 "z" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeStruct %6 %6 - %8 = OpTypeStruct %7 %6 - %9 = OpTypePointer Function %8 - %11 = OpConstant %6 1 - %12 = OpConstant %6 2 - %13 = OpConstantComposite %7 %11 %12 - %14 = OpConstant %6 3 - %15 = OpConstantComposite %8 %13 %14 - %16 = OpTypePointer Private %6 - %17 = OpVariable %16 Private - %19 = OpTypePointer Function %6 - %21 = OpTypeFloat 32 - %22 = OpTypePointer Private %21 - %23 = OpVariable %22 Private - %24 = OpTypeVector %21 2 - %25 = OpTypePointer Private %24 - %26 = OpVariable %25 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - %10 = OpVariable %9 Function - OpStore %10 %15 - %18 = OpLoad %6 %17 - %20 = OpAccessChain %19 %10 %11 - OpStore %20 %18 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto bad_type_id_does_not_exist = - TransformationAddTypePointer(100, SpvStorageClassFunction, 101); - auto bad_type_id_is_not_type = - TransformationAddTypePointer(100, SpvStorageClassFunction, 23); - auto bad_result_id_is_not_fresh = - TransformationAddTypePointer(17, SpvStorageClassFunction, 21); - - auto good_new_private_pointer_to_t = - TransformationAddTypePointer(101, SpvStorageClassPrivate, 7); - auto good_new_uniform_pointer_to_t = - TransformationAddTypePointer(102, SpvStorageClassUniform, 7); - auto good_another_function_pointer_to_s = - TransformationAddTypePointer(103, SpvStorageClassFunction, 8); - auto good_new_uniform_pointer_to_s = - TransformationAddTypePointer(104, SpvStorageClassUniform, 8); - auto good_another_private_pointer_to_float = - TransformationAddTypePointer(105, SpvStorageClassPrivate, 21); - auto good_new_private_pointer_to_private_pointer_to_float = - TransformationAddTypePointer(106, SpvStorageClassPrivate, 105); - auto good_new_uniform_pointer_to_vec2 = - TransformationAddTypePointer(107, SpvStorageClassUniform, 24); - auto good_new_private_pointer_to_uniform_pointer_to_vec2 = - TransformationAddTypePointer(108, SpvStorageClassPrivate, 107); - - ASSERT_FALSE( - bad_type_id_does_not_exist.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - bad_type_id_is_not_type.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - bad_result_id_is_not_fresh.IsApplicable(context.get(), fact_manager)); - - for (auto& transformation : - {good_new_private_pointer_to_t, good_new_uniform_pointer_to_t, - good_another_function_pointer_to_s, good_new_uniform_pointer_to_s, - good_another_private_pointer_to_float, - good_new_private_pointer_to_private_pointer_to_float, - good_new_uniform_pointer_to_vec2, - good_new_private_pointer_to_uniform_pointer_to_vec2}) { - ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager)); - transformation.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - } - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %7 "T" - OpMemberName %7 0 "a" - OpMemberName %7 1 "b" - OpName %8 "S" - OpMemberName %8 0 "t" - OpMemberName %8 1 "u" - OpName %10 "myS" - OpName %17 "x" - OpName %23 "y" - OpName %26 "z" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeStruct %6 %6 - %8 = OpTypeStruct %7 %6 - %9 = OpTypePointer Function %8 - %11 = OpConstant %6 1 - %12 = OpConstant %6 2 - %13 = OpConstantComposite %7 %11 %12 - %14 = OpConstant %6 3 - %15 = OpConstantComposite %8 %13 %14 - %16 = OpTypePointer Private %6 - %17 = OpVariable %16 Private - %19 = OpTypePointer Function %6 - %21 = OpTypeFloat 32 - %22 = OpTypePointer Private %21 - %23 = OpVariable %22 Private - %24 = OpTypeVector %21 2 - %25 = OpTypePointer Private %24 - %26 = OpVariable %25 Private - %101 = OpTypePointer Private %7 - %102 = OpTypePointer Uniform %7 - %103 = OpTypePointer Function %8 - %104 = OpTypePointer Uniform %8 - %105 = OpTypePointer Private %21 - %106 = OpTypePointer Private %105 - %107 = OpTypePointer Uniform %24 - %108 = OpTypePointer Private %107 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %10 = OpVariable %9 Function - OpStore %10 %15 - %18 = OpLoad %6 %17 - %20 = OpAccessChain %19 %10 %11 - OpStore %20 %18 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_composite_construct_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_composite_construct_test.cpp deleted file mode 100644 index d303368ad..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_composite_construct_test.cpp +++ /dev/null @@ -1,1356 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_composite_construct.h" -#include "source/fuzz/data_descriptor.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationCompositeConstructTest, ConstructArrays) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %11 "floats" - OpName %22 "x" - OpName %39 "vecs" - OpName %49 "bools" - OpName %60 "many_uvec3s" - OpDecorate %60 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 2 - %9 = OpTypeArray %6 %8 - %10 = OpTypePointer Function %9 - %12 = OpTypeInt 32 1 - %13 = OpConstant %12 0 - %14 = OpConstant %6 1 - %15 = OpTypePointer Function %6 - %17 = OpConstant %12 1 - %18 = OpConstant %6 2 - %20 = OpTypeVector %6 2 - %21 = OpTypePointer Function %20 - %32 = OpTypeBool - %36 = OpConstant %7 3 - %37 = OpTypeArray %20 %36 - %38 = OpTypePointer Private %37 - %39 = OpVariable %38 Private - %40 = OpConstant %6 3 - %41 = OpConstantComposite %20 %40 %40 - %42 = OpTypePointer Private %20 - %44 = OpConstant %12 2 - %47 = OpTypeArray %32 %36 - %48 = OpTypePointer Function %47 - %50 = OpConstantTrue %32 - %51 = OpTypePointer Function %32 - %56 = OpTypeVector %7 3 - %57 = OpTypeArray %56 %8 - %58 = OpTypeArray %57 %8 - %59 = OpTypePointer Function %58 - %61 = OpConstant %7 4 - %62 = OpConstantComposite %56 %61 %61 %61 - %63 = OpTypePointer Function %56 - %65 = OpConstant %7 5 - %66 = OpConstantComposite %56 %65 %65 %65 - %67 = OpConstant %7 6 - %68 = OpConstantComposite %56 %67 %67 %67 - %69 = OpConstantComposite %57 %66 %68 - %100 = OpUndef %57 - %70 = OpTypePointer Function %57 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %22 = OpVariable %21 Function - %49 = OpVariable %48 Function - %60 = OpVariable %59 Function - %16 = OpAccessChain %15 %11 %13 - OpStore %16 %14 - %19 = OpAccessChain %15 %11 %17 - OpStore %19 %18 - %23 = OpAccessChain %15 %11 %13 - %24 = OpLoad %6 %23 - %25 = OpAccessChain %15 %11 %17 - %26 = OpLoad %6 %25 - %27 = OpCompositeConstruct %20 %24 %26 - OpStore %22 %27 - %28 = OpAccessChain %15 %11 %13 - %29 = OpLoad %6 %28 - %30 = OpAccessChain %15 %11 %17 - %31 = OpLoad %6 %30 - %33 = OpFOrdGreaterThan %32 %29 %31 - OpSelectionMerge %35 None - OpBranchConditional %33 %34 %35 - %34 = OpLabel - %43 = OpAccessChain %42 %39 %17 - OpStore %43 %41 - %45 = OpLoad %20 %22 - %46 = OpAccessChain %42 %39 %44 - OpStore %46 %45 - OpBranch %35 - %35 = OpLabel - %52 = OpAccessChain %51 %49 %13 - OpStore %52 %50 - %53 = OpAccessChain %51 %49 %13 - %54 = OpLoad %32 %53 - %55 = OpAccessChain %51 %49 %17 - OpStore %55 %54 - %64 = OpAccessChain %63 %60 %13 %13 - OpStore %64 %62 - %71 = OpAccessChain %70 %60 %17 - OpStore %71 %69 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Make a vec2[3] - TransformationCompositeConstruct make_vec2_array_length_3( - 37, {41, 45, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), - 200); - // Bad: there are too many components - TransformationCompositeConstruct make_vec2_array_length_3_bad( - 37, {41, 45, 27, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), - 200); - ASSERT_TRUE( - make_vec2_array_length_3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - make_vec2_array_length_3_bad.IsApplicable(context.get(), fact_manager)); - make_vec2_array_length_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(41, {}), MakeDataDescriptor(200, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(45, {}), MakeDataDescriptor(200, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(27, {}), MakeDataDescriptor(200, {2}), context.get())); - - // Make a float[2] - TransformationCompositeConstruct make_float_array_length_2( - 9, {24, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201); - // Bad: %41 does not have type float - TransformationCompositeConstruct make_float_array_length_2_bad( - 9, {41, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201); - ASSERT_TRUE( - make_float_array_length_2.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - make_float_array_length_2_bad.IsApplicable(context.get(), fact_manager)); - make_float_array_length_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(24, {}), MakeDataDescriptor(201, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(40, {}), MakeDataDescriptor(201, {1}), context.get())); - - // Make a bool[3] - TransformationCompositeConstruct make_bool_array_length_3( - 47, {33, 50, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0), - 202); - // Bad: %54 is not available at the desired program point. - TransformationCompositeConstruct make_bool_array_length_3_bad( - 47, {33, 54, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0), - 202); - ASSERT_TRUE( - make_bool_array_length_3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - make_bool_array_length_3_bad.IsApplicable(context.get(), fact_manager)); - make_bool_array_length_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(33, {}), MakeDataDescriptor(202, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {2}), context.get())); - - // make a uvec3[2][2] - TransformationCompositeConstruct make_uvec3_array_length_2_2( - 58, {69, 100}, MakeInstructionDescriptor(64, SpvOpStore, 0), 203); - // Bad: Skip count 100 is too large. - TransformationCompositeConstruct make_uvec3_array_length_2_2_bad( - 58, {33, 54}, MakeInstructionDescriptor(64, SpvOpStore, 100), 203); - ASSERT_TRUE( - make_uvec3_array_length_2_2.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_uvec3_array_length_2_2_bad.IsApplicable(context.get(), - fact_manager)); - make_uvec3_array_length_2_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(69, {}), MakeDataDescriptor(203, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(100, {}), - MakeDataDescriptor(203, {1}), - context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %11 "floats" - OpName %22 "x" - OpName %39 "vecs" - OpName %49 "bools" - OpName %60 "many_uvec3s" - OpDecorate %60 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 2 - %9 = OpTypeArray %6 %8 - %10 = OpTypePointer Function %9 - %12 = OpTypeInt 32 1 - %13 = OpConstant %12 0 - %14 = OpConstant %6 1 - %15 = OpTypePointer Function %6 - %17 = OpConstant %12 1 - %18 = OpConstant %6 2 - %20 = OpTypeVector %6 2 - %21 = OpTypePointer Function %20 - %32 = OpTypeBool - %36 = OpConstant %7 3 - %37 = OpTypeArray %20 %36 - %38 = OpTypePointer Private %37 - %39 = OpVariable %38 Private - %40 = OpConstant %6 3 - %41 = OpConstantComposite %20 %40 %40 - %42 = OpTypePointer Private %20 - %44 = OpConstant %12 2 - %47 = OpTypeArray %32 %36 - %48 = OpTypePointer Function %47 - %50 = OpConstantTrue %32 - %51 = OpTypePointer Function %32 - %56 = OpTypeVector %7 3 - %57 = OpTypeArray %56 %8 - %58 = OpTypeArray %57 %8 - %59 = OpTypePointer Function %58 - %61 = OpConstant %7 4 - %62 = OpConstantComposite %56 %61 %61 %61 - %63 = OpTypePointer Function %56 - %65 = OpConstant %7 5 - %66 = OpConstantComposite %56 %65 %65 %65 - %67 = OpConstant %7 6 - %68 = OpConstantComposite %56 %67 %67 %67 - %69 = OpConstantComposite %57 %66 %68 - %100 = OpUndef %57 - %70 = OpTypePointer Function %57 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %22 = OpVariable %21 Function - %49 = OpVariable %48 Function - %60 = OpVariable %59 Function - %16 = OpAccessChain %15 %11 %13 - OpStore %16 %14 - %19 = OpAccessChain %15 %11 %17 - OpStore %19 %18 - %23 = OpAccessChain %15 %11 %13 - %24 = OpLoad %6 %23 - %25 = OpAccessChain %15 %11 %17 - %26 = OpLoad %6 %25 - %27 = OpCompositeConstruct %20 %24 %26 - OpStore %22 %27 - %28 = OpAccessChain %15 %11 %13 - %29 = OpLoad %6 %28 - %30 = OpAccessChain %15 %11 %17 - %31 = OpLoad %6 %30 - %33 = OpFOrdGreaterThan %32 %29 %31 - %202 = OpCompositeConstruct %47 %33 %50 %50 - OpSelectionMerge %35 None - OpBranchConditional %33 %34 %35 - %34 = OpLabel - %43 = OpAccessChain %42 %39 %17 - OpStore %43 %41 - %45 = OpLoad %20 %22 - %200 = OpCompositeConstruct %37 %41 %45 %27 - %46 = OpAccessChain %42 %39 %44 - OpStore %46 %45 - OpBranch %35 - %35 = OpLabel - %52 = OpAccessChain %51 %49 %13 - OpStore %52 %50 - %53 = OpAccessChain %51 %49 %13 - %54 = OpLoad %32 %53 - %55 = OpAccessChain %51 %49 %17 - OpStore %55 %54 - %64 = OpAccessChain %63 %60 %13 %13 - %203 = OpCompositeConstruct %58 %69 %100 - OpStore %64 %62 - %71 = OpAccessChain %70 %60 %17 - %201 = OpCompositeConstruct %9 %24 %40 - OpStore %71 %69 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationCompositeConstructTest, ConstructMatrices) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "v1" - OpName %12 "v2" - OpName %14 "v3" - OpName %19 "v4" - OpName %26 "v5" - OpName %29 "v6" - OpName %34 "m34" - OpName %37 "m43" - OpName %43 "vecs" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 3 - %8 = OpTypePointer Function %7 - %10 = OpConstant %6 1 - %11 = OpConstantComposite %7 %10 %10 %10 - %17 = OpTypeVector %6 4 - %18 = OpTypePointer Function %17 - %21 = OpConstant %6 2 - %32 = OpTypeMatrix %17 3 - %33 = OpTypePointer Private %32 - %34 = OpVariable %33 Private - %35 = OpTypeMatrix %7 4 - %36 = OpTypePointer Private %35 - %37 = OpVariable %36 Private - %38 = OpTypeVector %6 2 - %39 = OpTypeInt 32 0 - %40 = OpConstant %39 3 - %41 = OpTypeArray %38 %40 - %42 = OpTypePointer Private %41 - %43 = OpVariable %42 Private - %100 = OpUndef %7 - %101 = OpUndef %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %9 = OpVariable %8 Function - %12 = OpVariable %8 Function - %14 = OpVariable %8 Function - %19 = OpVariable %18 Function - %26 = OpVariable %18 Function - %29 = OpVariable %18 Function - OpStore %9 %11 - %13 = OpLoad %7 %9 - OpStore %12 %13 - %15 = OpLoad %7 %12 - %16 = OpVectorShuffle %7 %15 %15 2 1 0 - OpStore %14 %16 - %20 = OpLoad %7 %14 - %22 = OpCompositeExtract %6 %20 0 - %23 = OpCompositeExtract %6 %20 1 - %24 = OpCompositeExtract %6 %20 2 - %25 = OpCompositeConstruct %17 %22 %23 %24 %21 - OpStore %19 %25 - %27 = OpLoad %17 %19 - %28 = OpVectorShuffle %17 %27 %27 3 2 1 0 - OpStore %26 %28 - %30 = OpLoad %7 %9 - %31 = OpVectorShuffle %17 %30 %30 0 0 1 1 - OpStore %29 %31 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // make a mat3x4 - TransformationCompositeConstruct make_mat34( - 32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200); - // Bad: %35 is mat4x3, not mat3x4. - TransformationCompositeConstruct make_mat34_bad( - 35, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200); - ASSERT_TRUE(make_mat34.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_mat34_bad.IsApplicable(context.get(), fact_manager)); - make_mat34.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(28, {}), MakeDataDescriptor(200, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(31, {}), MakeDataDescriptor(200, {2}), context.get())); - - // make a mat4x3 - TransformationCompositeConstruct make_mat43( - 35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201); - // Bad: %25 does not match the matrix's column type. - TransformationCompositeConstruct make_mat43_bad( - 35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201); - ASSERT_TRUE(make_mat43.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_mat43_bad.IsApplicable(context.get(), fact_manager)); - make_mat43.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(11, {}), MakeDataDescriptor(201, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(13, {}), MakeDataDescriptor(201, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(16, {}), MakeDataDescriptor(201, {2}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(100, {}), - MakeDataDescriptor(201, {3}), - context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "v1" - OpName %12 "v2" - OpName %14 "v3" - OpName %19 "v4" - OpName %26 "v5" - OpName %29 "v6" - OpName %34 "m34" - OpName %37 "m43" - OpName %43 "vecs" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 3 - %8 = OpTypePointer Function %7 - %10 = OpConstant %6 1 - %11 = OpConstantComposite %7 %10 %10 %10 - %17 = OpTypeVector %6 4 - %18 = OpTypePointer Function %17 - %21 = OpConstant %6 2 - %32 = OpTypeMatrix %17 3 - %33 = OpTypePointer Private %32 - %34 = OpVariable %33 Private - %35 = OpTypeMatrix %7 4 - %36 = OpTypePointer Private %35 - %37 = OpVariable %36 Private - %38 = OpTypeVector %6 2 - %39 = OpTypeInt 32 0 - %40 = OpConstant %39 3 - %41 = OpTypeArray %38 %40 - %42 = OpTypePointer Private %41 - %43 = OpVariable %42 Private - %100 = OpUndef %7 - %101 = OpUndef %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %9 = OpVariable %8 Function - %12 = OpVariable %8 Function - %14 = OpVariable %8 Function - %19 = OpVariable %18 Function - %26 = OpVariable %18 Function - %29 = OpVariable %18 Function - OpStore %9 %11 - %13 = OpLoad %7 %9 - OpStore %12 %13 - %15 = OpLoad %7 %12 - %16 = OpVectorShuffle %7 %15 %15 2 1 0 - OpStore %14 %16 - %20 = OpLoad %7 %14 - %22 = OpCompositeExtract %6 %20 0 - %23 = OpCompositeExtract %6 %20 1 - %24 = OpCompositeExtract %6 %20 2 - %25 = OpCompositeConstruct %17 %22 %23 %24 %21 - OpStore %19 %25 - %27 = OpLoad %17 %19 - %28 = OpVectorShuffle %17 %27 %27 3 2 1 0 - OpStore %26 %28 - %30 = OpLoad %7 %9 - %31 = OpVectorShuffle %17 %30 %30 0 0 1 1 - %201 = OpCompositeConstruct %35 %11 %13 %16 %100 - OpStore %29 %31 - %200 = OpCompositeConstruct %32 %25 %28 %31 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationCompositeConstructTest, ConstructStructs) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "Inner" - OpMemberName %9 0 "a" - OpMemberName %9 1 "b" - OpName %11 "i1" - OpName %22 "i2" - OpName %33 "Outer" - OpMemberName %33 0 "c" - OpMemberName %33 1 "d" - OpMemberName %33 2 "e" - OpName %35 "o" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypeInt 32 1 - %9 = OpTypeStruct %7 %8 - %10 = OpTypePointer Function %9 - %12 = OpConstant %8 0 - %13 = OpConstant %6 2 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpTypePointer Function %6 - %18 = OpConstant %8 1 - %19 = OpConstant %8 3 - %20 = OpTypePointer Function %8 - %23 = OpTypePointer Function %7 - %31 = OpConstant %14 2 - %32 = OpTypeArray %9 %31 - %33 = OpTypeStruct %32 %9 %6 - %34 = OpTypePointer Function %33 - %36 = OpConstant %6 1 - %37 = OpConstantComposite %7 %36 %13 - %38 = OpConstant %8 2 - %39 = OpConstantComposite %9 %37 %38 - %40 = OpConstant %6 3 - %41 = OpConstant %6 4 - %42 = OpConstantComposite %7 %40 %41 - %56 = OpConstant %6 5 - %100 = OpUndef %9 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %22 = OpVariable %10 Function - %35 = OpVariable %34 Function - %17 = OpAccessChain %16 %11 %12 %15 - OpStore %17 %13 - %21 = OpAccessChain %20 %11 %18 - OpStore %21 %19 - %24 = OpAccessChain %23 %11 %12 - %25 = OpLoad %7 %24 - %26 = OpAccessChain %23 %22 %12 - OpStore %26 %25 - %27 = OpAccessChain %20 %11 %18 - %28 = OpLoad %8 %27 - %29 = OpIAdd %8 %28 %18 - %30 = OpAccessChain %20 %22 %18 - OpStore %30 %29 - %43 = OpAccessChain %20 %11 %18 - %44 = OpLoad %8 %43 - %45 = OpCompositeConstruct %9 %42 %44 - %46 = OpCompositeConstruct %32 %39 %45 - %47 = OpLoad %9 %22 - %48 = OpCompositeConstruct %33 %46 %47 %40 - OpStore %35 %48 - %49 = OpLoad %9 %11 - %50 = OpAccessChain %10 %35 %12 %12 - OpStore %50 %49 - %51 = OpLoad %9 %22 - %52 = OpAccessChain %10 %35 %12 %18 - OpStore %52 %51 - %53 = OpAccessChain %10 %35 %12 %12 - %54 = OpLoad %9 %53 - %55 = OpAccessChain %10 %35 %18 - OpStore %55 %54 - %57 = OpAccessChain %16 %35 %38 - OpStore %57 %56 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // make an Inner - TransformationCompositeConstruct make_inner( - 9, {25, 19}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200); - // Bad: Too few fields to make the struct. - TransformationCompositeConstruct make_inner_bad( - 9, {25}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200); - ASSERT_TRUE(make_inner.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_inner_bad.IsApplicable(context.get(), fact_manager)); - make_inner.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(19, {}), MakeDataDescriptor(200, {1}), context.get())); - - // make an Outer - TransformationCompositeConstruct make_outer( - 33, {46, 200, 56}, MakeInstructionDescriptor(200, SpvOpAccessChain, 0), - 201); - // Bad: %200 is not available at the desired program point. - TransformationCompositeConstruct make_outer_bad( - 33, {46, 200, 56}, - MakeInstructionDescriptor(200, SpvOpCompositeConstruct, 0), 201); - ASSERT_TRUE(make_outer.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_outer_bad.IsApplicable(context.get(), fact_manager)); - make_outer.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(46, {}), MakeDataDescriptor(201, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(200, {}), - MakeDataDescriptor(201, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(56, {}), MakeDataDescriptor(201, {2}), context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "Inner" - OpMemberName %9 0 "a" - OpMemberName %9 1 "b" - OpName %11 "i1" - OpName %22 "i2" - OpName %33 "Outer" - OpMemberName %33 0 "c" - OpMemberName %33 1 "d" - OpMemberName %33 2 "e" - OpName %35 "o" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypeInt 32 1 - %9 = OpTypeStruct %7 %8 - %10 = OpTypePointer Function %9 - %12 = OpConstant %8 0 - %13 = OpConstant %6 2 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpTypePointer Function %6 - %18 = OpConstant %8 1 - %19 = OpConstant %8 3 - %20 = OpTypePointer Function %8 - %23 = OpTypePointer Function %7 - %31 = OpConstant %14 2 - %32 = OpTypeArray %9 %31 - %33 = OpTypeStruct %32 %9 %6 - %34 = OpTypePointer Function %33 - %36 = OpConstant %6 1 - %37 = OpConstantComposite %7 %36 %13 - %38 = OpConstant %8 2 - %39 = OpConstantComposite %9 %37 %38 - %40 = OpConstant %6 3 - %41 = OpConstant %6 4 - %42 = OpConstantComposite %7 %40 %41 - %56 = OpConstant %6 5 - %100 = OpUndef %9 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - %22 = OpVariable %10 Function - %35 = OpVariable %34 Function - %17 = OpAccessChain %16 %11 %12 %15 - OpStore %17 %13 - %21 = OpAccessChain %20 %11 %18 - OpStore %21 %19 - %24 = OpAccessChain %23 %11 %12 - %25 = OpLoad %7 %24 - %26 = OpAccessChain %23 %22 %12 - OpStore %26 %25 - %27 = OpAccessChain %20 %11 %18 - %28 = OpLoad %8 %27 - %29 = OpIAdd %8 %28 %18 - %30 = OpAccessChain %20 %22 %18 - OpStore %30 %29 - %43 = OpAccessChain %20 %11 %18 - %44 = OpLoad %8 %43 - %45 = OpCompositeConstruct %9 %42 %44 - %46 = OpCompositeConstruct %32 %39 %45 - %47 = OpLoad %9 %22 - %48 = OpCompositeConstruct %33 %46 %47 %40 - OpStore %35 %48 - %49 = OpLoad %9 %11 - %50 = OpAccessChain %10 %35 %12 %12 - OpStore %50 %49 - %51 = OpLoad %9 %22 - %52 = OpAccessChain %10 %35 %12 %18 - OpStore %52 %51 - %53 = OpAccessChain %10 %35 %12 %12 - %54 = OpLoad %9 %53 - %55 = OpAccessChain %10 %35 %18 - OpStore %55 %54 - %200 = OpCompositeConstruct %9 %25 %19 - %201 = OpCompositeConstruct %33 %46 %200 %56 - %57 = OpAccessChain %16 %35 %38 - OpStore %57 %56 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationCompositeConstructTest, ConstructVectors) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "v2" - OpName %27 "v3" - OpName %46 "v4" - OpName %53 "iv2" - OpName %61 "uv3" - OpName %72 "bv4" - OpName %88 "uv2" - OpName %95 "bv3" - OpName %104 "bv2" - OpName %116 "iv3" - OpName %124 "iv4" - OpName %133 "uv4" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypePointer Function %7 - %10 = OpConstant %6 1 - %11 = OpConstant %6 2 - %12 = OpConstantComposite %7 %10 %11 - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Function %6 - %18 = OpConstant %13 1 - %21 = OpTypeBool - %25 = OpTypeVector %6 3 - %26 = OpTypePointer Function %25 - %33 = OpConstant %6 3 - %34 = OpConstant %6 -0.756802499 - %38 = OpConstant %13 2 - %44 = OpTypeVector %6 4 - %45 = OpTypePointer Function %44 - %50 = OpTypeInt 32 1 - %51 = OpTypeVector %50 2 - %52 = OpTypePointer Function %51 - %57 = OpTypePointer Function %50 - %59 = OpTypeVector %13 3 - %60 = OpTypePointer Function %59 - %65 = OpConstant %13 3 - %67 = OpTypePointer Function %13 - %70 = OpTypeVector %21 4 - %71 = OpTypePointer Function %70 - %73 = OpConstantTrue %21 - %74 = OpTypePointer Function %21 - %86 = OpTypeVector %13 2 - %87 = OpTypePointer Function %86 - %93 = OpTypeVector %21 3 - %94 = OpTypePointer Function %93 - %102 = OpTypeVector %21 2 - %103 = OpTypePointer Function %102 - %111 = OpConstantFalse %21 - %114 = OpTypeVector %50 3 - %115 = OpTypePointer Function %114 - %117 = OpConstant %50 3 - %122 = OpTypeVector %50 4 - %123 = OpTypePointer Function %122 - %131 = OpTypeVector %13 4 - %132 = OpTypePointer Function %131 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %9 = OpVariable %8 Function - %27 = OpVariable %26 Function - %46 = OpVariable %45 Function - %53 = OpVariable %52 Function - %61 = OpVariable %60 Function - %72 = OpVariable %71 Function - %88 = OpVariable %87 Function - %95 = OpVariable %94 Function - %104 = OpVariable %103 Function - %116 = OpVariable %115 Function - %124 = OpVariable %123 Function - %133 = OpVariable %132 Function - OpStore %9 %12 - %16 = OpAccessChain %15 %9 %14 - %17 = OpLoad %6 %16 - %19 = OpAccessChain %15 %9 %18 - %20 = OpLoad %6 %19 - %22 = OpFOrdGreaterThan %21 %17 %20 - OpSelectionMerge %24 None - OpBranchConditional %22 %23 %101 - %23 = OpLabel - %28 = OpAccessChain %15 %9 %14 - %29 = OpLoad %6 %28 - %30 = OpAccessChain %15 %9 %18 - %31 = OpLoad %6 %30 - %32 = OpFAdd %6 %29 %31 - %35 = OpCompositeConstruct %25 %32 %33 %34 - OpStore %27 %35 - %36 = OpAccessChain %15 %27 %14 - %37 = OpLoad %6 %36 - %39 = OpAccessChain %15 %27 %38 - %40 = OpLoad %6 %39 - %41 = OpFOrdLessThan %21 %37 %40 - OpSelectionMerge %43 None - OpBranchConditional %41 %42 %69 - %42 = OpLabel - %47 = OpAccessChain %15 %9 %18 - %48 = OpLoad %6 %47 - %49 = OpAccessChain %15 %46 %14 - OpStore %49 %48 - %54 = OpAccessChain %15 %27 %38 - %55 = OpLoad %6 %54 - %56 = OpConvertFToS %50 %55 - %58 = OpAccessChain %57 %53 %14 - OpStore %58 %56 - %62 = OpAccessChain %15 %46 %14 - %63 = OpLoad %6 %62 - %64 = OpConvertFToU %13 %63 - %66 = OpIAdd %13 %64 %65 - %68 = OpAccessChain %67 %61 %14 - OpStore %68 %66 - OpBranch %43 - %69 = OpLabel - %75 = OpAccessChain %74 %72 %14 - OpStore %75 %73 - %76 = OpAccessChain %74 %72 %14 - %77 = OpLoad %21 %76 - %78 = OpLogicalNot %21 %77 - %79 = OpAccessChain %74 %72 %18 - OpStore %79 %78 - %80 = OpAccessChain %74 %72 %14 - %81 = OpLoad %21 %80 - %82 = OpAccessChain %74 %72 %18 - %83 = OpLoad %21 %82 - %84 = OpLogicalAnd %21 %81 %83 - %85 = OpAccessChain %74 %72 %38 - OpStore %85 %84 - %89 = OpAccessChain %67 %88 %14 - %90 = OpLoad %13 %89 - %91 = OpINotEqual %21 %90 %14 - %92 = OpAccessChain %74 %72 %65 - OpStore %92 %91 - OpBranch %43 - %43 = OpLabel - %96 = OpLoad %70 %72 - %97 = OpCompositeExtract %21 %96 0 - %98 = OpCompositeExtract %21 %96 1 - %99 = OpCompositeExtract %21 %96 2 - %100 = OpCompositeConstruct %93 %97 %98 %99 - OpStore %95 %100 - OpBranch %24 - %101 = OpLabel - %105 = OpAccessChain %67 %88 %14 - %106 = OpLoad %13 %105 - %107 = OpINotEqual %21 %106 %14 - %108 = OpCompositeConstruct %102 %107 %107 - OpStore %104 %108 - OpBranch %24 - %24 = OpLabel - %109 = OpAccessChain %74 %104 %18 - %110 = OpLoad %21 %109 - %112 = OpLogicalOr %21 %110 %111 - %113 = OpAccessChain %74 %104 %14 - OpStore %113 %112 - %118 = OpAccessChain %57 %116 %14 - OpStore %118 %117 - %119 = OpAccessChain %57 %116 %14 - %120 = OpLoad %50 %119 - %121 = OpAccessChain %57 %53 %18 - OpStore %121 %120 - %125 = OpAccessChain %57 %116 %14 - %126 = OpLoad %50 %125 - %127 = OpAccessChain %57 %53 %18 - %128 = OpLoad %50 %127 - %129 = OpIAdd %50 %126 %128 - %130 = OpAccessChain %57 %124 %65 - OpStore %130 %129 - %134 = OpAccessChain %57 %116 %14 - %135 = OpLoad %50 %134 - %136 = OpBitcast %13 %135 - %137 = OpAccessChain %67 %133 %14 - OpStore %137 %136 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - TransformationCompositeConstruct make_vec2( - 7, {17, 11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200); - // Bad: not enough data for a vec2 - TransformationCompositeConstruct make_vec2_bad( - 7, {11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200); - ASSERT_TRUE(make_vec2.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_vec2_bad.IsApplicable(context.get(), fact_manager)); - make_vec2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(17, {}), MakeDataDescriptor(200, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(11, {}), MakeDataDescriptor(200, {1}), context.get())); - - TransformationCompositeConstruct make_vec3( - 25, {12, 32}, MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0), - 201); - // Bad: too much data for a vec3 - TransformationCompositeConstruct make_vec3_bad( - 25, {12, 32, 32}, - MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0), 201); - ASSERT_TRUE(make_vec3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_vec3_bad.IsApplicable(context.get(), fact_manager)); - make_vec3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(12, {0}), - MakeDataDescriptor(201, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(12, {1}), - MakeDataDescriptor(201, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(32, {}), MakeDataDescriptor(201, {2}), context.get())); - - TransformationCompositeConstruct make_vec4( - 44, {32, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0), - 202); - // Bad: id 48 is not available at the insertion points - TransformationCompositeConstruct make_vec4_bad( - 44, {48, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0), - 202); - ASSERT_TRUE(make_vec4.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_vec4_bad.IsApplicable(context.get(), fact_manager)); - make_vec4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(10, {}), MakeDataDescriptor(202, {2}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(11, {}), MakeDataDescriptor(202, {3}), context.get())); - - TransformationCompositeConstruct make_ivec2( - 51, {126, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203); - // Bad: if 128 is not available at the instruction that defines 128 - TransformationCompositeConstruct make_ivec2_bad( - 51, {128, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203); - ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_ivec2_bad.IsApplicable(context.get(), fact_manager)); - make_ivec2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(126, {}), - MakeDataDescriptor(203, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(120, {}), - MakeDataDescriptor(203, {1}), - context.get())); - - TransformationCompositeConstruct make_ivec3( - 114, {56, 117, 56}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0), - 204); - // Bad because 1300 is not an id - TransformationCompositeConstruct make_ivec3_bad( - 114, {56, 117, 1300}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0), - 204); - ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_ivec3_bad.IsApplicable(context.get(), fact_manager)); - make_ivec3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}), - MakeDataDescriptor(204, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {2}), context.get())); - - TransformationCompositeConstruct make_ivec4( - 122, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0), - 205); - // Bad because 86 is the wrong type. - TransformationCompositeConstruct make_ivec4_bad( - 86, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0), - 205); - ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_ivec4_bad.IsApplicable(context.get(), fact_manager)); - make_ivec4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(56, {}), MakeDataDescriptor(205, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}), - MakeDataDescriptor(205, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}), - MakeDataDescriptor(205, {2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}), - MakeDataDescriptor(205, {3}), - context.get())); - - TransformationCompositeConstruct make_uvec2( - 86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 0), 206); - TransformationCompositeConstruct make_uvec2_bad( - 86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 200), 206); - ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_uvec2_bad.IsApplicable(context.get(), fact_manager)); - make_uvec2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(18, {}), MakeDataDescriptor(206, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(38, {}), MakeDataDescriptor(206, {1}), context.get())); - - TransformationCompositeConstruct make_uvec3( - 59, {14, 18, 136}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207); - // Bad because 1300 is not an id - TransformationCompositeConstruct make_uvec3_bad( - 59, {14, 18, 1300}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207); - ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_uvec3_bad.IsApplicable(context.get(), fact_manager)); - make_uvec3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(14, {}), MakeDataDescriptor(207, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(18, {}), MakeDataDescriptor(207, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}), - MakeDataDescriptor(207, {2}), - context.get())); - - TransformationCompositeConstruct make_uvec4( - 131, {14, 18, 136, 136}, - MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208); - // Bad because 86 is the wrong type. - TransformationCompositeConstruct make_uvec4_bad( - 86, {14, 18, 136, 136}, - MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208); - ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_uvec4_bad.IsApplicable(context.get(), fact_manager)); - make_uvec4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(14, {}), MakeDataDescriptor(208, {0}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(18, {}), MakeDataDescriptor(208, {1}), context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}), - MakeDataDescriptor(208, {2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}), - MakeDataDescriptor(208, {3}), - context.get())); - - TransformationCompositeConstruct make_bvec2( - 102, - { - 111, - 41, - }, - MakeInstructionDescriptor(75, SpvOpAccessChain, 0), 209); - // Bad because 0 is not a valid base instruction id - TransformationCompositeConstruct make_bvec2_bad( - 102, - { - 111, - 41, - }, - MakeInstructionDescriptor(0, SpvOpExtInstImport, 0), 209); - ASSERT_TRUE(make_bvec2.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_bvec2_bad.IsApplicable(context.get(), fact_manager)); - make_bvec2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(111, {}), - MakeDataDescriptor(209, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(41, {}), MakeDataDescriptor(209, {1}), context.get())); - - TransformationCompositeConstruct make_bvec3( - 93, {108, 73}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210); - // Bad because there are too many components for a bvec3 - TransformationCompositeConstruct make_bvec3_bad( - 93, {108, 108}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210); - ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_bvec3_bad.IsApplicable(context.get(), fact_manager)); - make_bvec3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}), - MakeDataDescriptor(210, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}), - MakeDataDescriptor(210, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous( - MakeDataDescriptor(73, {}), MakeDataDescriptor(210, {2}), context.get())); - - TransformationCompositeConstruct make_bvec4( - 70, {108, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211); - // Bad because 21 is a type, not a result id - TransformationCompositeConstruct make_bvec4_bad( - 70, {21, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211); - ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(make_bvec4_bad.IsApplicable(context.get(), fact_manager)); - make_bvec4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}), - MakeDataDescriptor(211, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}), - MakeDataDescriptor(211, {1}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}), - MakeDataDescriptor(211, {2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}), - MakeDataDescriptor(211, {3}), - context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "v2" - OpName %27 "v3" - OpName %46 "v4" - OpName %53 "iv2" - OpName %61 "uv3" - OpName %72 "bv4" - OpName %88 "uv2" - OpName %95 "bv3" - OpName %104 "bv2" - OpName %116 "iv3" - OpName %124 "iv4" - OpName %133 "uv4" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypePointer Function %7 - %10 = OpConstant %6 1 - %11 = OpConstant %6 2 - %12 = OpConstantComposite %7 %10 %11 - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Function %6 - %18 = OpConstant %13 1 - %21 = OpTypeBool - %25 = OpTypeVector %6 3 - %26 = OpTypePointer Function %25 - %33 = OpConstant %6 3 - %34 = OpConstant %6 -0.756802499 - %38 = OpConstant %13 2 - %44 = OpTypeVector %6 4 - %45 = OpTypePointer Function %44 - %50 = OpTypeInt 32 1 - %51 = OpTypeVector %50 2 - %52 = OpTypePointer Function %51 - %57 = OpTypePointer Function %50 - %59 = OpTypeVector %13 3 - %60 = OpTypePointer Function %59 - %65 = OpConstant %13 3 - %67 = OpTypePointer Function %13 - %70 = OpTypeVector %21 4 - %71 = OpTypePointer Function %70 - %73 = OpConstantTrue %21 - %74 = OpTypePointer Function %21 - %86 = OpTypeVector %13 2 - %87 = OpTypePointer Function %86 - %93 = OpTypeVector %21 3 - %94 = OpTypePointer Function %93 - %102 = OpTypeVector %21 2 - %103 = OpTypePointer Function %102 - %111 = OpConstantFalse %21 - %114 = OpTypeVector %50 3 - %115 = OpTypePointer Function %114 - %117 = OpConstant %50 3 - %122 = OpTypeVector %50 4 - %123 = OpTypePointer Function %122 - %131 = OpTypeVector %13 4 - %132 = OpTypePointer Function %131 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %9 = OpVariable %8 Function - %27 = OpVariable %26 Function - %46 = OpVariable %45 Function - %53 = OpVariable %52 Function - %61 = OpVariable %60 Function - %72 = OpVariable %71 Function - %88 = OpVariable %87 Function - %95 = OpVariable %94 Function - %104 = OpVariable %103 Function - %116 = OpVariable %115 Function - %124 = OpVariable %123 Function - %133 = OpVariable %132 Function - OpStore %9 %12 - %206 = OpCompositeConstruct %86 %18 %38 - %16 = OpAccessChain %15 %9 %14 - %17 = OpLoad %6 %16 - %19 = OpAccessChain %15 %9 %18 - %20 = OpLoad %6 %19 - %22 = OpFOrdGreaterThan %21 %17 %20 - OpSelectionMerge %24 None - OpBranchConditional %22 %23 %101 - %23 = OpLabel - %28 = OpAccessChain %15 %9 %14 - %29 = OpLoad %6 %28 - %30 = OpAccessChain %15 %9 %18 - %31 = OpLoad %6 %30 - %32 = OpFAdd %6 %29 %31 - %201 = OpCompositeConstruct %25 %12 %32 - %35 = OpCompositeConstruct %25 %32 %33 %34 - OpStore %27 %35 - %36 = OpAccessChain %15 %27 %14 - %37 = OpLoad %6 %36 - %39 = OpAccessChain %15 %27 %38 - %40 = OpLoad %6 %39 - %41 = OpFOrdLessThan %21 %37 %40 - OpSelectionMerge %43 None - OpBranchConditional %41 %42 %69 - %42 = OpLabel - %47 = OpAccessChain %15 %9 %18 - %48 = OpLoad %6 %47 - %49 = OpAccessChain %15 %46 %14 - OpStore %49 %48 - %54 = OpAccessChain %15 %27 %38 - %55 = OpLoad %6 %54 - %56 = OpConvertFToS %50 %55 - %58 = OpAccessChain %57 %53 %14 - OpStore %58 %56 - %62 = OpAccessChain %15 %46 %14 - %63 = OpLoad %6 %62 - %64 = OpConvertFToU %13 %63 - %205 = OpCompositeConstruct %122 %56 %117 %117 %117 - %66 = OpIAdd %13 %64 %65 - %204 = OpCompositeConstruct %114 %56 %117 %56 - %68 = OpAccessChain %67 %61 %14 - OpStore %68 %66 - OpBranch %43 - %69 = OpLabel - %202 = OpCompositeConstruct %44 %32 %32 %10 %11 - %209 = OpCompositeConstruct %102 %111 %41 - %75 = OpAccessChain %74 %72 %14 - OpStore %75 %73 - %76 = OpAccessChain %74 %72 %14 - %77 = OpLoad %21 %76 - %78 = OpLogicalNot %21 %77 - %79 = OpAccessChain %74 %72 %18 - OpStore %79 %78 - %80 = OpAccessChain %74 %72 %14 - %81 = OpLoad %21 %80 - %82 = OpAccessChain %74 %72 %18 - %83 = OpLoad %21 %82 - %84 = OpLogicalAnd %21 %81 %83 - %85 = OpAccessChain %74 %72 %38 - OpStore %85 %84 - %89 = OpAccessChain %67 %88 %14 - %90 = OpLoad %13 %89 - %91 = OpINotEqual %21 %90 %14 - %92 = OpAccessChain %74 %72 %65 - OpStore %92 %91 - OpBranch %43 - %43 = OpLabel - %96 = OpLoad %70 %72 - %97 = OpCompositeExtract %21 %96 0 - %98 = OpCompositeExtract %21 %96 1 - %99 = OpCompositeExtract %21 %96 2 - %100 = OpCompositeConstruct %93 %97 %98 %99 - %200 = OpCompositeConstruct %7 %17 %11 - OpStore %95 %100 - OpBranch %24 - %101 = OpLabel - %105 = OpAccessChain %67 %88 %14 - %106 = OpLoad %13 %105 - %107 = OpINotEqual %21 %106 %14 - %108 = OpCompositeConstruct %102 %107 %107 - %210 = OpCompositeConstruct %93 %108 %73 - OpStore %104 %108 - %211 = OpCompositeConstruct %70 %108 %108 - OpBranch %24 - %24 = OpLabel - %109 = OpAccessChain %74 %104 %18 - %110 = OpLoad %21 %109 - %112 = OpLogicalOr %21 %110 %111 - %113 = OpAccessChain %74 %104 %14 - OpStore %113 %112 - %118 = OpAccessChain %57 %116 %14 - OpStore %118 %117 - %119 = OpAccessChain %57 %116 %14 - %120 = OpLoad %50 %119 - %121 = OpAccessChain %57 %53 %18 - OpStore %121 %120 - %125 = OpAccessChain %57 %116 %14 - %126 = OpLoad %50 %125 - %127 = OpAccessChain %57 %53 %18 - %203 = OpCompositeConstruct %51 %126 %120 - %128 = OpLoad %50 %127 - %129 = OpIAdd %50 %126 %128 - %130 = OpAccessChain %57 %124 %65 - OpStore %130 %129 - %134 = OpAccessChain %57 %116 %14 - %135 = OpLoad %50 %134 - %136 = OpBitcast %13 %135 - %208 = OpCompositeConstruct %131 %14 %18 %136 %136 - %137 = OpAccessChain %67 %133 %14 - OpStore %137 %136 - %207 = OpCompositeConstruct %59 %14 %18 %136 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp deleted file mode 100644 index 5cc211513..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp +++ /dev/null @@ -1,398 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_composite_extract.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationCompositeExtractTest, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpName %17 "FunnyPoint" - OpMemberName %17 0 "x" - OpMemberName %17 1 "y" - OpMemberName %17 2 "z" - OpName %19 "p" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %12 = OpTypeBool - %16 = OpTypeFloat 32 - %17 = OpTypeStruct %16 %16 %6 - %81 = OpTypeStruct %17 %16 - %18 = OpTypePointer Function %17 - %20 = OpConstant %6 0 - %23 = OpTypePointer Function %16 - %26 = OpConstant %6 1 - %30 = OpConstant %6 2 - %80 = OpUndef %16 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %19 = OpVariable %18 Function - %9 = OpLoad %6 %8 - %11 = OpLoad %6 %10 - %100 = OpCompositeConstruct %17 %80 %80 %26 - %104 = OpCompositeConstruct %81 %100 %80 - %13 = OpIEqual %12 %9 %11 - OpSelectionMerge %15 None - OpBranchConditional %13 %14 %25 - %14 = OpLabel - %21 = OpLoad %6 %8 - %22 = OpConvertSToF %16 %21 - %101 = OpCompositeConstruct %17 %22 %80 %30 - %24 = OpAccessChain %23 %19 %20 - OpStore %24 %22 - OpBranch %15 - %25 = OpLabel - %27 = OpLoad %6 %10 - %28 = OpConvertSToF %16 %27 - %102 = OpCompositeConstruct %17 %80 %28 %27 - %29 = OpAccessChain %23 %19 %26 - OpStore %29 %28 - OpBranch %15 - %15 = OpLabel - %31 = OpAccessChain %23 %19 %20 - %32 = OpLoad %16 %31 - %33 = OpAccessChain %23 %19 %26 - %34 = OpLoad %16 %33 - %103 = OpCompositeConstruct %17 %34 %32 %9 - %35 = OpFAdd %16 %32 %34 - %36 = OpConvertFToS %6 %35 - %37 = OpAccessChain %7 %19 %30 - OpStore %37 %36 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Instruction does not exist. - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 101, {0}) - .IsApplicable(context.get(), fact_manager)); - - // Id for composite is not a composite. - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 27, {}) - .IsApplicable(context.get(), fact_manager)); - - // Composite does not dominate instruction being inserted before. - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 101, {0}) - .IsApplicable(context.get(), fact_manager)); - - // Too many indices for extraction from struct composite. - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 200, 101, {0, 0}) - .IsApplicable(context.get(), fact_manager)); - - // Too many indices for extraction from struct composite. - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 0, 0}) - .IsApplicable(context.get(), fact_manager)); - - // Out of bounds index for extraction from struct composite. - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 3}) - .IsApplicable(context.get(), fact_manager)); - - // Result id already used. - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(35, SpvOpFAdd, 0), 80, 103, {0}) - .IsApplicable(context.get(), fact_manager)); - - TransformationCompositeExtract transformation_1( - MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2}); - ASSERT_TRUE(transformation_1.IsApplicable(context.get(), fact_manager)); - transformation_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - TransformationCompositeExtract transformation_2( - MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 202, 104, {0, 2}); - ASSERT_TRUE(transformation_2.IsApplicable(context.get(), fact_manager)); - transformation_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - TransformationCompositeExtract transformation_3( - MakeInstructionDescriptor(29, SpvOpAccessChain, 0), 203, 104, {0}); - ASSERT_TRUE(transformation_3.IsApplicable(context.get(), fact_manager)); - transformation_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - TransformationCompositeExtract transformation_4( - MakeInstructionDescriptor(24, SpvOpStore, 0), 204, 101, {0}); - ASSERT_TRUE(transformation_4.IsApplicable(context.get(), fact_manager)); - transformation_4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - TransformationCompositeExtract transformation_5( - MakeInstructionDescriptor(29, SpvOpBranch, 0), 205, 102, {2}); - ASSERT_TRUE(transformation_5.IsApplicable(context.get(), fact_manager)); - transformation_5.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - TransformationCompositeExtract transformation_6( - MakeInstructionDescriptor(37, SpvOpReturn, 0), 206, 103, {1}); - ASSERT_TRUE(transformation_6.IsApplicable(context.get(), fact_manager)); - transformation_6.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(201, {}), - MakeDataDescriptor(100, {2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(202, {}), - MakeDataDescriptor(104, {0, 2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(203, {}), - MakeDataDescriptor(104, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(204, {}), - MakeDataDescriptor(101, {0}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(205, {}), - MakeDataDescriptor(102, {2}), - context.get())); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(206, {}), - MakeDataDescriptor(103, {1}), - context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpName %17 "FunnyPoint" - OpMemberName %17 0 "x" - OpMemberName %17 1 "y" - OpMemberName %17 2 "z" - OpName %19 "p" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %12 = OpTypeBool - %16 = OpTypeFloat 32 - %17 = OpTypeStruct %16 %16 %6 - %81 = OpTypeStruct %17 %16 - %18 = OpTypePointer Function %17 - %20 = OpConstant %6 0 - %23 = OpTypePointer Function %16 - %26 = OpConstant %6 1 - %30 = OpConstant %6 2 - %80 = OpUndef %16 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %19 = OpVariable %18 Function - %9 = OpLoad %6 %8 - %11 = OpLoad %6 %10 - %100 = OpCompositeConstruct %17 %80 %80 %26 - %104 = OpCompositeConstruct %81 %100 %80 - %13 = OpIEqual %12 %9 %11 - OpSelectionMerge %15 None - OpBranchConditional %13 %14 %25 - %14 = OpLabel - %21 = OpLoad %6 %8 - %22 = OpConvertSToF %16 %21 - %101 = OpCompositeConstruct %17 %22 %80 %30 - %24 = OpAccessChain %23 %19 %20 - %204 = OpCompositeExtract %16 %101 0 - OpStore %24 %22 - OpBranch %15 - %25 = OpLabel - %27 = OpLoad %6 %10 - %28 = OpConvertSToF %16 %27 - %102 = OpCompositeConstruct %17 %80 %28 %27 - %203 = OpCompositeExtract %17 %104 0 - %29 = OpAccessChain %23 %19 %26 - OpStore %29 %28 - %205 = OpCompositeExtract %6 %102 2 - OpBranch %15 - %15 = OpLabel - %31 = OpAccessChain %23 %19 %20 - %32 = OpLoad %16 %31 - %33 = OpAccessChain %23 %19 %26 - %34 = OpLoad %16 %33 - %103 = OpCompositeConstruct %17 %34 %32 %9 - %35 = OpFAdd %16 %32 %34 - %201 = OpCompositeExtract %6 %100 2 - %36 = OpConvertFToS %6 %35 - %202 = OpCompositeExtract %6 %104 0 2 - %37 = OpAccessChain %7 %19 %30 - OpStore %37 %36 - %206 = OpCompositeExtract %16 %103 1 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationCompositeExtractTest, IllegalInsertionPoints) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %51 %27 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %25 "buf" - OpMemberName %25 0 "value" - OpName %27 "" - OpName %51 "color" - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 0 - OpDecorate %51 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %10 = OpConstant %6 0.300000012 - %11 = OpConstant %6 0.400000006 - %12 = OpConstant %6 0.5 - %13 = OpConstant %6 1 - %14 = OpConstantComposite %7 %10 %11 %12 %13 - %15 = OpTypeInt 32 1 - %18 = OpConstant %15 0 - %25 = OpTypeStruct %6 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %28 = OpTypePointer Uniform %6 - %32 = OpTypeBool - %103 = OpConstantTrue %32 - %34 = OpConstant %6 0.100000001 - %48 = OpConstant %15 1 - %50 = OpTypePointer Output %7 - %51 = OpVariable %50 Output - %100 = OpTypePointer Function %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %101 = OpVariable %100 Function - %102 = OpVariable %100 Function - OpBranch %19 - %19 = OpLabel - %60 = OpPhi %7 %14 %5 %58 %20 - %59 = OpPhi %15 %18 %5 %49 %20 - %29 = OpAccessChain %28 %27 %18 - %30 = OpLoad %6 %29 - %31 = OpConvertFToS %15 %30 - %33 = OpSLessThan %32 %59 %31 - OpLoopMerge %21 %20 None - OpBranchConditional %33 %20 %21 - %20 = OpLabel - %39 = OpCompositeExtract %6 %60 0 - %40 = OpFAdd %6 %39 %34 - %55 = OpCompositeInsert %7 %40 %60 0 - %44 = OpCompositeExtract %6 %60 1 - %45 = OpFSub %6 %44 %34 - %58 = OpCompositeInsert %7 %45 %55 1 - %49 = OpIAdd %15 %59 %48 - OpBranch %19 - %21 = OpLabel - OpStore %51 %60 - OpSelectionMerge %105 None - OpBranchConditional %103 %104 %105 - %104 = OpLabel - OpBranch %105 - %105 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Cannot insert before the OpVariables of a function. - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, {0}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, {1}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationCompositeExtract( - MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, {1}) - .IsApplicable(context.get(), fact_manager)); - // OK to insert right after the OpVariables. - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, {1}) - .IsApplicable(context.get(), fact_manager)); - - // Cannot insert before the OpPhis of a block. - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(60, SpvOpPhi, 0), 200, 14, {2}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(59, SpvOpPhi, 0), 200, 14, {3}) - .IsApplicable(context.get(), fact_manager)); - // OK to insert after the OpPhis. - ASSERT_TRUE( - TransformationCompositeExtract( - MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, {3}) - .IsApplicable(context.get(), fact_manager)); - - // Cannot insert before OpLoopMerge - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(33, SpvOpBranchConditional, 0), - 200, 14, {3}) - .IsApplicable(context.get(), fact_manager)); - - // Cannot insert before OpSelectionMerge - ASSERT_FALSE(TransformationCompositeExtract( - MakeInstructionDescriptor(21, SpvOpBranchConditional, 0), - 200, 14, {2}) - .IsApplicable(context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_copy_object_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_copy_object_test.cpp deleted file mode 100644 index b489f7159..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_copy_object_test.cpp +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/data_descriptor.h" -#include "source/fuzz/instruction_descriptor.h" -#include "source/fuzz/transformation_copy_object.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationCopyObjectTest, CopyBooleanConstants) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %6 = OpTypeBool - %7 = OpConstantTrue %6 - %8 = OpConstantFalse %6 - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - ASSERT_EQ(0, - fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()).size()); - - { - TransformationCopyObject copy_true( - 7, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100); - ASSERT_TRUE(copy_true.IsApplicable(context.get(), fact_manager)); - copy_true.Apply(context.get(), &fact_manager); - - std::vector ids_for_which_synonyms_are_known = - fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()); - ASSERT_EQ(2, ids_for_which_synonyms_are_known.size()); - ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(), - ids_for_which_synonyms_are_known.end(), - 7) != ids_for_which_synonyms_are_known.end()); - ASSERT_EQ(2, fact_manager.GetSynonymsForId(7, context.get()).size()); - protobufs::DataDescriptor descriptor_100 = MakeDataDescriptor(100, {}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}), - descriptor_100, context.get())); - } - - { - TransformationCopyObject copy_false( - 8, MakeInstructionDescriptor(100, SpvOpReturn, 0), 101); - ASSERT_TRUE(copy_false.IsApplicable(context.get(), fact_manager)); - copy_false.Apply(context.get(), &fact_manager); - std::vector ids_for_which_synonyms_are_known = - fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()); - ASSERT_EQ(4, ids_for_which_synonyms_are_known.size()); - ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(), - ids_for_which_synonyms_are_known.end(), - 8) != ids_for_which_synonyms_are_known.end()); - ASSERT_EQ(2, fact_manager.GetSynonymsForId(8, context.get()).size()); - protobufs::DataDescriptor descriptor_101 = MakeDataDescriptor(101, {}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(8, {}), - descriptor_101, context.get())); - } - - { - TransformationCopyObject copy_false_again( - 101, MakeInstructionDescriptor(5, SpvOpReturn, 0), 102); - ASSERT_TRUE(copy_false_again.IsApplicable(context.get(), fact_manager)); - copy_false_again.Apply(context.get(), &fact_manager); - std::vector ids_for_which_synonyms_are_known = - fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()); - ASSERT_EQ(5, ids_for_which_synonyms_are_known.size()); - ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(), - ids_for_which_synonyms_are_known.end(), - 101) != ids_for_which_synonyms_are_known.end()); - ASSERT_EQ(3, fact_manager.GetSynonymsForId(101, context.get()).size()); - protobufs::DataDescriptor descriptor_102 = MakeDataDescriptor(102, {}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(101, {}), - descriptor_102, context.get())); - } - - { - TransformationCopyObject copy_true_again( - 7, MakeInstructionDescriptor(102, SpvOpReturn, 0), 103); - ASSERT_TRUE(copy_true_again.IsApplicable(context.get(), fact_manager)); - copy_true_again.Apply(context.get(), &fact_manager); - std::vector ids_for_which_synonyms_are_known = - fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()); - ASSERT_EQ(6, ids_for_which_synonyms_are_known.size()); - ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(), - ids_for_which_synonyms_are_known.end(), - 7) != ids_for_which_synonyms_are_known.end()); - ASSERT_EQ(3, fact_manager.GetSynonymsForId(7, context.get()).size()); - protobufs::DataDescriptor descriptor_103 = MakeDataDescriptor(103, {}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}), - descriptor_103, context.get())); - } - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %6 = OpTypeBool - %7 = OpConstantTrue %6 - %8 = OpConstantFalse %6 - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %100 = OpCopyObject %6 %7 - %101 = OpCopyObject %6 %8 - %102 = OpCopyObject %6 %101 - %103 = OpCopyObject %6 %7 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationCopyObjectTest, CheckIllegalCases) { - // The following SPIR-V comes from this GLSL, pushed through spirv-opt - // and then doctored a bit. - // - // #version 310 es - // - // precision highp float; - // - // struct S { - // int a; - // float b; - // }; - // - // layout(set = 0, binding = 2) uniform block { - // S s; - // lowp float f; - // int ii; - // } ubuf; - // - // layout(location = 0) out vec4 color; - // - // void main() { - // float c = 0.0; - // lowp float d = 0.0; - // S localS = ubuf.s; - // for (int i = 0; i < ubuf.s.a; i++) { - // switch (ubuf.ii) { - // case 0: - // c += 0.1; - // d += 0.2; - // case 1: - // c += 0.1; - // if (c > d) { - // d += 0.2; - // } else { - // d += c; - // } - // break; - // default: - // i += 1; - // localS.b += d; - // } - // } - // color = vec4(c, d, localS.b, 1.0); - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %80 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %12 "S" - OpMemberName %12 0 "a" - OpMemberName %12 1 "b" - OpName %15 "S" - OpMemberName %15 0 "a" - OpMemberName %15 1 "b" - OpName %16 "block" - OpMemberName %16 0 "s" - OpMemberName %16 1 "f" - OpMemberName %16 2 "ii" - OpName %18 "ubuf" - OpName %80 "color" - OpMemberDecorate %12 0 RelaxedPrecision - OpMemberDecorate %15 0 RelaxedPrecision - OpMemberDecorate %15 0 Offset 0 - OpMemberDecorate %15 1 Offset 4 - OpMemberDecorate %16 0 Offset 0 - OpMemberDecorate %16 1 RelaxedPrecision - OpMemberDecorate %16 1 Offset 16 - OpMemberDecorate %16 2 RelaxedPrecision - OpMemberDecorate %16 2 Offset 20 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 2 - OpDecorate %38 RelaxedPrecision - OpDecorate %43 RelaxedPrecision - OpDecorate %53 RelaxedPrecision - OpDecorate %62 RelaxedPrecision - OpDecorate %69 RelaxedPrecision - OpDecorate %77 RelaxedPrecision - OpDecorate %80 Location 0 - OpDecorate %101 RelaxedPrecision - OpDecorate %102 RelaxedPrecision - OpDecorate %96 RelaxedPrecision - OpDecorate %108 RelaxedPrecision - OpDecorate %107 RelaxedPrecision - OpDecorate %98 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %9 = OpConstant %6 0 - %11 = OpTypeInt 32 1 - %12 = OpTypeStruct %11 %6 - %15 = OpTypeStruct %11 %6 - %16 = OpTypeStruct %15 %6 %11 - %17 = OpTypePointer Uniform %16 - %18 = OpVariable %17 Uniform - %19 = OpConstant %11 0 - %20 = OpTypePointer Uniform %15 - %27 = OpConstant %11 1 - %36 = OpTypePointer Uniform %11 - %39 = OpTypeBool - %41 = OpConstant %11 2 - %48 = OpConstant %6 0.100000001 - %51 = OpConstant %6 0.200000003 - %78 = OpTypeVector %6 4 - %79 = OpTypePointer Output %78 - %80 = OpVariable %79 Output - %85 = OpConstant %6 1 - %95 = OpUndef %12 - %112 = OpTypePointer Uniform %6 - %113 = OpTypeInt 32 0 - %114 = OpConstant %113 1 - %179 = OpTypePointer Function %39 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %180 = OpVariable %179 Function - %181 = OpVariable %179 Function - %182 = OpVariable %179 Function - %21 = OpAccessChain %20 %18 %19 - %115 = OpAccessChain %112 %21 %114 - %116 = OpLoad %6 %115 - %90 = OpCompositeInsert %12 %116 %95 1 - OpBranch %30 - %30 = OpLabel - %99 = OpPhi %12 %90 %5 %109 %47 - %98 = OpPhi %6 %9 %5 %107 %47 - %97 = OpPhi %6 %9 %5 %105 %47 - %96 = OpPhi %11 %19 %5 %77 %47 - %37 = OpAccessChain %36 %18 %19 %19 - %38 = OpLoad %11 %37 - %40 = OpSLessThan %39 %96 %38 - OpLoopMerge %32 %47 None - OpBranchConditional %40 %31 %32 - %31 = OpLabel - %42 = OpAccessChain %36 %18 %41 - %43 = OpLoad %11 %42 - OpSelectionMerge %45 None - OpSwitch %43 %46 0 %44 1 %45 - %46 = OpLabel - %69 = OpIAdd %11 %96 %27 - %72 = OpCompositeExtract %6 %99 1 - %73 = OpFAdd %6 %72 %98 - %93 = OpCompositeInsert %12 %73 %99 1 - OpBranch %47 - %44 = OpLabel - %50 = OpFAdd %6 %97 %48 - %53 = OpFAdd %6 %98 %51 - OpBranch %45 - %45 = OpLabel - %101 = OpPhi %6 %98 %31 %53 %44 - %100 = OpPhi %6 %97 %31 %50 %44 - %55 = OpFAdd %6 %100 %48 - %58 = OpFOrdGreaterThan %39 %55 %101 - OpSelectionMerge %60 None - OpBranchConditional %58 %59 %63 - %59 = OpLabel - %62 = OpFAdd %6 %101 %51 - OpBranch %60 - %63 = OpLabel - %66 = OpFAdd %6 %101 %55 - OpBranch %60 - %60 = OpLabel - %108 = OpPhi %6 %62 %59 %66 %63 - OpBranch %47 - %47 = OpLabel - %109 = OpPhi %12 %93 %46 %99 %60 - %107 = OpPhi %6 %98 %46 %108 %60 - %105 = OpPhi %6 %97 %46 %55 %60 - %102 = OpPhi %11 %69 %46 %96 %60 - %77 = OpIAdd %11 %102 %27 - OpBranch %30 - %32 = OpLabel - %84 = OpCompositeExtract %6 %99 1 - %86 = OpCompositeConstruct %78 %97 %98 %84 %85 - OpStore %80 %86 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Inapplicable because %18 is decorated. - ASSERT_FALSE(TransformationCopyObject( - 18, MakeInstructionDescriptor(21, SpvOpAccessChain, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because %77 is decorated. - ASSERT_FALSE(TransformationCopyObject( - 77, MakeInstructionDescriptor(77, SpvOpBranch, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because %80 is decorated. - ASSERT_FALSE(TransformationCopyObject( - 80, MakeInstructionDescriptor(77, SpvOpIAdd, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because %84 is not available at the requested point - ASSERT_FALSE( - TransformationCopyObject( - 84, MakeInstructionDescriptor(32, SpvOpCompositeExtract, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Fine because %84 is available at the requested point - ASSERT_TRUE( - TransformationCopyObject( - 84, MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because id %9 is already in use - ASSERT_FALSE( - TransformationCopyObject( - 84, MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0), 9) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because the requested point does not exist - ASSERT_FALSE(TransformationCopyObject( - 84, MakeInstructionDescriptor(86, SpvOpReturn, 2), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because %9 is not in a function - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(9, SpvOpTypeInt, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because the insert point is right before, or inside, a chunk - // of OpPhis - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(30, SpvOpPhi, 0), 200) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(99, SpvOpPhi, 1), 200) - .IsApplicable(context.get(), fact_manager)); - - // OK, because the insert point is just after a chunk of OpPhis. - ASSERT_TRUE(TransformationCopyObject( - 9, MakeInstructionDescriptor(96, SpvOpAccessChain, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because the insert point is right after an OpSelectionMerge - ASSERT_FALSE( - TransformationCopyObject( - 9, MakeInstructionDescriptor(58, SpvOpBranchConditional, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // OK, because the insert point is right before the OpSelectionMerge - ASSERT_TRUE(TransformationCopyObject( - 9, MakeInstructionDescriptor(58, SpvOpSelectionMerge, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because the insert point is right after an OpSelectionMerge - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(43, SpvOpSwitch, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // OK, because the insert point is right before the OpSelectionMerge - ASSERT_TRUE(TransformationCopyObject( - 9, MakeInstructionDescriptor(43, SpvOpSelectionMerge, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because the insert point is right after an OpLoopMerge - ASSERT_FALSE( - TransformationCopyObject( - 9, MakeInstructionDescriptor(40, SpvOpBranchConditional, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // OK, because the insert point is right before the OpLoopMerge - ASSERT_TRUE(TransformationCopyObject( - 9, MakeInstructionDescriptor(40, SpvOpLoopMerge, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because id %300 does not exist - ASSERT_FALSE(TransformationCopyObject( - 300, MakeInstructionDescriptor(40, SpvOpLoopMerge, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // Inapplicable because the following instruction is OpVariable - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(180, SpvOpVariable, 0), 200) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(181, SpvOpVariable, 0), 200) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationCopyObject( - 9, MakeInstructionDescriptor(182, SpvOpVariable, 0), 200) - .IsApplicable(context.get(), fact_manager)); - - // OK, because this is just past the group of OpVariable instructions. - ASSERT_TRUE(TransformationCopyObject( - 9, MakeInstructionDescriptor(182, SpvOpAccessChain, 0), 200) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationCopyObjectTest, MiscellaneousCopies) { - // The following SPIR-V comes from this GLSL: - // - // #version 310 es - // - // precision highp float; - // - // float g; - // - // vec4 h; - // - // void main() { - // int a; - // int b; - // b = int(g); - // h.x = float(a); - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "b" - OpName %11 "g" - OpName %16 "h" - OpName %17 "a" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypePointer Private %9 - %11 = OpVariable %10 Private - %14 = OpTypeVector %9 4 - %15 = OpTypePointer Private %14 - %16 = OpVariable %15 Private - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %17 = OpVariable %7 Function - %12 = OpLoad %9 %11 - %13 = OpConvertFToS %6 %12 - OpStore %8 %13 - %18 = OpLoad %6 %17 - %19 = OpConvertSToF %9 %18 - %22 = OpAccessChain %10 %16 %21 - OpStore %22 %19 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - std::vector transformations = { - TransformationCopyObject(19, MakeInstructionDescriptor(22, SpvOpStore, 0), - 100), - TransformationCopyObject( - 22, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 101), - TransformationCopyObject( - 12, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 102), - TransformationCopyObject( - 11, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 103), - TransformationCopyObject( - 16, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 104), - TransformationCopyObject( - 8, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 105), - TransformationCopyObject( - 17, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 106)}; - - for (auto& transformation : transformations) { - ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager)); - transformation.Apply(context.get(), &fact_manager); - } - - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "b" - OpName %11 "g" - OpName %16 "h" - OpName %17 "a" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypePointer Private %9 - %11 = OpVariable %10 Private - %14 = OpTypeVector %9 4 - %15 = OpTypePointer Private %14 - %16 = OpVariable %15 Private - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %17 = OpVariable %7 Function - %12 = OpLoad %9 %11 - %13 = OpConvertFToS %6 %12 - OpStore %8 %13 - %18 = OpLoad %6 %17 - %19 = OpConvertSToF %9 %18 - %22 = OpAccessChain %10 %16 %21 - %106 = OpCopyObject %7 %17 - %105 = OpCopyObject %7 %8 - %104 = OpCopyObject %15 %16 - %103 = OpCopyObject %10 %11 - %102 = OpCopyObject %9 %12 - %101 = OpCopyObject %10 %22 - %100 = OpCopyObject %9 %19 - OpStore %22 %19 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_move_block_down_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_move_block_down_test.cpp deleted file mode 100644 index 02761a2cf..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_move_block_down_test.cpp +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_move_block_down.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationMoveBlockDownTest, NoMovePossible1) { - // Block 11 cannot be moved down as it dominates block 12. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpDecorate %8 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %11 - %11 = OpLabel - OpStore %8 %9 - OpBranch %12 - %12 = OpLabel - OpStore %8 %10 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - auto transformation = TransformationMoveBlockDown(11); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationMoveBlockDownTest, NoMovePossible2) { - // Block 5 cannot be moved down as it is the entry block. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpDecorate %8 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpStore %8 %10 - OpReturn - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - auto transformation = TransformationMoveBlockDown(5); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationMoveBlockDownTest, NoMovePossible3) { - // Block 100 does not exist, so cannot be moved down. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpDecorate %8 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %11 - %11 = OpLabel - OpStore %8 %9 - OpBranch %12 - %12 = OpLabel - OpStore %8 %10 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - auto transformation = TransformationMoveBlockDown(100); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationMoveBlockDownTest, NoMovePossible4) { - // Block 12 is the last block in its function, so cannot be moved down. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpDecorate %8 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %11 - %11 = OpLabel - OpStore %8 %9 - OpBranch %12 - %12 = OpLabel - OpStore %8 %10 - OpReturn - OpFunctionEnd - %13 = OpFunction %2 None %3 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - auto transformation = TransformationMoveBlockDown(12); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationMoveBlockDownTest, ManyMovesPossible) { - // The SPIR-V arising from this shader has lots of opportunities for moving - // blocks around. - // - // void main() { - // int x; - // int y; - // if (x < y) { - // x = 1; - // if (y == x) { - // x = 3; - // } else { - // x = 4; - // } - // } else { - // if (y < x) { - // x = 5; - // } else { - // x = 6; - // } - // } - // } - - std::string before_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %9 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %17 RelaxedPrecision - OpDecorate %18 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %12 = OpTypeBool - %16 = OpConstant %6 1 - %22 = OpConstant %6 3 - %24 = OpConstant %6 4 - %31 = OpConstant %6 5 - %33 = OpConstant %6 6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %9 = OpLoad %6 %8 - %11 = OpLoad %6 %10 - %13 = OpSLessThan %12 %9 %11 - OpSelectionMerge %15 None - OpBranchConditional %13 %14 %25 - %14 = OpLabel - OpStore %8 %16 - %17 = OpLoad %6 %10 - %18 = OpLoad %6 %8 - %19 = OpIEqual %12 %17 %18 - OpSelectionMerge %21 None - OpBranchConditional %19 %20 %23 - %20 = OpLabel - OpStore %8 %22 - OpBranch %21 - %23 = OpLabel - OpStore %8 %24 - OpBranch %21 - %21 = OpLabel - OpBranch %15 - %25 = OpLabel - %26 = OpLoad %6 %10 - %27 = OpLoad %6 %8 - %28 = OpSLessThan %12 %26 %27 - OpSelectionMerge %30 None - OpBranchConditional %28 %29 %32 - %29 = OpLabel - OpStore %8 %31 - OpBranch %30 - %32 = OpLabel - OpStore %8 %33 - OpBranch %30 - %30 = OpLabel - OpBranch %15 - %15 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, before_transformation, kFuzzAssembleOption); - - FactManager fact_manager; - - // The block ids are: 5 14 20 23 21 25 29 32 30 15 - // We make a transformation to move each of them down, plus a transformation - // to move a non-block, 27, down. - auto move_down_5 = TransformationMoveBlockDown(5); - auto move_down_14 = TransformationMoveBlockDown(14); - auto move_down_20 = TransformationMoveBlockDown(20); - auto move_down_23 = TransformationMoveBlockDown(23); - auto move_down_21 = TransformationMoveBlockDown(21); - auto move_down_25 = TransformationMoveBlockDown(25); - auto move_down_29 = TransformationMoveBlockDown(29); - auto move_down_32 = TransformationMoveBlockDown(32); - auto move_down_30 = TransformationMoveBlockDown(30); - auto move_down_15 = TransformationMoveBlockDown(15); - auto move_down_27 = TransformationMoveBlockDown(27); - - // Dominance is as follows: - // 5 dominates everything else - // 14 dominates 20, 23, 21 - // 20 dominates nothing - // 23 dominates nothing - // 21 dominates nothing - // 25 dominates 29, 32, 30 - // 29 dominates nothing - // 32 dominates nothing - // 30 dominates nothing - // 15 dominates nothing - - // Current ordering: 5 14 20 23 21 25 29 32 30 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - // Let's bubble 20 all the way down. - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 23 20 21 25 29 32 30 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 23 21 20 25 29 32 30 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 23 21 25 20 29 32 30 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 23 21 25 29 20 32 30 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 23 21 25 29 32 20 30 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 23 21 25 29 32 30 20 15 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager)); - - move_down_20.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_bubbling_20_down = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %9 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %17 RelaxedPrecision - OpDecorate %18 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %12 = OpTypeBool - %16 = OpConstant %6 1 - %22 = OpConstant %6 3 - %24 = OpConstant %6 4 - %31 = OpConstant %6 5 - %33 = OpConstant %6 6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %9 = OpLoad %6 %8 - %11 = OpLoad %6 %10 - %13 = OpSLessThan %12 %9 %11 - OpSelectionMerge %15 None - OpBranchConditional %13 %14 %25 - %14 = OpLabel - OpStore %8 %16 - %17 = OpLoad %6 %10 - %18 = OpLoad %6 %8 - %19 = OpIEqual %12 %17 %18 - OpSelectionMerge %21 None - OpBranchConditional %19 %20 %23 - %23 = OpLabel - OpStore %8 %24 - OpBranch %21 - %21 = OpLabel - OpBranch %15 - %25 = OpLabel - %26 = OpLoad %6 %10 - %27 = OpLoad %6 %8 - %28 = OpSLessThan %12 %26 %27 - OpSelectionMerge %30 None - OpBranchConditional %28 %29 %32 - %29 = OpLabel - OpStore %8 %31 - OpBranch %30 - %32 = OpLabel - OpStore %8 %33 - OpBranch %30 - %30 = OpLabel - OpBranch %15 - %15 = OpLabel - OpReturn - %20 = OpLabel - OpStore %8 %22 - OpBranch %21 - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_bubbling_20_down, context.get())); - - // Current ordering: 5 14 23 21 25 29 32 30 15 20 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager)); - - move_down_23.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 21 23 25 29 32 30 15 20 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager)); - - move_down_23.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 21 25 23 29 32 30 15 20 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager)); - - move_down_21.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Current ordering: 5 14 25 21 23 29 32 30 15 20 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager)); - - move_down_14.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_more_shuffling = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %9 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %17 RelaxedPrecision - OpDecorate %18 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %12 = OpTypeBool - %16 = OpConstant %6 1 - %22 = OpConstant %6 3 - %24 = OpConstant %6 4 - %31 = OpConstant %6 5 - %33 = OpConstant %6 6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %9 = OpLoad %6 %8 - %11 = OpLoad %6 %10 - %13 = OpSLessThan %12 %9 %11 - OpSelectionMerge %15 None - OpBranchConditional %13 %14 %25 - %25 = OpLabel - %26 = OpLoad %6 %10 - %27 = OpLoad %6 %8 - %28 = OpSLessThan %12 %26 %27 - OpSelectionMerge %30 None - OpBranchConditional %28 %29 %32 - %14 = OpLabel - OpStore %8 %16 - %17 = OpLoad %6 %10 - %18 = OpLoad %6 %8 - %19 = OpIEqual %12 %17 %18 - OpSelectionMerge %21 None - OpBranchConditional %19 %20 %23 - %21 = OpLabel - OpBranch %15 - %23 = OpLabel - OpStore %8 %24 - OpBranch %21 - %29 = OpLabel - OpStore %8 %31 - OpBranch %30 - %32 = OpLabel - OpStore %8 %33 - OpBranch %30 - %30 = OpLabel - OpBranch %15 - %15 = OpLabel - OpReturn - %20 = OpLabel - OpStore %8 %22 - OpBranch %21 - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_more_shuffling, context.get())); - - // Final ordering: 5 25 14 21 23 29 32 30 15 20 - ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationMoveBlockDownTest, DoNotMoveUnreachable) { - // Block 6 is unreachable, so cannot be moved down. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - %6 = OpLabel - %7 = OpUndef %10 - OpBranch %8 - %8 = OpLabel - %9 = OpCopyObject %10 %7 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto transformation = TransformationMoveBlockDown(6); - ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp deleted file mode 100644 index bfc7fa77c..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp +++ /dev/null @@ -1,655 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h" - -#include "source/fuzz/fuzzer_util.h" -#include "source/fuzz/id_use_descriptor.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest, - BasicReplacements) { - // The test came from the following pseudo-GLSL, where int64 and uint64 denote - // 64-bit integer types (they were replaced with int and uint during - // translation to SPIR-V, and the generated SPIR-V has been doctored to - // accommodate them). - // - // #version 450 - // - // void main() { - // double d1, d2; - // d1 = 1.0; - // d2 = 2.0; - // float f1, f2; - // f1 = 4.0; - // f2 = 8.0; - // int i1, i2; - // i1 = 100; - // i2 = 200; - // - // uint u1, u2; - // u1 = 300u; - // u2 = 400u; - // - // int64 i64_1, i64_2; - // i64_1 = 500; - // i64_2 = 600; - // - // uint64 u64_1, u64_2; - // u64_1 = 700u; - // u64_2 = 800u; - // - // bool b, c, d, e; - // b = true; - // c = false; - // d = true || c; - // c = c && false; - // } - std::string shader = R"( - OpCapability Shader - OpCapability Float64 - OpCapability Int64 - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "d1" - OpName %10 "d2" - OpName %14 "f1" - OpName %16 "f2" - OpName %20 "i1" - OpName %22 "i2" - OpName %26 "u1" - OpName %28 "u2" - OpName %30 "i64_1" - OpName %32 "i64_2" - OpName %34 "u64_1" - OpName %36 "u64_2" - OpName %40 "b" - OpName %42 "c" - OpName %44 "d" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 64 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %12 = OpTypeFloat 32 - %13 = OpTypePointer Function %12 - %15 = OpConstant %12 4 - %17 = OpConstant %12 8 - %18 = OpTypeInt 32 1 - %60 = OpTypeInt 64 1 - %61 = OpTypePointer Function %60 - %19 = OpTypePointer Function %18 - %21 = OpConstant %18 -100 - %23 = OpConstant %18 200 - %24 = OpTypeInt 32 0 - %62 = OpTypeInt 64 0 - %63 = OpTypePointer Function %62 - %25 = OpTypePointer Function %24 - %27 = OpConstant %24 300 - %29 = OpConstant %24 400 - %31 = OpConstant %60 -600 - %33 = OpConstant %60 -500 - %35 = OpConstant %62 700 - %37 = OpConstant %62 800 - %38 = OpTypeBool - %39 = OpTypePointer Function %38 - %41 = OpConstantTrue %38 - %43 = OpConstantFalse %38 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %13 Function - %16 = OpVariable %13 Function - %20 = OpVariable %19 Function - %22 = OpVariable %19 Function - %26 = OpVariable %25 Function - %28 = OpVariable %25 Function - %30 = OpVariable %61 Function - %32 = OpVariable %61 Function - %34 = OpVariable %63 Function - %36 = OpVariable %63 Function - %40 = OpVariable %39 Function - %42 = OpVariable %39 Function - %44 = OpVariable %39 Function - OpStore %8 %9 - OpStore %10 %11 - OpStore %14 %15 - OpStore %16 %17 - OpStore %20 %21 - OpStore %22 %23 - OpStore %26 %27 - OpStore %28 %29 - OpStore %30 %31 - OpStore %32 %33 - OpStore %34 %35 - OpStore %36 %37 - OpStore %40 %41 - OpStore %42 %43 - %45 = OpLoad %38 %42 - %46 = OpLogicalOr %38 %41 %45 - OpStore %44 %46 - %47 = OpLoad %38 %42 - %48 = OpLogicalAnd %38 %47 %43 - OpStore %42 %48 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - std::vector uses_of_true = { - MakeIdUseDescriptor(41, MakeInstructionDescriptor(44, SpvOpStore, 12), 1), - MakeIdUseDescriptor(41, MakeInstructionDescriptor(46, SpvOpLogicalOr, 0), - 0)}; - - std::vector uses_of_false = { - MakeIdUseDescriptor(43, MakeInstructionDescriptor(44, SpvOpStore, 13), 1), - MakeIdUseDescriptor(43, MakeInstructionDescriptor(48, SpvOpLogicalAnd, 0), - 1)}; - - const uint32_t fresh_id = 100; - - std::vector fp_gt_opcodes = { - SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan, - SpvOpFUnordGreaterThanEqual}; - - std::vector fp_lt_opcodes = {SpvOpFOrdLessThan, SpvOpFOrdLessThanEqual, - SpvOpFUnordLessThan, - SpvOpFUnordLessThanEqual}; - - std::vector int_gt_opcodes = {SpvOpSGreaterThan, - SpvOpSGreaterThanEqual}; - - std::vector int_lt_opcodes = {SpvOpSLessThan, SpvOpSLessThanEqual}; - - std::vector uint_gt_opcodes = {SpvOpUGreaterThan, - SpvOpUGreaterThanEqual}; - - std::vector uint_lt_opcodes = {SpvOpULessThan, SpvOpULessThanEqual}; - -#define CHECK_OPERATOR(USE_DESCRIPTOR, LHS_ID, RHS_ID, OPCODE, FRESH_ID) \ - ASSERT_TRUE(TransformationReplaceBooleanConstantWithConstantBinary( \ - USE_DESCRIPTOR, LHS_ID, RHS_ID, OPCODE, FRESH_ID) \ - .IsApplicable(context.get(), fact_manager)); \ - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( \ - USE_DESCRIPTOR, RHS_ID, LHS_ID, OPCODE, FRESH_ID) \ - .IsApplicable(context.get(), fact_manager)); - -#define CHECK_TRANSFORMATION_APPLICABILITY(GT_OPCODES, LT_OPCODES, SMALL_ID, \ - LARGE_ID) \ - for (auto gt_opcode : GT_OPCODES) { \ - for (auto& true_use : uses_of_true) { \ - CHECK_OPERATOR(true_use, LARGE_ID, SMALL_ID, gt_opcode, fresh_id); \ - } \ - for (auto& false_use : uses_of_false) { \ - CHECK_OPERATOR(false_use, SMALL_ID, LARGE_ID, gt_opcode, fresh_id); \ - } \ - } \ - for (auto lt_opcode : LT_OPCODES) { \ - for (auto& true_use : uses_of_true) { \ - CHECK_OPERATOR(true_use, SMALL_ID, LARGE_ID, lt_opcode, fresh_id); \ - } \ - for (auto& false_use : uses_of_false) { \ - CHECK_OPERATOR(false_use, LARGE_ID, SMALL_ID, lt_opcode, fresh_id); \ - } \ - } - - // Float - { CHECK_TRANSFORMATION_APPLICABILITY(fp_gt_opcodes, fp_lt_opcodes, 15, 17); } - - // Double - { CHECK_TRANSFORMATION_APPLICABILITY(fp_gt_opcodes, fp_lt_opcodes, 9, 11); } - - // Int32 - { - CHECK_TRANSFORMATION_APPLICABILITY(int_gt_opcodes, int_lt_opcodes, 21, 23); - } - - // Int64 - { - CHECK_TRANSFORMATION_APPLICABILITY(int_gt_opcodes, int_lt_opcodes, 31, 33); - } - - // Uint32 - { - CHECK_TRANSFORMATION_APPLICABILITY(uint_gt_opcodes, uint_lt_opcodes, 27, - 29); - } - - // Uint64 - { - CHECK_TRANSFORMATION_APPLICABILITY(uint_gt_opcodes, uint_lt_opcodes, 35, - 37); - } - - // Target id is not fresh - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 15, 17, SpvOpFOrdLessThan, 15) - .IsApplicable(context.get(), fact_manager)); - - // LHS id does not exist - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 300, 17, SpvOpFOrdLessThan, 200) - .IsApplicable(context.get(), fact_manager)); - - // RHS id does not exist - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 15, 300, SpvOpFOrdLessThan, 200) - .IsApplicable(context.get(), fact_manager)); - - // LHS and RHS ids do not match type - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 11, 17, SpvOpFOrdLessThan, 200) - .IsApplicable(context.get(), fact_manager)); - - // Opcode not appropriate - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 15, 17, SpvOpFDiv, 200) - .IsApplicable(context.get(), fact_manager)); - - auto replace_true_with_double_comparison = - TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 11, 9, SpvOpFUnordGreaterThan, 100); - auto replace_true_with_uint32_comparison = - TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[1], 27, 29, SpvOpULessThanEqual, 101); - auto replace_false_with_float_comparison = - TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_false[0], 17, 15, SpvOpFOrdLessThan, 102); - auto replace_false_with_sint64_comparison = - TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_false[1], 33, 31, SpvOpSLessThan, 103); - - ASSERT_TRUE(replace_true_with_double_comparison.IsApplicable(context.get(), - fact_manager)); - replace_true_with_double_comparison.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(replace_true_with_uint32_comparison.IsApplicable(context.get(), - fact_manager)); - replace_true_with_uint32_comparison.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(replace_false_with_float_comparison.IsApplicable(context.get(), - fact_manager)); - replace_false_with_float_comparison.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_TRUE(replace_false_with_sint64_comparison.IsApplicable(context.get(), - fact_manager)); - replace_false_with_sint64_comparison.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after = R"( - OpCapability Shader - OpCapability Float64 - OpCapability Int64 - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "d1" - OpName %10 "d2" - OpName %14 "f1" - OpName %16 "f2" - OpName %20 "i1" - OpName %22 "i2" - OpName %26 "u1" - OpName %28 "u2" - OpName %30 "i64_1" - OpName %32 "i64_2" - OpName %34 "u64_1" - OpName %36 "u64_2" - OpName %40 "b" - OpName %42 "c" - OpName %44 "d" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 64 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %12 = OpTypeFloat 32 - %13 = OpTypePointer Function %12 - %15 = OpConstant %12 4 - %17 = OpConstant %12 8 - %18 = OpTypeInt 32 1 - %60 = OpTypeInt 64 1 - %61 = OpTypePointer Function %60 - %19 = OpTypePointer Function %18 - %21 = OpConstant %18 -100 - %23 = OpConstant %18 200 - %24 = OpTypeInt 32 0 - %62 = OpTypeInt 64 0 - %63 = OpTypePointer Function %62 - %25 = OpTypePointer Function %24 - %27 = OpConstant %24 300 - %29 = OpConstant %24 400 - %31 = OpConstant %60 -600 - %33 = OpConstant %60 -500 - %35 = OpConstant %62 700 - %37 = OpConstant %62 800 - %38 = OpTypeBool - %39 = OpTypePointer Function %38 - %41 = OpConstantTrue %38 - %43 = OpConstantFalse %38 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %13 Function - %16 = OpVariable %13 Function - %20 = OpVariable %19 Function - %22 = OpVariable %19 Function - %26 = OpVariable %25 Function - %28 = OpVariable %25 Function - %30 = OpVariable %61 Function - %32 = OpVariable %61 Function - %34 = OpVariable %63 Function - %36 = OpVariable %63 Function - %40 = OpVariable %39 Function - %42 = OpVariable %39 Function - %44 = OpVariable %39 Function - OpStore %8 %9 - OpStore %10 %11 - OpStore %14 %15 - OpStore %16 %17 - OpStore %20 %21 - OpStore %22 %23 - OpStore %26 %27 - OpStore %28 %29 - OpStore %30 %31 - OpStore %32 %33 - OpStore %34 %35 - OpStore %36 %37 - %100 = OpFUnordGreaterThan %38 %11 %9 - OpStore %40 %100 - %102 = OpFOrdLessThan %38 %17 %15 - OpStore %42 %102 - %45 = OpLoad %38 %42 - %101 = OpULessThanEqual %38 %27 %29 - %46 = OpLogicalOr %38 %101 %45 - OpStore %44 %46 - %47 = OpLoad %38 %42 - %103 = OpSLessThan %38 %33 %31 - %48 = OpLogicalAnd %38 %47 %103 - OpStore %42 %48 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after, context.get())); - - if (std::numeric_limits::has_quiet_NaN) { - double quiet_nan_double = std::numeric_limits::quiet_NaN(); - uint32_t words[2]; - memcpy(words, &quiet_nan_double, sizeof(double)); - opt::Instruction::OperandList operands = { - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, 6, 200, operands)); - fuzzerutil::UpdateModuleIdBound(context.get(), 200); - ASSERT_TRUE(IsValid(env, context.get())); - // The transformation is not applicable because %200 is NaN. - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 11, 200, SpvOpFOrdLessThan, 300) - .IsApplicable(context.get(), fact_manager)); - } - if (std::numeric_limits::has_infinity) { - double positive_infinity_double = std::numeric_limits::infinity(); - uint32_t words[2]; - memcpy(words, &positive_infinity_double, sizeof(double)); - opt::Instruction::OperandList operands = { - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[0]}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[1]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, 6, 201, operands)); - fuzzerutil::UpdateModuleIdBound(context.get(), 201); - ASSERT_TRUE(IsValid(env, context.get())); - // Even though the double constant %11 is less than the infinity %201, the - // transformation is restricted to only apply to finite values. - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 11, 201, SpvOpFOrdLessThan, 300) - .IsApplicable(context.get(), fact_manager)); - } - if (std::numeric_limits::has_infinity) { - float positive_infinity_float = std::numeric_limits::infinity(); - float negative_infinity_float = -1 * positive_infinity_float; - uint32_t words_positive_infinity[1]; - uint32_t words_negative_infinity[1]; - memcpy(words_positive_infinity, &positive_infinity_float, sizeof(float)); - memcpy(words_negative_infinity, &negative_infinity_float, sizeof(float)); - opt::Instruction::OperandList operands_positive_infinity = { - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words_positive_infinity[0]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, 12, 202, operands_positive_infinity)); - fuzzerutil::UpdateModuleIdBound(context.get(), 202); - opt::Instruction::OperandList operands = { - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words_negative_infinity[0]}}}; - context->module()->AddGlobalValue(MakeUnique( - context.get(), SpvOpConstant, 12, 203, operands)); - fuzzerutil::UpdateModuleIdBound(context.get(), 203); - ASSERT_TRUE(IsValid(env, context.get())); - // Even though the negative infinity at %203 is less than the positive - // infinity %202, the transformation is restricted to only apply to finite - // values. - ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary( - uses_of_true[0], 203, 202, SpvOpFOrdLessThan, 300) - .IsApplicable(context.get(), fact_manager)); - } -} - -TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest, - MergeInstructions) { - // The test came from the following GLSL: - // - // void main() { - // int x = 1; - // int y = 2; - // if (true) { - // x = 2; - // } - // while(false) { - // y = 2; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %12 = OpTypeBool - %13 = OpConstantTrue %12 - %21 = OpConstantFalse %12 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %11 - OpSelectionMerge %15 None - OpBranchConditional %13 %14 %15 - %14 = OpLabel - OpStore %8 %11 - OpBranch %15 - %15 = OpLabel - OpBranch %16 - %16 = OpLabel - OpLoopMerge %18 %19 None - OpBranchConditional %21 %17 %18 - %17 = OpLabel - OpStore %10 %11 - OpBranch %19 - %19 = OpLabel - OpBranch %16 - %18 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto use_of_true_in_if = MakeIdUseDescriptor( - 13, MakeInstructionDescriptor(10, SpvOpBranchConditional, 0), 0); - auto use_of_false_in_while = MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(16, SpvOpBranchConditional, 0), 0); - - auto replacement_1 = TransformationReplaceBooleanConstantWithConstantBinary( - use_of_true_in_if, 9, 11, SpvOpSLessThan, 100); - auto replacement_2 = TransformationReplaceBooleanConstantWithConstantBinary( - use_of_false_in_while, 9, 11, SpvOpSGreaterThanEqual, 101); - - ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager)); - replacement_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager)); - replacement_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %12 = OpTypeBool - %13 = OpConstantTrue %12 - %21 = OpConstantFalse %12 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %11 - %100 = OpSLessThan %12 %9 %11 - OpSelectionMerge %15 None - OpBranchConditional %100 %14 %15 - %14 = OpLabel - OpStore %8 %11 - OpBranch %15 - %15 = OpLabel - OpBranch %16 - %16 = OpLabel - %101 = OpSGreaterThanEqual %12 %9 %11 - OpLoopMerge %18 %19 None - OpBranchConditional %101 %17 %18 - %17 = OpLabel - OpStore %10 %11 - OpBranch %19 - %19 = OpLabel - OpBranch %16 - %18 = OpLabel - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after, context.get())); -} - -TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest, OpPhi) { - // Hand-written SPIR-V to check applicability of the transformation on an - // OpPhi argument. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpTypePointer Function %6 - %9 = OpConstantTrue %6 - %16 = OpConstantFalse %6 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 0 - %15 = OpConstant %10 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpSelectionMerge %20 None - OpBranchConditional %9 %21 %22 - %21 = OpLabel - OpBranch %20 - %22 = OpLabel - OpBranch %20 - %20 = OpLabel - %23 = OpPhi %6 %9 %21 %16 %22 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - auto replacement = TransformationReplaceBooleanConstantWithConstantBinary( - MakeIdUseDescriptor(9, MakeInstructionDescriptor(23, SpvOpPhi, 0), 0), 13, - 15, SpvOpSLessThan, 100); - - ASSERT_FALSE(replacement.IsApplicable(context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp deleted file mode 100644 index ac2e3f9a6..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp +++ /dev/null @@ -1,1447 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_replace_constant_with_uniform.h" -#include "source/fuzz/instruction_descriptor.h" -#include "source/fuzz/uniform_buffer_element_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -bool AddFactHelper( - FactManager* fact_manager, opt::IRContext* context, uint32_t word, - const protobufs::UniformBufferElementDescriptor& descriptor) { - protobufs::FactConstantUniform constant_uniform_fact; - constant_uniform_fact.add_constant_word(word); - *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() = - descriptor; - protobufs::Fact fact; - *fact.mutable_constant_uniform_fact() = constant_uniform_fact; - return fact_manager->AddFact(fact, context); -} - -TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) { - // This test came from the following GLSL: - // - // #version 450 - // - // uniform blockname { - // int a; - // int b; - // int c; - // }; - // - // void main() - // { - // int x; - // x = 1; - // x = x + 2; - // x = 3 + x; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "x" - OpName %16 "blockname" - OpMemberName %16 0 "a" - OpMemberName %16 1 "b" - OpMemberName %16 2 "c" - OpName %18 "" - OpMemberDecorate %16 0 Offset 0 - OpMemberDecorate %16 1 Offset 4 - OpMemberDecorate %16 2 Offset 8 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %50 = OpConstant %6 0 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %14 = OpConstant %6 3 - %16 = OpTypeStruct %6 %6 %6 - %17 = OpTypePointer Uniform %16 - %51 = OpTypePointer Uniform %6 - %18 = OpVariable %17 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpIAdd %6 %10 %11 - OpStore %8 %12 - %13 = OpLoad %6 %8 - %15 = OpIAdd %6 %14 %13 - OpStore %8 %15 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - protobufs::UniformBufferElementDescriptor blockname_a = - MakeUniformBufferElementDescriptor(0, 0, {0}); - protobufs::UniformBufferElementDescriptor blockname_b = - MakeUniformBufferElementDescriptor(0, 0, {1}); - protobufs::UniformBufferElementDescriptor blockname_c = - MakeUniformBufferElementDescriptor(0, 0, {2}); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, blockname_a)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, blockname_b)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 3, blockname_c)); - - // The constant ids are 9, 11 and 14, for 1, 2 and 3 respectively. - protobufs::IdUseDescriptor use_of_9_in_store = - MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1); - protobufs::IdUseDescriptor use_of_11_in_add = - MakeIdUseDescriptor(11, MakeInstructionDescriptor(12, SpvOpIAdd, 0), 1); - protobufs::IdUseDescriptor use_of_14_in_add = - MakeIdUseDescriptor(14, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0); - - // These transformations work: they match the facts. - auto transformation_use_of_9_in_store = - TransformationReplaceConstantWithUniform(use_of_9_in_store, blockname_a, - 100, 101); - ASSERT_TRUE(transformation_use_of_9_in_store.IsApplicable(context.get(), - fact_manager)); - auto transformation_use_of_11_in_add = - TransformationReplaceConstantWithUniform(use_of_11_in_add, blockname_b, - 102, 103); - ASSERT_TRUE(transformation_use_of_11_in_add.IsApplicable(context.get(), - fact_manager)); - auto transformation_use_of_14_in_add = - TransformationReplaceConstantWithUniform(use_of_14_in_add, blockname_c, - 104, 105); - ASSERT_TRUE(transformation_use_of_14_in_add.IsApplicable(context.get(), - fact_manager)); - - // The transformations are not applicable if we change which uniforms are - // applied to which constants. - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store, - blockname_b, 101, 102) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_add, - blockname_c, 101, 102) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_14_in_add, - blockname_a, 101, 102) - .IsApplicable(context.get(), fact_manager)); - - // The following transformations do not apply because the uniform descriptors - // are not sensible. - protobufs::UniformBufferElementDescriptor nonsense_uniform_descriptor1 = - MakeUniformBufferElementDescriptor(1, 2, {0}); - protobufs::UniformBufferElementDescriptor nonsense_uniform_descriptor2 = - MakeUniformBufferElementDescriptor(0, 0, {5}); - ASSERT_FALSE(TransformationReplaceConstantWithUniform( - use_of_9_in_store, nonsense_uniform_descriptor1, 101, 102) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationReplaceConstantWithUniform( - use_of_9_in_store, nonsense_uniform_descriptor2, 101, 102) - .IsApplicable(context.get(), fact_manager)); - - // The following transformation does not apply because the id descriptor is - // not sensible. - protobufs::IdUseDescriptor nonsense_id_use_descriptor = - MakeIdUseDescriptor(9, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0); - ASSERT_FALSE(TransformationReplaceConstantWithUniform( - nonsense_id_use_descriptor, blockname_a, 101, 102) - .IsApplicable(context.get(), fact_manager)); - - // The following transformations do not apply because the ids are not fresh. - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_add, - blockname_b, 15, 103) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_add, - blockname_b, 102, 15) - .IsApplicable(context.get(), fact_manager)); - - // Apply the use of 9 in a store. - transformation_use_of_9_in_store.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - std::string after_replacing_use_of_9_in_store = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "x" - OpName %16 "blockname" - OpMemberName %16 0 "a" - OpMemberName %16 1 "b" - OpMemberName %16 2 "c" - OpName %18 "" - OpMemberDecorate %16 0 Offset 0 - OpMemberDecorate %16 1 Offset 4 - OpMemberDecorate %16 2 Offset 8 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %50 = OpConstant %6 0 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %14 = OpConstant %6 3 - %16 = OpTypeStruct %6 %6 %6 - %17 = OpTypePointer Uniform %16 - %51 = OpTypePointer Uniform %6 - %18 = OpVariable %17 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %100 = OpAccessChain %51 %18 %50 - %101 = OpLoad %6 %100 - OpStore %8 %101 - %10 = OpLoad %6 %8 - %12 = OpIAdd %6 %10 %11 - OpStore %8 %12 - %13 = OpLoad %6 %8 - %15 = OpIAdd %6 %14 %13 - OpStore %8 %15 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_replacing_use_of_9_in_store, context.get())); - - ASSERT_TRUE(transformation_use_of_11_in_add.IsApplicable(context.get(), - fact_manager)); - // Apply the use of 11 in an add. - transformation_use_of_11_in_add.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - std::string after_replacing_use_of_11_in_add = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "x" - OpName %16 "blockname" - OpMemberName %16 0 "a" - OpMemberName %16 1 "b" - OpMemberName %16 2 "c" - OpName %18 "" - OpMemberDecorate %16 0 Offset 0 - OpMemberDecorate %16 1 Offset 4 - OpMemberDecorate %16 2 Offset 8 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %50 = OpConstant %6 0 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %14 = OpConstant %6 3 - %16 = OpTypeStruct %6 %6 %6 - %17 = OpTypePointer Uniform %16 - %51 = OpTypePointer Uniform %6 - %18 = OpVariable %17 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %100 = OpAccessChain %51 %18 %50 - %101 = OpLoad %6 %100 - OpStore %8 %101 - %10 = OpLoad %6 %8 - %102 = OpAccessChain %51 %18 %9 - %103 = OpLoad %6 %102 - %12 = OpIAdd %6 %10 %103 - OpStore %8 %12 - %13 = OpLoad %6 %8 - %15 = OpIAdd %6 %14 %13 - OpStore %8 %15 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_replacing_use_of_11_in_add, context.get())); - - ASSERT_TRUE(transformation_use_of_14_in_add.IsApplicable(context.get(), - fact_manager)); - // Apply the use of 15 in an add. - transformation_use_of_14_in_add.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - std::string after_replacing_use_of_14_in_add = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "x" - OpName %16 "blockname" - OpMemberName %16 0 "a" - OpMemberName %16 1 "b" - OpMemberName %16 2 "c" - OpName %18 "" - OpMemberDecorate %16 0 Offset 0 - OpMemberDecorate %16 1 Offset 4 - OpMemberDecorate %16 2 Offset 8 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %50 = OpConstant %6 0 - %9 = OpConstant %6 1 - %11 = OpConstant %6 2 - %14 = OpConstant %6 3 - %16 = OpTypeStruct %6 %6 %6 - %17 = OpTypePointer Uniform %16 - %51 = OpTypePointer Uniform %6 - %18 = OpVariable %17 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %100 = OpAccessChain %51 %18 %50 - %101 = OpLoad %6 %100 - OpStore %8 %101 - %10 = OpLoad %6 %8 - %102 = OpAccessChain %51 %18 %9 - %103 = OpLoad %6 %102 - %12 = OpIAdd %6 %10 %103 - OpStore %8 %12 - %13 = OpLoad %6 %8 - %104 = OpAccessChain %51 %18 %11 - %105 = OpLoad %6 %104 - %15 = OpIAdd %6 %105 %13 - OpStore %8 %15 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_replacing_use_of_14_in_add, context.get())); -} - -TEST(TransformationReplaceConstantWithUniformTest, NestedStruct) { - // This test came from the following GLSL: - // - // #version 450 - // - // struct U { - // int x; // == 4 - // }; - // - // struct T { - // int x; // == 3 - // U y; - // }; - // - // struct S { - // T x; - // int y; // == 2 - // }; - // - // uniform blockname { - // int x; // == 1 - // S y; - // }; - // - // void foo(int a) { } - // - // void main() - // { - // int x; - // x = 1; - // x = x + 2; - // x = 3 + x; - // foo(4); - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %10 "foo(i1;" - OpName %9 "a" - OpName %12 "x" - OpName %21 "param" - OpName %23 "U" - OpMemberName %23 0 "x" - OpName %24 "T" - OpMemberName %24 0 "x" - OpMemberName %24 1 "y" - OpName %25 "S" - OpMemberName %25 0 "x" - OpMemberName %25 1 "y" - OpName %26 "blockname" - OpMemberName %26 0 "x" - OpMemberName %26 1 "y" - OpName %28 "" - OpMemberDecorate %23 0 Offset 0 - OpMemberDecorate %24 0 Offset 0 - OpMemberDecorate %24 1 Offset 16 - OpMemberDecorate %25 0 Offset 0 - OpMemberDecorate %25 1 Offset 32 - OpMemberDecorate %26 0 Offset 0 - OpMemberDecorate %26 1 Offset 16 - OpDecorate %26 Block - OpDecorate %28 DescriptorSet 0 - OpDecorate %28 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %2 %7 - %50 = OpConstant %6 0 - %13 = OpConstant %6 1 - %15 = OpConstant %6 2 - %17 = OpConstant %6 3 - %20 = OpConstant %6 4 - %23 = OpTypeStruct %6 - %24 = OpTypeStruct %6 %23 - %25 = OpTypeStruct %24 %6 - %26 = OpTypeStruct %6 %25 - %27 = OpTypePointer Uniform %26 - %51 = OpTypePointer Uniform %6 - %28 = OpVariable %27 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %7 Function - %21 = OpVariable %7 Function - OpStore %12 %13 - %14 = OpLoad %6 %12 - %16 = OpIAdd %6 %14 %15 - OpStore %12 %16 - %18 = OpLoad %6 %12 - %19 = OpIAdd %6 %17 %18 - OpStore %12 %19 - OpStore %21 %20 - %22 = OpFunctionCall %2 %10 %21 - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %8 - %9 = OpFunctionParameter %7 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - protobufs::UniformBufferElementDescriptor blockname_1 = - MakeUniformBufferElementDescriptor(0, 0, {0}); - protobufs::UniformBufferElementDescriptor blockname_2 = - MakeUniformBufferElementDescriptor(0, 0, {1, 1}); - protobufs::UniformBufferElementDescriptor blockname_3 = - MakeUniformBufferElementDescriptor(0, 0, {1, 0, 0}); - protobufs::UniformBufferElementDescriptor blockname_4 = - MakeUniformBufferElementDescriptor(0, 0, {1, 0, 1, 0}); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, blockname_1)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, blockname_2)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 3, blockname_3)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 4, blockname_4)); - - // The constant ids are 13, 15, 17 and 20, for 1, 2, 3 and 4 respectively. - protobufs::IdUseDescriptor use_of_13_in_store = - MakeIdUseDescriptor(13, MakeInstructionDescriptor(21, SpvOpStore, 0), 1); - protobufs::IdUseDescriptor use_of_15_in_add = - MakeIdUseDescriptor(15, MakeInstructionDescriptor(16, SpvOpIAdd, 0), 1); - protobufs::IdUseDescriptor use_of_17_in_add = - MakeIdUseDescriptor(17, MakeInstructionDescriptor(19, SpvOpIAdd, 0), 0); - protobufs::IdUseDescriptor use_of_20_in_store = - MakeIdUseDescriptor(20, MakeInstructionDescriptor(19, SpvOpStore, 1), 1); - - // These transformations work: they match the facts. - auto transformation_use_of_13_in_store = - TransformationReplaceConstantWithUniform(use_of_13_in_store, blockname_1, - 100, 101); - ASSERT_TRUE(transformation_use_of_13_in_store.IsApplicable(context.get(), - fact_manager)); - auto transformation_use_of_15_in_add = - TransformationReplaceConstantWithUniform(use_of_15_in_add, blockname_2, - 102, 103); - ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(context.get(), - fact_manager)); - auto transformation_use_of_17_in_add = - TransformationReplaceConstantWithUniform(use_of_17_in_add, blockname_3, - 104, 105); - ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(), - fact_manager)); - auto transformation_use_of_20_in_store = - TransformationReplaceConstantWithUniform(use_of_20_in_store, blockname_4, - 106, 107); - ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(), - fact_manager)); - - ASSERT_TRUE(transformation_use_of_13_in_store.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(), - fact_manager)); - - transformation_use_of_13_in_store.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(), - fact_manager)); - - transformation_use_of_15_in_add.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(), - fact_manager)); - ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(), - fact_manager)); - - transformation_use_of_17_in_add.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(), - fact_manager)); - ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_FALSE(transformation_use_of_17_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(), - fact_manager)); - - transformation_use_of_20_in_store.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(), - fact_manager)); - ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_FALSE(transformation_use_of_17_in_add.IsApplicable(context.get(), - fact_manager)); - ASSERT_FALSE(transformation_use_of_20_in_store.IsApplicable(context.get(), - fact_manager)); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %10 "foo(i1;" - OpName %9 "a" - OpName %12 "x" - OpName %21 "param" - OpName %23 "U" - OpMemberName %23 0 "x" - OpName %24 "T" - OpMemberName %24 0 "x" - OpMemberName %24 1 "y" - OpName %25 "S" - OpMemberName %25 0 "x" - OpMemberName %25 1 "y" - OpName %26 "blockname" - OpMemberName %26 0 "x" - OpMemberName %26 1 "y" - OpName %28 "" - OpMemberDecorate %23 0 Offset 0 - OpMemberDecorate %24 0 Offset 0 - OpMemberDecorate %24 1 Offset 16 - OpMemberDecorate %25 0 Offset 0 - OpMemberDecorate %25 1 Offset 32 - OpMemberDecorate %26 0 Offset 0 - OpMemberDecorate %26 1 Offset 16 - OpDecorate %26 Block - OpDecorate %28 DescriptorSet 0 - OpDecorate %28 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %2 %7 - %50 = OpConstant %6 0 - %13 = OpConstant %6 1 - %15 = OpConstant %6 2 - %17 = OpConstant %6 3 - %20 = OpConstant %6 4 - %23 = OpTypeStruct %6 - %24 = OpTypeStruct %6 %23 - %25 = OpTypeStruct %24 %6 - %26 = OpTypeStruct %6 %25 - %27 = OpTypePointer Uniform %26 - %51 = OpTypePointer Uniform %6 - %28 = OpVariable %27 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %7 Function - %21 = OpVariable %7 Function - %100 = OpAccessChain %51 %28 %50 - %101 = OpLoad %6 %100 - OpStore %12 %101 - %14 = OpLoad %6 %12 - %102 = OpAccessChain %51 %28 %13 %13 - %103 = OpLoad %6 %102 - %16 = OpIAdd %6 %14 %103 - OpStore %12 %16 - %18 = OpLoad %6 %12 - %104 = OpAccessChain %51 %28 %13 %50 %50 - %105 = OpLoad %6 %104 - %19 = OpIAdd %6 %105 %18 - OpStore %12 %19 - %106 = OpAccessChain %51 %28 %13 %50 %13 %50 - %107 = OpLoad %6 %106 - OpStore %21 %107 - %22 = OpFunctionCall %2 %10 %21 - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %8 - %9 = OpFunctionParameter %7 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after, context.get())); -} - -TEST(TransformationReplaceConstantWithUniformTest, NoUniformIntPointerPresent) { - // This test came from the following GLSL: - // - // #version 450 - // - // uniform blockname { - // int x; // == 0 - // }; - // - // void main() - // { - // int a; - // a = 0; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "a" - OpName %10 "blockname" - OpMemberName %10 0 "x" - OpName %12 "" - OpMemberDecorate %10 0 Offset 0 - OpDecorate %10 Block - OpDecorate %12 DescriptorSet 0 - OpDecorate %12 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %10 = OpTypeStruct %6 - %11 = OpTypePointer Uniform %10 - %12 = OpVariable %11 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - protobufs::UniformBufferElementDescriptor blockname_0 = - MakeUniformBufferElementDescriptor(0, 0, {0}); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 0, blockname_0)); - - // The constant id is 9 for 0. - protobufs::IdUseDescriptor use_of_9_in_store = - MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1); - - // This transformation is not available because no uniform pointer to integer - // type is present: - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store, - blockname_0, 100, 101) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationReplaceConstantWithUniformTest, NoConstantPresentForIndex) { - // This test came from the following GLSL: - // - // #version 450 - // - // uniform blockname { - // int x; // == 0 - // int y; // == 9 - // }; - // - // void main() - // { - // int a; - // a = 9; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "a" - OpName %10 "blockname" - OpMemberName %10 0 "x" - OpMemberName %10 1 "y" - OpName %12 "" - OpMemberDecorate %10 0 Offset 0 - OpMemberDecorate %10 1 Offset 4 - OpDecorate %10 Block - OpDecorate %12 DescriptorSet 0 - OpDecorate %12 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 9 - %10 = OpTypeStruct %6 %6 - %11 = OpTypePointer Uniform %10 - %50 = OpTypePointer Uniform %6 - %12 = OpVariable %11 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - protobufs::UniformBufferElementDescriptor blockname_0 = - MakeUniformBufferElementDescriptor(0, 0, {0}); - protobufs::UniformBufferElementDescriptor blockname_9 = - MakeUniformBufferElementDescriptor(0, 0, {1}); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 9, blockname_9)); - - // The constant id is 9 for 9. - protobufs::IdUseDescriptor use_of_9_in_store = - MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1); - - // This transformation is not available because no constant is present for the - // index 1 required to index into the uniform buffer: - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store, - blockname_9, 100, 101) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationReplaceConstantWithUniformTest, - NoIntTypePresentToEnableIndexing) { - // This test came from the following GLSL: - // - // #version 450 - // - // uniform blockname { - // float f; // == 9 - // }; - // - // void main() - // { - // float a; - // a = 3.0; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "a" - OpName %10 "blockname" - OpMemberName %10 0 "f" - OpName %12 "" - OpMemberDecorate %10 0 Offset 0 - OpDecorate %10 Block - OpDecorate %12 DescriptorSet 0 - OpDecorate %12 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 3 - %10 = OpTypeStruct %6 - %11 = OpTypePointer Uniform %10 - %12 = OpVariable %11 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - protobufs::UniformBufferElementDescriptor blockname_3 = - MakeUniformBufferElementDescriptor(0, 0, {0}); - - uint32_t float_data[1]; - float temp = 3.0; - memcpy(&float_data[0], &temp, sizeof(float)); - ASSERT_TRUE( - AddFactHelper(&fact_manager, context.get(), float_data[0], blockname_3)); - - // The constant id is 9 for 3.0. - protobufs::IdUseDescriptor use_of_9_in_store = - MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1); - - // This transformation is not available because no integer type is present to - // allow a constant index to be expressed: - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store, - blockname_3, 100, 101) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationReplaceConstantWithUniformTest, - UniformFactsDoNotMatchConstants) { - // This test came from the following GLSL: - // - // #version 450 - // - // uniform blockname { - // int x; // == 9 - // int y; // == 10 - // }; - // - // void main() - // { - // int a; - // int b; - // a = 9; - // b = 10; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpName %12 "blockname" - OpMemberName %12 0 "x" - OpMemberName %12 1 "y" - OpName %14 "" - OpMemberDecorate %12 0 Offset 0 - OpMemberDecorate %12 1 Offset 4 - OpDecorate %12 Block - OpDecorate %14 DescriptorSet 0 - OpDecorate %14 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 9 - %11 = OpConstant %6 10 - %50 = OpConstant %6 0 - %51 = OpConstant %6 1 - %12 = OpTypeStruct %6 %6 - %13 = OpTypePointer Uniform %12 - %52 = OpTypePointer Uniform %6 - %14 = OpVariable %13 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %11 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - protobufs::UniformBufferElementDescriptor blockname_9 = - MakeUniformBufferElementDescriptor(0, 0, {0}); - protobufs::UniformBufferElementDescriptor blockname_10 = - MakeUniformBufferElementDescriptor(0, 0, {1}); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 9, blockname_9)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 10, blockname_10)); - - // The constant ids for 9 and 10 are 9 and 11 respectively - protobufs::IdUseDescriptor use_of_9_in_store = - MakeIdUseDescriptor(9, MakeInstructionDescriptor(10, SpvOpStore, 0), 1); - protobufs::IdUseDescriptor use_of_11_in_store = - MakeIdUseDescriptor(11, MakeInstructionDescriptor(10, SpvOpStore, 1), 1); - - // These are right: - ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_9_in_store, - blockname_9, 100, 101) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_11_in_store, - blockname_10, 102, 103) - .IsApplicable(context.get(), fact_manager)); - - // These are wrong because the constants do not match the facts about - // uniforms. - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_store, - blockname_9, 100, 101) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store, - blockname_10, 102, 103) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationReplaceConstantWithUniformTest, ComplexReplacements) { - // The following GLSL was the basis for this test: - - // #version 450 - // - // struct T { - // float a[5]; // [1.0, 1.5, 1.75, 1.875, 1.9375] - // ivec4 b; // (1, 2, 3, 4) - // vec3 c; // (2.0, 2.5, 2.75) - // uint d; // 42u - // bool e; // Not used in test - // }; - // - // uniform block { - // T f; - // int g; // 22 - // uvec2 h; // (100u, 200u) - // }; - // - // void main() - // { - // T myT; - // - // myT.a[0] = 1.9375; - // myT.a[1] = 1.875; - // myT.a[2] = 1.75; - // myT.a[3] = 1.5; - // myT.a[4] = 1.0; - // - // myT.b.x = 4; - // myT.b.y = 3; - // myT.b.z = 2; - // myT.b.w = 1; - // - // myT.b.r = 22; - // - // myT.c[0] = 2.75; - // myT.c[0] = 2.5; - // myT.c[0] = 2.0; - // - // myT.d = 42u; - // myT.d = 100u; - // myT.d = 200u; - // - // myT.e = true; // No attempt to replace 'true' by a uniform value - // - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %14 "T" - OpMemberName %14 0 "a" - OpMemberName %14 1 "b" - OpMemberName %14 2 "c" - OpMemberName %14 3 "d" - OpMemberName %14 4 "e" - OpName %16 "myT" - OpName %61 "T" - OpMemberName %61 0 "a" - OpMemberName %61 1 "b" - OpMemberName %61 2 "c" - OpMemberName %61 3 "d" - OpMemberName %61 4 "e" - OpName %63 "block" - OpMemberName %63 0 "f" - OpMemberName %63 1 "g" - OpMemberName %63 2 "h" - OpName %65 "" - OpDecorate %60 ArrayStride 16 - OpMemberDecorate %61 0 Offset 0 - OpMemberDecorate %61 1 Offset 80 - OpMemberDecorate %61 2 Offset 96 - OpMemberDecorate %61 3 Offset 108 - OpMemberDecorate %61 4 Offset 112 - OpMemberDecorate %63 0 Offset 0 - OpMemberDecorate %63 1 Offset 128 - OpMemberDecorate %63 2 Offset 136 - OpDecorate %63 Block - OpDecorate %65 DescriptorSet 0 - OpDecorate %65 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 5 - %9 = OpTypeArray %6 %8 - %10 = OpTypeInt 32 1 - %11 = OpTypeVector %10 4 - %12 = OpTypeVector %6 3 - %13 = OpTypeBool - %14 = OpTypeStruct %9 %11 %12 %7 %13 - %15 = OpTypePointer Function %14 - %17 = OpConstant %10 0 - %18 = OpConstant %6 1.9375 - %19 = OpTypePointer Function %6 - %21 = OpConstant %10 1 - %22 = OpConstant %6 1.875 - %24 = OpConstant %10 2 - %25 = OpConstant %6 1.75 - %27 = OpConstant %10 3 - %28 = OpConstant %6 1.5 - %30 = OpConstant %10 4 - %31 = OpConstant %6 1 - %33 = OpConstant %7 0 - %34 = OpTypePointer Function %10 - %36 = OpConstant %7 1 - %38 = OpConstant %7 2 - %40 = OpConstant %7 3 - %42 = OpConstant %10 22 - %44 = OpConstant %6 2.75 - %46 = OpConstant %6 2.5 - %48 = OpConstant %6 2 - %50 = OpConstant %7 42 - %51 = OpTypePointer Function %7 - %53 = OpConstant %7 100 - %55 = OpConstant %7 200 - %57 = OpConstantTrue %13 - %58 = OpTypePointer Function %13 - %60 = OpTypeArray %6 %8 - %61 = OpTypeStruct %60 %11 %12 %7 %7 - %62 = OpTypeVector %7 2 - %63 = OpTypeStruct %61 %10 %62 - %64 = OpTypePointer Uniform %63 - %100 = OpTypePointer Uniform %10 - %101 = OpTypePointer Uniform %7 - %102 = OpTypePointer Uniform %6 - %103 = OpTypePointer Uniform %13 - %65 = OpVariable %64 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %16 = OpVariable %15 Function - %20 = OpAccessChain %19 %16 %17 %17 - OpStore %20 %18 - %23 = OpAccessChain %19 %16 %17 %21 - OpStore %23 %22 - %26 = OpAccessChain %19 %16 %17 %24 - OpStore %26 %25 - %29 = OpAccessChain %19 %16 %17 %27 - OpStore %29 %28 - %32 = OpAccessChain %19 %16 %17 %30 - OpStore %32 %31 - %35 = OpAccessChain %34 %16 %21 %33 - OpStore %35 %30 - %37 = OpAccessChain %34 %16 %21 %36 - OpStore %37 %27 - %39 = OpAccessChain %34 %16 %21 %38 - OpStore %39 %24 - %41 = OpAccessChain %34 %16 %21 %40 - OpStore %41 %21 - %43 = OpAccessChain %34 %16 %21 %33 - OpStore %43 %42 - %45 = OpAccessChain %19 %16 %24 %33 - OpStore %45 %44 - %47 = OpAccessChain %19 %16 %24 %33 - OpStore %47 %46 - %49 = OpAccessChain %19 %16 %24 %33 - OpStore %49 %48 - %52 = OpAccessChain %51 %16 %27 - OpStore %52 %50 - %54 = OpAccessChain %51 %16 %27 - OpStore %54 %53 - %56 = OpAccessChain %51 %16 %27 - OpStore %56 %55 - %59 = OpAccessChain %58 %16 %30 - OpStore %59 %57 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - const float float_array_values[5] = {1.0, 1.5, 1.75, 1.875, 1.9375}; - uint32_t float_array_data[5]; - memcpy(&float_array_data, &float_array_values, sizeof(float_array_values)); - - const float float_vector_values[3] = {2.0, 2.5, 2.75}; - uint32_t float_vector_data[3]; - memcpy(&float_vector_data, &float_vector_values, sizeof(float_vector_values)); - - protobufs::UniformBufferElementDescriptor uniform_f_a_0 = - MakeUniformBufferElementDescriptor(0, 0, {0, 0, 0}); - protobufs::UniformBufferElementDescriptor uniform_f_a_1 = - MakeUniformBufferElementDescriptor(0, 0, {0, 0, 1}); - protobufs::UniformBufferElementDescriptor uniform_f_a_2 = - MakeUniformBufferElementDescriptor(0, 0, {0, 0, 2}); - protobufs::UniformBufferElementDescriptor uniform_f_a_3 = - MakeUniformBufferElementDescriptor(0, 0, {0, 0, 3}); - protobufs::UniformBufferElementDescriptor uniform_f_a_4 = - MakeUniformBufferElementDescriptor(0, 0, {0, 0, 4}); - - protobufs::UniformBufferElementDescriptor uniform_f_b_x = - MakeUniformBufferElementDescriptor(0, 0, {0, 1, 0}); - protobufs::UniformBufferElementDescriptor uniform_f_b_y = - MakeUniformBufferElementDescriptor(0, 0, {0, 1, 1}); - protobufs::UniformBufferElementDescriptor uniform_f_b_z = - MakeUniformBufferElementDescriptor(0, 0, {0, 1, 2}); - protobufs::UniformBufferElementDescriptor uniform_f_b_w = - MakeUniformBufferElementDescriptor(0, 0, {0, 1, 3}); - - protobufs::UniformBufferElementDescriptor uniform_f_c_x = - MakeUniformBufferElementDescriptor(0, 0, {0, 2, 0}); - protobufs::UniformBufferElementDescriptor uniform_f_c_y = - MakeUniformBufferElementDescriptor(0, 0, {0, 2, 1}); - protobufs::UniformBufferElementDescriptor uniform_f_c_z = - MakeUniformBufferElementDescriptor(0, 0, {0, 2, 2}); - - protobufs::UniformBufferElementDescriptor uniform_f_d = - MakeUniformBufferElementDescriptor(0, 0, {0, 3}); - - protobufs::UniformBufferElementDescriptor uniform_g = - MakeUniformBufferElementDescriptor(0, 0, {1}); - - protobufs::UniformBufferElementDescriptor uniform_h_x = - MakeUniformBufferElementDescriptor(0, 0, {2, 0}); - protobufs::UniformBufferElementDescriptor uniform_h_y = - MakeUniformBufferElementDescriptor(0, 0, {2, 1}); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[0], - uniform_f_a_0)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[1], - uniform_f_a_1)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[2], - uniform_f_a_2)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[3], - uniform_f_a_3)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[4], - uniform_f_a_4)); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, uniform_f_b_x)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, uniform_f_b_y)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 3, uniform_f_b_z)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 4, uniform_f_b_w)); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_vector_data[0], - uniform_f_c_x)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_vector_data[1], - uniform_f_c_y)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_vector_data[2], - uniform_f_c_z)); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 42, uniform_f_d)); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 22, uniform_g)); - - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 100, uniform_h_x)); - ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 200, uniform_h_y)); - - std::vector transformations; - - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(18, MakeInstructionDescriptor(20, SpvOpStore, 0), 1), - uniform_f_a_4, 200, 201)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(22, MakeInstructionDescriptor(23, SpvOpStore, 0), 1), - uniform_f_a_3, 202, 203)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(25, MakeInstructionDescriptor(26, SpvOpStore, 0), 1), - uniform_f_a_2, 204, 205)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(28, MakeInstructionDescriptor(29, SpvOpStore, 0), 1), - uniform_f_a_1, 206, 207)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(31, MakeInstructionDescriptor(32, SpvOpStore, 0), 1), - uniform_f_a_0, 208, 209)); - - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(30, MakeInstructionDescriptor(35, SpvOpStore, 0), 1), - uniform_f_b_w, 210, 211)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(27, MakeInstructionDescriptor(37, SpvOpStore, 0), 1), - uniform_f_b_z, 212, 213)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(24, MakeInstructionDescriptor(39, SpvOpStore, 0), 1), - uniform_f_b_y, 214, 215)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(21, MakeInstructionDescriptor(41, SpvOpStore, 0), 1), - uniform_f_b_x, 216, 217)); - - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(44, MakeInstructionDescriptor(45, SpvOpStore, 0), 1), - uniform_f_c_z, 220, 221)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(46, MakeInstructionDescriptor(47, SpvOpStore, 0), 1), - uniform_f_c_y, 222, 223)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(48, MakeInstructionDescriptor(49, SpvOpStore, 0), 1), - uniform_f_c_x, 224, 225)); - - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(50, MakeInstructionDescriptor(52, SpvOpStore, 0), 1), - uniform_f_d, 226, 227)); - - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(53, MakeInstructionDescriptor(54, SpvOpStore, 0), 1), - uniform_h_x, 228, 229)); - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(55, MakeInstructionDescriptor(56, SpvOpStore, 0), 1), - uniform_h_y, 230, 231)); - - transformations.emplace_back(TransformationReplaceConstantWithUniform( - MakeIdUseDescriptor(42, MakeInstructionDescriptor(43, SpvOpStore, 0), 1), - uniform_g, 218, 219)); - - for (auto& transformation : transformations) { - ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager)); - transformation.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - } - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %14 "T" - OpMemberName %14 0 "a" - OpMemberName %14 1 "b" - OpMemberName %14 2 "c" - OpMemberName %14 3 "d" - OpMemberName %14 4 "e" - OpName %16 "myT" - OpName %61 "T" - OpMemberName %61 0 "a" - OpMemberName %61 1 "b" - OpMemberName %61 2 "c" - OpMemberName %61 3 "d" - OpMemberName %61 4 "e" - OpName %63 "block" - OpMemberName %63 0 "f" - OpMemberName %63 1 "g" - OpMemberName %63 2 "h" - OpName %65 "" - OpDecorate %60 ArrayStride 16 - OpMemberDecorate %61 0 Offset 0 - OpMemberDecorate %61 1 Offset 80 - OpMemberDecorate %61 2 Offset 96 - OpMemberDecorate %61 3 Offset 108 - OpMemberDecorate %61 4 Offset 112 - OpMemberDecorate %63 0 Offset 0 - OpMemberDecorate %63 1 Offset 128 - OpMemberDecorate %63 2 Offset 136 - OpDecorate %63 Block - OpDecorate %65 DescriptorSet 0 - OpDecorate %65 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 5 - %9 = OpTypeArray %6 %8 - %10 = OpTypeInt 32 1 - %11 = OpTypeVector %10 4 - %12 = OpTypeVector %6 3 - %13 = OpTypeBool - %14 = OpTypeStruct %9 %11 %12 %7 %13 - %15 = OpTypePointer Function %14 - %17 = OpConstant %10 0 - %18 = OpConstant %6 1.9375 - %19 = OpTypePointer Function %6 - %21 = OpConstant %10 1 - %22 = OpConstant %6 1.875 - %24 = OpConstant %10 2 - %25 = OpConstant %6 1.75 - %27 = OpConstant %10 3 - %28 = OpConstant %6 1.5 - %30 = OpConstant %10 4 - %31 = OpConstant %6 1 - %33 = OpConstant %7 0 - %34 = OpTypePointer Function %10 - %36 = OpConstant %7 1 - %38 = OpConstant %7 2 - %40 = OpConstant %7 3 - %42 = OpConstant %10 22 - %44 = OpConstant %6 2.75 - %46 = OpConstant %6 2.5 - %48 = OpConstant %6 2 - %50 = OpConstant %7 42 - %51 = OpTypePointer Function %7 - %53 = OpConstant %7 100 - %55 = OpConstant %7 200 - %57 = OpConstantTrue %13 - %58 = OpTypePointer Function %13 - %60 = OpTypeArray %6 %8 - %61 = OpTypeStruct %60 %11 %12 %7 %7 - %62 = OpTypeVector %7 2 - %63 = OpTypeStruct %61 %10 %62 - %64 = OpTypePointer Uniform %63 - %100 = OpTypePointer Uniform %10 - %101 = OpTypePointer Uniform %7 - %102 = OpTypePointer Uniform %6 - %103 = OpTypePointer Uniform %13 - %65 = OpVariable %64 Uniform - %4 = OpFunction %2 None %3 - %5 = OpLabel - %16 = OpVariable %15 Function - %20 = OpAccessChain %19 %16 %17 %17 - %200 = OpAccessChain %102 %65 %17 %17 %30 - %201 = OpLoad %6 %200 - OpStore %20 %201 - %23 = OpAccessChain %19 %16 %17 %21 - %202 = OpAccessChain %102 %65 %17 %17 %27 - %203 = OpLoad %6 %202 - OpStore %23 %203 - %26 = OpAccessChain %19 %16 %17 %24 - %204 = OpAccessChain %102 %65 %17 %17 %24 - %205 = OpLoad %6 %204 - OpStore %26 %205 - %29 = OpAccessChain %19 %16 %17 %27 - %206 = OpAccessChain %102 %65 %17 %17 %21 - %207 = OpLoad %6 %206 - OpStore %29 %207 - %32 = OpAccessChain %19 %16 %17 %30 - %208 = OpAccessChain %102 %65 %17 %17 %17 - %209 = OpLoad %6 %208 - OpStore %32 %209 - %35 = OpAccessChain %34 %16 %21 %33 - %210 = OpAccessChain %100 %65 %17 %21 %27 - %211 = OpLoad %10 %210 - OpStore %35 %211 - %37 = OpAccessChain %34 %16 %21 %36 - %212 = OpAccessChain %100 %65 %17 %21 %24 - %213 = OpLoad %10 %212 - OpStore %37 %213 - %39 = OpAccessChain %34 %16 %21 %38 - %214 = OpAccessChain %100 %65 %17 %21 %21 - %215 = OpLoad %10 %214 - OpStore %39 %215 - %41 = OpAccessChain %34 %16 %21 %40 - %216 = OpAccessChain %100 %65 %17 %21 %17 - %217 = OpLoad %10 %216 - OpStore %41 %217 - %43 = OpAccessChain %34 %16 %21 %33 - %218 = OpAccessChain %100 %65 %21 - %219 = OpLoad %10 %218 - OpStore %43 %219 - %45 = OpAccessChain %19 %16 %24 %33 - %220 = OpAccessChain %102 %65 %17 %24 %24 - %221 = OpLoad %6 %220 - OpStore %45 %221 - %47 = OpAccessChain %19 %16 %24 %33 - %222 = OpAccessChain %102 %65 %17 %24 %21 - %223 = OpLoad %6 %222 - OpStore %47 %223 - %49 = OpAccessChain %19 %16 %24 %33 - %224 = OpAccessChain %102 %65 %17 %24 %17 - %225 = OpLoad %6 %224 - OpStore %49 %225 - %52 = OpAccessChain %51 %16 %27 - %226 = OpAccessChain %101 %65 %17 %27 - %227 = OpLoad %7 %226 - OpStore %52 %227 - %54 = OpAccessChain %51 %16 %27 - %228 = OpAccessChain %101 %65 %24 %17 - %229 = OpLoad %7 %228 - OpStore %54 %229 - %56 = OpAccessChain %51 %16 %27 - %230 = OpAccessChain %101 %65 %24 %21 - %231 = OpLoad %7 %230 - OpStore %56 %231 - %59 = OpAccessChain %58 %16 %30 - OpStore %59 %57 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp deleted file mode 100644 index 41b611667..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp +++ /dev/null @@ -1,1217 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_replace_id_with_synonym.h" -#include "source/fuzz/data_descriptor.h" -#include "source/fuzz/id_use_descriptor.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -// The following shader was obtained from this GLSL, which was then optimized -// with spirv-opt -O and manually edited to include some uses of OpCopyObject -// (to introduce id synonyms). -// -// #version 310 es -// -// precision highp int; -// precision highp float; -// -// layout(set = 0, binding = 0) uniform buf { -// int a; -// int b; -// int c; -// }; -// -// layout(location = 0) out vec4 color; -// -// void main() { -// int x = a; -// float f = 0.0; -// while (x < b) { -// switch(x % 4) { -// case 0: -// color[0] = f; -// break; -// case 1: -// color[1] = f; -// break; -// case 2: -// color[2] = f; -// break; -// case 3: -// color[3] = f; -// break; -// default: -// break; -// } -// if (x > c) { -// x++; -// } else { -// x += 2; -// } -// } -// color[0] += color[1] + float(x); -// } -const std::string kComplexShader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %42 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "buf" - OpMemberName %9 0 "a" - OpMemberName %9 1 "b" - OpMemberName %9 2 "c" - OpName %11 "" - OpName %42 "color" - OpMemberDecorate %9 0 Offset 0 - OpMemberDecorate %9 1 Offset 4 - OpMemberDecorate %9 2 Offset 8 - OpDecorate %9 Block - OpDecorate %11 DescriptorSet 0 - OpDecorate %11 Binding 0 - OpDecorate %42 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpTypeStruct %6 %6 %6 - %10 = OpTypePointer Uniform %9 - %11 = OpVariable %10 Uniform - %12 = OpConstant %6 0 - %13 = OpTypePointer Uniform %6 - %16 = OpTypeFloat 32 - %19 = OpConstant %16 0 - %26 = OpConstant %6 1 - %29 = OpTypeBool - %32 = OpConstant %6 4 - %40 = OpTypeVector %16 4 - %41 = OpTypePointer Output %40 - %42 = OpVariable %41 Output - %44 = OpTypeInt 32 0 - %45 = OpConstant %44 0 - %46 = OpTypePointer Output %16 - %50 = OpConstant %44 1 - %54 = OpConstant %44 2 - %58 = OpConstant %44 3 - %64 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %209 = OpCopyObject %6 %12 - %14 = OpAccessChain %13 %11 %12 - %15 = OpLoad %6 %14 - %200 = OpCopyObject %6 %15 - OpBranch %20 - %20 = OpLabel - %84 = OpPhi %6 %15 %5 %86 %69 - %27 = OpAccessChain %13 %11 %26 - %28 = OpLoad %6 %27 - %207 = OpCopyObject %6 %84 - %201 = OpCopyObject %6 %15 - %30 = OpSLessThan %29 %84 %28 - OpLoopMerge %22 %69 None - OpBranchConditional %30 %21 %22 - %21 = OpLabel - %33 = OpSMod %6 %84 %32 - %208 = OpCopyObject %6 %33 - OpSelectionMerge %39 None - OpSwitch %33 %38 0 %34 1 %35 2 %36 3 %37 - %38 = OpLabel - %202 = OpCopyObject %6 %15 - OpBranch %39 - %34 = OpLabel - %210 = OpCopyObject %16 %19 - %47 = OpAccessChain %46 %42 %45 - OpStore %47 %19 - OpBranch %39 - %35 = OpLabel - %51 = OpAccessChain %46 %42 %50 - OpStore %51 %19 - OpBranch %39 - %36 = OpLabel - %204 = OpCopyObject %44 %54 - %55 = OpAccessChain %46 %42 %54 - %203 = OpCopyObject %46 %55 - OpStore %55 %19 - OpBranch %39 - %37 = OpLabel - %59 = OpAccessChain %46 %42 %58 - OpStore %59 %19 - OpBranch %39 - %39 = OpLabel - %300 = OpIAdd %6 %15 %15 - %65 = OpAccessChain %13 %11 %64 - %66 = OpLoad %6 %65 - %67 = OpSGreaterThan %29 %84 %66 - OpSelectionMerge %1000 None - OpBranchConditional %67 %68 %72 - %68 = OpLabel - %71 = OpIAdd %6 %84 %26 - OpBranch %1000 - %72 = OpLabel - %74 = OpIAdd %6 %84 %64 - %205 = OpCopyObject %6 %74 - OpBranch %1000 - %1000 = OpLabel - %86 = OpPhi %6 %71 %68 %74 %72 - %301 = OpPhi %6 %71 %68 %15 %72 - OpBranch %69 - %69 = OpLabel - OpBranch %20 - %22 = OpLabel - %75 = OpAccessChain %46 %42 %50 - %76 = OpLoad %16 %75 - %78 = OpConvertSToF %16 %84 - %80 = OpAccessChain %46 %42 %45 - %206 = OpCopyObject %16 %78 - %81 = OpLoad %16 %80 - %79 = OpFAdd %16 %76 %78 - %82 = OpFAdd %16 %81 %79 - OpStore %80 %82 - OpReturn - OpFunctionEnd -)"; - -protobufs::Fact MakeSynonymFact(uint32_t first, uint32_t second) { - protobufs::FactDataSynonym data_synonym_fact; - *data_synonym_fact.mutable_data1() = MakeDataDescriptor(first, {}); - *data_synonym_fact.mutable_data2() = MakeDataDescriptor(second, {}); - protobufs::Fact result; - *result.mutable_data_synonym_fact() = data_synonym_fact; - return result; -} - -// Equips the fact manager with synonym facts for the above shader. -void SetUpIdSynonyms(FactManager* fact_manager, opt::IRContext* context) { - fact_manager->AddFact(MakeSynonymFact(15, 200), context); - fact_manager->AddFact(MakeSynonymFact(15, 201), context); - fact_manager->AddFact(MakeSynonymFact(15, 202), context); - fact_manager->AddFact(MakeSynonymFact(55, 203), context); - fact_manager->AddFact(MakeSynonymFact(54, 204), context); - fact_manager->AddFact(MakeSynonymFact(74, 205), context); - fact_manager->AddFact(MakeSynonymFact(78, 206), context); - fact_manager->AddFact(MakeSynonymFact(84, 207), context); - fact_manager->AddFact(MakeSynonymFact(33, 208), context); - fact_manager->AddFact(MakeSynonymFact(12, 209), context); - fact_manager->AddFact(MakeSynonymFact(19, 210), context); -} - -TEST(TransformationReplaceIdWithSynonymTest, IllegalTransformations) { - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, kComplexShader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - SetUpIdSynonyms(&fact_manager, context.get()); - - // %202 cannot replace %15 as in-operand 0 of %300, since %202 does not - // dominate %300. - auto synonym_does_not_dominate_use = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(15, MakeInstructionDescriptor(300, SpvOpIAdd, 0), 0), - 202); - ASSERT_FALSE( - synonym_does_not_dominate_use.IsApplicable(context.get(), fact_manager)); - - // %202 cannot replace %15 as in-operand 2 of %301, since this is the OpPhi's - // incoming value for block %72, and %202 does not dominate %72. - auto synonym_does_not_dominate_use_op_phi = - TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(15, MakeInstructionDescriptor(301, SpvOpPhi, 0), - 2), - 202); - ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(context.get(), - fact_manager)); - - // %200 is not a synonym for %84 - auto id_in_use_is_not_synonymous = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 84, MakeInstructionDescriptor(67, SpvOpSGreaterThan, 0), 0), - 200); - ASSERT_FALSE( - id_in_use_is_not_synonymous.IsApplicable(context.get(), fact_manager)); - - // %86 is not a synonym for anything (and in particular not for %74) - auto id_has_no_synonyms = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, SpvOpPhi, 0), 2), - 74); - ASSERT_FALSE(id_has_no_synonyms.IsApplicable(context.get(), fact_manager)); - - // This would lead to %207 = 'OpCopyObject %type %207' if it were allowed - auto synonym_use_is_in_synonym_definition = - TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 84, MakeInstructionDescriptor(207, SpvOpCopyObject, 0), 0), - 207); - ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(context.get(), - fact_manager)); - - // The id use descriptor does not lead to a use (%84 is not used in the - // definition of %207) - auto bad_id_use_descriptor = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 84, MakeInstructionDescriptor(200, SpvOpCopyObject, 0), 0), - 207); - ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(), fact_manager)); - - // This replacement would lead to an access chain into a struct using a - // non-constant index. - auto bad_access_chain = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 12, MakeInstructionDescriptor(14, SpvOpAccessChain, 0), 1), - 209); - ASSERT_FALSE(bad_access_chain.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) { - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, kComplexShader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - SetUpIdSynonyms(&fact_manager, context.get()); - - auto global_constant_synonym = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1), - 210); - ASSERT_TRUE( - global_constant_synonym.IsApplicable(context.get(), fact_manager)); - global_constant_synonym.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - auto replace_vector_access_chain_index = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 54, MakeInstructionDescriptor(55, SpvOpAccessChain, 0), 1), - 204); - ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(context.get(), - fact_manager)); - replace_vector_access_chain_index.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // This is an interesting case because it replaces something that is being - // copied with something that is already a synonym. - auto regular_replacement = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 15, MakeInstructionDescriptor(202, SpvOpCopyObject, 0), 0), - 201); - ASSERT_TRUE(regular_replacement.IsApplicable(context.get(), fact_manager)); - regular_replacement.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - auto regular_replacement2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(55, MakeInstructionDescriptor(203, SpvOpStore, 0), 0), - 203); - ASSERT_TRUE(regular_replacement2.IsApplicable(context.get(), fact_manager)); - regular_replacement2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - auto good_op_phi = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, SpvOpPhi, 0), 2), - 205); - ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), fact_manager)); - good_op_phi.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %42 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "buf" - OpMemberName %9 0 "a" - OpMemberName %9 1 "b" - OpMemberName %9 2 "c" - OpName %11 "" - OpName %42 "color" - OpMemberDecorate %9 0 Offset 0 - OpMemberDecorate %9 1 Offset 4 - OpMemberDecorate %9 2 Offset 8 - OpDecorate %9 Block - OpDecorate %11 DescriptorSet 0 - OpDecorate %11 Binding 0 - OpDecorate %42 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpTypeStruct %6 %6 %6 - %10 = OpTypePointer Uniform %9 - %11 = OpVariable %10 Uniform - %12 = OpConstant %6 0 - %13 = OpTypePointer Uniform %6 - %16 = OpTypeFloat 32 - %19 = OpConstant %16 0 - %26 = OpConstant %6 1 - %29 = OpTypeBool - %32 = OpConstant %6 4 - %40 = OpTypeVector %16 4 - %41 = OpTypePointer Output %40 - %42 = OpVariable %41 Output - %44 = OpTypeInt 32 0 - %45 = OpConstant %44 0 - %46 = OpTypePointer Output %16 - %50 = OpConstant %44 1 - %54 = OpConstant %44 2 - %58 = OpConstant %44 3 - %64 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %209 = OpCopyObject %6 %12 - %14 = OpAccessChain %13 %11 %12 - %15 = OpLoad %6 %14 - %200 = OpCopyObject %6 %15 - OpBranch %20 - %20 = OpLabel - %84 = OpPhi %6 %15 %5 %86 %69 - %27 = OpAccessChain %13 %11 %26 - %28 = OpLoad %6 %27 - %207 = OpCopyObject %6 %84 - %201 = OpCopyObject %6 %15 - %30 = OpSLessThan %29 %84 %28 - OpLoopMerge %22 %69 None - OpBranchConditional %30 %21 %22 - %21 = OpLabel - %33 = OpSMod %6 %84 %32 - %208 = OpCopyObject %6 %33 - OpSelectionMerge %39 None - OpSwitch %33 %38 0 %34 1 %35 2 %36 3 %37 - %38 = OpLabel - %202 = OpCopyObject %6 %201 - OpBranch %39 - %34 = OpLabel - %210 = OpCopyObject %16 %19 - %47 = OpAccessChain %46 %42 %45 - OpStore %47 %210 - OpBranch %39 - %35 = OpLabel - %51 = OpAccessChain %46 %42 %50 - OpStore %51 %19 - OpBranch %39 - %36 = OpLabel - %204 = OpCopyObject %44 %54 - %55 = OpAccessChain %46 %42 %204 - %203 = OpCopyObject %46 %55 - OpStore %203 %19 - OpBranch %39 - %37 = OpLabel - %59 = OpAccessChain %46 %42 %58 - OpStore %59 %19 - OpBranch %39 - %39 = OpLabel - %300 = OpIAdd %6 %15 %15 - %65 = OpAccessChain %13 %11 %64 - %66 = OpLoad %6 %65 - %67 = OpSGreaterThan %29 %84 %66 - OpSelectionMerge %1000 None - OpBranchConditional %67 %68 %72 - %68 = OpLabel - %71 = OpIAdd %6 %84 %26 - OpBranch %1000 - %72 = OpLabel - %74 = OpIAdd %6 %84 %64 - %205 = OpCopyObject %6 %74 - OpBranch %1000 - %1000 = OpLabel - %86 = OpPhi %6 %71 %68 %205 %72 - %301 = OpPhi %6 %71 %68 %15 %72 - OpBranch %69 - %69 = OpLabel - OpBranch %20 - %22 = OpLabel - %75 = OpAccessChain %46 %42 %50 - %76 = OpLoad %16 %75 - %78 = OpConvertSToF %16 %84 - %80 = OpAccessChain %46 %42 %45 - %206 = OpCopyObject %16 %78 - %81 = OpLoad %16 %80 - %79 = OpFAdd %16 %76 %78 - %82 = OpFAdd %16 %81 %79 - OpStore %80 %82 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) { - // The following SPIR-V comes from this GLSL, with object copies added: - // - // #version 310 es - // - // precision highp int; - // - // int g; - // - // void main() { - // int l; - // l = g; - // g = l; - // } - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "l" - OpName %10 "g" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypePointer Private %6 - %10 = OpVariable %9 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %100 = OpCopyObject %9 %10 - %101 = OpCopyObject %7 %8 - %11 = OpLoad %6 %10 - OpStore %8 %11 - %12 = OpLoad %6 %8 - OpStore %10 %12 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - fact_manager.AddFact(MakeSynonymFact(10, 100), context.get()); - fact_manager.AddFact(MakeSynonymFact(8, 101), context.get()); - - // Replace %10 with %100 in: - // %11 = OpLoad %6 %10 - auto replacement1 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, SpvOpLoad, 0), 0), - 100); - ASSERT_TRUE(replacement1.IsApplicable(context.get(), fact_manager)); - replacement1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %8 with %101 in: - // OpStore %8 %11 - auto replacement2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, SpvOpStore, 0), 0), - 101); - ASSERT_TRUE(replacement2.IsApplicable(context.get(), fact_manager)); - replacement2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %8 with %101 in: - // %12 = OpLoad %6 %8 - auto replacement3 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, SpvOpLoad, 0), 0), - 101); - ASSERT_TRUE(replacement3.IsApplicable(context.get(), fact_manager)); - replacement3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replace %10 with %100 in: - // OpStore %10 %12 - auto replacement4 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(10, MakeInstructionDescriptor(12, SpvOpStore, 0), 0), - 100); - ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager)); - replacement4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "l" - OpName %10 "g" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypePointer Private %6 - %10 = OpVariable %9 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %100 = OpCopyObject %9 %10 - %101 = OpCopyObject %7 %8 - %11 = OpLoad %6 %100 - OpStore %101 %11 - %12 = OpLoad %6 %101 - OpStore %100 %12 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationReplaceIdWithSynonymTest, - SynonymOfVariableNoGoodInFunctionCall) { - // The following SPIR-V comes from this GLSL, with an object copy added: - // - // #version 310 es - // - // precision highp int; - // - // void foo(int x) { } - // - // void main() { - // int a; - // a = 2; - // foo(a); - // } - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %10 "foo(i1;" - OpName %9 "x" - OpName %12 "a" - OpName %14 "param" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %2 %7 - %13 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %12 %13 - %15 = OpLoad %6 %12 - OpStore %14 %15 - %100 = OpCopyObject %7 %14 - %16 = OpFunctionCall %2 %10 %14 - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %8 - %9 = OpFunctionParameter %7 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - fact_manager.AddFact(MakeSynonymFact(14, 100), context.get()); - - // Replace %14 with %100 in: - // %16 = OpFunctionCall %2 %10 %14 - auto replacement = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 14, MakeInstructionDescriptor(16, SpvOpFunctionCall, 0), 1), - 100); - ASSERT_FALSE(replacement.IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) { - // The following SPIR-V comes from this GLSL, with object copies added: - // - // #version 310 es - // - // precision highp float; - // precision highp int; - // - // struct S { - // int[3] a; - // vec4 b; - // bool c; - // } d; - // - // float[20] e; - // - // struct T { - // float f; - // S g; - // } h; - // - // T[4] i; - // - // void main() { - // d.a[2] = 10; - // d.b[3] = 11.0; - // d.c = false; - // e[17] = 12.0; - // h.f = 13.0; - // h.g.a[1] = 14; - // h.g.b[0] = 15.0; - // h.g.c = true; - // i[0].f = 16.0; - // i[1].g.a[0] = 17; - // i[2].g.b[1] = 18.0; - // i[3].g.c = true; - // } - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %13 "S" - OpMemberName %13 0 "a" - OpMemberName %13 1 "b" - OpMemberName %13 2 "c" - OpName %15 "d" - OpName %31 "e" - OpName %35 "T" - OpMemberName %35 0 "f" - OpMemberName %35 1 "g" - OpName %37 "h" - OpName %50 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 3 - %9 = OpTypeArray %6 %8 - %10 = OpTypeFloat 32 - %11 = OpTypeVector %10 4 - %12 = OpTypeBool - %13 = OpTypeStruct %9 %11 %12 - %14 = OpTypePointer Private %13 - %15 = OpVariable %14 Private - %16 = OpConstant %6 0 - %17 = OpConstant %6 2 - %18 = OpConstant %6 10 - %19 = OpTypePointer Private %6 - %21 = OpConstant %6 1 - %22 = OpConstant %10 11 - %23 = OpTypePointer Private %10 - %25 = OpConstantFalse %12 - %26 = OpTypePointer Private %12 - %28 = OpConstant %7 20 - %29 = OpTypeArray %10 %28 - %30 = OpTypePointer Private %29 - %31 = OpVariable %30 Private - %32 = OpConstant %6 17 - %33 = OpConstant %10 12 - %35 = OpTypeStruct %10 %13 - %36 = OpTypePointer Private %35 - %37 = OpVariable %36 Private - %38 = OpConstant %10 13 - %40 = OpConstant %6 14 - %42 = OpConstant %10 15 - %43 = OpConstant %7 0 - %45 = OpConstantTrue %12 - %47 = OpConstant %7 4 - %48 = OpTypeArray %35 %47 - %49 = OpTypePointer Private %48 - %50 = OpVariable %49 Private - %51 = OpConstant %10 16 - %54 = OpConstant %10 18 - %55 = OpConstant %7 1 - %57 = OpConstant %6 3 - %4 = OpFunction %2 None %3 - %5 = OpLabel - - %100 = OpCopyObject %6 %16 ; 0 - %101 = OpCopyObject %6 %21 ; 1 - %102 = OpCopyObject %6 %17 ; 2 - %103 = OpCopyObject %6 %57 ; 3 - %104 = OpCopyObject %6 %18 ; 10 - %105 = OpCopyObject %6 %40 ; 14 - %106 = OpCopyObject %6 %32 ; 17 - %107 = OpCopyObject %7 %43 ; 0 - %108 = OpCopyObject %7 %55 ; 1 - %109 = OpCopyObject %7 %8 ; 3 - %110 = OpCopyObject %7 %47 ; 4 - %111 = OpCopyObject %7 %28 ; 20 - %112 = OpCopyObject %12 %45 ; true - - %20 = OpAccessChain %19 %15 %16 %17 - OpStore %20 %18 - %24 = OpAccessChain %23 %15 %21 %8 - OpStore %24 %22 - %27 = OpAccessChain %26 %15 %17 - OpStore %27 %25 - %34 = OpAccessChain %23 %31 %32 - OpStore %34 %33 - %39 = OpAccessChain %23 %37 %16 - OpStore %39 %38 - %41 = OpAccessChain %19 %37 %21 %16 %21 - OpStore %41 %40 - %44 = OpAccessChain %23 %37 %21 %21 %43 - OpStore %44 %42 - %46 = OpAccessChain %26 %37 %21 %17 - OpStore %46 %45 - %52 = OpAccessChain %23 %50 %16 %16 - OpStore %52 %51 - %53 = OpAccessChain %19 %50 %21 %21 %16 %16 - OpStore %53 %32 - %56 = OpAccessChain %23 %50 %17 %21 %21 %55 - OpStore %56 %54 - %58 = OpAccessChain %26 %50 %57 %21 %17 - OpStore %58 %45 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Add synonym facts corresponding to the OpCopyObject operations that have - // been applied to all constants in the module. - fact_manager.AddFact(MakeSynonymFact(16, 100), context.get()); - fact_manager.AddFact(MakeSynonymFact(21, 101), context.get()); - fact_manager.AddFact(MakeSynonymFact(17, 102), context.get()); - fact_manager.AddFact(MakeSynonymFact(57, 103), context.get()); - fact_manager.AddFact(MakeSynonymFact(18, 104), context.get()); - fact_manager.AddFact(MakeSynonymFact(40, 105), context.get()); - fact_manager.AddFact(MakeSynonymFact(32, 106), context.get()); - fact_manager.AddFact(MakeSynonymFact(43, 107), context.get()); - fact_manager.AddFact(MakeSynonymFact(55, 108), context.get()); - fact_manager.AddFact(MakeSynonymFact(8, 109), context.get()); - fact_manager.AddFact(MakeSynonymFact(47, 110), context.get()); - fact_manager.AddFact(MakeSynonymFact(28, 111), context.get()); - fact_manager.AddFact(MakeSynonymFact(45, 112), context.get()); - - // Replacements of the form %16 -> %100 - - // %20 = OpAccessChain %19 %15 *%16* %17 - // Corresponds to d.*a*[2] - // The index %16 used for a cannot be replaced - auto replacement1 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 1), - 100); - ASSERT_FALSE(replacement1.IsApplicable(context.get(), fact_manager)); - - // %39 = OpAccessChain %23 %37 *%16* - // Corresponds to h.*f* - // The index %16 used for f cannot be replaced - auto replacement2 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(39, SpvOpAccessChain, 0), 1), - 100); - ASSERT_FALSE(replacement2.IsApplicable(context.get(), fact_manager)); - - // %41 = OpAccessChain %19 %37 %21 *%16* %21 - // Corresponds to h.g.*a*[1] - // The index %16 used for a cannot be replaced - auto replacement3 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 2), - 100); - ASSERT_FALSE(replacement3.IsApplicable(context.get(), fact_manager)); - - // %52 = OpAccessChain %23 %50 *%16* %16 - // Corresponds to i[*0*].f - // The index %16 used for 0 *can* be replaced - auto replacement4 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 1), - 100); - ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager)); - replacement4.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // %52 = OpAccessChain %23 %50 %16 *%16* - // Corresponds to i[0].*f* - // The index %16 used for f cannot be replaced - auto replacement5 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 2), - 100); - ASSERT_FALSE(replacement5.IsApplicable(context.get(), fact_manager)); - - // %53 = OpAccessChain %19 %50 %21 %21 *%16* %16 - // Corresponds to i[1].g.*a*[0] - // The index %16 used for a cannot be replaced - auto replacement6 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 3), - 100); - ASSERT_FALSE(replacement6.IsApplicable(context.get(), fact_manager)); - - // %53 = OpAccessChain %19 %50 %21 %21 %16 *%16* - // Corresponds to i[1].g.a[*0*] - // The index %16 used for 0 *can* be replaced - auto replacement7 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 4), - 100); - ASSERT_TRUE(replacement7.IsApplicable(context.get(), fact_manager)); - replacement7.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replacements of the form %21 -> %101 - - // %24 = OpAccessChain %23 %15 *%21* %8 - // Corresponds to d.*b*[3] - // The index %24 used for b cannot be replaced - auto replacement8 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 1), - 101); - ASSERT_FALSE(replacement8.IsApplicable(context.get(), fact_manager)); - - // %41 = OpAccessChain %19 %37 *%21* %16 %21 - // Corresponds to h.*g*.a[1] - // The index %24 used for g cannot be replaced - auto replacement9 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 1), - 101); - ASSERT_FALSE(replacement9.IsApplicable(context.get(), fact_manager)); - - // %41 = OpAccessChain %19 %37 %21 %16 *%21* - // Corresponds to h.g.a[*1*] - // The index %24 used for 1 *can* be replaced - auto replacement10 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 3), - 101); - ASSERT_TRUE(replacement10.IsApplicable(context.get(), fact_manager)); - replacement10.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // %44 = OpAccessChain %23 %37 *%21* %21 %43 - // Corresponds to h.*g*.b[0] - // The index %24 used for g cannot be replaced - auto replacement11 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 1), - 101); - ASSERT_FALSE(replacement11.IsApplicable(context.get(), fact_manager)); - - // %44 = OpAccessChain %23 %37 %21 *%21* %43 - // Corresponds to h.g.*b*[0] - // The index %24 used for b cannot be replaced - auto replacement12 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 2), - 101); - ASSERT_FALSE(replacement12.IsApplicable(context.get(), fact_manager)); - - // %46 = OpAccessChain %26 %37 *%21* %17 - // Corresponds to h.*g*.c - // The index %24 used for g cannot be replaced - auto replacement13 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 1), - 101); - ASSERT_FALSE(replacement13.IsApplicable(context.get(), fact_manager)); - - // %53 = OpAccessChain %19 %50 *%21* %21 %16 %16 - // Corresponds to i[*1*].g.a[0] - // The index %24 used for 1 *can* be replaced - auto replacement14 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 1), - 101); - ASSERT_TRUE(replacement14.IsApplicable(context.get(), fact_manager)); - replacement14.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // %53 = OpAccessChain %19 %50 %21 *%21* %16 %16 - // Corresponds to i[1].*g*.a[0] - // The index %24 used for g cannot be replaced - auto replacement15 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 2), - 101); - ASSERT_FALSE(replacement15.IsApplicable(context.get(), fact_manager)); - - // %56 = OpAccessChain %23 %50 %17 *%21* %21 %55 - // Corresponds to i[2].*g*.b[1] - // The index %24 used for g cannot be replaced - auto replacement16 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 2), - 101); - ASSERT_FALSE(replacement16.IsApplicable(context.get(), fact_manager)); - - // %56 = OpAccessChain %23 %50 %17 %21 *%21* %55 - // Corresponds to i[2].g.*b*[1] - // The index %24 used for b cannot be replaced - auto replacement17 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 3), - 101); - ASSERT_FALSE(replacement17.IsApplicable(context.get(), fact_manager)); - - // %58 = OpAccessChain %26 %50 %57 *%21* %17 - // Corresponds to i[3].*g*.c - // The index %24 used for g cannot be replaced - auto replacement18 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 21, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 2), - 101); - ASSERT_FALSE(replacement18.IsApplicable(context.get(), fact_manager)); - - // Replacements of the form %17 -> %102 - - // %20 = OpAccessChain %19 %15 %16 %17 - // Corresponds to d.a[*2*] - // The index %17 used for 2 *can* be replaced - auto replacement19 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 17, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 2), - 102); - ASSERT_TRUE(replacement19.IsApplicable(context.get(), fact_manager)); - replacement19.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // %27 = OpAccessChain %26 %15 %17 - // Corresponds to d.c - // The index %17 used for c cannot be replaced - auto replacement20 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 17, MakeInstructionDescriptor(27, SpvOpAccessChain, 0), 1), - 102); - ASSERT_FALSE(replacement20.IsApplicable(context.get(), fact_manager)); - - // %46 = OpAccessChain %26 %37 %21 %17 - // Corresponds to h.g.*c* - // The index %17 used for c cannot be replaced - auto replacement21 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 17, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 2), - 102); - ASSERT_FALSE(replacement21.IsApplicable(context.get(), fact_manager)); - - // %56 = OpAccessChain %23 %50 %17 %21 %21 %55 - // Corresponds to i[*2*].g.b[1] - // The index %17 used for 2 *can* be replaced - auto replacement22 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 17, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 1), - 102); - ASSERT_TRUE(replacement22.IsApplicable(context.get(), fact_manager)); - replacement22.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // %58 = OpAccessChain %26 %50 %57 %21 %17 - // Corresponds to i[3].g.*c* - // The index %17 used for c cannot be replaced - auto replacement23 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 17, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 3), - 102); - ASSERT_FALSE(replacement23.IsApplicable(context.get(), fact_manager)); - - // Replacements of the form %57 -> %103 - - // %58 = OpAccessChain %26 %50 *%57* %21 %17 - // Corresponds to i[*3*].g.c - // The index %57 used for 3 *can* be replaced - auto replacement24 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 57, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 1), - 103); - ASSERT_TRUE(replacement24.IsApplicable(context.get(), fact_manager)); - replacement24.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replacements of the form %32 -> %106 - - // %34 = OpAccessChain %23 %31 *%32* - // Corresponds to e[*17*] - // The index %32 used for 17 *can* be replaced - auto replacement25 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 32, MakeInstructionDescriptor(34, SpvOpAccessChain, 0), 1), - 106); - ASSERT_TRUE(replacement25.IsApplicable(context.get(), fact_manager)); - replacement25.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replacements of the form %43 -> %107 - - // %44 = OpAccessChain %23 %37 %21 %21 *%43* - // Corresponds to h.g.b[*0*] - // The index %43 used for 0 *can* be replaced - auto replacement26 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 43, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 3), - 107); - ASSERT_TRUE(replacement26.IsApplicable(context.get(), fact_manager)); - replacement26.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replacements of the form %55 -> %108 - - // %56 = OpAccessChain %23 %50 %17 %21 %21 *%55* - // Corresponds to i[2].g.b[*1*] - // The index %55 used for 1 *can* be replaced - auto replacement27 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor( - 55, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 4), - 108); - ASSERT_TRUE(replacement27.IsApplicable(context.get(), fact_manager)); - replacement27.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - // Replacements of the form %8 -> %109 - - // %24 = OpAccessChain %23 %15 %21 *%8* - // Corresponds to d.b[*3*] - // The index %8 used for 3 *can* be replaced - auto replacement28 = TransformationReplaceIdWithSynonym( - MakeIdUseDescriptor(8, MakeInstructionDescriptor(24, SpvOpAccessChain, 0), - 2), - 109); - ASSERT_TRUE(replacement28.IsApplicable(context.get(), fact_manager)); - replacement28.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - const std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %13 "S" - OpMemberName %13 0 "a" - OpMemberName %13 1 "b" - OpMemberName %13 2 "c" - OpName %15 "d" - OpName %31 "e" - OpName %35 "T" - OpMemberName %35 0 "f" - OpMemberName %35 1 "g" - OpName %37 "h" - OpName %50 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 3 - %9 = OpTypeArray %6 %8 - %10 = OpTypeFloat 32 - %11 = OpTypeVector %10 4 - %12 = OpTypeBool - %13 = OpTypeStruct %9 %11 %12 - %14 = OpTypePointer Private %13 - %15 = OpVariable %14 Private - %16 = OpConstant %6 0 - %17 = OpConstant %6 2 - %18 = OpConstant %6 10 - %19 = OpTypePointer Private %6 - %21 = OpConstant %6 1 - %22 = OpConstant %10 11 - %23 = OpTypePointer Private %10 - %25 = OpConstantFalse %12 - %26 = OpTypePointer Private %12 - %28 = OpConstant %7 20 - %29 = OpTypeArray %10 %28 - %30 = OpTypePointer Private %29 - %31 = OpVariable %30 Private - %32 = OpConstant %6 17 - %33 = OpConstant %10 12 - %35 = OpTypeStruct %10 %13 - %36 = OpTypePointer Private %35 - %37 = OpVariable %36 Private - %38 = OpConstant %10 13 - %40 = OpConstant %6 14 - %42 = OpConstant %10 15 - %43 = OpConstant %7 0 - %45 = OpConstantTrue %12 - %47 = OpConstant %7 4 - %48 = OpTypeArray %35 %47 - %49 = OpTypePointer Private %48 - %50 = OpVariable %49 Private - %51 = OpConstant %10 16 - %54 = OpConstant %10 18 - %55 = OpConstant %7 1 - %57 = OpConstant %6 3 - %4 = OpFunction %2 None %3 - %5 = OpLabel - - %100 = OpCopyObject %6 %16 ; 0 - %101 = OpCopyObject %6 %21 ; 1 - %102 = OpCopyObject %6 %17 ; 2 - %103 = OpCopyObject %6 %57 ; 3 - %104 = OpCopyObject %6 %18 ; 10 - %105 = OpCopyObject %6 %40 ; 14 - %106 = OpCopyObject %6 %32 ; 17 - %107 = OpCopyObject %7 %43 ; 0 - %108 = OpCopyObject %7 %55 ; 1 - %109 = OpCopyObject %7 %8 ; 3 - %110 = OpCopyObject %7 %47 ; 4 - %111 = OpCopyObject %7 %28 ; 20 - %112 = OpCopyObject %12 %45 ; true - - %20 = OpAccessChain %19 %15 %16 %102 - OpStore %20 %18 - %24 = OpAccessChain %23 %15 %21 %109 - OpStore %24 %22 - %27 = OpAccessChain %26 %15 %17 - OpStore %27 %25 - %34 = OpAccessChain %23 %31 %106 - OpStore %34 %33 - %39 = OpAccessChain %23 %37 %16 - OpStore %39 %38 - %41 = OpAccessChain %19 %37 %21 %16 %101 - OpStore %41 %40 - %44 = OpAccessChain %23 %37 %21 %21 %107 - OpStore %44 %42 - %46 = OpAccessChain %26 %37 %21 %17 - OpStore %46 %45 - %52 = OpAccessChain %23 %50 %100 %16 - OpStore %52 %51 - %53 = OpAccessChain %19 %50 %101 %21 %16 %100 - OpStore %53 %32 - %56 = OpAccessChain %23 %50 %102 %21 %21 %108 - OpStore %56 %54 - %58 = OpAccessChain %26 %50 %103 %21 %17 - OpStore %58 %45 - OpReturn - OpFunctionEnd - )"; - - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_set_function_control_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_set_function_control_test.cpp deleted file mode 100644 index 536e965e3..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_set_function_control_test.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_set_function_control.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationSetFunctionControlTest, VariousScenarios) { - // This is a simple transformation; this test captures the important things - // to check for. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %54 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %11 "foo(i1;i1;" - OpName %9 "a" - OpName %10 "b" - OpName %13 "bar(" - OpName %17 "baz(i1;" - OpName %16 "x" - OpName %21 "boo(i1;i1;" - OpName %19 "a" - OpName %20 "b" - OpName %29 "g" - OpName %42 "param" - OpName %44 "param" - OpName %45 "param" - OpName %48 "param" - OpName %49 "param" - OpName %54 "color" - OpDecorate %54 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %6 %7 %7 - %15 = OpTypeFunction %6 %7 - %28 = OpTypePointer Private %6 - %29 = OpVariable %28 Private - %30 = OpConstant %6 2 - %31 = OpConstant %6 5 - %51 = OpTypeFloat 32 - %52 = OpTypeVector %51 4 - %53 = OpTypePointer Output %52 - %54 = OpVariable %53 Output - %4 = OpFunction %2 None %3 - %5 = OpLabel - %42 = OpVariable %7 Function - %44 = OpVariable %7 Function - %45 = OpVariable %7 Function - %48 = OpVariable %7 Function - %49 = OpVariable %7 Function - %41 = OpFunctionCall %2 %13 - OpStore %42 %30 - %43 = OpFunctionCall %6 %17 %42 - OpStore %44 %31 - %46 = OpLoad %6 %29 - OpStore %45 %46 - %47 = OpFunctionCall %6 %21 %44 %45 - OpStore %48 %43 - OpStore %49 %47 - %50 = OpFunctionCall %6 %11 %48 %49 - OpReturn - OpFunctionEnd - %11 = OpFunction %6 Const %8 - %9 = OpFunctionParameter %7 - %10 = OpFunctionParameter %7 - %12 = OpLabel - %23 = OpLoad %6 %9 - %24 = OpLoad %6 %10 - %25 = OpIAdd %6 %23 %24 - OpReturnValue %25 - OpFunctionEnd - %13 = OpFunction %2 Inline %3 - %14 = OpLabel - OpStore %29 %30 - OpReturn - OpFunctionEnd - %17 = OpFunction %6 Pure|DontInline %15 - %16 = OpFunctionParameter %7 - %18 = OpLabel - %32 = OpLoad %6 %16 - %33 = OpIAdd %6 %31 %32 - OpReturnValue %33 - OpFunctionEnd - %21 = OpFunction %6 DontInline %8 - %19 = OpFunctionParameter %7 - %20 = OpFunctionParameter %7 - %22 = OpLabel - %36 = OpLoad %6 %19 - %37 = OpLoad %6 %20 - %38 = OpIMul %6 %36 %37 - OpReturnValue %38 - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - // %36 is not a function - ASSERT_FALSE(TransformationSetFunctionControl(36, SpvFunctionControlMaskNone) - .IsApplicable(context.get(), fact_manager)); - // Cannot add the Pure function control to %4 as it did not already have it - ASSERT_FALSE(TransformationSetFunctionControl(4, SpvFunctionControlPureMask) - .IsApplicable(context.get(), fact_manager)); - // Cannot add the Const function control to %21 as it did not already - // have it - ASSERT_FALSE(TransformationSetFunctionControl(21, SpvFunctionControlConstMask) - .IsApplicable(context.get(), fact_manager)); - - // Set to None, removing Const - TransformationSetFunctionControl transformation1(11, - SpvFunctionControlMaskNone); - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - - // Set to Inline; silly to do it on an entry point, but it is allowed - TransformationSetFunctionControl transformation2( - 4, SpvFunctionControlInlineMask); - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - - // Set to Pure, removing DontInline - TransformationSetFunctionControl transformation3(17, - SpvFunctionControlPureMask); - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - - // Change from Inline to DontInline - TransformationSetFunctionControl transformation4( - 13, SpvFunctionControlDontInlineMask); - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %54 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %11 "foo(i1;i1;" - OpName %9 "a" - OpName %10 "b" - OpName %13 "bar(" - OpName %17 "baz(i1;" - OpName %16 "x" - OpName %21 "boo(i1;i1;" - OpName %19 "a" - OpName %20 "b" - OpName %29 "g" - OpName %42 "param" - OpName %44 "param" - OpName %45 "param" - OpName %48 "param" - OpName %49 "param" - OpName %54 "color" - OpDecorate %54 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %6 %7 %7 - %15 = OpTypeFunction %6 %7 - %28 = OpTypePointer Private %6 - %29 = OpVariable %28 Private - %30 = OpConstant %6 2 - %31 = OpConstant %6 5 - %51 = OpTypeFloat 32 - %52 = OpTypeVector %51 4 - %53 = OpTypePointer Output %52 - %54 = OpVariable %53 Output - %4 = OpFunction %2 Inline %3 - %5 = OpLabel - %42 = OpVariable %7 Function - %44 = OpVariable %7 Function - %45 = OpVariable %7 Function - %48 = OpVariable %7 Function - %49 = OpVariable %7 Function - %41 = OpFunctionCall %2 %13 - OpStore %42 %30 - %43 = OpFunctionCall %6 %17 %42 - OpStore %44 %31 - %46 = OpLoad %6 %29 - OpStore %45 %46 - %47 = OpFunctionCall %6 %21 %44 %45 - OpStore %48 %43 - OpStore %49 %47 - %50 = OpFunctionCall %6 %11 %48 %49 - OpReturn - OpFunctionEnd - %11 = OpFunction %6 None %8 - %9 = OpFunctionParameter %7 - %10 = OpFunctionParameter %7 - %12 = OpLabel - %23 = OpLoad %6 %9 - %24 = OpLoad %6 %10 - %25 = OpIAdd %6 %23 %24 - OpReturnValue %25 - OpFunctionEnd - %13 = OpFunction %2 DontInline %3 - %14 = OpLabel - OpStore %29 %30 - OpReturn - OpFunctionEnd - %17 = OpFunction %6 Pure %15 - %16 = OpFunctionParameter %7 - %18 = OpLabel - %32 = OpLoad %6 %16 - %33 = OpIAdd %6 %31 %32 - OpReturnValue %33 - OpFunctionEnd - %21 = OpFunction %6 DontInline %8 - %19 = OpFunctionParameter %7 - %20 = OpFunctionParameter %7 - %22 = OpLabel - %36 = OpLoad %6 %19 - %37 = OpLoad %6 %20 - %38 = OpIMul %6 %36 %37 - OpReturnValue %38 - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp deleted file mode 100644 index 83953ec0e..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp +++ /dev/null @@ -1,968 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_set_loop_control.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationSetLoopControlTest, VariousScenarios) { - // This test features loops with various different controls, and goes through - // a number of acceptable and unacceptable transformations to those controls. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - %32 = OpVariable %7 Function - %42 = OpVariable %7 Function - %52 = OpVariable %7 Function - %62 = OpVariable %7 Function - %72 = OpVariable %7 Function - %82 = OpVariable %7 Function - %92 = OpVariable %7 Function - %102 = OpVariable %7 Function - %112 = OpVariable %7 Function - %122 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %132 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %132 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %132 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %133 = OpPhi %6 %9 %12 %31 %26 - OpLoopMerge %25 %26 Unroll - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %133 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %31 = OpIAdd %6 %133 %20 - OpStore %22 %31 - OpBranch %23 - %25 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - %134 = OpPhi %6 %9 %25 %41 %36 - OpLoopMerge %35 %36 DontUnroll - OpBranch %37 - %37 = OpLabel - %39 = OpSLessThan %17 %134 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpBranch %36 - %36 = OpLabel - %41 = OpIAdd %6 %134 %20 - OpStore %32 %41 - OpBranch %33 - %35 = OpLabel - OpStore %42 %9 - OpBranch %43 - %43 = OpLabel - %135 = OpPhi %6 %9 %35 %51 %46 - OpLoopMerge %45 %46 DependencyInfinite - OpBranch %47 - %47 = OpLabel - %49 = OpSLessThan %17 %135 %16 - OpBranchConditional %49 %44 %45 - %44 = OpLabel - OpBranch %46 - %46 = OpLabel - %51 = OpIAdd %6 %135 %20 - OpStore %42 %51 - OpBranch %43 - %45 = OpLabel - OpStore %52 %9 - OpBranch %53 - %53 = OpLabel - %136 = OpPhi %6 %9 %45 %61 %56 - OpLoopMerge %55 %56 DependencyLength 3 - OpBranch %57 - %57 = OpLabel - %59 = OpSLessThan %17 %136 %16 - OpBranchConditional %59 %54 %55 - %54 = OpLabel - OpBranch %56 - %56 = OpLabel - %61 = OpIAdd %6 %136 %20 - OpStore %52 %61 - OpBranch %53 - %55 = OpLabel - OpStore %62 %9 - OpBranch %63 - %63 = OpLabel - %137 = OpPhi %6 %9 %55 %71 %66 - OpLoopMerge %65 %66 MinIterations 10 - OpBranch %67 - %67 = OpLabel - %69 = OpSLessThan %17 %137 %16 - OpBranchConditional %69 %64 %65 - %64 = OpLabel - OpBranch %66 - %66 = OpLabel - %71 = OpIAdd %6 %137 %20 - OpStore %62 %71 - OpBranch %63 - %65 = OpLabel - OpStore %72 %9 - OpBranch %73 - %73 = OpLabel - %138 = OpPhi %6 %9 %65 %81 %76 - OpLoopMerge %75 %76 MaxIterations 50 - OpBranch %77 - %77 = OpLabel - %79 = OpSLessThan %17 %138 %16 - OpBranchConditional %79 %74 %75 - %74 = OpLabel - OpBranch %76 - %76 = OpLabel - %81 = OpIAdd %6 %138 %20 - OpStore %72 %81 - OpBranch %73 - %75 = OpLabel - OpStore %82 %9 - OpBranch %83 - %83 = OpLabel - %139 = OpPhi %6 %9 %75 %91 %86 - OpLoopMerge %85 %86 IterationMultiple 4 - OpBranch %87 - %87 = OpLabel - %89 = OpSLessThan %17 %139 %16 - OpBranchConditional %89 %84 %85 - %84 = OpLabel - OpBranch %86 - %86 = OpLabel - %91 = OpIAdd %6 %139 %20 - OpStore %82 %91 - OpBranch %83 - %85 = OpLabel - OpStore %92 %9 - OpBranch %93 - %93 = OpLabel - %140 = OpPhi %6 %9 %85 %101 %96 - OpLoopMerge %95 %96 PeelCount 2 - OpBranch %97 - %97 = OpLabel - %99 = OpSLessThan %17 %140 %16 - OpBranchConditional %99 %94 %95 - %94 = OpLabel - OpBranch %96 - %96 = OpLabel - %101 = OpIAdd %6 %140 %20 - OpStore %92 %101 - OpBranch %93 - %95 = OpLabel - OpStore %102 %9 - OpBranch %103 - %103 = OpLabel - %141 = OpPhi %6 %9 %95 %111 %106 - OpLoopMerge %105 %106 PartialCount 3 - OpBranch %107 - %107 = OpLabel - %109 = OpSLessThan %17 %141 %16 - OpBranchConditional %109 %104 %105 - %104 = OpLabel - OpBranch %106 - %106 = OpLabel - %111 = OpIAdd %6 %141 %20 - OpStore %102 %111 - OpBranch %103 - %105 = OpLabel - OpStore %112 %9 - OpBranch %113 - %113 = OpLabel - %142 = OpPhi %6 %9 %105 %121 %116 - OpLoopMerge %115 %116 Unroll|PeelCount|PartialCount 3 4 - OpBranch %117 - %117 = OpLabel - %119 = OpSLessThan %17 %142 %16 - OpBranchConditional %119 %114 %115 - %114 = OpLabel - OpBranch %116 - %116 = OpLabel - %121 = OpIAdd %6 %142 %20 - OpStore %112 %121 - OpBranch %113 - %115 = OpLabel - OpStore %122 %9 - OpBranch %123 - %123 = OpLabel - %143 = OpPhi %6 %9 %115 %131 %126 - OpLoopMerge %125 %126 DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount 2 5 90 4 7 14 - OpBranch %127 - %127 = OpLabel - %129 = OpSLessThan %17 %143 %16 - OpBranchConditional %129 %124 %125 - %124 = OpLabel - OpBranch %126 - %126 = OpLabel - %131 = OpIAdd %6 %143 %20 - OpStore %122 %131 - OpBranch %123 - %125 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // These are the loop headers together with the selection controls of their - // merge instructions: - // %10 None - // %23 Unroll - // %33 DontUnroll - // %43 DependencyInfinite - // %53 DependencyLength 3 - // %63 MinIterations 10 - // %73 MaxIterations 50 - // %83 IterationMultiple 4 - // %93 PeelCount 2 - // %103 PartialCount 3 - // %113 Unroll|PeelCount|PartialCount 3 4 - // %123 - // DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount - // 2 5 90 4 7 14 - - ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(10, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 10, SpvLoopControlDependencyInfiniteMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(10, SpvLoopControlDependencyLengthMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(10, SpvLoopControlMinIterationsMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(10, SpvLoopControlMaxIterationsMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 10, SpvLoopControlIterationMultipleMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 0, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 3, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl( - 10, - SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, - 3, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(10, - SpvLoopControlUnrollMask | - SpvLoopControlPeelCountMask | - SpvLoopControlPartialCountMask, - 3, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl(10, - SpvLoopControlDontUnrollMask | - SpvLoopControlPeelCountMask | - SpvLoopControlPartialCountMask, - 3, 3) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl( - 23, - SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, - 3, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(23, SpvLoopControlMaxIterationsMask, 2, 3) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(33, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(33, SpvLoopControlMinIterationsMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 33, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl(33, - SpvLoopControlDontUnrollMask | - SpvLoopControlPartialCountMask, - 0, 10) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(43, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl( - 43, - SpvLoopControlMaskNone | SpvLoopControlDependencyInfiniteMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 43, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 43, - SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(43, - SpvLoopControlDependencyInfiniteMask | - SpvLoopControlDependencyLengthMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 43, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(53, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(53, SpvLoopControlMaxIterationsMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 53, SpvLoopControlMaskNone | SpvLoopControlDependencyLengthMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl( - 53, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 53, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyLengthMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(53, - SpvLoopControlDependencyInfiniteMask | - SpvLoopControlDependencyLengthMask, - 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 53, - SpvLoopControlUnrollMask | SpvLoopControlDependencyLengthMask | - SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, - 5, 3) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(63, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(63, - SpvLoopControlUnrollMask | - SpvLoopControlMinIterationsMask | - SpvLoopControlPeelCountMask | - SpvLoopControlPartialCountMask, - 5, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(63, - SpvLoopControlUnrollMask | - SpvLoopControlMinIterationsMask | - SpvLoopControlPeelCountMask, - 23, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 63, - SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | - SpvLoopControlPeelCountMask, - 2, 23) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(73, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 73, - SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | - SpvLoopControlPeelCountMask | - SpvLoopControlPartialCountMask, - 5, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(73, - SpvLoopControlUnrollMask | - SpvLoopControlMaxIterationsMask | - SpvLoopControlPeelCountMask, - 23, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 73, - SpvLoopControlUnrollMask | SpvLoopControlMaxIterationsMask | - SpvLoopControlPeelCountMask, - 2, 23) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 83, - SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | - SpvLoopControlPeelCountMask | - SpvLoopControlPartialCountMask, - 5, 3) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(83, - SpvLoopControlUnrollMask | - SpvLoopControlIterationMultipleMask | - SpvLoopControlPeelCountMask, - 23, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(83, - SpvLoopControlUnrollMask | - SpvLoopControlIterationMultipleMask | - SpvLoopControlPeelCountMask, - 2, 23) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(93, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 8) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(93, SpvLoopControlPartialCountMask, 0, 8) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl( - 93, - SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, - 16, 8) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(103, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl(103, - SpvLoopControlDontUnrollMask | - SpvLoopControlPartialCountMask, - 0, 60) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(113, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl( - 113, - SpvLoopControlIterationMultipleMask | SpvLoopControlPeelCountMask, 12, - 0) - .IsApplicable(context.get(), fact_manager)); - - ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlMaskNone, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl(123, SpvLoopControlDontUnrollMask, 0, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE( - TransformationSetLoopControl( - 123, - SpvLoopControlMinIterationsMask | SpvLoopControlMaxIterationsMask | - SpvLoopControlIterationMultipleMask | - SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, - 7, 8) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(TransformationSetLoopControl(123, - SpvLoopControlUnrollMask | - SpvLoopControlMinIterationsMask | - SpvLoopControlMaxIterationsMask | - SpvLoopControlPartialCountMask, - 0, 9) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSetLoopControl( - 123, - SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | - SpvLoopControlMaxIterationsMask | - SpvLoopControlPartialCountMask, - 7, 9) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSetLoopControl( - 123, - SpvLoopControlDontUnrollMask | SpvLoopControlMinIterationsMask | - SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask, - 7, 9) - .IsApplicable(context.get(), fact_manager)); - - TransformationSetLoopControl(10, - SpvLoopControlUnrollMask | - SpvLoopControlPeelCountMask | - SpvLoopControlPartialCountMask, - 3, 3) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl( - 43, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask, - 0, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(63, - SpvLoopControlUnrollMask | - SpvLoopControlMinIterationsMask | - SpvLoopControlPeelCountMask, - 23, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(73, - SpvLoopControlUnrollMask | - SpvLoopControlMaxIterationsMask | - SpvLoopControlPeelCountMask, - 23, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl( - 93, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 16, 8) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0) - .Apply(context.get(), &fact_manager); - TransformationSetLoopControl( - 123, - SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | - SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask, - 0, 9) - .Apply(context.get(), &fact_manager); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - %32 = OpVariable %7 Function - %42 = OpVariable %7 Function - %52 = OpVariable %7 Function - %62 = OpVariable %7 Function - %72 = OpVariable %7 Function - %82 = OpVariable %7 Function - %92 = OpVariable %7 Function - %102 = OpVariable %7 Function - %112 = OpVariable %7 Function - %122 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %132 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 Unroll|PeelCount|PartialCount 3 3 - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %132 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %132 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %133 = OpPhi %6 %9 %12 %31 %26 - OpLoopMerge %25 %26 DontUnroll - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %133 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %31 = OpIAdd %6 %133 %20 - OpStore %22 %31 - OpBranch %23 - %25 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - %134 = OpPhi %6 %9 %25 %41 %36 - OpLoopMerge %35 %36 Unroll - OpBranch %37 - %37 = OpLabel - %39 = OpSLessThan %17 %134 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpBranch %36 - %36 = OpLabel - %41 = OpIAdd %6 %134 %20 - OpStore %32 %41 - OpBranch %33 - %35 = OpLabel - OpStore %42 %9 - OpBranch %43 - %43 = OpLabel - %135 = OpPhi %6 %9 %35 %51 %46 - OpLoopMerge %45 %46 DontUnroll|DependencyInfinite - OpBranch %47 - %47 = OpLabel - %49 = OpSLessThan %17 %135 %16 - OpBranchConditional %49 %44 %45 - %44 = OpLabel - OpBranch %46 - %46 = OpLabel - %51 = OpIAdd %6 %135 %20 - OpStore %42 %51 - OpBranch %43 - %45 = OpLabel - OpStore %52 %9 - OpBranch %53 - %53 = OpLabel - %136 = OpPhi %6 %9 %45 %61 %56 - OpLoopMerge %55 %56 None - OpBranch %57 - %57 = OpLabel - %59 = OpSLessThan %17 %136 %16 - OpBranchConditional %59 %54 %55 - %54 = OpLabel - OpBranch %56 - %56 = OpLabel - %61 = OpIAdd %6 %136 %20 - OpStore %52 %61 - OpBranch %53 - %55 = OpLabel - OpStore %62 %9 - OpBranch %63 - %63 = OpLabel - %137 = OpPhi %6 %9 %55 %71 %66 - OpLoopMerge %65 %66 Unroll|MinIterations|PeelCount 10 23 - OpBranch %67 - %67 = OpLabel - %69 = OpSLessThan %17 %137 %16 - OpBranchConditional %69 %64 %65 - %64 = OpLabel - OpBranch %66 - %66 = OpLabel - %71 = OpIAdd %6 %137 %20 - OpStore %62 %71 - OpBranch %63 - %65 = OpLabel - OpStore %72 %9 - OpBranch %73 - %73 = OpLabel - %138 = OpPhi %6 %9 %65 %81 %76 - OpLoopMerge %75 %76 Unroll|MaxIterations|PeelCount 50 23 - OpBranch %77 - %77 = OpLabel - %79 = OpSLessThan %17 %138 %16 - OpBranchConditional %79 %74 %75 - %74 = OpLabel - OpBranch %76 - %76 = OpLabel - %81 = OpIAdd %6 %138 %20 - OpStore %72 %81 - OpBranch %73 - %75 = OpLabel - OpStore %82 %9 - OpBranch %83 - %83 = OpLabel - %139 = OpPhi %6 %9 %75 %91 %86 - OpLoopMerge %85 %86 DontUnroll - OpBranch %87 - %87 = OpLabel - %89 = OpSLessThan %17 %139 %16 - OpBranchConditional %89 %84 %85 - %84 = OpLabel - OpBranch %86 - %86 = OpLabel - %91 = OpIAdd %6 %139 %20 - OpStore %82 %91 - OpBranch %83 - %85 = OpLabel - OpStore %92 %9 - OpBranch %93 - %93 = OpLabel - %140 = OpPhi %6 %9 %85 %101 %96 - OpLoopMerge %95 %96 PeelCount|PartialCount 16 8 - OpBranch %97 - %97 = OpLabel - %99 = OpSLessThan %17 %140 %16 - OpBranchConditional %99 %94 %95 - %94 = OpLabel - OpBranch %96 - %96 = OpLabel - %101 = OpIAdd %6 %140 %20 - OpStore %92 %101 - OpBranch %93 - %95 = OpLabel - OpStore %102 %9 - OpBranch %103 - %103 = OpLabel - %141 = OpPhi %6 %9 %95 %111 %106 - OpLoopMerge %105 %106 PartialCount 60 - OpBranch %107 - %107 = OpLabel - %109 = OpSLessThan %17 %141 %16 - OpBranchConditional %109 %104 %105 - %104 = OpLabel - OpBranch %106 - %106 = OpLabel - %111 = OpIAdd %6 %141 %20 - OpStore %102 %111 - OpBranch %103 - %105 = OpLabel - OpStore %112 %9 - OpBranch %113 - %113 = OpLabel - %142 = OpPhi %6 %9 %105 %121 %116 - OpLoopMerge %115 %116 PeelCount 12 - OpBranch %117 - %117 = OpLabel - %119 = OpSLessThan %17 %142 %16 - OpBranchConditional %119 %114 %115 - %114 = OpLabel - OpBranch %116 - %116 = OpLabel - %121 = OpIAdd %6 %142 %20 - OpStore %112 %121 - OpBranch %113 - %115 = OpLabel - OpStore %122 %9 - OpBranch %123 - %123 = OpLabel - %143 = OpPhi %6 %9 %115 %131 %126 - OpLoopMerge %125 %126 Unroll|MinIterations|MaxIterations|PartialCount 5 90 9 - OpBranch %127 - %127 = OpLabel - %129 = OpSLessThan %17 %143 %16 - OpBranchConditional %129 %124 %125 - %124 = OpLabel - OpBranch %126 - %126 = OpLabel - %131 = OpIAdd %6 %143 %20 - OpStore %122 %131 - OpBranch %123 - %125 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) { - // This test checks that we do not allow introducing PeelCount and - // PartialCount loop controls if the SPIR-V version being used does not - // support them. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpIAdd %6 %19 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto consumer = nullptr; - const auto context_1_0 = - BuildModule(SPV_ENV_UNIVERSAL_1_0, consumer, shader, kFuzzAssembleOption); - const auto context_1_1 = - BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer, shader, kFuzzAssembleOption); - const auto context_1_2 = - BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer, shader, kFuzzAssembleOption); - const auto context_1_3 = - BuildModule(SPV_ENV_UNIVERSAL_1_3, consumer, shader, kFuzzAssembleOption); - const auto context_1_4 = - BuildModule(SPV_ENV_UNIVERSAL_1_4, consumer, shader, kFuzzAssembleOption); - const auto context_1_5 = - BuildModule(SPV_ENV_UNIVERSAL_1_5, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - TransformationSetLoopControl set_peel_and_partial( - 10, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 4, 4); - - // PeelCount and PartialCount were introduced in SPIRV 1.4, so are not valid - // in the context of older versions. - ASSERT_FALSE( - set_peel_and_partial.IsApplicable(context_1_0.get(), fact_manager)); - ASSERT_FALSE( - set_peel_and_partial.IsApplicable(context_1_1.get(), fact_manager)); - ASSERT_FALSE( - set_peel_and_partial.IsApplicable(context_1_2.get(), fact_manager)); - ASSERT_FALSE( - set_peel_and_partial.IsApplicable(context_1_3.get(), fact_manager)); - - ASSERT_TRUE( - set_peel_and_partial.IsApplicable(context_1_4.get(), fact_manager)); - ASSERT_TRUE( - set_peel_and_partial.IsApplicable(context_1_5.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp deleted file mode 100644 index ad4dc2567..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_set_memory_operands_mask.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationSetMemoryOperandsMaskTest, PreSpirv14) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %7 "Point3D" - OpMemberName %7 0 "x" - OpMemberName %7 1 "y" - OpMemberName %7 2 "z" - OpName %12 "global_points" - OpName %15 "block" - OpMemberName %15 0 "in_points" - OpMemberName %15 1 "in_point" - OpName %17 "" - OpName %133 "local_points" - OpMemberDecorate %7 0 Offset 0 - OpMemberDecorate %7 1 Offset 4 - OpMemberDecorate %7 2 Offset 8 - OpDecorate %10 ArrayStride 16 - OpMemberDecorate %15 0 Offset 0 - OpMemberDecorate %15 1 Offset 192 - OpDecorate %15 Block - OpDecorate %17 DescriptorSet 0 - OpDecorate %17 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeStruct %6 %6 %6 - %8 = OpTypeInt 32 0 - %9 = OpConstant %8 12 - %10 = OpTypeArray %7 %9 - %11 = OpTypePointer Private %10 - %12 = OpVariable %11 Private - %15 = OpTypeStruct %10 %7 - %16 = OpTypePointer Uniform %15 - %17 = OpVariable %16 Uniform - %18 = OpTypeInt 32 1 - %19 = OpConstant %18 0 - %20 = OpTypePointer Uniform %10 - %24 = OpTypePointer Private %7 - %27 = OpTypePointer Private %6 - %30 = OpConstant %18 1 - %132 = OpTypePointer Function %10 - %135 = OpTypePointer Uniform %7 - %145 = OpTypePointer Function %7 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %133 = OpVariable %132 Function - %21 = OpAccessChain %20 %17 %19 - OpCopyMemory %12 %21 Aligned 16 - OpCopyMemory %133 %12 Volatile - %136 = OpAccessChain %135 %17 %30 - %138 = OpAccessChain %24 %12 %19 - OpCopyMemory %138 %136 None - %146 = OpAccessChain %145 %133 %30 - %147 = OpLoad %7 %146 Volatile|Nontemporal|Aligned 16 - %148 = OpAccessChain %24 %12 %19 - OpStore %148 %147 Nontemporal - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Not OK: the instruction is not a memory access. - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpAccessChain, 0), - SpvMemoryAccessMaskNone, 0) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to remove Aligned - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(147, SpvOpLoad, 0), - SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask, - 0) - .IsApplicable(context.get(), fact_manager)); - - TransformationSetMemoryOperandsMask transformation1( - MakeInstructionDescriptor(147, SpvOpLoad, 0), - SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0); - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - - // Not OK to remove Aligned - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 0), - SpvMemoryAccessMaskNone, 0) - .IsApplicable(context.get(), fact_manager)); - - // OK: leaves the mask as is - ASSERT_TRUE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 0), - SpvMemoryAccessAlignedMask, 0) - .IsApplicable(context.get(), fact_manager)); - - // OK: adds Nontemporal and Volatile - TransformationSetMemoryOperandsMask transformation2( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 0), - SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask | - SpvMemoryAccessVolatileMask, - 0); - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - - // Not OK to remove Volatile - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 1), - SpvMemoryAccessNontemporalMask, 0) - .IsApplicable(context.get(), fact_manager)); - - // Not OK to add Aligned - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 1), - SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0) - .IsApplicable(context.get(), fact_manager)); - - // OK: adds Nontemporal - TransformationSetMemoryOperandsMask transformation3( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 1), - SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0); - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - - // OK: adds Nontemporal and Volatile - TransformationSetMemoryOperandsMask transformation4( - MakeInstructionDescriptor(138, SpvOpCopyMemory, 0), - SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0); - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - - // OK: removes Nontemporal, adds Volatile - TransformationSetMemoryOperandsMask transformation5( - MakeInstructionDescriptor(148, SpvOpStore, 0), - SpvMemoryAccessVolatileMask, 0); - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %7 "Point3D" - OpMemberName %7 0 "x" - OpMemberName %7 1 "y" - OpMemberName %7 2 "z" - OpName %12 "global_points" - OpName %15 "block" - OpMemberName %15 0 "in_points" - OpMemberName %15 1 "in_point" - OpName %17 "" - OpName %133 "local_points" - OpMemberDecorate %7 0 Offset 0 - OpMemberDecorate %7 1 Offset 4 - OpMemberDecorate %7 2 Offset 8 - OpDecorate %10 ArrayStride 16 - OpMemberDecorate %15 0 Offset 0 - OpMemberDecorate %15 1 Offset 192 - OpDecorate %15 Block - OpDecorate %17 DescriptorSet 0 - OpDecorate %17 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeStruct %6 %6 %6 - %8 = OpTypeInt 32 0 - %9 = OpConstant %8 12 - %10 = OpTypeArray %7 %9 - %11 = OpTypePointer Private %10 - %12 = OpVariable %11 Private - %15 = OpTypeStruct %10 %7 - %16 = OpTypePointer Uniform %15 - %17 = OpVariable %16 Uniform - %18 = OpTypeInt 32 1 - %19 = OpConstant %18 0 - %20 = OpTypePointer Uniform %10 - %24 = OpTypePointer Private %7 - %27 = OpTypePointer Private %6 - %30 = OpConstant %18 1 - %132 = OpTypePointer Function %10 - %135 = OpTypePointer Uniform %7 - %145 = OpTypePointer Function %7 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %133 = OpVariable %132 Function - %21 = OpAccessChain %20 %17 %19 - OpCopyMemory %12 %21 Aligned|Nontemporal|Volatile 16 - OpCopyMemory %133 %12 Nontemporal|Volatile - %136 = OpAccessChain %135 %17 %30 - %138 = OpAccessChain %24 %12 %19 - OpCopyMemory %138 %136 Nontemporal|Volatile - %146 = OpAccessChain %145 %133 %30 - %147 = OpLoad %7 %146 Aligned|Volatile 16 - %148 = OpAccessChain %24 %12 %19 - OpStore %148 %147 Volatile - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationSetMemoryOperandsMaskTest, Spirv14) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 %17 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %7 "Point3D" - OpMemberName %7 0 "x" - OpMemberName %7 1 "y" - OpMemberName %7 2 "z" - OpName %12 "global_points" - OpName %15 "block" - OpMemberName %15 0 "in_points" - OpMemberName %15 1 "in_point" - OpName %17 "" - OpName %133 "local_points" - OpMemberDecorate %7 0 Offset 0 - OpMemberDecorate %7 1 Offset 4 - OpMemberDecorate %7 2 Offset 8 - OpDecorate %10 ArrayStride 16 - OpMemberDecorate %15 0 Offset 0 - OpMemberDecorate %15 1 Offset 192 - OpDecorate %15 Block - OpDecorate %17 DescriptorSet 0 - OpDecorate %17 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeStruct %6 %6 %6 - %8 = OpTypeInt 32 0 - %9 = OpConstant %8 12 - %10 = OpTypeArray %7 %9 - %11 = OpTypePointer Private %10 - %12 = OpVariable %11 Private - %15 = OpTypeStruct %10 %7 - %16 = OpTypePointer Uniform %15 - %17 = OpVariable %16 Uniform - %18 = OpTypeInt 32 1 - %19 = OpConstant %18 0 - %20 = OpTypePointer Uniform %10 - %24 = OpTypePointer Private %7 - %27 = OpTypePointer Private %6 - %30 = OpConstant %18 1 - %132 = OpTypePointer Function %10 - %135 = OpTypePointer Uniform %7 - %145 = OpTypePointer Function %7 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %133 = OpVariable %132 Function - %21 = OpAccessChain %20 %17 %19 - OpCopyMemory %12 %21 Aligned 16 Nontemporal|Aligned 16 - OpCopyMemory %133 %12 Volatile - %136 = OpAccessChain %135 %17 %30 - %138 = OpAccessChain %24 %12 %19 - OpCopyMemory %138 %136 None Aligned 16 - OpCopyMemory %138 %136 Aligned 16 - %146 = OpAccessChain %145 %133 %30 - %147 = OpLoad %7 %146 Volatile|Nontemporal|Aligned 16 - %148 = OpAccessChain %24 %12 %19 - OpStore %148 %147 Nontemporal - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - TransformationSetMemoryOperandsMask transformation1( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 0), - SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1); - // Bad: cannot remove aligned - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 0), - SpvMemoryAccessVolatileMask, 1) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - - TransformationSetMemoryOperandsMask transformation2( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 1), - SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1); - // Bad: cannot remove volatile - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(21, SpvOpCopyMemory, 1), - SpvMemoryAccessNontemporalMask, 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - - TransformationSetMemoryOperandsMask transformation3( - MakeInstructionDescriptor(138, SpvOpCopyMemory, 0), - SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1); - // Bad: the first mask is None, so Aligned cannot be added to it. - ASSERT_FALSE(TransformationSetMemoryOperandsMask( - MakeInstructionDescriptor(138, SpvOpCopyMemory, 0), - SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, - 0) - .IsApplicable(context.get(), fact_manager)); - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - - TransformationSetMemoryOperandsMask transformation4( - MakeInstructionDescriptor(138, SpvOpCopyMemory, 1), - SpvMemoryAccessVolatileMask, 1); - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - - TransformationSetMemoryOperandsMask transformation5( - MakeInstructionDescriptor(147, SpvOpLoad, 0), - SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0); - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - - TransformationSetMemoryOperandsMask transformation6( - MakeInstructionDescriptor(148, SpvOpStore, 0), SpvMemoryAccessMaskNone, - 0); - ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager)); - transformation6.Apply(context.get(), &fact_manager); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 %17 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %7 "Point3D" - OpMemberName %7 0 "x" - OpMemberName %7 1 "y" - OpMemberName %7 2 "z" - OpName %12 "global_points" - OpName %15 "block" - OpMemberName %15 0 "in_points" - OpMemberName %15 1 "in_point" - OpName %17 "" - OpName %133 "local_points" - OpMemberDecorate %7 0 Offset 0 - OpMemberDecorate %7 1 Offset 4 - OpMemberDecorate %7 2 Offset 8 - OpDecorate %10 ArrayStride 16 - OpMemberDecorate %15 0 Offset 0 - OpMemberDecorate %15 1 Offset 192 - OpDecorate %15 Block - OpDecorate %17 DescriptorSet 0 - OpDecorate %17 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeStruct %6 %6 %6 - %8 = OpTypeInt 32 0 - %9 = OpConstant %8 12 - %10 = OpTypeArray %7 %9 - %11 = OpTypePointer Private %10 - %12 = OpVariable %11 Private - %15 = OpTypeStruct %10 %7 - %16 = OpTypePointer Uniform %15 - %17 = OpVariable %16 Uniform - %18 = OpTypeInt 32 1 - %19 = OpConstant %18 0 - %20 = OpTypePointer Uniform %10 - %24 = OpTypePointer Private %7 - %27 = OpTypePointer Private %6 - %30 = OpConstant %18 1 - %132 = OpTypePointer Function %10 - %135 = OpTypePointer Uniform %7 - %145 = OpTypePointer Function %7 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %133 = OpVariable %132 Function - %21 = OpAccessChain %20 %17 %19 - OpCopyMemory %12 %21 Aligned 16 Aligned|Volatile 16 - OpCopyMemory %133 %12 Volatile Nontemporal|Volatile - %136 = OpAccessChain %135 %17 %30 - %138 = OpAccessChain %24 %12 %19 - OpCopyMemory %138 %136 None Aligned|Nontemporal 16 - OpCopyMemory %138 %136 Aligned 16 Volatile - %146 = OpAccessChain %145 %133 %30 - %147 = OpLoad %7 %146 Volatile|Aligned 16 - %148 = OpAccessChain %24 %12 %19 - OpStore %148 %147 None - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_set_selection_control_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_set_selection_control_test.cpp deleted file mode 100644 index 9696417b0..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_set_selection_control_test.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_set_selection_control.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationSetSelectionControlTest, VariousScenarios) { - // This is a simple transformation; this test captures the important things - // to check for. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 3 - %25 = OpConstant %6 1 - %28 = OpConstant %6 2 - %38 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpSGreaterThan %17 %19 %20 - OpSelectionMerge %23 Flatten - OpBranchConditional %21 %22 %23 - %22 = OpLabel - %24 = OpLoad %6 %8 - %26 = OpIAdd %6 %24 %25 - OpStore %8 %26 - OpBranch %23 - %23 = OpLabel - %27 = OpLoad %6 %8 - %29 = OpSLessThan %17 %27 %28 - OpSelectionMerge %31 DontFlatten - OpBranchConditional %29 %30 %31 - %30 = OpLabel - %32 = OpLoad %6 %8 - %33 = OpISub %6 %32 %25 - OpStore %8 %33 - OpBranch %31 - %31 = OpLabel - %34 = OpLoad %6 %8 - OpSelectionMerge %37 None - OpSwitch %34 %36 0 %35 - %36 = OpLabel - OpBranch %37 - %35 = OpLabel - %39 = OpLoad %6 %8 - %40 = OpIAdd %6 %39 %38 - OpStore %8 %40 - OpBranch %36 - %37 = OpLabel - OpBranch %13 - %13 = OpLabel - %43 = OpLoad %6 %8 - %44 = OpIAdd %6 %43 %25 - OpStore %8 %44 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - // %44 is not a block - ASSERT_FALSE( - TransformationSetSelectionControl(44, SpvSelectionControlFlattenMask) - .IsApplicable(context.get(), fact_manager)); - // %13 does not end with OpSelectionMerge - ASSERT_FALSE( - TransformationSetSelectionControl(13, SpvSelectionControlMaskNone) - .IsApplicable(context.get(), fact_manager)); - // %10 ends in OpLoopMerge, not OpSelectionMerge - ASSERT_FALSE( - TransformationSetSelectionControl(10, SpvSelectionControlMaskNone) - .IsApplicable(context.get(), fact_manager)); - - TransformationSetSelectionControl transformation1( - 11, SpvSelectionControlDontFlattenMask); - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - - TransformationSetSelectionControl transformation2( - 23, SpvSelectionControlFlattenMask); - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - - TransformationSetSelectionControl transformation3( - 31, SpvSelectionControlMaskNone); - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - - TransformationSetSelectionControl transformation4( - 31, SpvSelectionControlFlattenMask); - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 3 - %25 = OpConstant %6 1 - %28 = OpConstant %6 2 - %38 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpSGreaterThan %17 %19 %20 - OpSelectionMerge %23 DontFlatten - OpBranchConditional %21 %22 %23 - %22 = OpLabel - %24 = OpLoad %6 %8 - %26 = OpIAdd %6 %24 %25 - OpStore %8 %26 - OpBranch %23 - %23 = OpLabel - %27 = OpLoad %6 %8 - %29 = OpSLessThan %17 %27 %28 - OpSelectionMerge %31 Flatten - OpBranchConditional %29 %30 %31 - %30 = OpLabel - %32 = OpLoad %6 %8 - %33 = OpISub %6 %32 %25 - OpStore %8 %33 - OpBranch %31 - %31 = OpLabel - %34 = OpLoad %6 %8 - OpSelectionMerge %37 Flatten - OpSwitch %34 %36 0 %35 - %36 = OpLabel - OpBranch %37 - %35 = OpLabel - %39 = OpLoad %6 %8 - %40 = OpIAdd %6 %39 %38 - OpStore %8 %40 - OpBranch %36 - %37 = OpLabel - OpBranch %13 - %13 = OpLabel - %43 = OpLoad %6 %8 - %44 = OpIAdd %6 %43 %25 - OpStore %8 %44 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_split_block_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_split_block_test.cpp deleted file mode 100644 index d162e0715..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_split_block_test.cpp +++ /dev/null @@ -1,779 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_split_block.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationSplitBlockTest, NotApplicable) { - // The SPIR-V in this test came from the following fragment shader, with - // local store elimination applied to get some OpPhi instructions. - // - // void main() { - // int x; - // int i; - // for (i = 0; i < 100; i++) { - // x += i; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - OpName %19 "x" - OpDecorate %8 RelaxedPrecision - OpDecorate %19 RelaxedPrecision - OpDecorate %22 RelaxedPrecision - OpDecorate %25 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %24 = OpConstant %6 1 - %28 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %27 = OpPhi %6 %28 %5 %22 %13 - %26 = OpPhi %6 %9 %5 %25 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %26 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %22 = OpIAdd %6 %27 %26 - OpStore %19 %22 - OpBranch %13 - %13 = OpLabel - %25 = OpIAdd %6 %26 %24 - OpStore %8 %25 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - // No split before OpVariable - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(8, SpvOpVariable, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(8, SpvOpVariable, 1), 100) - .IsApplicable(context.get(), fact_manager)); - - // No split before OpLabel - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(14, SpvOpLabel, 0), 100) - .IsApplicable(context.get(), fact_manager)); - - // No split if base instruction is outside a function - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(1, SpvOpLabel, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(1, SpvOpExecutionMode, 0), 100) - .IsApplicable(context.get(), fact_manager)); - - // No split if block is loop header - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100) - .IsApplicable(context.get(), fact_manager)); - - // No split if base instruction does not exist - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(88, SpvOpIAdd, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(88, SpvOpIMul, 22), 100) - .IsApplicable(context.get(), fact_manager)); - - // No split if too many instructions with the desired opcode are skipped - ASSERT_FALSE( - TransformationSplitBlock( - MakeInstructionDescriptor(18, SpvOpBranchConditional, 1), 100) - .IsApplicable(context.get(), fact_manager)); - - // No split if id in use - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 27) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 14) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationSplitBlockTest, SplitBlockSeveralTimes) { - // The SPIR-V in this test came from the following fragment shader: - // - // void main() { - // int a; - // int b; - // a = 1; - // b = a; - // a = b; - // b = 2; - // b++; - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %14 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpStore %10 %11 - %12 = OpLoad %6 %10 - OpStore %8 %12 - OpStore %10 %13 - %14 = OpLoad %6 %10 - %15 = OpIAdd %6 %14 %9 - OpStore %10 %15 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - auto split_1 = TransformationSplitBlock( - MakeInstructionDescriptor(5, SpvOpStore, 0), 100); - ASSERT_TRUE(split_1.IsApplicable(context.get(), fact_manager)); - split_1.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_split_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %14 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpBranch %100 - %100 = OpLabel - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpStore %10 %11 - %12 = OpLoad %6 %10 - OpStore %8 %12 - OpStore %10 %13 - %14 = OpLoad %6 %10 - %15 = OpIAdd %6 %14 %9 - OpStore %10 %15 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_split_1, context.get())); - - auto split_2 = TransformationSplitBlock( - MakeInstructionDescriptor(11, SpvOpStore, 0), 101); - ASSERT_TRUE(split_2.IsApplicable(context.get(), fact_manager)); - split_2.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_split_2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %14 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpBranch %100 - %100 = OpLabel - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpBranch %101 - %101 = OpLabel - OpStore %10 %11 - %12 = OpLoad %6 %10 - OpStore %8 %12 - OpStore %10 %13 - %14 = OpLoad %6 %10 - %15 = OpIAdd %6 %14 %9 - OpStore %10 %15 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_split_2, context.get())); - - auto split_3 = TransformationSplitBlock( - MakeInstructionDescriptor(14, SpvOpLoad, 0), 102); - ASSERT_TRUE(split_3.IsApplicable(context.get(), fact_manager)); - split_3.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_split_3 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - OpDecorate %14 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %13 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpBranch %100 - %100 = OpLabel - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpBranch %101 - %101 = OpLabel - OpStore %10 %11 - %12 = OpLoad %6 %10 - OpStore %8 %12 - OpStore %10 %13 - OpBranch %102 - %102 = OpLabel - %14 = OpLoad %6 %10 - %15 = OpIAdd %6 %14 %9 - OpStore %10 %15 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_split_3, context.get())); -} - -TEST(TransformationSplitBlockTest, SplitBlockBeforeSelectBranch) { - // The SPIR-V in this test came from the following fragment shader: - // - // void main() { - // int x, y; - // x = 2; - // if (x < y) { - // y = 3; - // } else { - // y = 4; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %13 = OpTypeBool - %17 = OpConstant %6 3 - %19 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %18 - %15 = OpLabel - OpStore %11 %17 - OpBranch %16 - %18 = OpLabel - OpStore %11 %19 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - // Illegal to split between the merge and the conditional branch. - ASSERT_FALSE( - TransformationSplitBlock( - MakeInstructionDescriptor(14, SpvOpBranchConditional, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSplitBlock( - MakeInstructionDescriptor(12, SpvOpBranchConditional, 0), 100) - .IsApplicable(context.get(), fact_manager)); - - auto split = TransformationSplitBlock( - MakeInstructionDescriptor(14, SpvOpSelectionMerge, 0), 100); - ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager)); - split.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_split = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %11 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - OpDecorate %12 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %13 = OpTypeBool - %17 = OpConstant %6 3 - %19 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %11 = OpVariable %7 Function - OpStore %8 %9 - %10 = OpLoad %6 %8 - %12 = OpLoad %6 %11 - %14 = OpSLessThan %13 %10 %12 - OpBranch %100 - %100 = OpLabel - OpSelectionMerge %16 None - OpBranchConditional %14 %15 %18 - %15 = OpLabel - OpStore %11 %17 - OpBranch %16 - %18 = OpLabel - OpStore %11 %19 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_split, context.get())); -} - -TEST(TransformationSplitBlockTest, SplitBlockBeforeSwitchBranch) { - // The SPIR-V in this test came from the following fragment shader: - // - // void main() { - // int x, y; - // switch (y) { - // case 1: - // x = 2; - // case 2: - // break; - // case 3: - // x = 4; - // default: - // x = 6; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "y" - OpName %15 "x" - OpDecorate %8 RelaxedPrecision - OpDecorate %9 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %16 = OpConstant %6 2 - %18 = OpConstant %6 4 - %19 = OpConstant %6 6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %15 = OpVariable %7 Function - %9 = OpLoad %6 %8 - OpSelectionMerge %14 None - OpSwitch %9 %13 1 %10 2 %11 3 %12 - %13 = OpLabel - OpStore %15 %19 - OpBranch %14 - %10 = OpLabel - OpStore %15 %16 - OpBranch %11 - %11 = OpLabel - OpBranch %14 - %12 = OpLabel - OpStore %15 %18 - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - // Illegal to split between the merge and the conditional branch. - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(9, SpvOpSwitch, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE(TransformationSplitBlock( - MakeInstructionDescriptor(15, SpvOpSwitch, 0), 100) - .IsApplicable(context.get(), fact_manager)); - - auto split = TransformationSplitBlock( - MakeInstructionDescriptor(9, SpvOpSelectionMerge, 0), 100); - ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager)); - split.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_split = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "y" - OpName %15 "x" - OpDecorate %8 RelaxedPrecision - OpDecorate %9 RelaxedPrecision - OpDecorate %15 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %16 = OpConstant %6 2 - %18 = OpConstant %6 4 - %19 = OpConstant %6 6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %15 = OpVariable %7 Function - %9 = OpLoad %6 %8 - OpBranch %100 - %100 = OpLabel - OpSelectionMerge %14 None - OpSwitch %9 %13 1 %10 2 %11 3 %12 - %13 = OpLabel - OpStore %15 %19 - OpBranch %14 - %10 = OpLabel - OpStore %15 %16 - OpBranch %11 - %11 = OpLabel - OpBranch %14 - %12 = OpLabel - OpStore %15 %18 - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_split, context.get())); -} - -TEST(TransformationSplitBlockTest, NoSplitDuringOpPhis) { - // The SPIR-V in this test came from the following fragment shader, with - // local store elimination applied to get some OpPhi instructions. - // - // void main() { - // int x; - // int i; - // for (i = 0; i < 100; i++) { - // x += i; - // } - // } - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "i" - OpName %19 "x" - OpDecorate %8 RelaxedPrecision - OpDecorate %19 RelaxedPrecision - OpDecorate %22 RelaxedPrecision - OpDecorate %25 RelaxedPrecision - OpDecorate %26 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %24 = OpConstant %6 1 - %28 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %27 = OpPhi %6 %28 %5 %22 %13 - %26 = OpPhi %6 %9 %5 %25 %13 - OpBranch %50 - %50 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %26 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %22 = OpIAdd %6 %27 %26 - OpStore %19 %22 - OpBranch %13 - %13 = OpLabel - %25 = OpIAdd %6 %26 %24 - OpStore %8 %25 - OpBranch %50 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - // We cannot split before OpPhi instructions, since the number of incoming - // blocks may not appropriately match after splitting. - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(26, SpvOpPhi, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100) - .IsApplicable(context.get(), fact_manager)); -} - -TEST(TransformationSplitBlockTest, SplitOpPhiWithSinglePredecessor) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpBranch %20 - %20 = OpLabel - %21 = OpPhi %6 %11 %5 - OpStore %10 %21 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - - FactManager fact_manager; - - ASSERT_TRUE( - TransformationSplitBlock(MakeInstructionDescriptor(21, SpvOpPhi, 0), 100) - .IsApplicable(context.get(), fact_manager)); - // An equivalent transformation to the above, just described with respect to a - // different base instruction. - auto split = - TransformationSplitBlock(MakeInstructionDescriptor(20, SpvOpPhi, 0), 100); - ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager)); - split.Apply(context.get(), &fact_manager); - ASSERT_TRUE(IsValid(env, context.get())); - - std::string after_split = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpBranch %20 - %20 = OpLabel - OpBranch %100 - %100 = OpLabel - %21 = OpPhi %6 %11 %20 - OpStore %10 %21 - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_split, context.get())); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/transformation_vector_shuffle_test.cpp b/3rdparty/spirv-tools/test/fuzz/transformation_vector_shuffle_test.cpp deleted file mode 100644 index 385c38b44..000000000 --- a/3rdparty/spirv-tools/test/fuzz/transformation_vector_shuffle_test.cpp +++ /dev/null @@ -1,532 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/transformation_vector_shuffle.h" -#include "source/fuzz/instruction_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(TransformationVectorShuffle, BasicTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpTypeVector %6 2 - %10 = OpConstantTrue %6 - %11 = OpConstantFalse %6 - %12 = OpConstantComposite %7 %10 %11 - %112 = OpUndef %7 - %13 = OpTypeVector %6 3 - %16 = OpConstantComposite %13 %10 %11 %10 - %17 = OpTypeVector %6 4 - %20 = OpConstantComposite %17 %10 %11 %10 %11 - %21 = OpTypeInt 32 1 - %22 = OpTypeVector %21 2 - %25 = OpConstant %21 1 - %26 = OpConstant %21 0 - %27 = OpConstantComposite %22 %25 %26 - %28 = OpTypeVector %21 3 - %31 = OpConstantComposite %28 %25 %26 %25 - %32 = OpTypeVector %21 4 - %33 = OpTypePointer Function %32 - %35 = OpConstantComposite %32 %25 %26 %25 %26 - %36 = OpTypeInt 32 0 - %37 = OpTypeVector %36 2 - %40 = OpConstant %36 1 - %41 = OpConstant %36 0 - %42 = OpConstantComposite %37 %40 %41 - %43 = OpTypeVector %36 3 - %46 = OpConstantComposite %43 %40 %41 %40 - %47 = OpTypeVector %36 4 - %50 = OpConstantComposite %47 %40 %41 %40 %41 - %51 = OpTypeFloat 32 - %55 = OpConstant %51 1 - %56 = OpConstant %51 0 - %58 = OpTypeVector %51 3 - %61 = OpConstantComposite %58 %55 %56 %55 - %62 = OpTypeVector %51 4 - %65 = OpConstantComposite %62 %55 %56 %55 %56 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpSelectionMerge %100 None - OpBranchConditional %10 %101 %102 - %101 = OpLabel - %103 = OpCompositeConstruct %62 %55 %55 %55 %56 - OpBranch %100 - %102 = OpLabel - OpBranch %100 - %100 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}), - MakeDataDescriptor(12, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}), - MakeDataDescriptor(12, {1}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}), - MakeDataDescriptor(16, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}), - MakeDataDescriptor(16, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}), - MakeDataDescriptor(16, {2}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}), - MakeDataDescriptor(20, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}), - MakeDataDescriptor(20, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}), - MakeDataDescriptor(20, {2}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}), - MakeDataDescriptor(20, {3}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}), - MakeDataDescriptor(27, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}), - MakeDataDescriptor(27, {1}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}), - MakeDataDescriptor(31, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}), - MakeDataDescriptor(31, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}), - MakeDataDescriptor(31, {2}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}), - MakeDataDescriptor(35, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}), - MakeDataDescriptor(35, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}), - MakeDataDescriptor(35, {2}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}), - MakeDataDescriptor(35, {3}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}), - MakeDataDescriptor(42, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}), - MakeDataDescriptor(42, {1}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}), - MakeDataDescriptor(46, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}), - MakeDataDescriptor(46, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}), - MakeDataDescriptor(46, {2}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}), - MakeDataDescriptor(50, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}), - MakeDataDescriptor(50, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}), - MakeDataDescriptor(50, {2}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}), - MakeDataDescriptor(50, {3}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}), - MakeDataDescriptor(61, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(56, {}), - MakeDataDescriptor(61, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}), - MakeDataDescriptor(61, {2}), context.get()); - - fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}), - MakeDataDescriptor(65, {0}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(56, {}), - MakeDataDescriptor(65, {1}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}), - MakeDataDescriptor(65, {2}), context.get()); - fact_manager.AddFactDataSynonym(MakeDataDescriptor(56, {}), - MakeDataDescriptor(65, {3}), context.get()); - - // %103 does not dominate the return instruction. - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 103, 65, - {3, 5, 7}) - .IsApplicable(context.get(), fact_manager)); - - // Illegal to shuffle a bvec2 and a vec3 - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 112, 61, - {0, 2, 4}) - .IsApplicable(context.get(), fact_manager)); - - // Illegal to shuffle an ivec2 and a uvec4 - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 50, - {1, 3, 5}) - .IsApplicable(context.get(), fact_manager)); - - // Vector 1 does not exist - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 300, 50, - {1, 3, 5}) - .IsApplicable(context.get(), fact_manager)); - - // Vector 2 does not exist - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 300, - {1, 3, 5}) - .IsApplicable(context.get(), fact_manager)); - - // Index out of range - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0, 20}) - .IsApplicable(context.get(), fact_manager)); - - // Too many indices - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, - {0, 1, 0, 1, 0, 1, 0, 1}) - .IsApplicable(context.get(), fact_manager)); - - // Too few indices - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {}) - .IsApplicable(context.get(), fact_manager)); - - // Too few indices again - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0}) - .IsApplicable(context.get(), fact_manager)); - - // Indices define unknown type: we do not have vec2 - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 65, 65, {0, 1}) - .IsApplicable(context.get(), fact_manager)); - - // The instruction to insert before does not exist - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpCompositeConstruct, 1), - 201, 20, 12, {0xFFFFFFFF, 3, 5}) - .IsApplicable(context.get(), fact_manager)); - - // The 'fresh' id is already in use - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 12, 12, 112, {}) - .IsApplicable(context.get(), fact_manager)); - - protobufs::DataDescriptor temp_dd; - - TransformationVectorShuffle transformation1( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {1, 0}); - ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager)); - transformation1.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(200, {0}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(200, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}), temp_dd, - context.get())); - - TransformationVectorShuffle transformation2( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 201, 20, 12, - {0xFFFFFFFF, 3, 5}); - ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager)); - transformation2.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(201, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(201, {2}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}), temp_dd, - context.get())); - - TransformationVectorShuffle transformation3( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 202, 27, 35, {5, 4, 1}); - ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager)); - transformation3.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(202, {0}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(26, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(202, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(202, {2}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(26, {}), temp_dd, - context.get())); - - TransformationVectorShuffle transformation4( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 203, 42, 46, {0, 1}); - ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager)); - transformation4.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(203, {0}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(203, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd, - context.get())); - - TransformationVectorShuffle transformation5( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 204, 42, 46, {2, 3, 4}); - ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager)); - transformation5.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(204, {0}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(204, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(204, {2}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd, - context.get())); - - TransformationVectorShuffle transformation6( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 205, 42, 42, - {0, 1, 2, 3}); - ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager)); - transformation6.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(205, {0}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(205, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(205, {2}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd, - context.get())); - temp_dd = MakeDataDescriptor(205, {3}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd, - context.get())); - - // swizzle vec4 from vec4 and vec4 using some undefs - TransformationVectorShuffle transformation7( - MakeInstructionDescriptor(100, SpvOpReturn, 0), 206, 65, 65, - {0xFFFFFFFF, 3, 6, 0xFFFFFFFF}); - ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager)); - transformation7.Apply(context.get(), &fact_manager); - temp_dd = MakeDataDescriptor(206, {1}); - ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(56, {}), temp_dd, - context.get())); - - std::string after_transformation = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpTypeVector %6 2 - %10 = OpConstantTrue %6 - %11 = OpConstantFalse %6 - %12 = OpConstantComposite %7 %10 %11 - %112 = OpUndef %7 - %13 = OpTypeVector %6 3 - %16 = OpConstantComposite %13 %10 %11 %10 - %17 = OpTypeVector %6 4 - %20 = OpConstantComposite %17 %10 %11 %10 %11 - %21 = OpTypeInt 32 1 - %22 = OpTypeVector %21 2 - %25 = OpConstant %21 1 - %26 = OpConstant %21 0 - %27 = OpConstantComposite %22 %25 %26 - %28 = OpTypeVector %21 3 - %31 = OpConstantComposite %28 %25 %26 %25 - %32 = OpTypeVector %21 4 - %33 = OpTypePointer Function %32 - %35 = OpConstantComposite %32 %25 %26 %25 %26 - %36 = OpTypeInt 32 0 - %37 = OpTypeVector %36 2 - %40 = OpConstant %36 1 - %41 = OpConstant %36 0 - %42 = OpConstantComposite %37 %40 %41 - %43 = OpTypeVector %36 3 - %46 = OpConstantComposite %43 %40 %41 %40 - %47 = OpTypeVector %36 4 - %50 = OpConstantComposite %47 %40 %41 %40 %41 - %51 = OpTypeFloat 32 - %55 = OpConstant %51 1 - %56 = OpConstant %51 0 - %58 = OpTypeVector %51 3 - %61 = OpConstantComposite %58 %55 %56 %55 - %62 = OpTypeVector %51 4 - %65 = OpConstantComposite %62 %55 %56 %55 %56 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpSelectionMerge %100 None - OpBranchConditional %10 %101 %102 - %101 = OpLabel - %103 = OpCompositeConstruct %62 %55 %55 %55 %56 - OpBranch %100 - %102 = OpLabel - OpBranch %100 - %100 = OpLabel - %200 = OpVectorShuffle %7 %12 %112 1 0 - %201 = OpVectorShuffle %13 %20 %12 0xFFFFFFFF 3 5 - %202 = OpVectorShuffle %28 %27 %35 5 4 1 - %203 = OpVectorShuffle %37 %42 %46 0 1 - %204 = OpVectorShuffle %43 %42 %46 2 3 4 - %205 = OpVectorShuffle %47 %42 %42 0 1 2 3 - %206 = OpVectorShuffle %62 %65 %65 0xFFFFFFFF 3 6 0xFFFFFFFF - OpReturn - OpFunctionEnd - )"; - ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); -} - -TEST(TransformationVectorShuffleTest, IllegalInsertionPoints) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %51 %27 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %25 "buf" - OpMemberName %25 0 "value" - OpName %27 "" - OpName %51 "color" - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 0 - OpDecorate %51 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %150 = OpTypeVector %6 2 - %10 = OpConstant %6 0.300000012 - %11 = OpConstant %6 0.400000006 - %12 = OpConstant %6 0.5 - %13 = OpConstant %6 1 - %14 = OpConstantComposite %7 %10 %11 %12 %13 - %15 = OpTypeInt 32 1 - %18 = OpConstant %15 0 - %25 = OpTypeStruct %6 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %28 = OpTypePointer Uniform %6 - %32 = OpTypeBool - %103 = OpConstantTrue %32 - %34 = OpConstant %6 0.100000001 - %48 = OpConstant %15 1 - %50 = OpTypePointer Output %7 - %51 = OpVariable %50 Output - %100 = OpTypePointer Function %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %101 = OpVariable %100 Function - %102 = OpVariable %100 Function - OpBranch %19 - %19 = OpLabel - %60 = OpPhi %7 %14 %5 %58 %20 - %59 = OpPhi %15 %18 %5 %49 %20 - %29 = OpAccessChain %28 %27 %18 - %30 = OpLoad %6 %29 - %31 = OpConvertFToS %15 %30 - %33 = OpSLessThan %32 %59 %31 - OpLoopMerge %21 %20 None - OpBranchConditional %33 %20 %21 - %20 = OpLabel - %39 = OpCompositeExtract %6 %60 0 - %40 = OpFAdd %6 %39 %34 - %55 = OpCompositeInsert %7 %40 %60 0 - %44 = OpCompositeExtract %6 %60 1 - %45 = OpFSub %6 %44 %34 - %58 = OpCompositeInsert %7 %45 %55 1 - %49 = OpIAdd %15 %59 %48 - OpBranch %19 - %21 = OpLabel - OpStore %51 %60 - OpSelectionMerge %105 None - OpBranchConditional %103 %104 %105 - %104 = OpLabel - OpBranch %105 - %105 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_4; - const auto consumer = nullptr; - const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); - ASSERT_TRUE(IsValid(env, context.get())); - - FactManager fact_manager; - - // Cannot insert before the OpVariables of a function. - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, 14, {0, 1}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, 14, {1, 2}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, 14, {1, 2}) - .IsApplicable(context.get(), fact_manager)); - // OK to insert right after the OpVariables. - ASSERT_FALSE( - TransformationVectorShuffle( - MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, 14, {1, 1}) - .IsApplicable(context.get(), fact_manager)); - - // Cannot insert before the OpPhis of a block. - ASSERT_FALSE( - TransformationVectorShuffle(MakeInstructionDescriptor(60, SpvOpPhi, 0), - 200, 14, 14, {2, 0}) - .IsApplicable(context.get(), fact_manager)); - ASSERT_FALSE( - TransformationVectorShuffle(MakeInstructionDescriptor(59, SpvOpPhi, 0), - 200, 14, 14, {3, 0}) - .IsApplicable(context.get(), fact_manager)); - // OK to insert after the OpPhis. - ASSERT_TRUE(TransformationVectorShuffle( - MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, - 14, {3, 4}) - .IsApplicable(context.get(), fact_manager)); - - // Cannot insert before OpLoopMerge - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(33, SpvOpBranchConditional, 0), - 200, 14, 14, {3}) - .IsApplicable(context.get(), fact_manager)); - - // Cannot insert before OpSelectionMerge - ASSERT_FALSE(TransformationVectorShuffle( - MakeInstructionDescriptor(21, SpvOpBranchConditional, 0), - 200, 14, 14, {2}) - .IsApplicable(context.get(), fact_manager)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzz/uniform_buffer_element_descriptor_test.cpp b/3rdparty/spirv-tools/test/fuzz/uniform_buffer_element_descriptor_test.cpp deleted file mode 100644 index 6c6d52a04..000000000 --- a/3rdparty/spirv-tools/test/fuzz/uniform_buffer_element_descriptor_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/fuzz/uniform_buffer_element_descriptor.h" -#include "test/fuzz/fuzz_test_util.h" - -namespace spvtools { -namespace fuzz { -namespace { - -TEST(UniformBufferElementDescriptorTest, TestEquality) { - // Test that equality works as expected for various buffer element - // descriptors. - - protobufs::UniformBufferElementDescriptor descriptor1 = - MakeUniformBufferElementDescriptor(0, 0, {1, 2, 3}); - protobufs::UniformBufferElementDescriptor descriptor2 = - MakeUniformBufferElementDescriptor(0, 0, {1, 2, 3}); - protobufs::UniformBufferElementDescriptor descriptor3 = - MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3}); - protobufs::UniformBufferElementDescriptor descriptor4 = - MakeUniformBufferElementDescriptor(1, 0, {1, 2, 3}); - protobufs::UniformBufferElementDescriptor descriptor5 = - MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3}); - protobufs::UniformBufferElementDescriptor descriptor6 = - MakeUniformBufferElementDescriptor(0, 0, {1, 2, 4}); - protobufs::UniformBufferElementDescriptor descriptor7 = - MakeUniformBufferElementDescriptor(0, 0, {1, 2}); - - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor1)); - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor2)); - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor3, &descriptor3)); - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor4, &descriptor4)); - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor5, &descriptor5)); - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor6, &descriptor6)); - ASSERT_TRUE( - UniformBufferElementDescriptorEquals()(&descriptor7, &descriptor7)); - - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor3)); - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor3, &descriptor1)); - - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor4)); - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor4, &descriptor1)); - - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor5)); - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor5, &descriptor1)); - - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor6)); - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor6, &descriptor1)); - - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor7)); - ASSERT_FALSE( - UniformBufferElementDescriptorEquals()(&descriptor7, &descriptor1)); -} - -} // namespace -} // namespace fuzz -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/fuzzers/BUILD.gn b/3rdparty/spirv-tools/test/fuzzers/BUILD.gn deleted file mode 100644 index be1258a45..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/BUILD.gn +++ /dev/null @@ -1,215 +0,0 @@ -# Copyright 2018 Google Inc. All rights reserved. -# -# 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. - -import("//testing/libfuzzer/fuzzer_test.gni") -import("//testing/test.gni") - -config("fuzzer_config") { - configs = [ "../..:spvtools_internal_config" ] -} - -group("fuzzers") { - testonly = true - deps = [] - - if (!build_with_chromium || use_fuzzing_engine) { - deps += [ ":fuzzers_bin" ] - } -} - -if (!build_with_chromium || use_fuzzing_engine) { - group("fuzzers_bin") { - testonly = true - - deps = [ - ":spvtools_as_fuzzer", - ":spvtools_binary_parser_fuzzer", - ":spvtools_dis_fuzzer", - ":spvtools_opt_legalization_fuzzer", - ":spvtools_opt_performance_fuzzer", - ":spvtools_opt_size_fuzzer", - ":spvtools_opt_webgputovulkan_fuzzer", - ":spvtools_opt_vulkantowebgpu_fuzzer", - ":spvtools_val_fuzzer", - ":spvtools_val_webgpu_fuzzer", - ] - } -} - -template("spvtools_fuzzer") { - source_set(target_name) { - testonly = true - sources = invoker.sources - deps = [ - "../..:spvtools", - "../..:spvtools_opt", - "../..:spvtools_val", - ] - if (defined(invoker.deps)) { - deps += invoker.deps - } - - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ - "//build/config/compiler:no_chromium_code", - ":fuzzer_config", - ] - } -} - -spvtools_fuzzer("spvtools_as_fuzzer_src") { - sources = [ - "spvtools_as_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_binary_parser_fuzzer_src") { - sources = [ - "spvtools_binary_parser_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_dis_fuzzer_src") { - sources = [ - "spvtools_dis_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_opt_performance_fuzzer_src") { - sources = [ - "spvtools_opt_performance_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_opt_legalization_fuzzer_src") { - sources = [ - "spvtools_opt_legalization_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_opt_size_fuzzer_src") { - sources = [ - "spvtools_opt_size_fuzzer.cpp", - ] -} - - -spvtools_fuzzer("spvtools_opt_webgputovulkan_fuzzer_src") { - sources = [ - "spvtools_opt_webgputovulkan_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_opt_vulkantowebgpu_fuzzer_src") { - sources = [ - "spvtools_opt_vulkantowebgpu_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_val_fuzzer_src") { - sources = [ - "spvtools_val_fuzzer.cpp", - ] -} - -spvtools_fuzzer("spvtools_val_webgpu_fuzzer_src") { - sources = [ - "spvtools_val_webgpu_fuzzer.cpp", - ] -} - -if (!build_with_chromium || use_fuzzing_engine) { - fuzzer_test("spvtools_as_fuzzer") { - sources = [] - deps = [ - ":spvtools_as_fuzzer_src", - ] - # Intentionally doesn't use the seed corpus, because it consumes - # part of the input as not part of the file. - } - - fuzzer_test("spvtools_binary_parser_fuzzer") { - sources = [] - deps = [ - ":spvtools_binary_parser_fuzzer_src", - ] - # Intentionally doesn't use the seed corpus, because it consumes - # part of the input as not part of the file. - } - - fuzzer_test("spvtools_dis_fuzzer") { - sources = [] - deps = [ - ":spvtools_dis_fuzzer_src", - ] - # Intentionally doesn't use the seed corpus, because it consumes - # part of the input as not part of the file. - } - - fuzzer_test("spvtools_opt_performance_fuzzer") { - sources = [] - deps = [ - ":spvtools_opt_performance_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } - - fuzzer_test("spvtools_opt_legalization_fuzzer") { - sources = [] - deps = [ - ":spvtools_opt_legalization_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } - - fuzzer_test("spvtools_opt_size_fuzzer") { - sources = [] - deps = [ - ":spvtools_opt_size_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } - - fuzzer_test("spvtools_opt_webgputovulkan_fuzzer") { - sources = [] - deps = [ - ":spvtools_opt_webgputovulkan_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } - - fuzzer_test("spvtools_opt_vulkantowebgpu_fuzzer") { - sources = [] - deps = [ - ":spvtools_opt_vulkantowebgpu_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } - - fuzzer_test("spvtools_val_fuzzer") { - sources = [] - deps = [ - ":spvtools_val_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } - - fuzzer_test("spvtools_val_webgpu_fuzzer") { - sources = [] - deps = [ - ":spvtools_val_webgpu_fuzzer_src", - ] - seed_corpus = "corpora/spv" - } -} diff --git a/3rdparty/spirv-tools/test/fuzzers/corpora/spv/simple.spv b/3rdparty/spirv-tools/test/fuzzers/corpora/spv/simple.spv deleted file mode 100644 index f972a56fd..000000000 Binary files a/3rdparty/spirv-tools/test/fuzzers/corpora/spv/simple.spv and /dev/null differ diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_as_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_as_fuzzer.cpp deleted file mode 100644 index 8cecb05f5..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_as_fuzzer.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2019 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 // memcpy -#include - -#include "source/spirv_target_env.h" -#include "spirv-tools/libspirv.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size < sizeof(spv_target_env) + 1) return 0; - - const spv_context context = - spvContextCreate(*reinterpret_cast(data)); - if (context == nullptr) return 0; - - data += sizeof(spv_target_env); - size -= sizeof(spv_target_env); - - std::vector input; - - std::vector input_str; - size_t char_count = input.size() * sizeof(uint32_t) / sizeof(char); - input_str.resize(char_count); - memcpy(input_str.data(), input.data(), input.size() * sizeof(uint32_t)); - - spv_binary binary = nullptr; - spv_diagnostic diagnostic = nullptr; - spvTextToBinaryWithOptions(context, input_str.data(), input_str.size(), - SPV_TEXT_TO_BINARY_OPTION_NONE, &binary, - &diagnostic); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - diagnostic = nullptr; - } - - if (binary) { - spvBinaryDestroy(binary); - binary = nullptr; - } - - spvTextToBinaryWithOptions(context, input_str.data(), input_str.size(), - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS, - &binary, &diagnostic); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - diagnostic = nullptr; - } - - if (binary) { - spvBinaryDestroy(binary); - binary = nullptr; - } - - spvContextDestroy(context); - - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_binary_parser_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_binary_parser_fuzzer.cpp deleted file mode 100644 index 76ba4d9e9..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_binary_parser_fuzzer.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2018 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 "spirv-tools/libspirv.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size < sizeof(spv_target_env) + 1) return 0; - - const spv_context context = - spvContextCreate(*reinterpret_cast(data)); - if (context == nullptr) return 0; - - data += sizeof(spv_target_env); - size -= sizeof(spv_target_env); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - spvBinaryParse(context, nullptr, input.data(), input.size(), nullptr, nullptr, - nullptr); - - spvContextDestroy(context); - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_dis_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_dis_fuzzer.cpp deleted file mode 100644 index ca9a52d86..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_dis_fuzzer.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2019 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 // memcpy -#include - -#include "source/spirv_target_env.h" -#include "spirv-tools/libspirv.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size < sizeof(spv_target_env) + 1) return 0; - - const spv_context context = - spvContextCreate(*reinterpret_cast(data)); - if (context == nullptr) return 0; - - data += sizeof(spv_target_env); - size -= sizeof(spv_target_env); - - std::vector input; - input.resize(size >> 2); - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - std::vector input_str; - size_t char_count = input.size() * sizeof(uint32_t) / sizeof(char); - input_str.resize(char_count); - memcpy(input_str.data(), input.data(), input.size() * sizeof(uint32_t)); - - spv_text text = nullptr; - spv_diagnostic diagnostic = nullptr; - - for (uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE; - options < - (SPV_BINARY_TO_TEXT_OPTION_PRINT | SPV_BINARY_TO_TEXT_OPTION_COLOR | - SPV_BINARY_TO_TEXT_OPTION_INDENT | - SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET | - SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - options++) { - spvBinaryToText(context, input.data(), input.size(), options, &text, - &diagnostic); - if (diagnostic) { - spvDiagnosticDestroy(diagnostic); - diagnostic = nullptr; - } - - if (text) { - spvTextDestroy(text); - text = nullptr; - } - } - - spvContextDestroy(context); - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_legalization_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_legalization_fuzzer.cpp deleted file mode 100644 index b45a98c37..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_legalization_fuzzer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2018 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 "spirv-tools/optimizer.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_3); - optimizer.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - optimizer.RegisterLegalizationPasses(); - optimizer.Run(input.data(), input.size(), &input); - - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_performance_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_performance_fuzzer.cpp deleted file mode 100644 index 6c3bd6aba..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_performance_fuzzer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2018 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 "spirv-tools/optimizer.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_3); - optimizer.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - optimizer.RegisterPerformancePasses(); - optimizer.Run(input.data(), input.size(), &input); - - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_size_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_size_fuzzer.cpp deleted file mode 100644 index 68c797477..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_size_fuzzer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2018 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 "spirv-tools/optimizer.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_3); - optimizer.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - optimizer.RegisterSizePasses(); - optimizer.Run(input.data(), input.size(), &input); - - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_vulkantowebgpu_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_vulkantowebgpu_fuzzer.cpp deleted file mode 100644 index 9371c0df0..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_vulkantowebgpu_fuzzer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2019 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 "spirv-tools/optimizer.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_1); - optimizer.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - optimizer.RegisterVulkanToWebGPUPasses(); - optimizer.Run(input.data(), input.size(), &input); - - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_webgputovulkan_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_webgputovulkan_fuzzer.cpp deleted file mode 100644 index 78ddbb75c..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_opt_webgputovulkan_fuzzer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2019 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 "spirv-tools/optimizer.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::Optimizer optimizer(SPV_ENV_WEBGPU_0); - optimizer.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - optimizer.RegisterWebGPUToVulkanPasses(); - optimizer.Run(input.data(), input.size(), &input); - - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_val_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_val_fuzzer.cpp deleted file mode 100644 index 5dc4303b4..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_val_fuzzer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2018 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 "spirv-tools/libspirv.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_3); - tools.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - tools.Validate(input); - return 0; -} diff --git a/3rdparty/spirv-tools/test/fuzzers/spvtools_val_webgpu_fuzzer.cpp b/3rdparty/spirv-tools/test/fuzzers/spvtools_val_webgpu_fuzzer.cpp deleted file mode 100644 index bed6e1a21..000000000 --- a/3rdparty/spirv-tools/test/fuzzers/spvtools_val_webgpu_fuzzer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2019 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 "spirv-tools/libspirv.hpp" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - spvtools::SpirvTools tools(SPV_ENV_WEBGPU_0); - tools.SetMessageConsumer([](spv_message_level_t, const char*, - const spv_position_t&, const char*) {}); - - std::vector input; - input.resize(size >> 2); - - size_t count = 0; - for (size_t i = 0; (i + 3) < size; i += 4) { - input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | - (data[i + 3]) << 24; - } - - tools.Validate(input); - return 0; -} diff --git a/3rdparty/spirv-tools/test/generator_magic_number_test.cpp b/3rdparty/spirv-tools/test/generator_magic_number_test.cpp deleted file mode 100644 index 7131ac456..000000000 --- a/3rdparty/spirv-tools/test/generator_magic_number_test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/opcode.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::spvtest::EnumCase; -using ::testing::Eq; -using GeneratorMagicNumberTest = - ::testing::TestWithParam>; - -TEST_P(GeneratorMagicNumberTest, Single) { - EXPECT_THAT(std::string(spvGeneratorStr(GetParam().value())), - GetParam().name()); -} - -INSTANTIATE_TEST_SUITE_P( - Registered, GeneratorMagicNumberTest, - ::testing::ValuesIn(std::vector>{ - {SPV_GENERATOR_KHRONOS, "Khronos"}, - {SPV_GENERATOR_LUNARG, "LunarG"}, - {SPV_GENERATOR_VALVE, "Valve"}, - {SPV_GENERATOR_CODEPLAY, "Codeplay"}, - {SPV_GENERATOR_NVIDIA, "NVIDIA"}, - {SPV_GENERATOR_ARM, "ARM"}, - {SPV_GENERATOR_KHRONOS_LLVM_TRANSLATOR, - "Khronos LLVM/SPIR-V Translator"}, - {SPV_GENERATOR_KHRONOS_ASSEMBLER, "Khronos SPIR-V Tools Assembler"}, - {SPV_GENERATOR_KHRONOS_GLSLANG, "Khronos Glslang Reference Front End"}, - })); - -INSTANTIATE_TEST_SUITE_P( - Unregistered, GeneratorMagicNumberTest, - ::testing::ValuesIn(std::vector>{ - // We read registered entries from the SPIR-V XML Registry file - // which can change over time. - {spv_generator_t(1000), "Unknown"}, - {spv_generator_t(9999), "Unknown"}, - })); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/hex_float_test.cpp b/3rdparty/spirv-tools/test/hex_float_test.cpp deleted file mode 100644 index c422f7563..000000000 --- a/3rdparty/spirv-tools/test/hex_float_test.cpp +++ /dev/null @@ -1,1331 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/util/hex_float.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace utils { -namespace { - -using ::testing::Eq; - -// In this file "encode" means converting a number into a string, -// and "decode" means converting a string into a number. - -using HexFloatTest = - ::testing::TestWithParam, std::string>>; -using DecodeHexFloatTest = - ::testing::TestWithParam>>; -using HexDoubleTest = - ::testing::TestWithParam, std::string>>; -using DecodeHexDoubleTest = - ::testing::TestWithParam>>; -using RoundTripFloatTest = ::testing::TestWithParam; -using RoundTripDoubleTest = ::testing::TestWithParam; - -// Hex-encodes a float value. -template -std::string EncodeViaHexFloat(const T& value) { - std::stringstream ss; - ss << HexFloat(value); - return ss.str(); -} - -// The following two tests can't be DRY because they take different parameter -// types. - -TEST_P(HexFloatTest, EncodeCorrectly) { - EXPECT_THAT(EncodeViaHexFloat(GetParam().first), Eq(GetParam().second)); -} - -TEST_P(HexDoubleTest, EncodeCorrectly) { - EXPECT_THAT(EncodeViaHexFloat(GetParam().first), Eq(GetParam().second)); -} - -// Decodes a hex-float string. -template -FloatProxy Decode(const std::string& str) { - HexFloat> decoded(0.f); - EXPECT_TRUE((std::stringstream(str) >> decoded).eof()); - return decoded.value(); -} - -TEST_P(HexFloatTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().second), Eq(GetParam().first)); -} - -TEST_P(HexDoubleTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().second), Eq(GetParam().first)); -} - -INSTANTIATE_TEST_SUITE_P( - Float32Tests, HexFloatTest, - ::testing::ValuesIn(std::vector, std::string>>({ - {0.f, "0x0p+0"}, - {1.f, "0x1p+0"}, - {2.f, "0x1p+1"}, - {3.f, "0x1.8p+1"}, - {0.5f, "0x1p-1"}, - {0.25f, "0x1p-2"}, - {0.75f, "0x1.8p-1"}, - {-0.f, "-0x0p+0"}, - {-1.f, "-0x1p+0"}, - {-0.5f, "-0x1p-1"}, - {-0.25f, "-0x1p-2"}, - {-0.75f, "-0x1.8p-1"}, - - // Larger numbers - {512.f, "0x1p+9"}, - {-512.f, "-0x1p+9"}, - {1024.f, "0x1p+10"}, - {-1024.f, "-0x1p+10"}, - {1024.f + 8.f, "0x1.02p+10"}, - {-1024.f - 8.f, "-0x1.02p+10"}, - - // Small numbers - {1.0f / 512.f, "0x1p-9"}, - {1.0f / -512.f, "-0x1p-9"}, - {1.0f / 1024.f, "0x1p-10"}, - {1.0f / -1024.f, "-0x1p-10"}, - {1.0f / 1024.f + 1.0f / 8.f, "0x1.02p-3"}, - {1.0f / -1024.f - 1.0f / 8.f, "-0x1.02p-3"}, - - // lowest non-denorm - {float(ldexp(1.0f, -126)), "0x1p-126"}, - {float(ldexp(-1.0f, -126)), "-0x1p-126"}, - - // Denormalized values - {float(ldexp(1.0f, -127)), "0x1p-127"}, - {float(ldexp(1.0f, -127) / 2.0f), "0x1p-128"}, - {float(ldexp(1.0f, -127) / 4.0f), "0x1p-129"}, - {float(ldexp(1.0f, -127) / 8.0f), "0x1p-130"}, - {float(ldexp(-1.0f, -127)), "-0x1p-127"}, - {float(ldexp(-1.0f, -127) / 2.0f), "-0x1p-128"}, - {float(ldexp(-1.0f, -127) / 4.0f), "-0x1p-129"}, - {float(ldexp(-1.0f, -127) / 8.0f), "-0x1p-130"}, - - {float(ldexp(1.0, -127) + (ldexp(1.0, -127) / 2.0f)), "0x1.8p-127"}, - {float(ldexp(1.0, -127) / 2.0 + (ldexp(1.0, -127) / 4.0f)), - "0x1.8p-128"}, - - }))); - -INSTANTIATE_TEST_SUITE_P( - Float32NanTests, HexFloatTest, - ::testing::ValuesIn(std::vector, std::string>>({ - // Various NAN and INF cases - {uint32_t(0xFF800000), "-0x1p+128"}, // -inf - {uint32_t(0x7F800000), "0x1p+128"}, // inf - {uint32_t(0xFFC00000), "-0x1.8p+128"}, // -nan - {uint32_t(0xFF800100), "-0x1.0002p+128"}, // -nan - {uint32_t(0xFF800c00), "-0x1.0018p+128"}, // -nan - {uint32_t(0xFF80F000), "-0x1.01ep+128"}, // -nan - {uint32_t(0xFFFFFFFF), "-0x1.fffffep+128"}, // -nan - {uint32_t(0x7FC00000), "0x1.8p+128"}, // +nan - {uint32_t(0x7F800100), "0x1.0002p+128"}, // +nan - {uint32_t(0x7f800c00), "0x1.0018p+128"}, // +nan - {uint32_t(0x7F80F000), "0x1.01ep+128"}, // +nan - {uint32_t(0x7FFFFFFF), "0x1.fffffep+128"}, // +nan - }))); - -INSTANTIATE_TEST_SUITE_P( - Float64Tests, HexDoubleTest, - ::testing::ValuesIn( - std::vector, std::string>>({ - {0., "0x0p+0"}, - {1., "0x1p+0"}, - {2., "0x1p+1"}, - {3., "0x1.8p+1"}, - {0.5, "0x1p-1"}, - {0.25, "0x1p-2"}, - {0.75, "0x1.8p-1"}, - {-0., "-0x0p+0"}, - {-1., "-0x1p+0"}, - {-0.5, "-0x1p-1"}, - {-0.25, "-0x1p-2"}, - {-0.75, "-0x1.8p-1"}, - - // Larger numbers - {512., "0x1p+9"}, - {-512., "-0x1p+9"}, - {1024., "0x1p+10"}, - {-1024., "-0x1p+10"}, - {1024. + 8., "0x1.02p+10"}, - {-1024. - 8., "-0x1.02p+10"}, - - // Large outside the range of normal floats - {ldexp(1.0, 128), "0x1p+128"}, - {ldexp(1.0, 129), "0x1p+129"}, - {ldexp(-1.0, 128), "-0x1p+128"}, - {ldexp(-1.0, 129), "-0x1p+129"}, - {ldexp(1.0, 128) + ldexp(1.0, 90), "0x1.0000000004p+128"}, - {ldexp(1.0, 129) + ldexp(1.0, 120), "0x1.008p+129"}, - {ldexp(-1.0, 128) + ldexp(1.0, 90), "-0x1.fffffffff8p+127"}, - {ldexp(-1.0, 129) + ldexp(1.0, 120), "-0x1.ffp+128"}, - - // Small numbers - {1.0 / 512., "0x1p-9"}, - {1.0 / -512., "-0x1p-9"}, - {1.0 / 1024., "0x1p-10"}, - {1.0 / -1024., "-0x1p-10"}, - {1.0 / 1024. + 1.0 / 8., "0x1.02p-3"}, - {1.0 / -1024. - 1.0 / 8., "-0x1.02p-3"}, - - // Small outside the range of normal floats - {ldexp(1.0, -128), "0x1p-128"}, - {ldexp(1.0, -129), "0x1p-129"}, - {ldexp(-1.0, -128), "-0x1p-128"}, - {ldexp(-1.0, -129), "-0x1p-129"}, - {ldexp(1.0, -128) + ldexp(1.0, -90), "0x1.0000000004p-90"}, - {ldexp(1.0, -129) + ldexp(1.0, -120), "0x1.008p-120"}, - {ldexp(-1.0, -128) + ldexp(1.0, -90), "0x1.fffffffff8p-91"}, - {ldexp(-1.0, -129) + ldexp(1.0, -120), "0x1.ffp-121"}, - - // lowest non-denorm - {ldexp(1.0, -1022), "0x1p-1022"}, - {ldexp(-1.0, -1022), "-0x1p-1022"}, - - // Denormalized values - {ldexp(1.0, -1023), "0x1p-1023"}, - {ldexp(1.0, -1023) / 2.0, "0x1p-1024"}, - {ldexp(1.0, -1023) / 4.0, "0x1p-1025"}, - {ldexp(1.0, -1023) / 8.0, "0x1p-1026"}, - {ldexp(-1.0, -1024), "-0x1p-1024"}, - {ldexp(-1.0, -1024) / 2.0, "-0x1p-1025"}, - {ldexp(-1.0, -1024) / 4.0, "-0x1p-1026"}, - {ldexp(-1.0, -1024) / 8.0, "-0x1p-1027"}, - - {ldexp(1.0, -1023) + (ldexp(1.0, -1023) / 2.0), "0x1.8p-1023"}, - {ldexp(1.0, -1023) / 2.0 + (ldexp(1.0, -1023) / 4.0), - "0x1.8p-1024"}, - - }))); - -INSTANTIATE_TEST_SUITE_P( - Float64NanTests, HexDoubleTest, - ::testing::ValuesIn(std::vector< - std::pair, std::string>>({ - // Various NAN and INF cases - {uint64_t(0xFFF0000000000000LL), "-0x1p+1024"}, // -inf - {uint64_t(0x7FF0000000000000LL), "0x1p+1024"}, // +inf - {uint64_t(0xFFF8000000000000LL), "-0x1.8p+1024"}, // -nan - {uint64_t(0xFFF0F00000000000LL), "-0x1.0fp+1024"}, // -nan - {uint64_t(0xFFF0000000000001LL), "-0x1.0000000000001p+1024"}, // -nan - {uint64_t(0xFFF0000300000000LL), "-0x1.00003p+1024"}, // -nan - {uint64_t(0xFFFFFFFFFFFFFFFFLL), "-0x1.fffffffffffffp+1024"}, // -nan - {uint64_t(0x7FF8000000000000LL), "0x1.8p+1024"}, // +nan - {uint64_t(0x7FF0F00000000000LL), "0x1.0fp+1024"}, // +nan - {uint64_t(0x7FF0000000000001LL), "0x1.0000000000001p+1024"}, // -nan - {uint64_t(0x7FF0000300000000LL), "0x1.00003p+1024"}, // -nan - {uint64_t(0x7FFFFFFFFFFFFFFFLL), "0x1.fffffffffffffp+1024"}, // -nan - }))); - -// Tests that encoding a value and decoding it again restores -// the same value. -TEST_P(RoundTripFloatTest, CanStoreAccurately) { - std::stringstream ss; - ss << FloatProxy(GetParam()); - ss.seekg(0); - FloatProxy res; - ss >> res; - EXPECT_THAT(GetParam(), Eq(res.getAsFloat())); -} - -TEST_P(RoundTripDoubleTest, CanStoreAccurately) { - std::stringstream ss; - ss << FloatProxy(GetParam()); - ss.seekg(0); - FloatProxy res; - ss >> res; - EXPECT_THAT(GetParam(), Eq(res.getAsFloat())); -} - -INSTANTIATE_TEST_SUITE_P( - Float32StoreTests, RoundTripFloatTest, - ::testing::ValuesIn(std::vector( - {// Value requiring more than 6 digits of precision to be - // represented accurately. - 3.0000002f}))); - -INSTANTIATE_TEST_SUITE_P( - Float64StoreTests, RoundTripDoubleTest, - ::testing::ValuesIn(std::vector( - {// Value requiring more than 15 digits of precision to be - // represented accurately. - 1.5000000000000002}))); - -TEST(HexFloatStreamTest, OperatorLeftShiftPreservesFloatAndFill) { - std::stringstream s; - s << std::setw(4) << std::oct << std::setfill('x') << 8 << " " - << FloatProxy(uint32_t(0xFF800100)) << " " << std::setw(4) << 9; - EXPECT_THAT(s.str(), Eq(std::string("xx10 -0x1.0002p+128 xx11"))); -} - -TEST(HexDoubleStreamTest, OperatorLeftShiftPreservesFloatAndFill) { - std::stringstream s; - s << std::setw(4) << std::oct << std::setfill('x') << 8 << " " - << FloatProxy(uint64_t(0x7FF0F00000000000LL)) << " " << std::setw(4) - << 9; - EXPECT_THAT(s.str(), Eq(std::string("xx10 0x1.0fp+1024 xx11"))); -} - -TEST_P(DecodeHexFloatTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().first), Eq(GetParam().second)); -} - -TEST_P(DecodeHexDoubleTest, DecodeCorrectly) { - EXPECT_THAT(Decode(GetParam().first), Eq(GetParam().second)); -} - -INSTANTIATE_TEST_SUITE_P( - Float32DecodeTests, DecodeHexFloatTest, - ::testing::ValuesIn(std::vector>>({ - {"0x0p+000", 0.f}, - {"0x0p0", 0.f}, - {"0x0p-0", 0.f}, - - // flush to zero cases - {"0x1p-500", 0.f}, // Exponent underflows. - {"-0x1p-500", -0.f}, - {"0x0.00000000001p-126", 0.f}, // Fraction causes underflow. - {"-0x0.0000000001p-127", -0.f}, - {"-0x0.01p-142", -0.f}, // Fraction causes additional underflow. - {"0x0.01p-142", 0.f}, - - // Some floats that do not encode the same way as they decode. - {"0x2p+0", 2.f}, - {"0xFFp+0", 255.f}, - {"0x0.8p+0", 0.5f}, - {"0x0.4p+0", 0.25f}, - }))); - -INSTANTIATE_TEST_SUITE_P( - Float32DecodeInfTests, DecodeHexFloatTest, - ::testing::ValuesIn(std::vector>>({ - // inf cases - {"-0x1p+128", uint32_t(0xFF800000)}, // -inf - {"0x32p+127", uint32_t(0x7F800000)}, // inf - {"0x32p+500", uint32_t(0x7F800000)}, // inf - {"-0x32p+127", uint32_t(0xFF800000)}, // -inf - }))); - -INSTANTIATE_TEST_SUITE_P( - Float64DecodeTests, DecodeHexDoubleTest, - ::testing::ValuesIn( - std::vector>>({ - {"0x0p+000", 0.}, - {"0x0p0", 0.}, - {"0x0p-0", 0.}, - - // flush to zero cases - {"0x1p-5000", 0.}, // Exponent underflows. - {"-0x1p-5000", -0.}, - {"0x0.0000000000000001p-1023", 0.}, // Fraction causes underflow. - {"-0x0.000000000000001p-1024", -0.}, - {"-0x0.01p-1090", -0.f}, // Fraction causes additional underflow. - {"0x0.01p-1090", 0.}, - - // Some floats that do not encode the same way as they decode. - {"0x2p+0", 2.}, - {"0xFFp+0", 255.}, - {"0x0.8p+0", 0.5}, - {"0x0.4p+0", 0.25}, - }))); - -INSTANTIATE_TEST_SUITE_P( - Float64DecodeInfTests, DecodeHexDoubleTest, - ::testing::ValuesIn( - std::vector>>({ - // inf cases - {"-0x1p+1024", uint64_t(0xFFF0000000000000)}, // -inf - {"0x32p+1023", uint64_t(0x7FF0000000000000)}, // inf - {"0x32p+5000", uint64_t(0x7FF0000000000000)}, // inf - {"-0x32p+1023", uint64_t(0xFFF0000000000000)}, // -inf - }))); - -TEST(FloatProxy, ValidConversion) { - EXPECT_THAT(FloatProxy(1.f).getAsFloat(), Eq(1.0f)); - EXPECT_THAT(FloatProxy(32.f).getAsFloat(), Eq(32.0f)); - EXPECT_THAT(FloatProxy(-1.f).getAsFloat(), Eq(-1.0f)); - EXPECT_THAT(FloatProxy(0.f).getAsFloat(), Eq(0.0f)); - EXPECT_THAT(FloatProxy(-0.f).getAsFloat(), Eq(-0.0f)); - EXPECT_THAT(FloatProxy(1.2e32f).getAsFloat(), Eq(1.2e32f)); - - EXPECT_TRUE(std::isinf(FloatProxy(uint32_t(0xFF800000)).getAsFloat())); - EXPECT_TRUE(std::isinf(FloatProxy(uint32_t(0x7F800000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFFC00000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFF800100)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFF800c00)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFF80F000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0xFFFFFFFF)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7FC00000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7F800100)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7f800c00)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7F80F000)).getAsFloat())); - EXPECT_TRUE(std::isnan(FloatProxy(uint32_t(0x7FFFFFFF)).getAsFloat())); - - EXPECT_THAT(FloatProxy(uint32_t(0xFF800000)).data(), Eq(0xFF800000u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7F800000)).data(), Eq(0x7F800000u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFFC00000)).data(), Eq(0xFFC00000u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFF800100)).data(), Eq(0xFF800100u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFF800c00)).data(), Eq(0xFF800c00u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFF80F000)).data(), Eq(0xFF80F000u)); - EXPECT_THAT(FloatProxy(uint32_t(0xFFFFFFFF)).data(), Eq(0xFFFFFFFFu)); - EXPECT_THAT(FloatProxy(uint32_t(0x7FC00000)).data(), Eq(0x7FC00000u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7F800100)).data(), Eq(0x7F800100u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7f800c00)).data(), Eq(0x7f800c00u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7F80F000)).data(), Eq(0x7F80F000u)); - EXPECT_THAT(FloatProxy(uint32_t(0x7FFFFFFF)).data(), Eq(0x7FFFFFFFu)); -} - -TEST(FloatProxy, Nan) { - EXPECT_TRUE(FloatProxy(uint32_t(0xFFC00000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFF800100)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFF800c00)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFF80F000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0xFFFFFFFF)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7FC00000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7F800100)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7f800c00)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7F80F000)).isNan()); - EXPECT_TRUE(FloatProxy(uint32_t(0x7FFFFFFF)).isNan()); -} - -TEST(FloatProxy, Negation) { - EXPECT_THAT((-FloatProxy(1.f)).getAsFloat(), Eq(-1.0f)); - EXPECT_THAT((-FloatProxy(0.f)).getAsFloat(), Eq(-0.0f)); - - EXPECT_THAT((-FloatProxy(-1.f)).getAsFloat(), Eq(1.0f)); - EXPECT_THAT((-FloatProxy(-0.f)).getAsFloat(), Eq(0.0f)); - - EXPECT_THAT((-FloatProxy(32.f)).getAsFloat(), Eq(-32.0f)); - EXPECT_THAT((-FloatProxy(-32.f)).getAsFloat(), Eq(32.0f)); - - EXPECT_THAT((-FloatProxy(1.2e32f)).getAsFloat(), Eq(-1.2e32f)); - EXPECT_THAT((-FloatProxy(-1.2e32f)).getAsFloat(), Eq(1.2e32f)); - - EXPECT_THAT( - (-FloatProxy(std::numeric_limits::infinity())).getAsFloat(), - Eq(-std::numeric_limits::infinity())); - EXPECT_THAT((-FloatProxy(-std::numeric_limits::infinity())) - .getAsFloat(), - Eq(std::numeric_limits::infinity())); -} - -// Test conversion of FloatProxy values to strings. -// -// In previous cases, we always wrapped the FloatProxy value in a HexFloat -// before conversion to a string. In the following cases, the FloatProxy -// decides for itself whether to print as a regular number or as a hex float. - -using FloatProxyFloatTest = - ::testing::TestWithParam, std::string>>; -using FloatProxyDoubleTest = - ::testing::TestWithParam, std::string>>; - -// Converts a float value to a string via a FloatProxy. -template -std::string EncodeViaFloatProxy(const T& value) { - std::stringstream ss; - ss << value; - return ss.str(); -} - -// Converts a floating point string so that the exponent prefix -// is 'e', and the exponent value does not have leading zeros. -// The Microsoft runtime library likes to write things like "2.5E+010". -// Convert that to "2.5e+10". -// We don't care what happens to strings that are not floating point -// strings. -std::string NormalizeExponentInFloatString(std::string in) { - std::string result; - // Reserve one spot for the terminating null, even when the sscanf fails. - std::vector prefix(in.size() + 1); - char e; - char plus_or_minus; - int exponent; // in base 10 - if ((4 == std::sscanf(in.c_str(), "%[-+.0123456789]%c%c%d", prefix.data(), &e, - &plus_or_minus, &exponent)) && - (e == 'e' || e == 'E') && - (plus_or_minus == '-' || plus_or_minus == '+')) { - // It looks like a floating point value with exponent. - std::stringstream out; - out << prefix.data() << 'e' << plus_or_minus << exponent; - result = out.str(); - } else { - result = in; - } - return result; -} - -TEST(NormalizeFloat, Sample) { - EXPECT_THAT(NormalizeExponentInFloatString(""), Eq("")); - EXPECT_THAT(NormalizeExponentInFloatString("1e-12"), Eq("1e-12")); - EXPECT_THAT(NormalizeExponentInFloatString("1E+14"), Eq("1e+14")); - EXPECT_THAT(NormalizeExponentInFloatString("1e-0012"), Eq("1e-12")); - EXPECT_THAT(NormalizeExponentInFloatString("1.263E+014"), Eq("1.263e+14")); -} - -// The following two tests can't be DRY because they take different parameter -// types. -TEST_P(FloatProxyFloatTest, EncodeCorrectly) { - EXPECT_THAT( - NormalizeExponentInFloatString(EncodeViaFloatProxy(GetParam().first)), - Eq(GetParam().second)); -} - -TEST_P(FloatProxyDoubleTest, EncodeCorrectly) { - EXPECT_THAT( - NormalizeExponentInFloatString(EncodeViaFloatProxy(GetParam().first)), - Eq(GetParam().second)); -} - -INSTANTIATE_TEST_SUITE_P( - Float32Tests, FloatProxyFloatTest, - ::testing::ValuesIn(std::vector, std::string>>({ - // Zero - {0.f, "0"}, - // Normal numbers - {1.f, "1"}, - {-0.25f, "-0.25"}, - {1000.0f, "1000"}, - - // Still normal numbers, but with large magnitude exponents. - {float(ldexp(1.f, 126)), "8.50705917e+37"}, - {float(ldexp(-1.f, -126)), "-1.17549435e-38"}, - - // denormalized values are printed as hex floats. - {float(ldexp(1.0f, -127)), "0x1p-127"}, - {float(ldexp(1.5f, -128)), "0x1.8p-128"}, - {float(ldexp(1.25, -129)), "0x1.4p-129"}, - {float(ldexp(1.125, -130)), "0x1.2p-130"}, - {float(ldexp(-1.0f, -127)), "-0x1p-127"}, - {float(ldexp(-1.0f, -128)), "-0x1p-128"}, - {float(ldexp(-1.0f, -129)), "-0x1p-129"}, - {float(ldexp(-1.5f, -130)), "-0x1.8p-130"}, - - // NaNs - {FloatProxy(uint32_t(0xFFC00000)), "-0x1.8p+128"}, - {FloatProxy(uint32_t(0xFF800100)), "-0x1.0002p+128"}, - - {std::numeric_limits::infinity(), "0x1p+128"}, - {-std::numeric_limits::infinity(), "-0x1p+128"}, - }))); - -INSTANTIATE_TEST_SUITE_P( - Float64Tests, FloatProxyDoubleTest, - ::testing::ValuesIn( - std::vector, std::string>>({ - {0., "0"}, - {1., "1"}, - {-0.25, "-0.25"}, - {1000.0, "1000"}, - - // Large outside the range of normal floats - {ldexp(1.0, 128), "3.4028236692093846e+38"}, - {ldexp(1.5, 129), "1.0208471007628154e+39"}, - {ldexp(-1.0, 128), "-3.4028236692093846e+38"}, - {ldexp(-1.5, 129), "-1.0208471007628154e+39"}, - - // Small outside the range of normal floats - {ldexp(1.5, -129), "2.2040519077917891e-39"}, - {ldexp(-1.5, -129), "-2.2040519077917891e-39"}, - - // lowest non-denorm - {ldexp(1.0, -1022), "2.2250738585072014e-308"}, - {ldexp(-1.0, -1022), "-2.2250738585072014e-308"}, - - // Denormalized values - {ldexp(1.125, -1023), "0x1.2p-1023"}, - {ldexp(-1.375, -1024), "-0x1.6p-1024"}, - - // NaNs - {uint64_t(0x7FF8000000000000LL), "0x1.8p+1024"}, - {uint64_t(0xFFF0F00000000000LL), "-0x1.0fp+1024"}, - - // Infinity - {std::numeric_limits::infinity(), "0x1p+1024"}, - {-std::numeric_limits::infinity(), "-0x1p+1024"}, - - }))); - -// double is used so that unbiased_exponent can be used with the output -// of ldexp directly. -int32_t unbiased_exponent(double f) { - return HexFloat>(static_cast(f)) - .getUnbiasedNormalizedExponent(); -} - -int16_t unbiased_half_exponent(uint16_t f) { - return HexFloat>(f).getUnbiasedNormalizedExponent(); -} - -TEST(HexFloatOperationTest, UnbiasedExponent) { - // Float cases - EXPECT_EQ(0, unbiased_exponent(ldexp(1.0f, 0))); - EXPECT_EQ(-32, unbiased_exponent(ldexp(1.0f, -32))); - EXPECT_EQ(42, unbiased_exponent(ldexp(1.0f, 42))); - EXPECT_EQ(125, unbiased_exponent(ldexp(1.0f, 125))); - - EXPECT_EQ(128, - HexFloat>(std::numeric_limits::infinity()) - .getUnbiasedNormalizedExponent()); - - EXPECT_EQ(-100, unbiased_exponent(ldexp(1.0f, -100))); - EXPECT_EQ(-127, unbiased_exponent(ldexp(1.0f, -127))); // First denorm - EXPECT_EQ(-128, unbiased_exponent(ldexp(1.0f, -128))); - EXPECT_EQ(-129, unbiased_exponent(ldexp(1.0f, -129))); - EXPECT_EQ(-140, unbiased_exponent(ldexp(1.0f, -140))); - // Smallest representable number - EXPECT_EQ(-126 - 23, unbiased_exponent(ldexp(1.0f, -126 - 23))); - // Should get rounded to 0 first. - EXPECT_EQ(0, unbiased_exponent(ldexp(1.0f, -127 - 23))); - - // Float16 cases - // The exponent is represented in the bits 0x7C00 - // The offset is -15 - EXPECT_EQ(0, unbiased_half_exponent(0x3C00)); - EXPECT_EQ(3, unbiased_half_exponent(0x4800)); - EXPECT_EQ(-1, unbiased_half_exponent(0x3800)); - EXPECT_EQ(-14, unbiased_half_exponent(0x0400)); - EXPECT_EQ(16, unbiased_half_exponent(0x7C00)); - EXPECT_EQ(10, unbiased_half_exponent(0x6400)); - - // Smallest representable number - EXPECT_EQ(-24, unbiased_half_exponent(0x0001)); -} - -// Creates a float that is the sum of 1/(2 ^ fractions[i]) for i in factions -float float_fractions(const std::vector& fractions) { - float f = 0; - for (int32_t i : fractions) { - f += std::ldexp(1.0f, -i); - } - return f; -} - -// Returns the normalized significand of a HexFloat> -// that was created by calling float_fractions with the input fractions, -// raised to the power of exp. -uint32_t normalized_significand(const std::vector& fractions, - uint32_t exp) { - return HexFloat>( - static_cast(ldexp(float_fractions(fractions), exp))) - .getNormalizedSignificand(); -} - -// Sets the bits from MSB to LSB of the significand part of a float. -// For example 0 would set the bit 23 (counting from LSB to MSB), -// and 1 would set the 22nd bit. -uint32_t bits_set(const std::vector& bits) { - const uint32_t top_bit = 1u << 22u; - uint32_t val = 0; - for (uint32_t i : bits) { - val |= top_bit >> i; - } - return val; -} - -// The same as bits_set but for a Float16 value instead of 32-bit floating -// point. -uint16_t half_bits_set(const std::vector& bits) { - const uint32_t top_bit = 1u << 9u; - uint32_t val = 0; - for (uint32_t i : bits) { - val |= top_bit >> i; - } - return static_cast(val); -} - -TEST(HexFloatOperationTest, NormalizedSignificand) { - // For normalized numbers (the following) it should be a simple matter - // of getting rid of the top implicit bit - EXPECT_EQ(bits_set({}), normalized_significand({0}, 0)); - EXPECT_EQ(bits_set({0}), normalized_significand({0, 1}, 0)); - EXPECT_EQ(bits_set({0, 1}), normalized_significand({0, 1, 2}, 0)); - EXPECT_EQ(bits_set({1}), normalized_significand({0, 2}, 0)); - EXPECT_EQ(bits_set({1}), normalized_significand({0, 2}, 32)); - EXPECT_EQ(bits_set({1}), normalized_significand({0, 2}, 126)); - - // For denormalized numbers we expect the normalized significand to - // shift as if it were normalized. This means, in practice that the - // top_most set bit will be cut off. Looks very similar to above (on purpose) - EXPECT_EQ(bits_set({}), - normalized_significand({0}, static_cast(-127))); - EXPECT_EQ(bits_set({3}), - normalized_significand({0, 4}, static_cast(-128))); - EXPECT_EQ(bits_set({3}), - normalized_significand({0, 4}, static_cast(-127))); - EXPECT_EQ(bits_set({}), - normalized_significand({22}, static_cast(-127))); - EXPECT_EQ(bits_set({0}), - normalized_significand({21, 22}, static_cast(-127))); -} - -// Returns the 32-bit floating point value created by -// calling setFromSignUnbiasedExponentAndNormalizedSignificand -// on a HexFloat> -float set_from_sign(bool negative, int32_t unbiased_exponent, - uint32_t significand, bool round_denorm_up) { - HexFloat> f(0.f); - f.setFromSignUnbiasedExponentAndNormalizedSignificand( - negative, unbiased_exponent, significand, round_denorm_up); - return f.value().getAsFloat(); -} - -TEST(HexFloatOperationTests, - SetFromSignUnbiasedExponentAndNormalizedSignificand) { - EXPECT_EQ(1.f, set_from_sign(false, 0, 0, false)); - - // Tests insertion of various denormalized numbers with and without round up. - EXPECT_EQ(static_cast(ldexp(1.f, -149)), - set_from_sign(false, -149, 0, false)); - EXPECT_EQ(static_cast(ldexp(1.f, -149)), - set_from_sign(false, -149, 0, true)); - EXPECT_EQ(0.f, set_from_sign(false, -150, 1, false)); - EXPECT_EQ(static_cast(ldexp(1.f, -149)), - set_from_sign(false, -150, 1, true)); - - EXPECT_EQ(ldexp(1.0f, -127), set_from_sign(false, -127, 0, false)); - EXPECT_EQ(ldexp(1.0f, -128), set_from_sign(false, -128, 0, false)); - EXPECT_EQ(float_fractions({0, 1, 2, 5}), - set_from_sign(false, 0, bits_set({0, 1, 4}), false)); - EXPECT_EQ(ldexp(float_fractions({0, 1, 2, 5}), -32), - set_from_sign(false, -32, bits_set({0, 1, 4}), false)); - EXPECT_EQ(ldexp(float_fractions({0, 1, 2, 5}), -128), - set_from_sign(false, -128, bits_set({0, 1, 4}), false)); - - // The negative cases from above. - EXPECT_EQ(-1.f, set_from_sign(true, 0, 0, false)); - EXPECT_EQ(-ldexp(1.0, -127), set_from_sign(true, -127, 0, false)); - EXPECT_EQ(-ldexp(1.0, -128), set_from_sign(true, -128, 0, false)); - EXPECT_EQ(-float_fractions({0, 1, 2, 5}), - set_from_sign(true, 0, bits_set({0, 1, 4}), false)); - EXPECT_EQ(-ldexp(float_fractions({0, 1, 2, 5}), -32), - set_from_sign(true, -32, bits_set({0, 1, 4}), false)); - EXPECT_EQ(-ldexp(float_fractions({0, 1, 2, 5}), -128), - set_from_sign(true, -128, bits_set({0, 1, 4}), false)); -} - -TEST(HexFloatOperationTests, NonRounding) { - // Rounding from 32-bit hex-float to 32-bit hex-float should be trivial, - // except in the denorm case which is a bit more complex. - using HF = HexFloat>; - bool carry_bit = false; - - round_direction rounding[] = {round_direction::kToZero, - round_direction::kToNearestEven, - round_direction::kToPositiveInfinity, - round_direction::kToNegativeInfinity}; - - // Everything fits, so this should be straight-forward - for (round_direction round : rounding) { - EXPECT_EQ(bits_set({}), - HF(0.f).getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ(bits_set({0}), - HF(float_fractions({0, 1})) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ(bits_set({1, 3}), - HF(float_fractions({0, 2, 4})) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ( - bits_set({0, 1, 4}), - HF(static_cast(-ldexp(float_fractions({0, 1, 2, 5}), -128))) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - - EXPECT_EQ(bits_set({0, 1, 4, 22}), - HF(static_cast(float_fractions({0, 1, 2, 5, 23}))) - .getRoundedNormalizedSignificand(round, &carry_bit)); - EXPECT_FALSE(carry_bit); - } -} - -using RD = round_direction; -struct RoundSignificandCase { - float source_float; - std::pair expected_results; - round_direction round; -}; - -using HexFloatRoundTest = ::testing::TestWithParam; - -TEST_P(HexFloatRoundTest, RoundDownToFP16) { - using HF = HexFloat>; - using HF16 = HexFloat>; - - HF input_value(GetParam().source_float); - bool carry_bit = false; - EXPECT_EQ(GetParam().expected_results.first, - input_value.getRoundedNormalizedSignificand(GetParam().round, - &carry_bit)); - EXPECT_EQ(carry_bit, GetParam().expected_results.second); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P(F32ToF16, HexFloatRoundTest, - ::testing::ValuesIn(std::vector( - { - {float_fractions({0}), std::make_pair(half_bits_set({}), false), RD::kToZero}, - {float_fractions({0}), std::make_pair(half_bits_set({}), false), RD::kToNearestEven}, - {float_fractions({0}), std::make_pair(half_bits_set({}), false), RD::kToPositiveInfinity}, - {float_fractions({0}), std::make_pair(half_bits_set({}), false), RD::kToNegativeInfinity}, - {float_fractions({0, 1}), std::make_pair(half_bits_set({0}), false), RD::kToZero}, - - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0}), false), RD::kToZero}, - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0, 9}), false), RD::kToPositiveInfinity}, - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0}), false), RD::kToNegativeInfinity}, - {float_fractions({0, 1, 11}), std::make_pair(half_bits_set({0}), false), RD::kToNearestEven}, - - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 9}), false), RD::kToZero}, - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 8}), false), RD::kToPositiveInfinity}, - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 9}), false), RD::kToNegativeInfinity}, - {float_fractions({0, 1, 10, 11}), std::make_pair(half_bits_set({0, 8}), false), RD::kToNearestEven}, - - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), RD::kToZero}, - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), RD::kToPositiveInfinity}, - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), RD::kToNegativeInfinity}, - {float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), RD::kToNearestEven}, - - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), RD::kToZero}, - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0}), false), RD::kToPositiveInfinity}, - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), RD::kToNegativeInfinity}, - {-float_fractions({0, 1, 11, 12}), std::make_pair(half_bits_set({0, 9}), false), RD::kToNearestEven}, - - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0}), false), RD::kToZero}, - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0, 9}), false), RD::kToPositiveInfinity}, - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0}), false), RD::kToNegativeInfinity}, - {float_fractions({0, 1, 11, 22}), std::make_pair(half_bits_set({0, 9}), false), RD::kToNearestEven}, - - // Carries - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), false), RD::kToZero}, - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({}), true), RD::kToPositiveInfinity}, - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), false), RD::kToNegativeInfinity}, - {float_fractions({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), std::make_pair(half_bits_set({}), true), RD::kToNearestEven}, - - // Cases where original number was denorm. Note: this should have no effect - // the number is pre-normalized. - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -128)), std::make_pair(half_bits_set({0}), false), RD::kToZero}, - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -129)), std::make_pair(half_bits_set({0, 9}), false), RD::kToPositiveInfinity}, - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -131)), std::make_pair(half_bits_set({0}), false), RD::kToNegativeInfinity}, - {static_cast(ldexp(float_fractions({0, 1, 11, 13}), -130)), std::make_pair(half_bits_set({0, 9}), false), RD::kToNearestEven}, - }))); -// clang-format on - -struct UpCastSignificandCase { - uint16_t source_half; - uint32_t expected_result; -}; - -using HexFloatRoundUpSignificandTest = - ::testing::TestWithParam; -TEST_P(HexFloatRoundUpSignificandTest, Widening) { - using HF = HexFloat>; - using HF16 = HexFloat>; - bool carry_bit = false; - - round_direction rounding[] = {round_direction::kToZero, - round_direction::kToNearestEven, - round_direction::kToPositiveInfinity, - round_direction::kToNegativeInfinity}; - - // Everything fits, so everything should just be bit-shifts. - for (round_direction round : rounding) { - carry_bit = false; - HF16 input_value(GetParam().source_half); - EXPECT_EQ( - GetParam().expected_result, - input_value.getRoundedNormalizedSignificand(round, &carry_bit)) - << std::hex << "0x" - << input_value.getRoundedNormalizedSignificand(round, &carry_bit) - << " 0x" << GetParam().expected_result; - EXPECT_FALSE(carry_bit); - } -} - -INSTANTIATE_TEST_SUITE_P( - F16toF32, HexFloatRoundUpSignificandTest, - // 0xFC00 of the source 16-bit hex value cover the sign and the exponent. - // They are ignored for this test. - ::testing::ValuesIn(std::vector({ - {0x3F00, 0x600000}, - {0x0F00, 0x600000}, - {0x0F01, 0x602000}, - {0x0FFF, 0x7FE000}, - }))); - -struct DownCastTest { - float source_float; - uint16_t expected_half; - std::vector directions; -}; - -std::string get_round_text(round_direction direction) { -#define CASE(round_direction) \ - case round_direction: \ - return #round_direction - - switch (direction) { - CASE(round_direction::kToZero); - CASE(round_direction::kToPositiveInfinity); - CASE(round_direction::kToNegativeInfinity); - CASE(round_direction::kToNearestEven); - } -#undef CASE - return ""; -} - -using HexFloatFP32To16Tests = ::testing::TestWithParam; - -TEST_P(HexFloatFP32To16Tests, NarrowingCasts) { - using HF = HexFloat>; - using HF16 = HexFloat>; - HF f(GetParam().source_float); - for (auto round : GetParam().directions) { - HF16 half(0); - f.castTo(half, round); - EXPECT_EQ(GetParam().expected_half, half.value().getAsFloat().get_value()) - << get_round_text(round) << " " << std::hex - << BitwiseCast(GetParam().source_float) - << " cast to: " << half.value().getAsFloat().get_value(); - } -} - -const uint16_t positive_infinity = 0x7C00; -const uint16_t negative_infinity = 0xFC00; - -INSTANTIATE_TEST_SUITE_P( - F32ToF16, HexFloatFP32To16Tests, - ::testing::ValuesIn(std::vector({ - // Exactly representable as half. - {0.f, - 0x0, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {-0.f, - 0x8000, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {1.0f, - 0x3C00, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {-1.0f, - 0xBC00, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - - {float_fractions({0, 1, 10}), - 0x3E01, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {-float_fractions({0, 1, 10}), - 0xBE01, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(ldexp(float_fractions({0, 1, 10}), 3)), - 0x4A01, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(-ldexp(float_fractions({0, 1, 10}), 3)), - 0xCA01, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - - // Underflow - {static_cast(ldexp(1.0f, -25)), - 0x0, - {RD::kToZero, RD::kToNegativeInfinity, RD::kToNearestEven}}, - {static_cast(ldexp(1.0f, -25)), 0x1, {RD::kToPositiveInfinity}}, - {static_cast(-ldexp(1.0f, -25)), - 0x8000, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNearestEven}}, - {static_cast(-ldexp(1.0f, -25)), - 0x8001, - {RD::kToNegativeInfinity}}, - {static_cast(ldexp(1.0f, -24)), - 0x1, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - - // Overflow - {static_cast(ldexp(1.0f, 16)), - positive_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(ldexp(1.0f, 18)), - positive_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(ldexp(1.3f, 16)), - positive_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(-ldexp(1.0f, 16)), - negative_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(-ldexp(1.0f, 18)), - negative_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {static_cast(-ldexp(1.3f, 16)), - negative_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - - // Transfer of Infinities - {std::numeric_limits::infinity(), - positive_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - {-std::numeric_limits::infinity(), - negative_infinity, - {RD::kToZero, RD::kToPositiveInfinity, RD::kToNegativeInfinity, - RD::kToNearestEven}}, - - // Nans are below because we cannot test for equality. - }))); - -struct UpCastCase { - uint16_t source_half; - float expected_float; -}; - -using HexFloatFP16To32Tests = ::testing::TestWithParam; -TEST_P(HexFloatFP16To32Tests, WideningCasts) { - using HF = HexFloat>; - using HF16 = HexFloat>; - HF16 f(GetParam().source_half); - - round_direction rounding[] = {round_direction::kToZero, - round_direction::kToNearestEven, - round_direction::kToPositiveInfinity, - round_direction::kToNegativeInfinity}; - - // Everything fits, so everything should just be bit-shifts. - for (round_direction round : rounding) { - HF flt(0.f); - f.castTo(flt, round); - EXPECT_EQ(GetParam().expected_float, flt.value().getAsFloat()) - << get_round_text(round) << " " << std::hex - << BitwiseCast(GetParam().source_half) - << " cast to: " << flt.value().getAsFloat(); - } -} - -INSTANTIATE_TEST_SUITE_P( - F16ToF32, HexFloatFP16To32Tests, - ::testing::ValuesIn(std::vector({ - {0x0000, 0.f}, - {0x8000, -0.f}, - {0x3C00, 1.0f}, - {0xBC00, -1.0f}, - {0x3F00, float_fractions({0, 1, 2})}, - {0xBF00, -float_fractions({0, 1, 2})}, - {0x3F01, float_fractions({0, 1, 2, 10})}, - {0xBF01, -float_fractions({0, 1, 2, 10})}, - - // denorm - {0x0001, static_cast(ldexp(1.0, -24))}, - {0x0002, static_cast(ldexp(1.0, -23))}, - {0x8001, static_cast(-ldexp(1.0, -24))}, - {0x8011, static_cast(-ldexp(1.0, -20) + -ldexp(1.0, -24))}, - - // inf - {0x7C00, std::numeric_limits::infinity()}, - {0xFC00, -std::numeric_limits::infinity()}, - }))); - -TEST(HexFloatOperationTests, NanTests) { - using HF = HexFloat>; - using HF16 = HexFloat>; - round_direction rounding[] = {round_direction::kToZero, - round_direction::kToNearestEven, - round_direction::kToPositiveInfinity, - round_direction::kToNegativeInfinity}; - - // Everything fits, so everything should just be bit-shifts. - for (round_direction round : rounding) { - HF16 f16(0); - HF f(0.f); - HF(std::numeric_limits::quiet_NaN()).castTo(f16, round); - EXPECT_TRUE(f16.value().isNan()); - HF(std::numeric_limits::signaling_NaN()).castTo(f16, round); - EXPECT_TRUE(f16.value().isNan()); - - HF16(0x7C01).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0x7C11).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0xFC01).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0x7C10).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - HF16(0xFF00).castTo(f, round); - EXPECT_TRUE(f.value().isNan()); - } -} - -// A test case for parsing good and bad HexFloat> literals. -template -struct FloatParseCase { - std::string literal; - bool negate_value; - bool expect_success; - HexFloat> expected_value; -}; - -using ParseNormalFloatTest = ::testing::TestWithParam>; - -TEST_P(ParseNormalFloatTest, Samples) { - std::stringstream input(GetParam().literal); - HexFloat> parsed_value(0.0f); - ParseNormalFloat(input, GetParam().negate_value, parsed_value); - EXPECT_NE(GetParam().expect_success, input.fail()) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - if (GetParam().expect_success) { - EXPECT_THAT(parsed_value.value(), Eq(GetParam().expected_value.value())) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - } -} - -// Returns a FloatParseCase with expected failure. -template -FloatParseCase BadFloatParseCase(std::string literal, bool negate_value, - T expected_value) { - HexFloat> proxy_expected_value(expected_value); - return FloatParseCase{literal, negate_value, false, proxy_expected_value}; -} - -// Returns a FloatParseCase that should successfully parse to a given value. -template -FloatParseCase GoodFloatParseCase(std::string literal, bool negate_value, - T expected_value) { - HexFloat> proxy_expected_value(expected_value); - return FloatParseCase{literal, negate_value, true, proxy_expected_value}; -} - -INSTANTIATE_TEST_SUITE_P( - FloatParse, ParseNormalFloatTest, - ::testing::ValuesIn(std::vector>{ - // Failing cases due to trivially incorrect syntax. - BadFloatParseCase("abc", false, 0.0f), - BadFloatParseCase("abc", true, 0.0f), - - // Valid cases. - GoodFloatParseCase("0", false, 0.0f), - GoodFloatParseCase("0.0", false, 0.0f), - GoodFloatParseCase("-0.0", false, -0.0f), - GoodFloatParseCase("2.0", false, 2.0f), - GoodFloatParseCase("-2.0", false, -2.0f), - GoodFloatParseCase("+2.0", false, 2.0f), - // Cases with negate_value being true. - GoodFloatParseCase("0.0", true, -0.0f), - GoodFloatParseCase("2.0", true, -2.0f), - - // When negate_value is true, we should not accept a - // leading minus or plus. - BadFloatParseCase("-0.0", true, 0.0f), - BadFloatParseCase("-2.0", true, 0.0f), - BadFloatParseCase("+0.0", true, 0.0f), - BadFloatParseCase("+2.0", true, 0.0f), - - // Overflow is an error for 32-bit float parsing. - BadFloatParseCase("1e40", false, FLT_MAX), - BadFloatParseCase("1e40", true, -FLT_MAX), - BadFloatParseCase("-1e40", false, -FLT_MAX), - // We can't have -1e40 and negate_value == true since - // that represents an original case of "--1e40" which - // is invalid. - })); - -using ParseNormalFloat16Test = - ::testing::TestWithParam>; - -TEST_P(ParseNormalFloat16Test, Samples) { - std::stringstream input(GetParam().literal); - HexFloat> parsed_value(0); - ParseNormalFloat(input, GetParam().negate_value, parsed_value); - EXPECT_NE(GetParam().expect_success, input.fail()) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - if (GetParam().expect_success) { - EXPECT_THAT(parsed_value.value(), Eq(GetParam().expected_value.value())) - << " literal: " << GetParam().literal - << " negate: " << GetParam().negate_value; - } -} - -INSTANTIATE_TEST_SUITE_P( - Float16Parse, ParseNormalFloat16Test, - ::testing::ValuesIn(std::vector>{ - // Failing cases due to trivially incorrect syntax. - BadFloatParseCase("abc", false, uint16_t{0}), - BadFloatParseCase("abc", true, uint16_t{0}), - - // Valid cases. - GoodFloatParseCase("0", false, uint16_t{0}), - GoodFloatParseCase("0.0", false, uint16_t{0}), - GoodFloatParseCase("-0.0", false, uint16_t{0x8000}), - GoodFloatParseCase("2.0", false, uint16_t{0x4000}), - GoodFloatParseCase("-2.0", false, uint16_t{0xc000}), - GoodFloatParseCase("+2.0", false, uint16_t{0x4000}), - // Cases with negate_value being true. - GoodFloatParseCase("0.0", true, uint16_t{0x8000}), - GoodFloatParseCase("2.0", true, uint16_t{0xc000}), - - // When negate_value is true, we should not accept a leading minus or - // plus. - BadFloatParseCase("-0.0", true, uint16_t{0}), - BadFloatParseCase("-2.0", true, uint16_t{0}), - BadFloatParseCase("+0.0", true, uint16_t{0}), - BadFloatParseCase("+2.0", true, uint16_t{0}), - })); - -// A test case for detecting infinities. -template -struct OverflowParseCase { - std::string input; - bool expect_success; - T expected_value; -}; - -using FloatProxyParseOverflowFloatTest = - ::testing::TestWithParam>; - -TEST_P(FloatProxyParseOverflowFloatTest, Sample) { - std::istringstream input(GetParam().input); - HexFloat> value(0.0f); - input >> value; - EXPECT_NE(GetParam().expect_success, input.fail()); - if (GetParam().expect_success) { - EXPECT_THAT(value.value().getAsFloat(), GetParam().expected_value); - } -} - -INSTANTIATE_TEST_SUITE_P( - FloatOverflow, FloatProxyParseOverflowFloatTest, - ::testing::ValuesIn(std::vector>({ - {"0", true, 0.0f}, - {"0.0", true, 0.0f}, - {"1.0", true, 1.0f}, - {"1e38", true, 1e38f}, - {"-1e38", true, -1e38f}, - {"1e40", false, FLT_MAX}, - {"-1e40", false, -FLT_MAX}, - {"1e400", false, FLT_MAX}, - {"-1e400", false, -FLT_MAX}, - }))); - -using FloatProxyParseOverflowDoubleTest = - ::testing::TestWithParam>; - -TEST_P(FloatProxyParseOverflowDoubleTest, Sample) { - std::istringstream input(GetParam().input); - HexFloat> value(0.0); - input >> value; - EXPECT_NE(GetParam().expect_success, input.fail()); - if (GetParam().expect_success) { - EXPECT_THAT(value.value().getAsFloat(), Eq(GetParam().expected_value)); - } -} - -INSTANTIATE_TEST_SUITE_P( - DoubleOverflow, FloatProxyParseOverflowDoubleTest, - ::testing::ValuesIn(std::vector>({ - {"0", true, 0.0}, - {"0.0", true, 0.0}, - {"1.0", true, 1.0}, - {"1e38", true, 1e38}, - {"-1e38", true, -1e38}, - {"1e40", true, 1e40}, - {"-1e40", true, -1e40}, - {"1e400", false, DBL_MAX}, - {"-1e400", false, -DBL_MAX}, - }))); - -using FloatProxyParseOverflowFloat16Test = - ::testing::TestWithParam>; - -TEST_P(FloatProxyParseOverflowFloat16Test, Sample) { - std::istringstream input(GetParam().input); - HexFloat> value(0); - input >> value; - EXPECT_NE(GetParam().expect_success, input.fail()) - << " literal: " << GetParam().input; - if (GetParam().expect_success) { - EXPECT_THAT(value.value().data(), Eq(GetParam().expected_value)) - << " literal: " << GetParam().input; - } -} - -INSTANTIATE_TEST_SUITE_P( - Float16Overflow, FloatProxyParseOverflowFloat16Test, - ::testing::ValuesIn(std::vector>({ - {"0", true, uint16_t{0}}, - {"0.0", true, uint16_t{0}}, - {"1.0", true, uint16_t{0x3c00}}, - // Overflow for 16-bit float is an error, and returns max or - // lowest value. - {"1e38", false, uint16_t{0x7bff}}, - {"1e40", false, uint16_t{0x7bff}}, - {"1e400", false, uint16_t{0x7bff}}, - {"-1e38", false, uint16_t{0xfbff}}, - {"-1e40", false, uint16_t{0xfbff}}, - {"-1e400", false, uint16_t{0xfbff}}, - }))); - -TEST(FloatProxy, Max) { - EXPECT_THAT(FloatProxy::max().getAsFloat().get_value(), - Eq(uint16_t{0x7bff})); - EXPECT_THAT(FloatProxy::max().getAsFloat(), - Eq(std::numeric_limits::max())); - EXPECT_THAT(FloatProxy::max().getAsFloat(), - Eq(std::numeric_limits::max())); -} - -TEST(FloatProxy, Lowest) { - EXPECT_THAT(FloatProxy::lowest().getAsFloat().get_value(), - Eq(uint16_t{0xfbff})); - EXPECT_THAT(FloatProxy::lowest().getAsFloat(), - Eq(std::numeric_limits::lowest())); - EXPECT_THAT(FloatProxy::lowest().getAsFloat(), - Eq(std::numeric_limits::lowest())); -} - -// TODO(awoloszyn): Add fp16 tests and HexFloatTraits. -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/immediate_int_test.cpp b/3rdparty/spirv-tools/test/immediate_int_test.cpp deleted file mode 100644 index 393075a4e..000000000 --- a/3rdparty/spirv-tools/test/immediate_int_test.cpp +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/util/bitutils.h" -#include "test/test_fixture.h" - -namespace spvtools { -namespace utils { -namespace { - -using spvtest::Concatenate; -using spvtest::MakeInstruction; -using spvtest::ScopedContext; -using spvtest::TextToBinaryTest; -using ::testing::ElementsAre; -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::StrEq; - -TEST_F(TextToBinaryTest, ImmediateIntOpCode) { - SetText("!0x00FF00FF"); - ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(ScopedContext().context, text.str, - text.length, &binary, &diagnostic)); - EXPECT_EQ(0x00FF00FFu, binary->code[5]); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - } -} - -TEST_F(TextToBinaryTest, ImmediateIntOperand) { - SetText("OpCapability !0x00FF00FF"); - EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(ScopedContext().context, text.str, - text.length, &binary, &diagnostic)); - EXPECT_EQ(0x00FF00FFu, binary->code[6]); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - } -} - -using ImmediateIntTest = TextToBinaryTest; - -TEST_F(ImmediateIntTest, AnyWordInSimpleStatement) { - EXPECT_THAT(CompiledInstructions("!0x00040018 %a %b %123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 3}))); - EXPECT_THAT(CompiledInstructions("!0x00040018 !1 %b %123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 1, 2}))); - EXPECT_THAT(CompiledInstructions("%a = OpTypeMatrix !2 %123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 2}))); - EXPECT_THAT(CompiledInstructions("%a = OpTypeMatrix %b !123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 123}))); - EXPECT_THAT(CompiledInstructions("!0x00040018 %a !2 %123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 2}))); - EXPECT_THAT(CompiledInstructions("!0x00040018 !1 %b !123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 1, 123}))); - EXPECT_THAT(CompiledInstructions("!0x00040018 !1 !2 !123"), - Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 123}))); -} - -TEST_F(ImmediateIntTest, AnyWordAfterEqualsAndOpCode) { - EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 %c 123"), - Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 2, 123}))); - EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b !3 123"), - Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123}))); - EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b %c !123"), - Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123}))); - EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b !3 !123"), - Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123}))); - EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 !3 123"), - Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 3, 123}))); - EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 !3 !123"), - Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 3, 123}))); -} - -TEST_F(ImmediateIntTest, ResultIdInAssignment) { - EXPECT_EQ("!2 not allowed before =.", - CompileFailure("!2 = OpArrayLength %12 %1 123")); - EXPECT_EQ("!2 not allowed before =.", - CompileFailure("!2 = !0x00040044 %12 %1 123")); -} - -TEST_F(ImmediateIntTest, OpCodeInAssignment) { - EXPECT_EQ("Invalid Opcode prefix '!0x00040044'.", - CompileFailure("%2 = !0x00040044 %12 %1 123")); -} - -// Literal integers after ! are handled correctly. -TEST_F(ImmediateIntTest, IntegerFollowingImmediate) { - const SpirvVector original = CompiledInstructions("%1 = OpTypeInt 8 1"); - EXPECT_EQ(original, CompiledInstructions("!0x00040015 1 8 1")); - EXPECT_EQ(original, CompiledInstructions("!0x00040015 !1 8 1")); - - // With !, we can (and can only) accept 32-bit number literals, - // even when we declare the return type is 64-bit. - EXPECT_EQ(Concatenate({ - MakeInstruction(SpvOpTypeInt, {1, 64, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 4294967295}), - }), - CompiledInstructions("%i64 = OpTypeInt 64 0\n" - "!0x0004002b %i64 !2 4294967295")); - // 64-bit integer literal. - EXPECT_EQ("Invalid word following !: 5000000000", - CompileFailure("%2 = OpConstant !1 5000000000")); - EXPECT_EQ("Invalid word following !: 5000000000", - CompileFailure("%i64 = OpTypeInt 64 0\n" - "!0x0005002b %i64 !2 5000000000")); - - // Negative integer. - EXPECT_EQ(CompiledInstructions("%i64 = OpTypeInt 32 1\n" - "%2 = OpConstant %i64 -123"), - CompiledInstructions("%i64 = OpTypeInt 32 1\n" - "!0x0004002b %i64 !2 -123")); - - // TODO(deki): uncomment assertions below and make them pass. - // Hex value(s). - // EXPECT_EQ(CompileSuccessfully("%1 = OpConstant %10 0x12345678"), - // CompileSuccessfully("OpConstant %10 !1 0x12345678", kCAF)); - // EXPECT_EQ( - // CompileSuccessfully("%1 = OpConstant %10 0x12345678 0x87654321"), - // CompileSuccessfully("OpConstant %10 !1 0x12345678 0x87654321", kCAF)); -} - -// Literal floats after ! are handled correctly. -TEST_F(ImmediateIntTest, FloatFollowingImmediate) { - EXPECT_EQ( - CompiledInstructions("%1 = OpTypeFloat 32\n%2 = OpConstant %1 0.123"), - CompiledInstructions("%1 = OpTypeFloat 32\n!0x0004002b %1 !2 0.123")); - EXPECT_EQ( - CompiledInstructions("%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0.5"), - CompiledInstructions("%1 = OpTypeFloat 32\n!0x0004002b %1 !2 -0.5")); - EXPECT_EQ( - CompiledInstructions("%1 = OpTypeFloat 32\n%2 = OpConstant %1 0.123"), - CompiledInstructions("%1 = OpTypeFloat 32\n!0x0004002b %1 %2 0.123")); - EXPECT_EQ( - CompiledInstructions("%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0.5"), - CompiledInstructions("%1 = OpTypeFloat 32\n!0x0004002b %1 %2 -0.5")); - - EXPECT_EQ(Concatenate({ - MakeInstruction(SpvOpTypeInt, {1, 64, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0xb, 0xa}), - MakeInstruction(SpvOpSwitch, - {2, 1234, BitwiseCast(2.5f), 3}), - }), - CompiledInstructions("%i64 = OpTypeInt 64 0\n" - "%big = OpConstant %i64 0xa0000000b\n" - "OpSwitch %big !1234 2.5 %target\n")); -} - -// Literal strings after ! are handled correctly. -TEST_F(ImmediateIntTest, StringFollowingImmediate) { - // Try a variety of strings, including empty and single-character. - for (std::string name : {"", "s", "longish", "really looooooooooooooooong"}) { - const SpirvVector original = - CompiledInstructions("OpMemberName %10 4 \"" + name + "\""); - EXPECT_EQ(original, - CompiledInstructions("OpMemberName %10 !4 \"" + name + "\"")) - << name; - EXPECT_EQ(original, - CompiledInstructions("OpMemberName !1 !4 \"" + name + "\"")) - << name; - const uint16_t wordCount = static_cast(4 + name.size() / 4); - const uint32_t firstWord = spvOpcodeMake(wordCount, SpvOpMemberName); - EXPECT_EQ(original, CompiledInstructions("!" + std::to_string(firstWord) + - " %10 !4 \"" + name + "\"")) - << name; - } -} - -// IDs after ! are handled correctly. -TEST_F(ImmediateIntTest, IdFollowingImmediate) { - EXPECT_EQ(CompileSuccessfully("%123 = OpDecorationGroup"), - CompileSuccessfully("!0x00020049 %123")); - EXPECT_EQ(CompileSuccessfully("%group = OpDecorationGroup"), - CompileSuccessfully("!0x00020049 %group")); -} - -// ! after ! is handled correctly. -TEST_F(ImmediateIntTest, ImmediateFollowingImmediate) { - const SpirvVector original = CompiledInstructions("%a = OpTypeMatrix %b 7"); - EXPECT_EQ(original, CompiledInstructions("%a = OpTypeMatrix !2 !7")); - EXPECT_EQ(original, CompiledInstructions("!0x00040018 %a !2 !7")); -} - -TEST_F(ImmediateIntTest, InvalidStatement) { - EXPECT_THAT(Subvector(CompileSuccessfully("!4 !3 !2 !1"), kFirstInstruction), - ElementsAre(4, 3, 2, 1)); -} - -TEST_F(ImmediateIntTest, InvalidStatementBetweenValidOnes) { - EXPECT_THAT(Subvector(CompileSuccessfully( - "%10 = OpTypeFloat 32 !5 !6 !7 OpEmitVertex"), - kFirstInstruction), - ElementsAre(spvOpcodeMake(3, SpvOpTypeFloat), 1, 32, 5, 6, 7, - spvOpcodeMake(1, SpvOpEmitVertex))); -} - -TEST_F(ImmediateIntTest, NextOpcodeRecognized) { - const SpirvVector original = CompileSuccessfully(R"( -%1 = OpLoad %10 %2 Volatile -%4 = OpCompositeInsert %11 %1 %3 0 1 2 -)"); - const SpirvVector alternate = CompileSuccessfully(R"( -%1 = OpLoad %10 %2 !1 -%4 = OpCompositeInsert %11 %1 %3 0 1 2 -)"); - EXPECT_EQ(original, alternate); -} - -TEST_F(ImmediateIntTest, WrongLengthButNextOpcodeStillRecognized) { - const SpirvVector original = CompileSuccessfully(R"( -%1 = OpLoad %10 %2 Volatile -OpCopyMemorySized %3 %4 %1 -)"); - const SpirvVector alternate = CompileSuccessfully(R"( -!0x0002003D %10 %1 %2 !1 -OpCopyMemorySized %3 %4 %1 -)"); - EXPECT_EQ(0x0002003Du, alternate[kFirstInstruction]); - EXPECT_EQ(Subvector(original, kFirstInstruction + 1), - Subvector(alternate, kFirstInstruction + 1)); -} - -// Like NextOpcodeRecognized, but next statement is in assignment form. -TEST_F(ImmediateIntTest, NextAssignmentRecognized) { - const SpirvVector original = CompileSuccessfully(R"( -%1 = OpLoad %10 %2 None -%4 = OpFunctionCall %10 %3 %123 -)"); - const SpirvVector alternate = CompileSuccessfully(R"( -%1 = OpLoad %10 %2 !0 -%4 = OpFunctionCall %10 %3 %123 -)"); - EXPECT_EQ(original, alternate); -} - -// Two instructions in a row each have ! opcode. -TEST_F(ImmediateIntTest, ConsecutiveImmediateOpcodes) { - const SpirvVector original = CompileSuccessfully(R"( -%1 = OpConstantSampler %10 Clamp 78 Linear -%4 = OpFRem %11 %3 %2 -%5 = OpIsValidEvent %12 %2 -)"); - const SpirvVector alternate = CompileSuccessfully(R"( -!0x0006002D %10 %1 !2 78 !1 -!0x0005008C %11 %4 %3 %2 -%5 = OpIsValidEvent %12 %2 -)"); - EXPECT_EQ(original, alternate); -} - -// ! followed by, eg, an enum or '=' or a random bareword. -TEST_F(ImmediateIntTest, ForbiddenOperands) { - EXPECT_THAT(CompileFailure("OpMemoryModel !0 OpenCL"), HasSubstr("OpenCL")); - EXPECT_THAT(CompileFailure("!1 %0 = !2"), HasSubstr("=")); - EXPECT_THAT(CompileFailure("OpMemoryModel !0 random_bareword"), - HasSubstr("random_bareword")); - // Immediate integers longer than one 32-bit word. - EXPECT_THAT(CompileFailure("!5000000000"), HasSubstr("5000000000")); - EXPECT_THAT(CompileFailure("!999999999999999999"), - HasSubstr("999999999999999999")); - EXPECT_THAT(CompileFailure("!0x00020049 !5000000000"), - HasSubstr("5000000000")); - // Negative numbers. - EXPECT_THAT(CompileFailure("!0x00020049 !-123"), HasSubstr("-123")); -} - -TEST_F(ImmediateIntTest, NotInteger) { - EXPECT_THAT(CompileFailure("!abc"), StrEq("Invalid immediate integer: !abc")); - EXPECT_THAT(CompileFailure("!12.3"), - StrEq("Invalid immediate integer: !12.3")); - EXPECT_THAT(CompileFailure("!12K"), StrEq("Invalid immediate integer: !12K")); -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/libspirv_macros_test.cpp b/3rdparty/spirv-tools/test/libspirv_macros_test.cpp deleted file mode 100644 index bf5add671..000000000 --- a/3rdparty/spirv-tools/test/libspirv_macros_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -TEST(Macros, BitShiftInnerParens) { ASSERT_EQ(65536, SPV_BIT(2 << 3)); } - -TEST(Macros, BitShiftOuterParens) { ASSERT_EQ(15, SPV_BIT(4) - 1); } - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/CMakeLists.txt b/3rdparty/spirv-tools/test/link/CMakeLists.txt deleted file mode 100644 index ee41b9161..000000000 --- a/3rdparty/spirv-tools/test/link/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2017 Pierre Moreau -# -# 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. - - -add_spvtools_unittest(TARGET link - SRCS - binary_version_test.cpp - entry_points_test.cpp - global_values_amount_test.cpp - ids_limit_test.cpp - matching_imports_to_exports_test.cpp - memory_model_test.cpp - partial_linkage_test.cpp - unique_ids_test.cpp - type_match_test.cpp - LIBS SPIRV-Tools-opt SPIRV-Tools-link -) diff --git a/3rdparty/spirv-tools/test/link/binary_version_test.cpp b/3rdparty/spirv-tools/test/link/binary_version_test.cpp deleted file mode 100644 index 0ceeebae2..000000000 --- a/3rdparty/spirv-tools/test/link/binary_version_test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using BinaryVersion = spvtest::LinkerTest; - -TEST_F(BinaryVersion, LinkerChoosesMaxSpirvVersion) { - // clang-format off - spvtest::Binaries binaries = { - { - SpvMagicNumber, - 0x00000300u, - SPV_GENERATOR_CODEPLAY, - 1u, // NOTE: Bound - 0u // NOTE: Schema; reserved - }, - { - SpvMagicNumber, - 0x00000600u, - SPV_GENERATOR_CODEPLAY, - 1u, // NOTE: Bound - 0u // NOTE: Schema; reserved - }, - { - SpvMagicNumber, - 0x00000100u, - SPV_GENERATOR_CODEPLAY, - 1u, // NOTE: Bound - 0u // NOTE: Schema; reserved - } - }; - // clang-format on - spvtest::Binary linked_binary; - - ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), std::string()); - - EXPECT_EQ(0x00000600u, linked_binary[1]); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/entry_points_test.cpp b/3rdparty/spirv-tools/test/link/entry_points_test.cpp deleted file mode 100644 index bac8e02ef..000000000 --- a/3rdparty/spirv-tools/test/link/entry_points_test.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using ::testing::HasSubstr; - -class EntryPoints : public spvtest::LinkerTest {}; - -TEST_F(EntryPoints, SameModelDifferentName) { - const std::string body1 = R"( -OpEntryPoint GLCompute %3 "foo" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -OpFunctionEnd -)"; - const std::string body2 = R"( -OpEntryPoint GLCompute %3 "bar" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -OpFunctionEnd -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), std::string()); -} - -TEST_F(EntryPoints, DifferentModelSameName) { - const std::string body1 = R"( -OpEntryPoint GLCompute %3 "foo" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -OpFunctionEnd -)"; - const std::string body2 = R"( -OpEntryPoint Vertex %3 "foo" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -OpFunctionEnd -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), std::string()); -} - -TEST_F(EntryPoints, SameModelAndName) { - const std::string body1 = R"( -OpEntryPoint GLCompute %3 "foo" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -OpFunctionEnd -)"; - const std::string body2 = R"( -OpEntryPoint GLCompute %3 "foo" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -OpFunctionEnd -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INTERNAL, - AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("The entry point \"foo\", with execution model " - "GLCompute, was already defined.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/global_values_amount_test.cpp b/3rdparty/spirv-tools/test/link/global_values_amount_test.cpp deleted file mode 100644 index 2c4ee1f03..000000000 --- a/3rdparty/spirv-tools/test/link/global_values_amount_test.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using ::testing::HasSubstr; - -class EntryPointsAmountTest : public spvtest::LinkerTest { - public: - EntryPointsAmountTest() { binaries.reserve(0xFFFF); } - - void SetUp() override { - binaries.push_back({SpvMagicNumber, - SpvVersion, - SPV_GENERATOR_CODEPLAY, - 10u, // NOTE: Bound - 0u, // NOTE: Schema; reserved - - 3u << SpvWordCountShift | SpvOpTypeFloat, - 1u, // NOTE: Result ID - 32u, // NOTE: Width - - 4u << SpvWordCountShift | SpvOpTypePointer, - 2u, // NOTE: Result ID - SpvStorageClassInput, - 1u, // NOTE: Type ID - - 2u << SpvWordCountShift | SpvOpTypeVoid, - 3u, // NOTE: Result ID - - 3u << SpvWordCountShift | SpvOpTypeFunction, - 4u, // NOTE: Result ID - 3u, // NOTE: Return type - - 5u << SpvWordCountShift | SpvOpFunction, - 3u, // NOTE: Result type - 5u, // NOTE: Result ID - SpvFunctionControlMaskNone, - 4u, // NOTE: Function type - - 2u << SpvWordCountShift | SpvOpLabel, - 6u, // NOTE: Result ID - - 4u << SpvWordCountShift | SpvOpVariable, - 2u, // NOTE: Type ID - 7u, // NOTE: Result ID - SpvStorageClassFunction, - - 4u << SpvWordCountShift | SpvOpVariable, - 2u, // NOTE: Type ID - 8u, // NOTE: Result ID - SpvStorageClassFunction, - - 4u << SpvWordCountShift | SpvOpVariable, - 2u, // NOTE: Type ID - 9u, // NOTE: Result ID - SpvStorageClassFunction, - - 1u << SpvWordCountShift | SpvOpReturn, - - 1u << SpvWordCountShift | SpvOpFunctionEnd}); - for (size_t i = 0u; i < 2u; ++i) { - spvtest::Binary binary = { - SpvMagicNumber, - SpvVersion, - SPV_GENERATOR_CODEPLAY, - 103u, // NOTE: Bound - 0u, // NOTE: Schema; reserved - - 3u << SpvWordCountShift | SpvOpTypeFloat, - 1u, // NOTE: Result ID - 32u, // NOTE: Width - - 4u << SpvWordCountShift | SpvOpTypePointer, - 2u, // NOTE: Result ID - SpvStorageClassInput, - 1u // NOTE: Type ID - }; - - for (uint32_t j = 0u; j < 0xFFFFu / 2u; ++j) { - binary.push_back(4u << SpvWordCountShift | SpvOpVariable); - binary.push_back(2u); // NOTE: Type ID - binary.push_back(j + 3u); // NOTE: Result ID - binary.push_back(SpvStorageClassInput); - } - binaries.push_back(binary); - } - } - void TearDown() override { binaries.clear(); } - - spvtest::Binaries binaries; -}; - -TEST_F(EntryPointsAmountTest, UnderLimit) { - spvtest::Binary linked_binary; - - EXPECT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), std::string()); -} - -TEST_F(EntryPointsAmountTest, OverLimit) { - binaries.push_back({SpvMagicNumber, - SpvVersion, - SPV_GENERATOR_CODEPLAY, - 5u, // NOTE: Bound - 0u, // NOTE: Schema; reserved - - 3u << SpvWordCountShift | SpvOpTypeFloat, - 1u, // NOTE: Result ID - 32u, // NOTE: Width - - 4u << SpvWordCountShift | SpvOpTypePointer, - 2u, // NOTE: Result ID - SpvStorageClassInput, - 1u, // NOTE: Type ID - - 4u << SpvWordCountShift | SpvOpVariable, - 2u, // NOTE: Type ID - 3u, // NOTE: Result ID - SpvStorageClassInput, - - 4u << SpvWordCountShift | SpvOpVariable, - 2u, // NOTE: Type ID - 4u, // NOTE: Result ID - SpvStorageClassInput}); - - spvtest::Binary linked_binary; - - EXPECT_EQ(SPV_ERROR_INTERNAL, Link(binaries, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("The limit of global values, 65535, was exceeded; " - "65536 global values were found.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/ids_limit_test.cpp b/3rdparty/spirv-tools/test/link/ids_limit_test.cpp deleted file mode 100644 index 6d7815a24..000000000 --- a/3rdparty/spirv-tools/test/link/ids_limit_test.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using ::testing::HasSubstr; -using IdsLimit = spvtest::LinkerTest; - -TEST_F(IdsLimit, UnderLimit) { - spvtest::Binaries binaries = { - { - SpvMagicNumber, SpvVersion, SPV_GENERATOR_CODEPLAY, - 0x2FFFFFu, // NOTE: Bound - 0u, // NOTE: Schema; reserved - }, - { - SpvMagicNumber, SpvVersion, SPV_GENERATOR_CODEPLAY, - 0x100000u, // NOTE: Bound - 0u, // NOTE: Schema; reserved - }}; - spvtest::Binary linked_binary; - - ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), std::string()); - EXPECT_EQ(0x3FFFFEu, linked_binary[3]); -} - -TEST_F(IdsLimit, OverLimit) { - spvtest::Binaries binaries = { - { - SpvMagicNumber, SpvVersion, SPV_GENERATOR_CODEPLAY, - 0x2FFFFFu, // NOTE: Bound - 0u, // NOTE: Schema; reserved - }, - { - SpvMagicNumber, SpvVersion, SPV_GENERATOR_CODEPLAY, - 0x100000u, // NOTE: Bound - 0u, // NOTE: Schema; reserved - }, - { - SpvMagicNumber, SpvVersion, SPV_GENERATOR_CODEPLAY, - 3u, // NOTE: Bound - 0u, // NOTE: Schema; reserved - }}; - - spvtest::Binary linked_binary; - - EXPECT_EQ(SPV_ERROR_INVALID_ID, Link(binaries, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("The limit of IDs, 4194303, was exceeded: 4194304 is " - "the current ID bound.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/linker_fixture.h b/3rdparty/spirv-tools/test/link/linker_fixture.h deleted file mode 100644 index 7bb122354..000000000 --- a/3rdparty/spirv-tools/test/link/linker_fixture.h +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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. - -#ifndef TEST_LINK_LINKER_FIXTURE_H_ -#define TEST_LINK_LINKER_FIXTURE_H_ - -#include -#include -#include - -#include "effcee/effcee.h" -#include "re2/re2.h" -#include "source/spirv_constant.h" -#include "spirv-tools/linker.hpp" -#include "test/unit_spirv.h" - -namespace spvtest { - -using Binary = std::vector; -using Binaries = std::vector; - -class LinkerTest : public ::testing::Test { - public: - LinkerTest() - : context_(SPV_ENV_UNIVERSAL_1_2), - tools_(SPV_ENV_UNIVERSAL_1_2), - assemble_options_(spvtools::SpirvTools::kDefaultAssembleOption), - disassemble_options_(spvtools::SpirvTools::kDefaultDisassembleOption) { - const auto consumer = [this](spv_message_level_t level, const char*, - const spv_position_t& position, - const char* message) { - if (!error_message_.empty()) error_message_ += "\n"; - switch (level) { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - error_message_ += "ERROR"; - break; - case SPV_MSG_WARNING: - error_message_ += "WARNING"; - break; - case SPV_MSG_INFO: - error_message_ += "INFO"; - break; - case SPV_MSG_DEBUG: - error_message_ += "DEBUG"; - break; - } - error_message_ += ": " + std::to_string(position.index) + ": " + message; - }; - context_.SetMessageConsumer(consumer); - tools_.SetMessageConsumer(consumer); - } - - void TearDown() override { error_message_.clear(); } - - // Assembles each of the given strings into SPIR-V binaries before linking - // them together. SPV_ERROR_INVALID_TEXT is returned if the assembling failed - // for any of the input strings, and SPV_ERROR_INVALID_POINTER if - // |linked_binary| is a null pointer. - spv_result_t AssembleAndLink( - const std::vector& bodies, spvtest::Binary* linked_binary, - spvtools::LinkerOptions options = spvtools::LinkerOptions()) { - if (!linked_binary) return SPV_ERROR_INVALID_POINTER; - - spvtest::Binaries binaries(bodies.size()); - for (size_t i = 0u; i < bodies.size(); ++i) - if (!tools_.Assemble(bodies[i], binaries.data() + i, assemble_options_)) - return SPV_ERROR_INVALID_TEXT; - - return spvtools::Link(context_, binaries, linked_binary, options); - } - - // Assembles and links a vector of SPIR-V bodies based on the |templateBody|. - // Template arguments to be replaced are written as {a,b,...}. - // SPV_ERROR_INVALID_TEXT is returned if the assembling failed for any of the - // resulting bodies (or errors in the template), and SPV_ERROR_INVALID_POINTER - // if |linked_binary| is a null pointer. - spv_result_t ExpandAndLink( - const std::string& templateBody, spvtest::Binary* linked_binary, - spvtools::LinkerOptions options = spvtools::LinkerOptions()) { - if (!linked_binary) return SPV_ERROR_INVALID_POINTER; - - // Find out how many template arguments there are, we assume they all have - // the same number. We'll error later if they don't. - re2::StringPiece temp(templateBody); - re2::StringPiece x; - int cnt = 0; - if (!RE2::FindAndConsume(&temp, "{")) return SPV_ERROR_INVALID_TEXT; - while (RE2::FindAndConsume(&temp, "([,}])", &x) && x[0] == ',') cnt++; - cnt++; - if (cnt <= 1) return SPV_ERROR_INVALID_TEXT; - - // Construct a regex for a single common strip and template expansion. - std::string regex("([^{]*){"); - for (int i = 0; i < cnt; i++) regex += (i > 0) ? ",([^,]*)" : "([^,]*)"; - regex += "}"; - RE2 pattern(regex); - - // Prepare the RE2::Args for processing. - re2::StringPiece common; - std::vector variants(cnt); - std::vector args(cnt + 1); - args[0] = RE2::Arg(&common); - std::vector pargs(cnt + 1); - pargs[0] = &args[0]; - for (int i = 0; i < cnt; i++) { - args[i + 1] = RE2::Arg(&variants[i]); - pargs[i + 1] = &args[i + 1]; - } - - // Reset and construct the bodies bit by bit. - std::vector bodies(cnt); - re2::StringPiece temp2(templateBody); - while (RE2::ConsumeN(&temp2, pattern, pargs.data(), cnt + 1)) { - for (int i = 0; i < cnt; i++) { - bodies[i].append(common.begin(), common.end()); - bodies[i].append(variants[i].begin(), variants[i].end()); - } - } - RE2::Consume(&temp2, "([^{]*)", &common); - for (int i = 0; i < cnt; i++) - bodies[i].append(common.begin(), common.end()); - - // Run through the assemble and link stages of the process. - return AssembleAndLink(bodies, linked_binary, options); - } - - // Expand the |templateBody| and link the results as with ExpandAndLink, - // then disassemble and test that the result matches the |expected|. - void ExpandAndCheck( - const std::string& templateBody, const std::string& expected, - const spvtools::LinkerOptions options = spvtools::LinkerOptions()) { - spvtest::Binary linked_binary; - spv_result_t res = ExpandAndLink(templateBody, &linked_binary, options); - EXPECT_EQ(SPV_SUCCESS, res) << GetErrorMessage() << "\nExpanded from:\n" - << templateBody; - if (res == SPV_SUCCESS) { - std::string result; - EXPECT_TRUE( - tools_.Disassemble(linked_binary, &result, disassemble_options_)) - << GetErrorMessage(); - EXPECT_EQ(expected, result); - } - } - - // An alternative to ExpandAndCheck, which uses the |templateBody| as the - // match pattern for the disassembled linked result. - void ExpandAndMatch( - const std::string& templateBody, - const spvtools::LinkerOptions options = spvtools::LinkerOptions()) { - spvtest::Binary linked_binary; - spv_result_t res = ExpandAndLink(templateBody, &linked_binary, options); - EXPECT_EQ(SPV_SUCCESS, res) << GetErrorMessage() << "\nExpanded from:\n" - << templateBody; - if (res == SPV_SUCCESS) { - std::string result; - EXPECT_TRUE( - tools_.Disassemble(linked_binary, &result, disassemble_options_)) - << GetErrorMessage(); - auto match_res = effcee::Match(result, templateBody); - EXPECT_EQ(effcee::Result::Status::Ok, match_res.status()) - << match_res.message() << "\nExpanded from:\n" - << templateBody << "\nChecking result:\n" - << result; - } - } - - // Links the given SPIR-V binaries together; SPV_ERROR_INVALID_POINTER is - // returned if |linked_binary| is a null pointer. - spv_result_t Link( - const spvtest::Binaries& binaries, spvtest::Binary* linked_binary, - spvtools::LinkerOptions options = spvtools::LinkerOptions()) { - if (!linked_binary) return SPV_ERROR_INVALID_POINTER; - return spvtools::Link(context_, binaries, linked_binary, options); - } - - // Disassembles |binary| and outputs the result in |text|. If |text| is a - // null pointer, SPV_ERROR_INVALID_POINTER is returned. - spv_result_t Disassemble(const spvtest::Binary& binary, std::string* text) { - if (!text) return SPV_ERROR_INVALID_POINTER; - return tools_.Disassemble(binary, text, disassemble_options_) - ? SPV_SUCCESS - : SPV_ERROR_INVALID_BINARY; - } - - // Sets the options for the assembler. - void SetAssembleOptions(uint32_t assemble_options) { - assemble_options_ = assemble_options; - } - - // Sets the options used by the disassembler. - void SetDisassembleOptions(uint32_t disassemble_options) { - disassemble_options_ = disassemble_options; - } - - // Returns the accumulated error messages for the test. - std::string GetErrorMessage() const { return error_message_; } - - private: - spvtools::Context context_; - spvtools::SpirvTools - tools_; // An instance for calling SPIRV-Tools functionalities. - uint32_t assemble_options_; - uint32_t disassemble_options_; - std::string error_message_; -}; - -} // namespace spvtest - -#endif // TEST_LINK_LINKER_FIXTURE_H_ diff --git a/3rdparty/spirv-tools/test/link/matching_imports_to_exports_test.cpp b/3rdparty/spirv-tools/test/link/matching_imports_to_exports_test.cpp deleted file mode 100644 index 59e62d51b..000000000 --- a/3rdparty/spirv-tools/test/link/matching_imports_to_exports_test.cpp +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using ::testing::HasSubstr; -using MatchingImportsToExports = spvtest::LinkerTest; - -TEST_F(MatchingImportsToExports, Default) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -%3 = OpVariable %2 Input -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 42 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)) - << GetErrorMessage(); - - const std::string expected_res = - R"(OpModuleProcessed "Linked by SPIR-V Tools Linker" -%1 = OpTypeFloat 32 -%2 = OpVariable %1 Input -%3 = OpConstant %1 42 -%4 = OpVariable %1 Uniform %3 -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -TEST_F(MatchingImportsToExports, NotALibraryExtraExports) { - const std::string body = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body}, &linked_binary)) - << GetErrorMessage(); - - const std::string expected_res = - R"(OpModuleProcessed "Linked by SPIR-V Tools Linker" -%1 = OpTypeFloat 32 -%2 = OpVariable %1 Uniform -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -TEST_F(MatchingImportsToExports, LibraryExtraExports) { - const std::string body = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -)"; - - spvtest::Binary linked_binary; - LinkerOptions options; - options.SetCreateLibrary(true); - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body}, &linked_binary, options)) - << GetErrorMessage(); - - const std::string expected_res = R"(OpCapability Linkage -OpModuleProcessed "Linked by SPIR-V Tools Linker" -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -TEST_F(MatchingImportsToExports, UnresolvedImports) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -)"; - const std::string body2 = R"()"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("Unresolved external reference to \"foo\".")); -} - -TEST_F(MatchingImportsToExports, TypeMismatch) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -%3 = OpVariable %2 Input -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 42 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - AssembleAndLink({body1, body2}, &linked_binary)) - << GetErrorMessage(); - EXPECT_THAT( - GetErrorMessage(), - HasSubstr("Type mismatch on symbol \"foo\" between imported " - "variable/function %1 and exported variable/function %4")); -} - -TEST_F(MatchingImportsToExports, MultipleDefinitions) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -%3 = OpVariable %2 Input -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 42 -%1 = OpVariable %2 Uniform %3 -)"; - const std::string body3 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 -1 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - AssembleAndLink({body1, body2, body3}, &linked_binary)) - << GetErrorMessage(); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("Too many external references, 2, were found " - "for \"foo\".")); -} - -TEST_F(MatchingImportsToExports, SameNameDifferentTypes) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -%3 = OpVariable %2 Input -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 42 -%1 = OpVariable %2 Uniform %3 -)"; - const std::string body3 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 12 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - AssembleAndLink({body1, body2, body3}, &linked_binary)) - << GetErrorMessage(); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("Too many external references, 2, were found " - "for \"foo\".")); -} - -TEST_F(MatchingImportsToExports, DecorationMismatch) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -OpDecorate %2 Constant -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -%3 = OpVariable %2 Input -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 42 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - AssembleAndLink({body1, body2}, &linked_binary)) - << GetErrorMessage(); - EXPECT_THAT( - GetErrorMessage(), - HasSubstr("Type mismatch on symbol \"foo\" between imported " - "variable/function %1 and exported variable/function %4")); -} - -TEST_F(MatchingImportsToExports, - FuncParamAttrDifferButStillMatchExportToImport) { - const std::string body1 = R"( -OpCapability Kernel -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -OpDecorate %2 FuncParamAttr Zext -%3 = OpTypeVoid -%4 = OpTypeInt 32 0 -%5 = OpTypeFunction %3 %4 -%1 = OpFunction %3 None %5 -%2 = OpFunctionParameter %4 -OpFunctionEnd -)"; - const std::string body2 = R"( -OpCapability Kernel -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -OpDecorate %2 FuncParamAttr Sext -%3 = OpTypeVoid -%4 = OpTypeInt 32 0 -%5 = OpTypeFunction %3 %4 -%1 = OpFunction %3 None %5 -%2 = OpFunctionParameter %4 -%6 = OpLabel -OpReturn -OpFunctionEnd -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)) - << GetErrorMessage(); - - const std::string expected_res = R"(OpCapability Kernel -OpModuleProcessed "Linked by SPIR-V Tools Linker" -OpDecorate %1 FuncParamAttr Sext -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypeFunction %2 %3 -%5 = OpFunction %2 None %4 -%1 = OpFunctionParameter %3 -%6 = OpLabel -OpReturn -OpFunctionEnd -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -TEST_F(MatchingImportsToExports, FunctionCtrl) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%4 = OpTypeFloat 32 -%5 = OpVariable %4 Uniform -%1 = OpFunction %2 None %3 -OpFunctionEnd -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%1 = OpFunction %2 Inline %3 -%4 = OpLabel -OpReturn -OpFunctionEnd -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)) - << GetErrorMessage(); - - const std::string expected_res = - R"(OpModuleProcessed "Linked by SPIR-V Tools Linker" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpVariable %3 Uniform -%5 = OpFunction %1 Inline %2 -%6 = OpLabel -OpReturn -OpFunctionEnd -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -TEST_F(MatchingImportsToExports, UseExportedFuncParamAttr) { - const std::string body1 = R"( -OpCapability Kernel -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -OpDecorate %2 FuncParamAttr Zext -%2 = OpDecorationGroup -OpGroupDecorate %2 %3 %4 -%5 = OpTypeVoid -%6 = OpTypeInt 32 0 -%7 = OpTypeFunction %5 %6 -%1 = OpFunction %5 None %7 -%3 = OpFunctionParameter %6 -OpFunctionEnd -%8 = OpFunction %5 None %7 -%4 = OpFunctionParameter %6 -OpFunctionEnd -)"; - const std::string body2 = R"( -OpCapability Kernel -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Export -OpDecorate %2 FuncParamAttr Sext -%3 = OpTypeVoid -%4 = OpTypeInt 32 0 -%5 = OpTypeFunction %3 %4 -%1 = OpFunction %3 None %5 -%2 = OpFunctionParameter %4 -%6 = OpLabel -OpReturn -OpFunctionEnd -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)) - << GetErrorMessage(); - - const std::string expected_res = R"(OpCapability Kernel -OpModuleProcessed "Linked by SPIR-V Tools Linker" -OpDecorate %1 FuncParamAttr Zext -%1 = OpDecorationGroup -OpGroupDecorate %1 %2 -OpDecorate %3 FuncParamAttr Sext -%4 = OpTypeVoid -%5 = OpTypeInt 32 0 -%6 = OpTypeFunction %4 %5 -%7 = OpFunction %4 None %6 -%2 = OpFunctionParameter %5 -OpFunctionEnd -%8 = OpFunction %4 None %6 -%3 = OpFunctionParameter %5 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/memory_model_test.cpp b/3rdparty/spirv-tools/test/link/memory_model_test.cpp deleted file mode 100644 index 2add5046c..000000000 --- a/3rdparty/spirv-tools/test/link/memory_model_test.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using ::testing::HasSubstr; -using MemoryModel = spvtest::LinkerTest; - -TEST_F(MemoryModel, Default) { - const std::string body1 = R"( -OpMemoryModel Logical Simple -)"; - const std::string body2 = R"( -OpMemoryModel Logical Simple -)"; - - spvtest::Binary linked_binary; - ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), std::string()); - - EXPECT_EQ(SpvAddressingModelLogical, linked_binary[6]); - EXPECT_EQ(SpvMemoryModelSimple, linked_binary[7]); -} - -TEST_F(MemoryModel, AddressingMismatch) { - const std::string body1 = R"( -OpMemoryModel Logical Simple -)"; - const std::string body2 = R"( -OpMemoryModel Physical32 Simple -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INTERNAL, - AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT( - GetErrorMessage(), - HasSubstr("Conflicting addressing models: Logical vs Physical32.")); -} - -TEST_F(MemoryModel, MemoryMismatch) { - const std::string body1 = R"( -OpMemoryModel Logical Simple -)"; - const std::string body2 = R"( -OpMemoryModel Logical GLSL450 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INTERNAL, - AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("Conflicting memory models: Simple vs GLSL450.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/partial_linkage_test.cpp b/3rdparty/spirv-tools/test/link/partial_linkage_test.cpp deleted file mode 100644 index c43b06e55..000000000 --- a/3rdparty/spirv-tools/test/link/partial_linkage_test.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2018 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using ::testing::HasSubstr; -using PartialLinkage = spvtest::LinkerTest; - -TEST_F(PartialLinkage, Allowed) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -OpDecorate %2 LinkageAttributes "bar" Import -%3 = OpTypeFloat 32 -%1 = OpVariable %3 Uniform -%2 = OpVariable %3 Uniform -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "bar" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 3.1415 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - LinkerOptions linker_options; - linker_options.SetAllowPartialLinkage(true); - ASSERT_EQ(SPV_SUCCESS, - AssembleAndLink({body1, body2}, &linked_binary, linker_options)); - - const std::string expected_res = R"(OpCapability Linkage -OpModuleProcessed "Linked by SPIR-V Tools Linker" -OpDecorate %1 LinkageAttributes "foo" Import -%2 = OpTypeFloat 32 -%1 = OpVariable %2 Uniform -%3 = OpConstant %2 3.1415 -%4 = OpVariable %2 Uniform %3 -)"; - std::string res_body; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body)) - << GetErrorMessage(); - EXPECT_EQ(expected_res, res_body); -} - -TEST_F(PartialLinkage, Disallowed) { - const std::string body1 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "foo" Import -OpDecorate %2 LinkageAttributes "bar" Import -%3 = OpTypeFloat 32 -%1 = OpVariable %3 Uniform -%2 = OpVariable %3 Uniform -)"; - const std::string body2 = R"( -OpCapability Linkage -OpDecorate %1 LinkageAttributes "bar" Export -%2 = OpTypeFloat 32 -%3 = OpConstant %2 3.1415 -%1 = OpVariable %2 Uniform %3 -)"; - - spvtest::Binary linked_binary; - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - AssembleAndLink({body1, body2}, &linked_binary)); - EXPECT_THAT(GetErrorMessage(), - HasSubstr("Unresolved external reference to \"foo\".")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/type_match_test.cpp b/3rdparty/spirv-tools/test/link/type_match_test.cpp deleted file mode 100644 index dae70c163..000000000 --- a/3rdparty/spirv-tools/test/link/type_match_test.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2019 The Khronos Group 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using TypeMatch = spvtest::LinkerTest; - -// Basic types -#define PartInt(D, N) D(N) " = OpTypeInt 32 0" -#define PartFloat(D, N) D(N) " = OpTypeFloat 32" -#define PartOpaque(D, N) D(N) " = OpTypeOpaque \"bar\"" -#define PartSampler(D, N) D(N) " = OpTypeSampler" -#define PartEvent(D, N) D(N) " = OpTypeEvent" -#define PartDeviceEvent(D, N) D(N) " = OpTypeDeviceEvent" -#define PartReserveId(D, N) D(N) " = OpTypeReserveId" -#define PartQueue(D, N) D(N) " = OpTypeQueue" -#define PartPipe(D, N) D(N) " = OpTypePipe ReadWrite" -#define PartPipeStorage(D, N) D(N) " = OpTypePipeStorage" -#define PartNamedBarrier(D, N) D(N) " = OpTypeNamedBarrier" - -// Compound types -#define PartVector(DR, DA, N, T) DR(N) " = OpTypeVector " DA(T) " 3" -#define PartMatrix(DR, DA, N, T) DR(N) " = OpTypeMatrix " DA(T) " 4" -#define PartImage(DR, DA, N, T) \ - DR(N) " = OpTypeImage " DA(T) " 2D 0 0 0 0 Rgba32f" -#define PartSampledImage(DR, DA, N, T) DR(N) " = OpTypeSampledImage " DA(T) -#define PartArray(DR, DA, N, T) DR(N) " = OpTypeArray " DA(T) " " DA(const) -#define PartRuntimeArray(DR, DA, N, T) DR(N) " = OpTypeRuntimeArray " DA(T) -#define PartStruct(DR, DA, N, T) DR(N) " = OpTypeStruct " DA(T) " " DA(T) -#define PartPointer(DR, DA, N, T) DR(N) " = OpTypePointer Workgroup " DA(T) -#define PartFunction(DR, DA, N, T) DR(N) " = OpTypeFunction " DA(T) " " DA(T) - -#define CheckDecoRes(S) "[[" #S ":%\\w+]]" -#define CheckDecoArg(S) "[[" #S "]]" -#define InstDeco(S) "%" #S - -#define MatchPart1(F, N) \ - "; CHECK: " Part##F(CheckDecoRes, N) "\n" Part##F(InstDeco, N) "\n" -#define MatchPart2(F, N, T) \ - "; CHECK: " Part##F(CheckDecoRes, CheckDecoArg, N, T) "\n" Part##F( \ - InstDeco, InstDeco, N, T) "\n" - -#define MatchF(N, CODE) \ - TEST_F(TypeMatch, N) { \ - const std::string base = \ - "OpCapability Linkage\n" \ - "OpCapability NamedBarrier\n" \ - "OpCapability PipeStorage\n" \ - "OpCapability Pipes\n" \ - "OpCapability DeviceEnqueue\n" \ - "OpCapability Kernel\n" \ - "OpCapability Shader\n" \ - "OpCapability Addresses\n" \ - "OpDecorate %var LinkageAttributes \"foo\" " \ - "{Import,Export}\n" \ - "; CHECK: [[baseint:%\\w+]] = OpTypeInt 32 1\n" \ - "%baseint = OpTypeInt 32 1\n" \ - "; CHECK: [[const:%\\w+]] = OpConstant [[baseint]] 3\n" \ - "%const = OpConstant %baseint 3\n" CODE \ - "; CHECK: OpVariable [[type]] Uniform\n" \ - "%var = OpVariable %type Uniform"; \ - ExpandAndMatch(base); \ - } - -#define Match1(T) MatchF(Type##T, MatchPart1(T, type)) -#define Match2(T, A) \ - MatchF(T##OfType##A, MatchPart1(A, a) MatchPart2(T, type, a)) -#define Match3(T, A, B) \ - MatchF(T##Of##A##Of##B, \ - MatchPart1(B, b) MatchPart2(A, a, b) MatchPart2(T, type, a)) - -// clang-format off -// Basic types -Match1(Int) -Match1(Float) -Match1(Opaque) -Match1(Sampler) -Match1(Event) -Match1(DeviceEvent) -Match1(ReserveId) -Match1(Queue) -Match1(Pipe) -Match1(PipeStorage) -Match1(NamedBarrier) - -// Simpler (restricted) compound types -Match2(Vector, Float) -Match3(Matrix, Vector, Float) -Match2(Image, Float) - -// Unrestricted compound types -#define MatchCompounds1(A) \ - Match2(RuntimeArray, A) \ - Match2(Struct, A) \ - Match2(Pointer, A) \ - Match2(Function, A) \ - Match2(Array, A) -#define MatchCompounds2(A, B) \ - Match3(RuntimeArray, A, B) \ - Match3(Struct, A, B) \ - Match3(Pointer, A, B) \ - Match3(Function, A, B) \ - Match3(Array, A, B) - -MatchCompounds1(Float) -MatchCompounds2(Array, Float) -MatchCompounds2(RuntimeArray, Float) -MatchCompounds2(Struct, Float) -MatchCompounds2(Pointer, Float) -MatchCompounds2(Function, Float) -// clang-format on - -// ForwardPointer tests, which don't fit into the previous mold -#define MatchFpF(N, CODE) \ - MatchF(N, \ - "; CHECK: OpTypeForwardPointer [[type:%\\w+]] Workgroup\n" \ - "OpTypeForwardPointer %type Workgroup\n" CODE \ - "; CHECK: [[type]] = OpTypePointer Workgroup [[realtype]]\n" \ - "%type = OpTypePointer Workgroup %realtype\n") -#define MatchFp1(T) MatchFpF(ForwardPointerOf##T, MatchPart1(T, realtype)) -#define MatchFp2(T, A) \ - MatchFpF(ForwardPointerOf##T, MatchPart1(A, a) MatchPart2(T, realtype, a)) - - // clang-format off -MatchFp1(Float) -MatchFp2(Array, Float) -MatchFp2(RuntimeArray, Float) -MatchFp2(Struct, Float) -MatchFp2(Function, Float) -// clang-format on - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/link/unique_ids_test.cpp b/3rdparty/spirv-tools/test/link/unique_ids_test.cpp deleted file mode 100644 index 55c70ea67..000000000 --- a/3rdparty/spirv-tools/test/link/unique_ids_test.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "test/link/linker_fixture.h" - -namespace spvtools { -namespace { - -using UniqueIds = spvtest::LinkerTest; - -TEST_F(UniqueIds, UniquelyMerged) { - std::vector bodies(2); - bodies[0] = - // clang-format off - "OpCapability Shader\n" - "%1 = OpExtInstImport \"GLSL.std.450\"\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\"\n" - "OpSource ESSL 310\n" - "OpName %main \"main\"\n" - "OpName %f_ \"f(\"\n" - "OpName %gv1 \"gv1\"\n" - "OpName %gv2 \"gv2\"\n" - "OpName %lv1 \"lv1\"\n" - "OpName %lv2 \"lv2\"\n" - "OpName %lv1_0 \"lv1\"\n" - "%void = OpTypeVoid\n" - "%10 = OpTypeFunction %void\n" - "%float = OpTypeFloat 32\n" - "%12 = OpTypeFunction %float\n" - "%_ptr_Private_float = OpTypePointer Private %float\n" - "%gv1 = OpVariable %_ptr_Private_float Private\n" - "%float_10 = OpConstant %float 10\n" - "%gv2 = OpVariable %_ptr_Private_float Private\n" - "%float_100 = OpConstant %float 100\n" - "%_ptr_Function_float = OpTypePointer Function %float\n" - "%main = OpFunction %void None %10\n" - "%17 = OpLabel\n" - "%lv1_0 = OpVariable %_ptr_Function_float Function\n" - "OpStore %gv1 %float_10\n" - "OpStore %gv2 %float_100\n" - "%18 = OpLoad %float %gv1\n" - "%19 = OpLoad %float %gv2\n" - "%20 = OpFSub %float %18 %19\n" - "OpStore %lv1_0 %20\n" - "OpReturn\n" - "OpFunctionEnd\n" - "%f_ = OpFunction %float None %12\n" - "%21 = OpLabel\n" - "%lv1 = OpVariable %_ptr_Function_float Function\n" - "%lv2 = OpVariable %_ptr_Function_float Function\n" - "%22 = OpLoad %float %gv1\n" - "%23 = OpLoad %float %gv2\n" - "%24 = OpFAdd %float %22 %23\n" - "OpStore %lv1 %24\n" - "%25 = OpLoad %float %gv1\n" - "%26 = OpLoad %float %gv2\n" - "%27 = OpFMul %float %25 %26\n" - "OpStore %lv2 %27\n" - "%28 = OpLoad %float %lv1\n" - "%29 = OpLoad %float %lv2\n" - "%30 = OpFDiv %float %28 %29\n" - "OpReturnValue %30\n" - "OpFunctionEnd\n"; - // clang-format on - bodies[1] = - // clang-format off - "OpCapability Shader\n" - "%1 = OpExtInstImport \"GLSL.std.450\"\n" - "OpMemoryModel Logical GLSL450\n" - "OpSource ESSL 310\n" - "OpName %main \"main2\"\n" - "OpName %f_ \"f(\"\n" - "OpName %gv1 \"gv12\"\n" - "OpName %gv2 \"gv22\"\n" - "OpName %lv1 \"lv12\"\n" - "OpName %lv2 \"lv22\"\n" - "OpName %lv1_0 \"lv12\"\n" - "%void = OpTypeVoid\n" - "%10 = OpTypeFunction %void\n" - "%float = OpTypeFloat 32\n" - "%12 = OpTypeFunction %float\n" - "%_ptr_Private_float = OpTypePointer Private %float\n" - "%gv1 = OpVariable %_ptr_Private_float Private\n" - "%float_10 = OpConstant %float 10\n" - "%gv2 = OpVariable %_ptr_Private_float Private\n" - "%float_100 = OpConstant %float 100\n" - "%_ptr_Function_float = OpTypePointer Function %float\n" - "%main = OpFunction %void None %10\n" - "%17 = OpLabel\n" - "%lv1_0 = OpVariable %_ptr_Function_float Function\n" - "OpStore %gv1 %float_10\n" - "OpStore %gv2 %float_100\n" - "%18 = OpLoad %float %gv1\n" - "%19 = OpLoad %float %gv2\n" - "%20 = OpFSub %float %18 %19\n" - "OpStore %lv1_0 %20\n" - "OpReturn\n" - "OpFunctionEnd\n" - "%f_ = OpFunction %float None %12\n" - "%21 = OpLabel\n" - "%lv1 = OpVariable %_ptr_Function_float Function\n" - "%lv2 = OpVariable %_ptr_Function_float Function\n" - "%22 = OpLoad %float %gv1\n" - "%23 = OpLoad %float %gv2\n" - "%24 = OpFAdd %float %22 %23\n" - "OpStore %lv1 %24\n" - "%25 = OpLoad %float %gv1\n" - "%26 = OpLoad %float %gv2\n" - "%27 = OpFMul %float %25 %26\n" - "OpStore %lv2 %27\n" - "%28 = OpLoad %float %lv1\n" - "%29 = OpLoad %float %lv2\n" - "%30 = OpFDiv %float %28 %29\n" - "OpReturnValue %30\n" - "OpFunctionEnd\n"; - // clang-format on - - spvtest::Binary linked_binary; - LinkerOptions options; - options.SetVerifyIds(true); - spv_result_t res = AssembleAndLink(bodies, &linked_binary, options); - EXPECT_EQ(SPV_SUCCESS, res); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/log_test.cpp b/3rdparty/spirv-tools/test/log_test.cpp deleted file mode 100644 index ec66aa1ec..000000000 --- a/3rdparty/spirv-tools/test/log_test.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// 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 "source/opt/log.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace spvtools { -namespace { - -using ::testing::MatchesRegex; - -TEST(Log, Unimplemented) { - int invocation = 0; - auto consumer = [&invocation](spv_message_level_t level, const char* source, - const spv_position_t&, const char* message) { - ++invocation; - EXPECT_EQ(SPV_MSG_INTERNAL_ERROR, level); - EXPECT_THAT(source, MatchesRegex(".*log_test.cpp$")); - EXPECT_STREQ("unimplemented: the-ultimite-feature", message); - }; - - SPIRV_UNIMPLEMENTED(consumer, "the-ultimite-feature"); - EXPECT_EQ(1, invocation); -} - -TEST(Log, Unreachable) { - int invocation = 0; - auto consumer = [&invocation](spv_message_level_t level, const char* source, - const spv_position_t&, const char* message) { - ++invocation; - EXPECT_EQ(SPV_MSG_INTERNAL_ERROR, level); - EXPECT_THAT(source, MatchesRegex(".*log_test.cpp$")); - EXPECT_STREQ("unreachable", message); - }; - - SPIRV_UNREACHABLE(consumer); - EXPECT_EQ(1, invocation); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/name_mapper_test.cpp b/3rdparty/spirv-tools/test/name_mapper_test.cpp deleted file mode 100644 index 00fbeed68..000000000 --- a/3rdparty/spirv-tools/test/name_mapper_test.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// 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 "gmock/gmock.h" -#include "source/name_mapper.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::ScopedContext; -using ::testing::Eq; - -TEST(TrivialNameTest, Samples) { - auto mapper = GetTrivialNameMapper(); - EXPECT_EQ(mapper(1), "1"); - EXPECT_EQ(mapper(1999), "1999"); - EXPECT_EQ(mapper(1024), "1024"); -} - -// A test case for the name mappers that actually look at an assembled module. -struct NameIdCase { - std::string assembly; // Input assembly text - uint32_t id; - std::string expected_name; -}; - -using FriendlyNameTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(FriendlyNameTest, SingleMapping) { - ScopedContext context(SPV_ENV_UNIVERSAL_1_1); - auto words = CompileSuccessfully(GetParam().assembly, SPV_ENV_UNIVERSAL_1_1); - auto friendly_mapper = - FriendlyNameMapper(context.context, words.data(), words.size()); - NameMapper mapper = friendly_mapper.GetNameMapper(); - EXPECT_THAT(mapper(GetParam().id), Eq(GetParam().expected_name)) - << GetParam().assembly << std::endl - << " for id " << GetParam().id; -} - -INSTANTIATE_TEST_SUITE_P(ScalarType, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeVoid", 1, "void"}, - {"%1 = OpTypeBool", 1, "bool"}, - {"%1 = OpTypeInt 8 0", 1, "uchar"}, - {"%1 = OpTypeInt 8 1", 1, "char"}, - {"%1 = OpTypeInt 16 0", 1, "ushort"}, - {"%1 = OpTypeInt 16 1", 1, "short"}, - {"%1 = OpTypeInt 32 0", 1, "uint"}, - {"%1 = OpTypeInt 32 1", 1, "int"}, - {"%1 = OpTypeInt 64 0", 1, "ulong"}, - {"%1 = OpTypeInt 64 1", 1, "long"}, - {"%1 = OpTypeInt 1 0", 1, "u1"}, - {"%1 = OpTypeInt 1 1", 1, "i1"}, - {"%1 = OpTypeInt 33 0", 1, "u33"}, - {"%1 = OpTypeInt 33 1", 1, "i33"}, - - {"%1 = OpTypeFloat 16", 1, "half"}, - {"%1 = OpTypeFloat 32", 1, "float"}, - {"%1 = OpTypeFloat 64", 1, "double"}, - {"%1 = OpTypeFloat 10", 1, "fp10"}, - {"%1 = OpTypeFloat 55", 1, "fp55"}, - })); - -INSTANTIATE_TEST_SUITE_P( - VectorType, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeBool %2 = OpTypeVector %1 1", 2, "v1bool"}, - {"%1 = OpTypeBool %2 = OpTypeVector %1 2", 2, "v2bool"}, - {"%1 = OpTypeBool %2 = OpTypeVector %1 3", 2, "v3bool"}, - {"%1 = OpTypeBool %2 = OpTypeVector %1 4", 2, "v4bool"}, - - {"%1 = OpTypeInt 8 0 %2 = OpTypeVector %1 2", 2, "v2uchar"}, - {"%1 = OpTypeInt 16 1 %2 = OpTypeVector %1 3", 2, "v3short"}, - {"%1 = OpTypeInt 32 0 %2 = OpTypeVector %1 4", 2, "v4uint"}, - {"%1 = OpTypeInt 64 1 %2 = OpTypeVector %1 3", 2, "v3long"}, - {"%1 = OpTypeInt 20 0 %2 = OpTypeVector %1 4", 2, "v4u20"}, - {"%1 = OpTypeInt 21 1 %2 = OpTypeVector %1 3", 2, "v3i21"}, - - {"%1 = OpTypeFloat 32 %2 = OpTypeVector %1 2", 2, "v2float"}, - // OpName overrides the element name. - {"OpName %1 \"time\" %1 = OpTypeFloat 32 %2 = OpTypeVector %1 2", 2, - "v2time"}, - })); - -INSTANTIATE_TEST_SUITE_P( - MatrixType, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeBool %2 = OpTypeVector %1 2 %3 = OpTypeMatrix %2 2", 3, - "mat2v2bool"}, - {"%1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 = OpTypeMatrix %2 3", 3, - "mat3v2float"}, - {"%1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 = OpTypeMatrix %2 4", 3, - "mat4v2float"}, - {"OpName %1 \"time\" %1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 = " - "OpTypeMatrix %2 4", - 3, "mat4v2time"}, - {"OpName %2 \"lat_long\" %1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 " - "= OpTypeMatrix %2 4", - 3, "mat4lat_long"}, - })); - -INSTANTIATE_TEST_SUITE_P( - OpName, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"OpName %1 \"abcdefg\"", 1, "abcdefg"}, - {"OpName %1 \"Hello world!\"", 1, "Hello_world_"}, - {"OpName %1 \"0123456789\"", 1, "0123456789"}, - {"OpName %1 \"_\"", 1, "_"}, - // An empty string is not valid for SPIR-V assembly IDs. - {"OpName %1 \"\"", 1, "_"}, - // Test uniqueness when presented with things mapping to "_" - {"OpName %1 \"\" OpName %2 \"\"", 1, "_"}, - {"OpName %1 \"\" OpName %2 \"\"", 2, "__0"}, - {"OpName %1 \"\" OpName %2 \"\" OpName %3 \"_\"", 3, "__1"}, - // Test uniqueness of names that are forced to be - // numbers. - {"OpName %1 \"2\" OpName %2 \"2\"", 1, "2"}, - {"OpName %1 \"2\" OpName %2 \"2\"", 2, "2_0"}, - // Test uniqueness in the face of forward references - // for Ids that don't already have friendly names. - // In particular, the first OpDecorate assigns the name, and - // the second one can't override it. - {"OpDecorate %1 Volatile OpDecorate %1 Restrict", 1, "1"}, - // But a forced name can override the name that - // would have been assigned via the OpDecorate - // forward reference. - {"OpName %1 \"mememe\" OpDecorate %1 Volatile OpDecorate %1 Restrict", - 1, "mememe"}, - // OpName can override other inferences. We assume valid instruction - // ordering, where OpName precedes type definitions. - {"OpName %1 \"myfloat\" %1 = OpTypeFloat 32", 1, "myfloat"}, - })); - -INSTANTIATE_TEST_SUITE_P( - UniquenessHeuristic, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeVoid %2 = OpTypeVoid %3 = OpTypeVoid", 1, "void"}, - {"%1 = OpTypeVoid %2 = OpTypeVoid %3 = OpTypeVoid", 2, "void_0"}, - {"%1 = OpTypeVoid %2 = OpTypeVoid %3 = OpTypeVoid", 3, "void_1"}, - })); - -INSTANTIATE_TEST_SUITE_P(Arrays, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"OpName %2 \"FortyTwo\" %1 = OpTypeFloat 32 " - "%2 = OpConstant %1 42 %3 = OpTypeArray %1 %2", - 3, "_arr_float_FortyTwo"}, - {"%1 = OpTypeInt 32 0 " - "%2 = OpTypeRuntimeArray %1", - 2, "_runtimearr_uint"}, - })); - -INSTANTIATE_TEST_SUITE_P(Structs, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeBool " - "%2 = OpTypeStruct %1 %1 %1", - 2, "_struct_2"}, - {"%1 = OpTypeBool " - "%2 = OpTypeStruct %1 %1 %1 " - "%3 = OpTypeStruct %2 %2", - 3, "_struct_3"}, - })); - -INSTANTIATE_TEST_SUITE_P( - Pointer, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeFloat 32 %2 = OpTypePointer Workgroup %1", 2, - "_ptr_Workgroup_float"}, - {"%1 = OpTypeBool %2 = OpTypePointer Private %1", 2, - "_ptr_Private_bool"}, - // OpTypeForwardPointer doesn't force generation of the name for its - // target type. - {"%1 = OpTypeBool OpTypeForwardPointer %2 Private %2 = OpTypePointer " - "Private %1", - 2, "_ptr_Private_bool"}, - })); - -INSTANTIATE_TEST_SUITE_P(ExoticTypes, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeEvent", 1, "Event"}, - {"%1 = OpTypeDeviceEvent", 1, "DeviceEvent"}, - {"%1 = OpTypeReserveId", 1, "ReserveId"}, - {"%1 = OpTypeQueue", 1, "Queue"}, - {"%1 = OpTypeOpaque \"hello world!\"", 1, - "Opaque_hello_world_"}, - {"%1 = OpTypePipe ReadOnly", 1, "PipeReadOnly"}, - {"%1 = OpTypePipe WriteOnly", 1, "PipeWriteOnly"}, - {"%1 = OpTypePipe ReadWrite", 1, "PipeReadWrite"}, - {"%1 = OpTypePipeStorage", 1, "PipeStorage"}, - {"%1 = OpTypeNamedBarrier", 1, "NamedBarrier"}, - })); - -// Makes a test case for a BuiltIn variable declaration. -NameIdCase BuiltInCase(std::string assembly_name, std::string expected) { - return NameIdCase{std::string("OpDecorate %1 BuiltIn ") + assembly_name + - " %1 = OpVariable %2 Input", - 1, expected}; -} - -// Makes a test case for a BuiltIn variable declaration. In this overload, -// the expected result is the same as the assembly name. -NameIdCase BuiltInCase(std::string assembly_name) { - return BuiltInCase(assembly_name, assembly_name); -} - -// Makes a test case for a BuiltIn variable declaration. In this overload, -// the expected result is the same as the assembly name, but with a "gl_" -// prefix. -NameIdCase BuiltInGLCase(std::string assembly_name) { - return BuiltInCase(assembly_name, std::string("gl_") + assembly_name); -} - -INSTANTIATE_TEST_SUITE_P( - BuiltIns, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - BuiltInGLCase("Position"), - BuiltInGLCase("PointSize"), - BuiltInGLCase("ClipDistance"), - BuiltInGLCase("CullDistance"), - BuiltInCase("VertexId", "gl_VertexID"), - BuiltInCase("InstanceId", "gl_InstanceID"), - BuiltInCase("PrimitiveId", "gl_PrimitiveID"), - BuiltInCase("InvocationId", "gl_InvocationID"), - BuiltInGLCase("Layer"), - BuiltInGLCase("ViewportIndex"), - BuiltInGLCase("TessLevelOuter"), - BuiltInGLCase("TessLevelInner"), - BuiltInGLCase("TessCoord"), - BuiltInGLCase("PatchVertices"), - BuiltInGLCase("FragCoord"), - BuiltInGLCase("PointCoord"), - BuiltInGLCase("FrontFacing"), - BuiltInCase("SampleId", "gl_SampleID"), - BuiltInGLCase("SamplePosition"), - BuiltInGLCase("SampleMask"), - BuiltInGLCase("FragDepth"), - BuiltInGLCase("HelperInvocation"), - BuiltInCase("NumWorkgroups", "gl_NumWorkGroups"), - BuiltInCase("WorkgroupSize", "gl_WorkGroupSize"), - BuiltInCase("WorkgroupId", "gl_WorkGroupID"), - BuiltInCase("LocalInvocationId", "gl_LocalInvocationID"), - BuiltInCase("GlobalInvocationId", "gl_GlobalInvocationID"), - BuiltInGLCase("LocalInvocationIndex"), - BuiltInCase("WorkDim"), - BuiltInCase("GlobalSize"), - BuiltInCase("EnqueuedWorkgroupSize"), - BuiltInCase("GlobalOffset"), - BuiltInCase("GlobalLinearId"), - BuiltInCase("SubgroupSize"), - BuiltInCase("SubgroupMaxSize"), - BuiltInCase("NumSubgroups"), - BuiltInCase("NumEnqueuedSubgroups"), - BuiltInCase("SubgroupId"), - BuiltInCase("SubgroupLocalInvocationId"), - BuiltInGLCase("VertexIndex"), - BuiltInGLCase("InstanceIndex"), - BuiltInCase("SubgroupEqMaskKHR"), - BuiltInCase("SubgroupGeMaskKHR"), - BuiltInCase("SubgroupGtMaskKHR"), - BuiltInCase("SubgroupLeMaskKHR"), - BuiltInCase("SubgroupLtMaskKHR"), - })); - -INSTANTIATE_TEST_SUITE_P(DebugNameOverridesBuiltin, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"OpName %1 \"foo\" OpDecorate %1 BuiltIn WorkDim " - "%1 = OpVariable %2 Input", - 1, "foo"}})); - -INSTANTIATE_TEST_SUITE_P( - SimpleIntegralConstants, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 0", 2, "uint_0"}, - {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 1", 2, "uint_1"}, - {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 2", 2, "uint_2"}, - {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 9", 2, "uint_9"}, - {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 42", 2, "uint_42"}, - {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 0", 2, "int_0"}, - {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 1", 2, "int_1"}, - {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 2", 2, "int_2"}, - {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 9", 2, "int_9"}, - {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 42", 2, "int_42"}, - {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 -42", 2, "int_n42"}, - // Exotic bit widths - {"%1 = OpTypeInt 33 0 %2 = OpConstant %1 0", 2, "u33_0"}, - {"%1 = OpTypeInt 33 1 %2 = OpConstant %1 10", 2, "i33_10"}, - {"%1 = OpTypeInt 33 1 %2 = OpConstant %1 -19", 2, "i33_n19"}, - })); - -INSTANTIATE_TEST_SUITE_P( - SimpleFloatConstants, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ff4p+16", 2, - "half_0x1_ff4p_16"}, - {"%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.d2cp-10", 2, - "half_n0x1_d2cpn10"}, - // 32-bit floats - {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -3.125", 2, "float_n3_125"}, - {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128", 2, - "float_0x1_8p_128"}, // NaN - {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128", 2, - "float_n0x1_0002p_128"}, // NaN - {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128", 2, - "float_0x1p_128"}, // Inf - {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128", 2, - "float_n0x1p_128"}, // -Inf - // 64-bit floats - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -3.125", 2, "double_n3_125"}, - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.ffffffffffffap-1023", 2, - "double_0x1_ffffffffffffapn1023"}, // small normal - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.ffffffffffffap-1023", 2, - "double_n0x1_ffffffffffffapn1023"}, - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024", 2, - "double_0x1_8p_1024"}, // NaN - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0002p+1024", 2, - "double_n0x1_0002p_1024"}, // NaN - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024", 2, - "double_0x1p_1024"}, // Inf - {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024", 2, - "double_n0x1p_1024"}, // -Inf - })); - -INSTANTIATE_TEST_SUITE_P( - BooleanConstants, FriendlyNameTest, - ::testing::ValuesIn(std::vector{ - {"%1 = OpTypeBool\n%2 = OpConstantTrue %1", 2, "true"}, - {"%1 = OpTypeBool\n%2 = OpConstantFalse %1", 2, "false"}, - })); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/named_id_test.cpp b/3rdparty/spirv-tools/test/named_id_test.cpp deleted file mode 100644 index 01f09be5d..000000000 --- a/3rdparty/spirv-tools/test/named_id_test.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using NamedIdTest = spvtest::TextToBinaryTest; - -TEST_F(NamedIdTest, Default) { - const std::string input = R"( - OpCapability Shader - OpMemoryModel Logical Simple - OpEntryPoint Vertex %main "foo" - %void = OpTypeVoid -%fnMain = OpTypeFunction %void - %main = OpFunction %void None %fnMain -%lbMain = OpLabel - OpReturn - OpFunctionEnd)"; - const std::string output = - "OpCapability Shader\n" - "OpMemoryModel Logical Simple\n" - "OpEntryPoint Vertex %1 \"foo\"\n" - "%2 = OpTypeVoid\n" - "%3 = OpTypeFunction %2\n" - "%1 = OpFunction %2 None %3\n" - "%4 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n"; - EXPECT_EQ(output, EncodeAndDecodeSuccessfully(input)); -} - -struct IdCheckCase { - std::string id; - bool valid; -}; - -using IdValidityTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(IdValidityTest, IdTypes) { - const std::string input = GetParam().id + " = OpTypeVoid"; - SetText(input); - if (GetParam().valid) { - CompileSuccessfully(input); - } else { - CompileFailure(input); - } -} - -INSTANTIATE_TEST_SUITE_P( - ValidAndInvalidIds, IdValidityTest, - ::testing::ValuesIn(std::vector( - {{"%1", true}, {"%2abc", true}, {"%3Def", true}, - {"%4GHI", true}, {"%5_j_k", true}, {"%6J_M", true}, - {"%n", true}, {"%O", true}, {"%p7", true}, - {"%Q8", true}, {"%R_S", true}, {"%T_10_U", true}, - {"%V_11", true}, {"%W_X_13", true}, {"%_A", true}, - {"%_", true}, {"%__", true}, {"%A_", true}, - {"%_A_", true}, - - {"%@", false}, {"%!", false}, {"%ABC!", false}, - {"%__A__@", false}, {"%%", false}, {"%-", false}, - {"%foo_@_bar", false}, {"%", false}, - - {"5", false}, {"32", false}, {"foo", false}, - {"a%bar", false}}))); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opcode_make_test.cpp b/3rdparty/spirv-tools/test/opcode_make_test.cpp deleted file mode 100644 index 6481ef326..000000000 --- a/3rdparty/spirv-tools/test/opcode_make_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -// A sampling of word counts. Covers extreme points well, and all bit -// positions, and some combinations of bit positions. -const uint16_t kSampleWordCounts[] = { - 0, 1, 2, 3, 4, 8, 16, 32, 64, 127, 128, - 256, 511, 512, 1024, 2048, 4096, 8192, 16384, 32768, 0xfffe, 0xffff}; - -// A sampling of opcode values. Covers the lower values well, a few samples -// around the number of core instructions (as of this writing), and some -// higher values. -const uint16_t kSampleOpcodes[] = {0, 1, 2, 3, 4, 100, - 300, 305, 1023, 0xfffe, 0xffff}; - -TEST(OpcodeMake, Samples) { - for (auto wordCount : kSampleWordCounts) { - for (auto opcode : kSampleOpcodes) { - uint32_t word = 0; - word |= uint32_t(opcode); - word |= uint32_t(wordCount) << 16; - EXPECT_EQ(word, spvOpcodeMake(wordCount, SpvOp(opcode))); - } - } -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opcode_require_capabilities_test.cpp b/3rdparty/spirv-tools/test/opcode_require_capabilities_test.cpp deleted file mode 100644 index 07e86f87b..000000000 --- a/3rdparty/spirv-tools/test/opcode_require_capabilities_test.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -#include "source/enum_set.h" - -namespace spvtools { -namespace { - -using spvtest::ElementsIn; - -// Capabilities required by an Opcode. -struct ExpectedOpCodeCapabilities { - SpvOp opcode; - CapabilitySet capabilities; -}; - -using OpcodeTableCapabilitiesTest = - ::testing::TestWithParam; - -TEST_P(OpcodeTableCapabilitiesTest, TableEntryMatchesExpectedCapabilities) { - auto env = SPV_ENV_UNIVERSAL_1_1; - spv_opcode_table opcodeTable; - ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable, env)); - spv_opcode_desc entry; - ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableValueLookup(env, opcodeTable, - GetParam().opcode, &entry)); - EXPECT_EQ( - ElementsIn(GetParam().capabilities), - ElementsIn(CapabilitySet(entry->numCapabilities, entry->capabilities))); -} - -INSTANTIATE_TEST_SUITE_P( - TableRowTest, OpcodeTableCapabilitiesTest, - // Spot-check a few opcodes. - ::testing::Values( - ExpectedOpCodeCapabilities{ - SpvOpImageQuerySize, - CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}}, - ExpectedOpCodeCapabilities{ - SpvOpImageQuerySizeLod, - CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}}, - ExpectedOpCodeCapabilities{ - SpvOpImageQueryLevels, - CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}}, - ExpectedOpCodeCapabilities{ - SpvOpImageQuerySamples, - CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}}, - ExpectedOpCodeCapabilities{SpvOpImageSparseSampleImplicitLod, - CapabilitySet{SpvCapabilitySparseResidency}}, - ExpectedOpCodeCapabilities{SpvOpCopyMemorySized, - CapabilitySet{SpvCapabilityAddresses}}, - ExpectedOpCodeCapabilities{SpvOpArrayLength, - CapabilitySet{SpvCapabilityShader}}, - ExpectedOpCodeCapabilities{SpvOpFunction, CapabilitySet()}, - ExpectedOpCodeCapabilities{SpvOpConvertFToS, CapabilitySet()}, - ExpectedOpCodeCapabilities{SpvOpEmitStreamVertex, - CapabilitySet{SpvCapabilityGeometryStreams}}, - ExpectedOpCodeCapabilities{SpvOpTypeNamedBarrier, - CapabilitySet{SpvCapabilityNamedBarrier}}, - ExpectedOpCodeCapabilities{ - SpvOpGetKernelMaxNumSubgroups, - CapabilitySet{SpvCapabilitySubgroupDispatch}})); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opcode_split_test.cpp b/3rdparty/spirv-tools/test/opcode_split_test.cpp deleted file mode 100644 index 43fedb385..000000000 --- a/3rdparty/spirv-tools/test/opcode_split_test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -TEST(OpcodeSplit, Default) { - uint32_t word = spvOpcodeMake(42, (SpvOp)23); - uint16_t wordCount = 0; - uint16_t opcode; - spvOpcodeSplit(word, &wordCount, &opcode); - ASSERT_EQ(42, wordCount); - ASSERT_EQ(23, opcode); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opcode_table_get_test.cpp b/3rdparty/spirv-tools/test/opcode_table_get_test.cpp deleted file mode 100644 index 5ebd6c113..000000000 --- a/3rdparty/spirv-tools/test/opcode_table_get_test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using GetTargetOpcodeTableGetTest = ::testing::TestWithParam; -using ::testing::ValuesIn; - -TEST_P(GetTargetOpcodeTableGetTest, SanityCheck) { - spv_opcode_table table; - ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&table, GetParam())); - ASSERT_NE(0u, table->count); - ASSERT_NE(nullptr, table->entries); -} - -TEST_P(GetTargetOpcodeTableGetTest, InvalidPointerTable) { - ASSERT_EQ(SPV_ERROR_INVALID_POINTER, spvOpcodeTableGet(nullptr, GetParam())); -} - -INSTANTIATE_TEST_SUITE_P(OpcodeTableGet, GetTargetOpcodeTableGetTest, - ValuesIn(spvtest::AllTargetEnvironments())); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/operand-class-test-coverage.csv b/3rdparty/spirv-tools/test/operand-class-test-coverage.csv deleted file mode 100644 index 116fdfeee..000000000 --- a/3rdparty/spirv-tools/test/operand-class-test-coverage.csv +++ /dev/null @@ -1,43 +0,0 @@ -Operand class,Example instruction,Notes,example unit test,negative-enum coverage location -" OperandNone,",UNUSED,not in grammar,,not enum -" OperandId,",many,ID,too many to count,not enum -" OperandOptionalId,","Source, Variable",OPTIONAL_ID,OpSourceAcceptsOptionalFileId,not enum -" OperandOptionalImage,",ImageFetch,,ImageOperandsTest,"TEST_F(ImageOperandsTest, WrongOperand)" -" OperandVariableIds,",ExtInst,,,not enum -" OperandOptionalLiteral,",ExecutionMode,,AnyExecutionMode,not enum -" OperandOptionalLiteralString,",Source,,OpSourceAcceptsOptionalSourceText,not enum -" OperandVariableLiterals,",Decorate,,OpDecorateSimpleTest,not enum -" OperandVariableIdLiteral,",GroupMemberDecorate,,GroupMemberDecorate*,not enum -" OperandVariableLiteralId,",Switch,,Switch*,not enum -" OperandLiteralNumber,","Source, Switch, ...",,Switch*,not enum -" OperandLiteralString,",SourceContinued,,OpSourceContinued,not enum -" OperandSource,",Source,,OpSource,not enum -" OperandExecutionModel,",EntryPoint,,OpEntryPointTest,"TEST_F(OpEntryPointTest, WrongModel)" -" OperandAddressing,",OpMemoryModel,,OpMemoryModelTest,"TEST_F(OpMemoryModelTest, WrongModel)" -" OperandMemory,",OpMemoryModel,,OpMemoryModelTest,"TEST_F(OpMemoryModelTest, WrongModel)" -" OperandExecutionMode,",OpExecutionMode,,OpExecutionModeTest,"TEST_F(OpExecutionModeTest, WrongMode)" -" OperandStorage,","TypePointer, TypeForwardPointer, Variable",,StorageClassTest,"TEST_F(OpTypeForwardPointerTest, WrongClass)" -" OperandDimensionality,",TypeImage,,DimTest/AnyDim,"TEST_F(DimTest, WrongDim)" -" OperandSamplerAddressingMode,",ConstantSampler,,SamplerAddressingModeTest,"TEST_F(SamplerAddressingModeTest, WrongMode)" -" OperandSamplerFilterMode,",ConstantSampler,,AnySamplerFilterMode,"TEST_F(SamplerFilterModeTest, WrongMode)" -" OperandSamplerImageFormat,",TypeImage,SAMPLER_IMAGE_FORMAT,ImageFormatTest,"TEST_F(ImageFormatTest, WrongFormat)" -" OperandImageChannelOrder,",UNUSED,returned as result value only,, -" OperandImageChannelDataType,",UNUSED,returned as result value only,, -" OperandImageOperands,",UNUSED,used to make a spec section,,see OperandOptionalImage -" OperandFPFastMath,",OpDecorate,,CombinedFPFastMathMask,"TEST_F(OpDecorateEnumTest, WrongFPFastMathMode)" -" OperandFPRoundingMode,",OpDecorate,,,"TEST_F(OpDecorateEnumTest, WrongFPRoundingMode)" -" OperandLinkageType,",OpDecorate,,OpDecorateLinkageTest,"TEST_F(OpDecorateLinkageTest, WrongType)" -" OperandAccessQualifier,",OpTypePipe,,AnyAccessQualifier,"TEST_F(OpTypePipeTest, WrongAccessQualifier)" -" OperandFuncParamAttr,",OpDecorate,,TextToBinaryDecorateFuncParamAttr,"TEST_F(OpDecorateEnumTest, WrongFuncParamAttr)" -" OperandDecoration,",OpDecorate,,AnyAccessQualifier,"TEST_F(OpTypePipeTest, WrongAccessQualifier)" -" OperandBuiltIn,",OpDecorate,,TextToBinaryDecorateBultIn,"TEST_F(OpDecorateEnumTest, WrongBuiltIn)" -" OperandSelect,",SelectionMerge,,TextToBinarySelectionMerge,"TEST_F(OpSelectionMergeTest, WrongSelectionControl)" -" OperandLoop,",LoopMerge,,CombinedLoopControlMask,"TEST_F(OpLoopMergeTest, WrongLoopControl)" -" OperandFunction,",Function,,AnySingleFunctionControlMask,"TEST_F(OpFunctionControlTest, WrongFunctionControl)" -" OperandMemorySemantics,",OpMemoryBarrier,"it's an ID, not in grammar",OpMemoryBarrier*,not enum -" OperandMemoryAccess,",UNUSED,"should be on opstore, but hacked in opcode.cpp",,not enum -" OperandScope,",MemoryBarrier,"it's an ID, not in grammar",OpMemoryBarrier*,not enum -" OperandGroupOperation,",GroupIAdd,,GroupOperationTest,"TEST_F(GroupOperationTest, WrongGroupOperation)" -" OperandKernelEnqueueFlags,",OpEnqueueKernel,"it's an ID, not in grammar",should not have one,not enum -" OperandKernelProfilingInfo,",OpCaptureEventProfilingInfo,"it's an ID, not in grammar",should not have one,not enum -" OperandCapability,",Capability,,OpCapabilityTest,"TEST_F(TextToBinaryCapability, BadInvalidCapability)" diff --git a/3rdparty/spirv-tools/test/operand_capabilities_test.cpp b/3rdparty/spirv-tools/test/operand_capabilities_test.cpp deleted file mode 100644 index 11955970e..000000000 --- a/3rdparty/spirv-tools/test/operand_capabilities_test.cpp +++ /dev/null @@ -1,748 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Test capability dependencies for enums. - -#include -#include - -#include "gmock/gmock.h" -#include "source/enum_set.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::ElementsIn; -using ::testing::Combine; -using ::testing::Eq; -using ::testing::TestWithParam; -using ::testing::Values; -using ::testing::ValuesIn; - -// A test case for mapping an enum to a capability mask. -struct EnumCapabilityCase { - spv_operand_type_t type; - uint32_t value; - CapabilitySet expected_capabilities; -}; - -// Test fixture for testing EnumCapabilityCases. -using EnumCapabilityTest = - TestWithParam>; - -TEST_P(EnumCapabilityTest, Sample) { - const auto env = std::get<0>(GetParam()); - const auto context = spvContextCreate(env); - const AssemblyGrammar grammar(context); - spv_operand_desc entry; - - ASSERT_EQ(SPV_SUCCESS, - grammar.lookupOperand(std::get<1>(GetParam()).type, - std::get<1>(GetParam()).value, &entry)); - const auto cap_set = grammar.filterCapsAgainstTargetEnv( - entry->capabilities, entry->numCapabilities); - - EXPECT_THAT(ElementsIn(cap_set), - Eq(ElementsIn(std::get<1>(GetParam()).expected_capabilities))) - << " capability value " << std::get<1>(GetParam()).value; - spvContextDestroy(context); -} - -#define CASE0(TYPE, VALUE) \ - { \ - SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), {} \ - } -#define CASE1(TYPE, VALUE, CAP) \ - { \ - SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \ - SpvCapability##CAP \ - } \ - } -#define CASE2(TYPE, VALUE, CAP1, CAP2) \ - { \ - SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \ - SpvCapability##CAP1, SpvCapability##CAP2 \ - } \ - } -#define CASE3(TYPE, VALUE, CAP1, CAP2, CAP3) \ - { \ - SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \ - SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3 \ - } \ - } -#define CASE5(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5) \ - { \ - SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \ - SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3, \ - SpvCapability##CAP4, SpvCapability##CAP5 \ - } \ - } - -// See SPIR-V Section 3.3 Execution Model -INSTANTIATE_TEST_SUITE_P( - ExecutionModel, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(EXECUTION_MODEL, ExecutionModelVertex, Shader), - CASE1(EXECUTION_MODEL, ExecutionModelTessellationControl, - Tessellation), - CASE1(EXECUTION_MODEL, ExecutionModelTessellationEvaluation, - Tessellation), - CASE1(EXECUTION_MODEL, ExecutionModelGeometry, Geometry), - CASE1(EXECUTION_MODEL, ExecutionModelFragment, Shader), - CASE1(EXECUTION_MODEL, ExecutionModelGLCompute, Shader), - CASE1(EXECUTION_MODEL, ExecutionModelKernel, Kernel), - }))); - -// See SPIR-V Section 3.4 Addressing Model -INSTANTIATE_TEST_SUITE_P( - AddressingModel, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(ADDRESSING_MODEL, AddressingModelLogical), - CASE1(ADDRESSING_MODEL, AddressingModelPhysical32, Addresses), - CASE1(ADDRESSING_MODEL, AddressingModelPhysical64, Addresses), - }))); - -// See SPIR-V Section 3.5 Memory Model -INSTANTIATE_TEST_SUITE_P( - MemoryModel, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(MEMORY_MODEL, MemoryModelSimple, Shader), - CASE1(MEMORY_MODEL, MemoryModelGLSL450, Shader), - CASE1(MEMORY_MODEL, MemoryModelOpenCL, Kernel), - }))); - -// See SPIR-V Section 3.6 Execution Mode -INSTANTIATE_TEST_SUITE_P( - ExecutionMode, EnumCapabilityTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(EXECUTION_MODE, ExecutionModeInvocations, Geometry), - CASE1(EXECUTION_MODE, ExecutionModeSpacingEqual, Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeSpacingFractionalEven, - Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeSpacingFractionalOdd, - Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeVertexOrderCw, Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeVertexOrderCcw, Tessellation), - CASE1(EXECUTION_MODE, ExecutionModePixelCenterInteger, Shader), - CASE1(EXECUTION_MODE, ExecutionModeOriginUpperLeft, Shader), - CASE1(EXECUTION_MODE, ExecutionModeOriginLowerLeft, Shader), - CASE1(EXECUTION_MODE, ExecutionModeEarlyFragmentTests, Shader), - CASE1(EXECUTION_MODE, ExecutionModePointMode, Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeXfb, TransformFeedback), - CASE1(EXECUTION_MODE, ExecutionModeDepthReplacing, Shader), - CASE1(EXECUTION_MODE, ExecutionModeDepthGreater, Shader), - CASE1(EXECUTION_MODE, ExecutionModeDepthLess, Shader), - CASE1(EXECUTION_MODE, ExecutionModeDepthUnchanged, Shader), - CASE0(EXECUTION_MODE, ExecutionModeLocalSize), - CASE1(EXECUTION_MODE, ExecutionModeLocalSizeHint, Kernel), - CASE1(EXECUTION_MODE, ExecutionModeInputPoints, Geometry), - CASE1(EXECUTION_MODE, ExecutionModeInputLines, Geometry), - CASE1(EXECUTION_MODE, ExecutionModeInputLinesAdjacency, Geometry), - CASE2(EXECUTION_MODE, ExecutionModeTriangles, Geometry, - Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeInputTrianglesAdjacency, - Geometry), - CASE1(EXECUTION_MODE, ExecutionModeQuads, Tessellation), - CASE1(EXECUTION_MODE, ExecutionModeIsolines, Tessellation), - CASE3(EXECUTION_MODE, ExecutionModeOutputVertices, Geometry, - Tessellation, MeshShadingNV), - CASE2(EXECUTION_MODE, ExecutionModeOutputPoints, Geometry, - MeshShadingNV), - CASE1(EXECUTION_MODE, ExecutionModeOutputLineStrip, Geometry), - CASE1(EXECUTION_MODE, ExecutionModeOutputTriangleStrip, Geometry), - CASE1(EXECUTION_MODE, ExecutionModeVecTypeHint, Kernel), - CASE1(EXECUTION_MODE, ExecutionModeContractionOff, Kernel), - }))); - -INSTANTIATE_TEST_SUITE_P( - ExecutionModeV11, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(EXECUTION_MODE, ExecutionModeInitializer, Kernel), - CASE1(EXECUTION_MODE, ExecutionModeFinalizer, Kernel), - CASE1(EXECUTION_MODE, ExecutionModeSubgroupSize, - SubgroupDispatch), - CASE1(EXECUTION_MODE, ExecutionModeSubgroupsPerWorkgroup, - SubgroupDispatch)}))); - -// See SPIR-V Section 3.7 Storage Class -INSTANTIATE_TEST_SUITE_P( - StorageClass, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(STORAGE_CLASS, StorageClassUniformConstant), - CASE1(STORAGE_CLASS, StorageClassUniform, Shader), - CASE1(STORAGE_CLASS, StorageClassOutput, Shader), - CASE0(STORAGE_CLASS, StorageClassWorkgroup), - CASE0(STORAGE_CLASS, StorageClassCrossWorkgroup), - CASE1(STORAGE_CLASS, StorageClassPrivate, Shader), - CASE0(STORAGE_CLASS, StorageClassFunction), - CASE1(STORAGE_CLASS, StorageClassGeneric, - GenericPointer), // Bug 14287 - CASE1(STORAGE_CLASS, StorageClassPushConstant, Shader), - CASE1(STORAGE_CLASS, StorageClassAtomicCounter, AtomicStorage), - CASE0(STORAGE_CLASS, StorageClassImage), - }))); - -// See SPIR-V Section 3.8 Dim -INSTANTIATE_TEST_SUITE_P( - Dim, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE2(DIMENSIONALITY, Dim1D, Sampled1D, Image1D), - CASE3(DIMENSIONALITY, Dim2D, Kernel, Shader, ImageMSArray), - CASE0(DIMENSIONALITY, Dim3D), - CASE2(DIMENSIONALITY, DimCube, Shader, ImageCubeArray), - CASE2(DIMENSIONALITY, DimRect, SampledRect, ImageRect), - CASE2(DIMENSIONALITY, DimBuffer, SampledBuffer, ImageBuffer), - CASE1(DIMENSIONALITY, DimSubpassData, InputAttachment), - }))); - -// See SPIR-V Section 3.9 Sampler Addressing Mode -INSTANTIATE_TEST_SUITE_P( - SamplerAddressingMode, EnumCapabilityTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeNone, Kernel), - CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeClampToEdge, - Kernel), - CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeClamp, Kernel), - CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeRepeat, Kernel), - CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeRepeatMirrored, - Kernel), - }))); - -// See SPIR-V Section 3.10 Sampler Filter Mode -INSTANTIATE_TEST_SUITE_P( - SamplerFilterMode, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(SAMPLER_FILTER_MODE, SamplerFilterModeNearest, Kernel), - CASE1(SAMPLER_FILTER_MODE, SamplerFilterModeLinear, Kernel), - }))); - -// See SPIR-V Section 3.11 Image Format -INSTANTIATE_TEST_SUITE_P( - ImageFormat, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - // clang-format off - CASE0(SAMPLER_IMAGE_FORMAT, ImageFormatUnknown), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32f, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16f, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR32f, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8Snorm, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32f, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16f, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR11fG11fB10f, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16f, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgb10A2, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16Snorm, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16Snorm, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8Snorm, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16Snorm, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8Snorm, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32i, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16i, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8i, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR32i, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32i, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16i, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8i, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16i, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8i, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32ui, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16ui, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8ui, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8ui, Shader), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgb10a2ui, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32ui, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16ui, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8ui, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16ui, StorageImageExtendedFormats), - CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8ui, StorageImageExtendedFormats), - // clang-format on - }))); - -// See SPIR-V Section 3.12 Image Channel Order -INSTANTIATE_TEST_SUITE_P( - ImageChannelOrder, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderR, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderA, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRG, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRA, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGB, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBA, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderBGRA, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderARGB, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderIntensity, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderLuminance, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRx, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGx, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBx, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepth, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepthStencil, - Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGB, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBx, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBA, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersBGRA, Kernel), - CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderABGR, Kernel), - }))); - -// See SPIR-V Section 3.13 Image Channel Data Type -INSTANTIATE_TEST_SUITE_P( - ImageChannelDataType, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - // clang-format off - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSnormInt8, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSnormInt16, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt8, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt16, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormShort565, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormShort555, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt101010, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt8, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt16, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt32, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt8, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt16, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt32, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeHalfFloat, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeFloat, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt24, Kernel), - CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt101010_2, Kernel), - // clang-format on - }))); - -// See SPIR-V Section 3.14 Image Operands -INSTANTIATE_TEST_SUITE_P( - ImageOperands, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - // clang-format off - CASE0(OPTIONAL_IMAGE, ImageOperandsMaskNone), - CASE1(OPTIONAL_IMAGE, ImageOperandsBiasMask, Shader), - CASE0(OPTIONAL_IMAGE, ImageOperandsLodMask), - CASE0(OPTIONAL_IMAGE, ImageOperandsGradMask), - CASE0(OPTIONAL_IMAGE, ImageOperandsConstOffsetMask), - CASE1(OPTIONAL_IMAGE, ImageOperandsOffsetMask, ImageGatherExtended), - CASE1(OPTIONAL_IMAGE, ImageOperandsConstOffsetsMask, ImageGatherExtended), - CASE0(OPTIONAL_IMAGE, ImageOperandsSampleMask), - CASE1(OPTIONAL_IMAGE, ImageOperandsMinLodMask, MinLod), - // clang-format on - }))); - -// See SPIR-V Section 3.15 FP Fast Math Mode -INSTANTIATE_TEST_SUITE_P( - FPFastMathMode, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(FP_FAST_MATH_MODE, FPFastMathModeMaskNone), - CASE1(FP_FAST_MATH_MODE, FPFastMathModeNotNaNMask, Kernel), - CASE1(FP_FAST_MATH_MODE, FPFastMathModeNotInfMask, Kernel), - CASE1(FP_FAST_MATH_MODE, FPFastMathModeNSZMask, Kernel), - CASE1(FP_FAST_MATH_MODE, FPFastMathModeAllowRecipMask, Kernel), - CASE1(FP_FAST_MATH_MODE, FPFastMathModeFastMask, Kernel), - }))); - -// See SPIR-V Section 3.17 Linkage Type -INSTANTIATE_TEST_SUITE_P( - LinkageType, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(LINKAGE_TYPE, LinkageTypeExport, Linkage), - CASE1(LINKAGE_TYPE, LinkageTypeImport, Linkage), - }))); - -// See SPIR-V Section 3.18 Access Qualifier -INSTANTIATE_TEST_SUITE_P( - AccessQualifier, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(ACCESS_QUALIFIER, AccessQualifierReadOnly, Kernel), - CASE1(ACCESS_QUALIFIER, AccessQualifierWriteOnly, Kernel), - CASE1(ACCESS_QUALIFIER, AccessQualifierReadWrite, Kernel), - }))); - -// See SPIR-V Section 3.19 Function Parameter Attribute -INSTANTIATE_TEST_SUITE_P( - FunctionParameterAttribute, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - // clang-format off - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeZext, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeSext, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeByVal, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeSret, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoAlias, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoCapture, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoWrite, Kernel), - CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoReadWrite, Kernel), - // clang-format on - }))); - -// See SPIR-V Section 3.20 Decoration -INSTANTIATE_TEST_SUITE_P( - Decoration, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(DECORATION, DecorationRelaxedPrecision, Shader), - // DecorationSpecId handled below. - CASE1(DECORATION, DecorationBlock, Shader), - CASE1(DECORATION, DecorationBufferBlock, Shader), - CASE1(DECORATION, DecorationRowMajor, Matrix), - CASE1(DECORATION, DecorationColMajor, Matrix), - CASE1(DECORATION, DecorationArrayStride, Shader), - CASE1(DECORATION, DecorationMatrixStride, Matrix), // Bug 15234 - CASE1(DECORATION, DecorationGLSLShared, Shader), - CASE1(DECORATION, DecorationGLSLPacked, Shader), - CASE1(DECORATION, DecorationCPacked, Kernel), - CASE0(DECORATION, DecorationBuiltIn), // Bug 15248 - // Value 12 placeholder - CASE1(DECORATION, DecorationNoPerspective, Shader), - CASE1(DECORATION, DecorationFlat, Shader), - CASE1(DECORATION, DecorationPatch, Tessellation), - CASE1(DECORATION, DecorationCentroid, Shader), - CASE1(DECORATION, DecorationSample, - SampleRateShading), // Bug 15234 - CASE1(DECORATION, DecorationInvariant, Shader), - CASE0(DECORATION, DecorationRestrict), - CASE0(DECORATION, DecorationAliased), - CASE0(DECORATION, DecorationVolatile), - CASE1(DECORATION, DecorationConstant, Kernel), - CASE0(DECORATION, DecorationCoherent), - CASE0(DECORATION, DecorationNonWritable), - CASE0(DECORATION, DecorationNonReadable), - CASE1(DECORATION, DecorationUniform, Shader), - // Value 27 is an intentional gap in the spec numbering. - CASE1(DECORATION, DecorationSaturatedConversion, Kernel), - CASE1(DECORATION, DecorationStream, GeometryStreams), - CASE1(DECORATION, DecorationLocation, Shader), - CASE1(DECORATION, DecorationComponent, Shader), - CASE1(DECORATION, DecorationIndex, Shader), - CASE1(DECORATION, DecorationBinding, Shader), - CASE1(DECORATION, DecorationDescriptorSet, Shader), - CASE1(DECORATION, DecorationOffset, Shader), // Bug 15268 - CASE1(DECORATION, DecorationXfbBuffer, TransformFeedback), - CASE1(DECORATION, DecorationXfbStride, TransformFeedback), - CASE1(DECORATION, DecorationFuncParamAttr, Kernel), - CASE1(DECORATION, DecorationFPFastMathMode, Kernel), - CASE1(DECORATION, DecorationLinkageAttributes, Linkage), - CASE1(DECORATION, DecorationNoContraction, Shader), - CASE1(DECORATION, DecorationInputAttachmentIndex, - InputAttachment), - CASE1(DECORATION, DecorationAlignment, Kernel), - }))); - -#if 0 -// SpecId has different requirements in v1.0 and v1.1: -INSTANTIATE_TEST_SUITE_P(DecorationSpecIdV10, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0), - ValuesIn(std::vector{CASE1( - DECORATION, DecorationSpecId, Shader)}))); -#endif - -INSTANTIATE_TEST_SUITE_P( - DecorationV11, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE2(DECORATION, DecorationSpecId, Shader, Kernel), - CASE1(DECORATION, DecorationMaxByteOffset, Addresses)}))); - -// See SPIR-V Section 3.21 BuiltIn -INSTANTIATE_TEST_SUITE_P( - BuiltIn, EnumCapabilityTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - // clang-format off - CASE1(BUILT_IN, BuiltInPosition, Shader), - CASE1(BUILT_IN, BuiltInPointSize, Shader), - // 2 is an intentional gap in the spec numbering. - CASE1(BUILT_IN, BuiltInClipDistance, ClipDistance), // Bug 1407, 15234 - CASE1(BUILT_IN, BuiltInCullDistance, CullDistance), // Bug 1407, 15234 - CASE1(BUILT_IN, BuiltInVertexId, Shader), - CASE1(BUILT_IN, BuiltInInstanceId, Shader), - CASE3(BUILT_IN, BuiltInPrimitiveId, Geometry, Tessellation, - RayTracingNV), - CASE2(BUILT_IN, BuiltInInvocationId, Geometry, Tessellation), - CASE2(BUILT_IN, BuiltInLayer, Geometry, ShaderViewportIndexLayerEXT), - CASE2(BUILT_IN, BuiltInViewportIndex, MultiViewport, ShaderViewportIndexLayerEXT), // Bug 15234 - CASE1(BUILT_IN, BuiltInTessLevelOuter, Tessellation), - CASE1(BUILT_IN, BuiltInTessLevelInner, Tessellation), - CASE1(BUILT_IN, BuiltInTessCoord, Tessellation), - CASE1(BUILT_IN, BuiltInPatchVertices, Tessellation), - CASE1(BUILT_IN, BuiltInFragCoord, Shader), - CASE1(BUILT_IN, BuiltInPointCoord, Shader), - CASE1(BUILT_IN, BuiltInFrontFacing, Shader), - CASE1(BUILT_IN, BuiltInSampleId, SampleRateShading), // Bug 15234 - CASE1(BUILT_IN, BuiltInSamplePosition, SampleRateShading), // Bug 15234 - CASE1(BUILT_IN, BuiltInSampleMask, Shader), // Bug 15234, Issue 182 - // Value 21 intentionally missing - CASE1(BUILT_IN, BuiltInFragDepth, Shader), - CASE1(BUILT_IN, BuiltInHelperInvocation, Shader), - CASE0(BUILT_IN, BuiltInNumWorkgroups), - CASE0(BUILT_IN, BuiltInWorkgroupSize), - CASE0(BUILT_IN, BuiltInWorkgroupId), - CASE0(BUILT_IN, BuiltInLocalInvocationId), - CASE0(BUILT_IN, BuiltInGlobalInvocationId), - CASE0(BUILT_IN, BuiltInLocalInvocationIndex), - CASE1(BUILT_IN, BuiltInWorkDim, Kernel), - CASE1(BUILT_IN, BuiltInGlobalSize, Kernel), - CASE1(BUILT_IN, BuiltInEnqueuedWorkgroupSize, Kernel), - CASE1(BUILT_IN, BuiltInGlobalOffset, Kernel), - CASE1(BUILT_IN, BuiltInGlobalLinearId, Kernel), - // Value 35 intentionally missing - CASE2(BUILT_IN, BuiltInSubgroupSize, Kernel, SubgroupBallotKHR), - CASE1(BUILT_IN, BuiltInSubgroupMaxSize, Kernel), - CASE1(BUILT_IN, BuiltInNumSubgroups, Kernel), - CASE1(BUILT_IN, BuiltInNumEnqueuedSubgroups, Kernel), - CASE1(BUILT_IN, BuiltInSubgroupId, Kernel), - CASE2(BUILT_IN, BuiltInSubgroupLocalInvocationId, Kernel, SubgroupBallotKHR), - CASE1(BUILT_IN, BuiltInVertexIndex, Shader), - CASE1(BUILT_IN, BuiltInInstanceIndex, Shader), - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - BuiltInV1_5, EnumCapabilityTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_5), - ValuesIn(std::vector{ - // SPIR-V 1.5 adds new capabilities to enable these two builtins. - CASE3(BUILT_IN, BuiltInLayer, Geometry, ShaderLayer, - ShaderViewportIndexLayerEXT), - CASE3(BUILT_IN, BuiltInViewportIndex, MultiViewport, - ShaderViewportIndex, ShaderViewportIndexLayerEXT), - }))); - -// See SPIR-V Section 3.22 Selection Control -INSTANTIATE_TEST_SUITE_P( - SelectionControl, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(SELECTION_CONTROL, SelectionControlMaskNone), - CASE0(SELECTION_CONTROL, SelectionControlFlattenMask), - CASE0(SELECTION_CONTROL, SelectionControlDontFlattenMask), - }))); - -// See SPIR-V Section 3.23 Loop Control -INSTANTIATE_TEST_SUITE_P( - LoopControl, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(LOOP_CONTROL, LoopControlMaskNone), - CASE0(LOOP_CONTROL, LoopControlUnrollMask), - CASE0(LOOP_CONTROL, LoopControlDontUnrollMask), - }))); - -INSTANTIATE_TEST_SUITE_P( - LoopControlV11, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(LOOP_CONTROL, LoopControlDependencyInfiniteMask), - CASE0(LOOP_CONTROL, LoopControlDependencyLengthMask), - }))); - -// See SPIR-V Section 3.24 Function Control -INSTANTIATE_TEST_SUITE_P( - FunctionControl, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(FUNCTION_CONTROL, FunctionControlMaskNone), - CASE0(FUNCTION_CONTROL, FunctionControlInlineMask), - CASE0(FUNCTION_CONTROL, FunctionControlDontInlineMask), - CASE0(FUNCTION_CONTROL, FunctionControlPureMask), - CASE0(FUNCTION_CONTROL, FunctionControlConstMask), - }))); - -// See SPIR-V Section 3.25 Memory Semantics -INSTANTIATE_TEST_SUITE_P( - MemorySemantics, EnumCapabilityTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMaskNone), - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsAcquireMask), - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsReleaseMask), - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsAcquireReleaseMask), - CASE0(MEMORY_SEMANTICS_ID, - MemorySemanticsSequentiallyConsistentMask), - CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsUniformMemoryMask, - Shader), - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsSubgroupMemoryMask), - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsWorkgroupMemoryMask), - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsCrossWorkgroupMemoryMask), - CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsAtomicCounterMemoryMask, - AtomicStorage), // Bug 15234 - CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsImageMemoryMask), - }))); - -// See SPIR-V Section 3.26 Memory Access -INSTANTIATE_TEST_SUITE_P( - MemoryAccess, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMaskNone), - CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessVolatileMask), - CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessAlignedMask), - CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessNontemporalMask), - }))); - -// See SPIR-V Section 3.27 Scope -INSTANTIATE_TEST_SUITE_P( - Scope, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3), - ValuesIn(std::vector{ - CASE0(SCOPE_ID, ScopeCrossDevice), - CASE0(SCOPE_ID, ScopeDevice), - CASE0(SCOPE_ID, ScopeWorkgroup), - CASE0(SCOPE_ID, ScopeSubgroup), - CASE0(SCOPE_ID, ScopeInvocation), - CASE1(SCOPE_ID, ScopeQueueFamilyKHR, VulkanMemoryModelKHR), - }))); - -// See SPIR-V Section 3.28 Group Operation -INSTANTIATE_TEST_SUITE_P( - GroupOperation, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE3(GROUP_OPERATION, GroupOperationReduce, Kernel, - GroupNonUniformArithmetic, GroupNonUniformBallot), - CASE3(GROUP_OPERATION, GroupOperationInclusiveScan, Kernel, - GroupNonUniformArithmetic, GroupNonUniformBallot), - CASE3(GROUP_OPERATION, GroupOperationExclusiveScan, Kernel, - GroupNonUniformArithmetic, GroupNonUniformBallot), - }))); - -// See SPIR-V Section 3.29 Kernel Enqueue Flags -INSTANTIATE_TEST_SUITE_P( - KernelEnqueueFlags, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsNoWait, Kernel), - CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsWaitKernel, Kernel), - CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsWaitWorkGroup, - Kernel), - }))); - -// See SPIR-V Section 3.30 Kernel Profiling Info -INSTANTIATE_TEST_SUITE_P( - KernelProfilingInfo, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE0(KERNEL_PROFILING_INFO, KernelProfilingInfoMaskNone), - CASE1(KERNEL_PROFILING_INFO, KernelProfilingInfoCmdExecTimeMask, - Kernel), - }))); - -// See SPIR-V Section 3.31 Capability -INSTANTIATE_TEST_SUITE_P( - CapabilityDependsOn, EnumCapabilityTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - // clang-format off - CASE0(CAPABILITY, CapabilityMatrix), - CASE1(CAPABILITY, CapabilityShader, Matrix), - CASE1(CAPABILITY, CapabilityGeometry, Shader), - CASE1(CAPABILITY, CapabilityTessellation, Shader), - CASE0(CAPABILITY, CapabilityAddresses), - CASE0(CAPABILITY, CapabilityLinkage), - CASE0(CAPABILITY, CapabilityKernel), - CASE1(CAPABILITY, CapabilityVector16, Kernel), - CASE1(CAPABILITY, CapabilityFloat16Buffer, Kernel), - CASE0(CAPABILITY, CapabilityFloat16), // Bug 15234 - CASE0(CAPABILITY, CapabilityFloat64), - CASE0(CAPABILITY, CapabilityInt64), - CASE1(CAPABILITY, CapabilityInt64Atomics, Int64), - CASE1(CAPABILITY, CapabilityImageBasic, Kernel), - CASE1(CAPABILITY, CapabilityImageReadWrite, ImageBasic), - CASE1(CAPABILITY, CapabilityImageMipmap, ImageBasic), - // Value 16 intentionally missing. - CASE1(CAPABILITY, CapabilityPipes, Kernel), - CASE0(CAPABILITY, CapabilityGroups), - CASE1(CAPABILITY, CapabilityDeviceEnqueue, Kernel), - CASE1(CAPABILITY, CapabilityLiteralSampler, Kernel), - CASE1(CAPABILITY, CapabilityAtomicStorage, Shader), - CASE0(CAPABILITY, CapabilityInt16), - CASE1(CAPABILITY, CapabilityTessellationPointSize, Tessellation), - CASE1(CAPABILITY, CapabilityGeometryPointSize, Geometry), - CASE1(CAPABILITY, CapabilityImageGatherExtended, Shader), - // Value 26 intentionally missing. - CASE1(CAPABILITY, CapabilityStorageImageMultisample, Shader), - CASE1(CAPABILITY, CapabilityUniformBufferArrayDynamicIndexing, Shader), - CASE1(CAPABILITY, CapabilitySampledImageArrayDynamicIndexing, Shader), - CASE1(CAPABILITY, CapabilityStorageBufferArrayDynamicIndexing, Shader), - CASE1(CAPABILITY, CapabilityStorageImageArrayDynamicIndexing, Shader), - CASE1(CAPABILITY, CapabilityClipDistance, Shader), - CASE1(CAPABILITY, CapabilityCullDistance, Shader), - CASE1(CAPABILITY, CapabilityImageCubeArray, SampledCubeArray), - CASE1(CAPABILITY, CapabilitySampleRateShading, Shader), - CASE1(CAPABILITY, CapabilityImageRect, SampledRect), - CASE1(CAPABILITY, CapabilitySampledRect, Shader), - CASE1(CAPABILITY, CapabilityGenericPointer, Addresses), - CASE0(CAPABILITY, CapabilityInt8), - CASE1(CAPABILITY, CapabilityInputAttachment, Shader), - CASE1(CAPABILITY, CapabilitySparseResidency, Shader), - CASE1(CAPABILITY, CapabilityMinLod, Shader), - CASE1(CAPABILITY, CapabilityImage1D, Sampled1D), - CASE1(CAPABILITY, CapabilitySampledCubeArray, Shader), - CASE1(CAPABILITY, CapabilityImageBuffer, SampledBuffer), - CASE1(CAPABILITY, CapabilityImageMSArray, Shader), - CASE1(CAPABILITY, CapabilityStorageImageExtendedFormats, Shader), - CASE1(CAPABILITY, CapabilityImageQuery, Shader), - CASE1(CAPABILITY, CapabilityDerivativeControl, Shader), - CASE1(CAPABILITY, CapabilityInterpolationFunction, Shader), - CASE1(CAPABILITY, CapabilityTransformFeedback, Shader), - CASE1(CAPABILITY, CapabilityGeometryStreams, Geometry), - CASE1(CAPABILITY, CapabilityStorageImageReadWithoutFormat, Shader), - CASE1(CAPABILITY, CapabilityStorageImageWriteWithoutFormat, Shader), - CASE1(CAPABILITY, CapabilityMultiViewport, Geometry), - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - CapabilityDependsOnV11, EnumCapabilityTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector{ - CASE1(CAPABILITY, CapabilitySubgroupDispatch, DeviceEnqueue), - CASE1(CAPABILITY, CapabilityNamedBarrier, Kernel), - CASE1(CAPABILITY, CapabilityPipeStorage, Pipes), - }))); - -#undef CASE0 -#undef CASE1 -#undef CASE2 - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/operand_pattern_test.cpp b/3rdparty/spirv-tools/test/operand_pattern_test.cpp deleted file mode 100644 index 1caf008fb..000000000 --- a/3rdparty/spirv-tools/test/operand_pattern_test.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/operand.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::testing::Eq; - -TEST(OperandPattern, InitiallyEmpty) { - spv_operand_pattern_t empty; - EXPECT_THAT(empty, Eq(spv_operand_pattern_t{})); - EXPECT_EQ(0u, empty.size()); - EXPECT_TRUE(empty.empty()); -} - -TEST(OperandPattern, PushBacksAreOnTheRight) { - spv_operand_pattern_t pattern; - - pattern.push_back(SPV_OPERAND_TYPE_ID); - EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID})); - EXPECT_EQ(1u, pattern.size()); - EXPECT_TRUE(!pattern.empty()); - EXPECT_EQ(SPV_OPERAND_TYPE_ID, pattern.back()); - - pattern.push_back(SPV_OPERAND_TYPE_NONE); - EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID, - SPV_OPERAND_TYPE_NONE})); - EXPECT_EQ(2u, pattern.size()); - EXPECT_TRUE(!pattern.empty()); - EXPECT_EQ(SPV_OPERAND_TYPE_NONE, pattern.back()); -} - -TEST(OperandPattern, PopBacksAreOnTheRight) { - spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_ID, - SPV_OPERAND_TYPE_LITERAL_INTEGER}; - - pattern.pop_back(); - EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID})); - - pattern.pop_back(); - EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{})); -} - -// A test case for typed mask expansion -struct MaskExpansionCase { - spv_operand_type_t type; - uint32_t mask; - spv_operand_pattern_t initial; - spv_operand_pattern_t expected; -}; - -using MaskExpansionTest = ::testing::TestWithParam; - -TEST_P(MaskExpansionTest, Sample) { - spv_operand_table operandTable = nullptr; - auto env = SPV_ENV_UNIVERSAL_1_0; - ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable, env)); - - spv_operand_pattern_t pattern(GetParam().initial); - spvPushOperandTypesForMask(env, operandTable, GetParam().type, - GetParam().mask, &pattern); - EXPECT_THAT(pattern, Eq(GetParam().expected)); -} - -// These macros let us write non-trivial examples without too much text. -#define PREFIX0 SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE -#define PREFIX1 \ - SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, \ - SPV_OPERAND_TYPE_ID -INSTANTIATE_TEST_SUITE_P( - OperandPattern, MaskExpansionTest, - ::testing::ValuesIn(std::vector{ - // No bits means no change. - {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, 0, {PREFIX0}, {PREFIX0}}, - // Unknown bits means no change. Use all bits that aren't in the - // grammar. - // The last mask enum is 0x20 - {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, - 0xffffffc0, - {PREFIX1}, - {PREFIX1}}, - // Volatile has no operands. - {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, - SpvMemoryAccessVolatileMask, - {PREFIX0}, - {PREFIX0}}, - // Aligned has one literal number operand. - {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, - SpvMemoryAccessAlignedMask, - {PREFIX1}, - {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}}, - // Volatile with Aligned still has just one literal number operand. - {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, - SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, - {PREFIX1}, - {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}}, - })); -#undef PREFIX0 -#undef PREFIX1 - -// Returns a vector of all operand types that can be used in a pattern. -std::vector allOperandTypes() { - std::vector result; - for (int i = 0; i < SPV_OPERAND_TYPE_NUM_OPERAND_TYPES; i++) { - result.push_back(spv_operand_type_t(i)); - } - return result; -} - -using MatchableOperandExpansionTest = - ::testing::TestWithParam; - -TEST_P(MatchableOperandExpansionTest, MatchableOperandsDontExpand) { - const spv_operand_type_t type = GetParam(); - if (!spvOperandIsVariable(type)) { - spv_operand_pattern_t pattern; - const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern); - EXPECT_FALSE(did_expand); - EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{})); - } -} - -INSTANTIATE_TEST_SUITE_P(MatchableOperandExpansion, - MatchableOperandExpansionTest, - ::testing::ValuesIn(allOperandTypes())); - -using VariableOperandExpansionTest = - ::testing::TestWithParam; - -TEST_P(VariableOperandExpansionTest, NonMatchableOperandsExpand) { - const spv_operand_type_t type = GetParam(); - if (spvOperandIsVariable(type)) { - spv_operand_pattern_t pattern; - const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern); - EXPECT_TRUE(did_expand); - EXPECT_FALSE(pattern.empty()); - // For the existing rules, the first expansion of a zero-or-more operand - // type yields a matchable operand type. This isn't strictly necessary. - EXPECT_FALSE(spvOperandIsVariable(pattern.back())); - } -} - -INSTANTIATE_TEST_SUITE_P(NonMatchableOperandExpansion, - VariableOperandExpansionTest, - ::testing::ValuesIn(allOperandTypes())); - -TEST(AlternatePatternFollowingImmediate, Empty) { - EXPECT_THAT(spvAlternatePatternFollowingImmediate({}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); -} - -TEST(AlternatePatternFollowingImmediate, SingleElement) { - // Spot-check a random selection of types. - EXPECT_THAT(spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT( - spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT( - spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT(spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); -} - -TEST(AlternatePatternFollowingImmediate, SingleResultId) { - EXPECT_THAT( - spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_RESULT_ID})); -} - -TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) { - EXPECT_THAT( - spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER, - SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL, - SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); -} - -TEST(AlternatePatternFollowingImmediate, ResultIdFront) { - EXPECT_THAT(spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_RESULT_ID, - SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT( - spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID, - SPV_OPERAND_TYPE_FP_ROUNDING_MODE, - SPV_OPERAND_TYPE_ID}), - Eq(spv_operand_pattern_t{ - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID, - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT( - spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY, - SPV_OPERAND_TYPE_LINKAGE_TYPE, - SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, - SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID, - SPV_OPERAND_TYPE_VARIABLE_ID}), - Eq(spv_operand_pattern_t{ - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID, - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV})); -} - -TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) { - EXPECT_THAT(spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, - SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_RESULT_ID, - SPV_OPERAND_TYPE_OPTIONAL_CIV})); - EXPECT_THAT( - spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE, - SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, - SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE, - SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}), - Eq(spv_operand_pattern_t{ - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID, - SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_OPTIONAL_CIV})); -} - -TEST(AlternatePatternFollowingImmediate, ResultIdBack) { - EXPECT_THAT(spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_RESULT_ID})); - EXPECT_THAT(spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID, - SPV_OPERAND_TYPE_RESULT_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_RESULT_ID})); - EXPECT_THAT( - spvAlternatePatternFollowingImmediate( - {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE, - SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, - SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID, - SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}), - Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV, - SPV_OPERAND_TYPE_RESULT_ID})); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/operand_test.cpp b/3rdparty/spirv-tools/test/operand_test.cpp deleted file mode 100644 index 4e2c3215b..000000000 --- a/3rdparty/spirv-tools/test/operand_test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using GetTargetTest = ::testing::TestWithParam; -using ::testing::ValuesIn; - -TEST_P(GetTargetTest, Default) { - spv_operand_table table; - ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&table, GetParam())); - ASSERT_NE(0u, table->count); - ASSERT_NE(nullptr, table->types); -} - -TEST_P(GetTargetTest, InvalidPointerTable) { - ASSERT_EQ(SPV_ERROR_INVALID_POINTER, spvOperandTableGet(nullptr, GetParam())); -} - -INSTANTIATE_TEST_SUITE_P(OperandTableGet, GetTargetTest, - ValuesIn(std::vector{ - SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0})); - -TEST(OperandString, AllAreDefinedExceptVariable) { - // None has no string, so don't test it. - EXPECT_EQ(0u, SPV_OPERAND_TYPE_NONE); - // Start testing at enum with value 1, skipping None. - for (int i = 1; i < int(SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE); i++) { - EXPECT_NE(nullptr, spvOperandTypeStr(static_cast(i))) - << " Operand type " << i; - } -} - -TEST(OperandIsConcreteMask, Sample) { - // Check a few operand types preceding the concrete mask types. - EXPECT_FALSE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_NONE)); - EXPECT_FALSE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_ID)); - EXPECT_FALSE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_LITERAL_INTEGER)); - EXPECT_FALSE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_CAPABILITY)); - - // Check all the concrete mask operand types. - EXPECT_TRUE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_IMAGE)); - EXPECT_TRUE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_FP_FAST_MATH_MODE)); - EXPECT_TRUE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_SELECTION_CONTROL)); - EXPECT_TRUE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_LOOP_CONTROL)); - EXPECT_TRUE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_FUNCTION_CONTROL)); - EXPECT_TRUE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_MEMORY_ACCESS)); - - // Check a few operand types after the concrete mask types, including the - // optional forms for Image and MemoryAccess. - EXPECT_FALSE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_OPTIONAL_ID)); - EXPECT_FALSE(spvOperandIsConcreteMask(SPV_OPERAND_TYPE_OPTIONAL_IMAGE)); - EXPECT_FALSE( - spvOperandIsConcreteMask(SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS)); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/CMakeLists.txt b/3rdparty/spirv-tools/test/opt/CMakeLists.txt deleted file mode 100644 index 327f26563..000000000 --- a/3rdparty/spirv-tools/test/opt/CMakeLists.txt +++ /dev/null @@ -1,107 +0,0 @@ -# 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. - -add_subdirectory(dominator_tree) -add_subdirectory(loop_optimizations) - -add_spvtools_unittest(TARGET opt - SRCS aggressive_dead_code_elim_test.cpp - amd_ext_to_khr.cpp - assembly_builder_test.cpp - block_merge_test.cpp - ccp_test.cpp - cfg_cleanup_test.cpp - cfg_test.cpp - code_sink_test.cpp - combine_access_chains_test.cpp - compact_ids_test.cpp - constants_test.cpp - constant_manager_test.cpp - convert_relaxed_to_half_test.cpp - copy_prop_array_test.cpp - dead_branch_elim_test.cpp - dead_insert_elim_test.cpp - dead_variable_elim_test.cpp - decompose_initialized_variables_test.cpp - decoration_manager_test.cpp - def_use_test.cpp - desc_sroa_test.cpp - eliminate_dead_const_test.cpp - eliminate_dead_functions_test.cpp - eliminate_dead_member_test.cpp - feature_manager_test.cpp - fix_storage_class_test.cpp - flatten_decoration_test.cpp - fold_spec_const_op_composite_test.cpp - fold_test.cpp - freeze_spec_const_test.cpp - function_test.cpp - generate_webgpu_initializers_test.cpp - graphics_robust_access_test.cpp - if_conversion_test.cpp - inline_opaque_test.cpp - inline_test.cpp - insert_extract_elim_test.cpp - inst_bindless_check_test.cpp - inst_buff_addr_check_test.cpp - instruction_list_test.cpp - instruction_test.cpp - ir_builder.cpp - ir_context_test.cpp - ir_loader_test.cpp - iterator_test.cpp - legalize_vector_shuffle_test.cpp - line_debug_info_test.cpp - local_access_chain_convert_test.cpp - local_redundancy_elimination_test.cpp - local_single_block_elim.cpp - local_single_store_elim_test.cpp - local_ssa_elim_test.cpp - module_test.cpp - module_utils.h - optimizer_test.cpp - pass_manager_test.cpp - pass_merge_return_test.cpp - pass_remove_duplicates_test.cpp - pass_utils.cpp - private_to_local_test.cpp - process_lines_test.cpp - propagator_test.cpp - reduce_load_size_test.cpp - redundancy_elimination_test.cpp - register_liveness.cpp - relax_float_ops_test.cpp - replace_invalid_opc_test.cpp - scalar_analysis.cpp - scalar_replacement_test.cpp - set_spec_const_default_value_test.cpp - simplification_test.cpp - split_invalid_unreachable_test.cpp - strength_reduction_test.cpp - strip_atomic_counter_memory_test.cpp - strip_debug_info_test.cpp - strip_reflect_info_test.cpp - struct_cfg_analysis_test.cpp - type_manager_test.cpp - types_test.cpp - unify_const_test.cpp - upgrade_memory_model_test.cpp - utils_test.cpp pass_utils.cpp - value_table_test.cpp - vector_dce_test.cpp - workaround1209_test.cpp - wrap_opkill_test.cpp - LIBS SPIRV-Tools-opt - PCH_FILE pch_test_opt -) diff --git a/3rdparty/spirv-tools/test/opt/aggressive_dead_code_elim_test.cpp b/3rdparty/spirv-tools/test/opt/aggressive_dead_code_elim_test.cpp deleted file mode 100644 index e7303baab..000000000 --- a/3rdparty/spirv-tools/test/opt/aggressive_dead_code_elim_test.cpp +++ /dev/null @@ -1,6772 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using AggressiveDCETest = PassTest<::testing::Test>; - -TEST_F(AggressiveDCETest, EliminateExtendedInst) { - // #version 140 - // - // in vec4 BaseColor; - // in vec4 Dead; - // - // void main() - // { - // vec4 v = BaseColor; - // vec4 dv = sqrt(Dead); - // gl_FragColor = v; - // } - - const std::string predefs1 = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string predefs2 = - R"(%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%dv = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%17 = OpLoad %v4float %Dead -%18 = OpExtInst %v4float %1 Sqrt %17 -OpStore %dv %18 -%19 = OpLoad %v4float %v -OpStore %gl_FragColor %19 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%19 = OpLoad %v4float %v -OpStore %gl_FragColor %19 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2 + func_before, - predefs1 + names_after + predefs2 + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateFrexp) { - // Note: SPIR-V hand-edited to utilize Frexp - // - // #version 450 - // - // in vec4 BaseColor; - // in vec4 Dead; - // out vec4 Color; - // out ivec4 iv2; - // - // void main() - // { - // vec4 v = BaseColor; - // vec4 dv = frexp(Dead, iv2); - // Color = v; - // } - - const std::string predefs1 = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %iv2 %Color -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %iv2 "iv2" -OpName %ResType "ResType" -OpName %Color "Color" -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %iv2 "iv2" -OpName %Color "Color" -)"; - - const std::string predefs2_before = - R"(%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%int = OpTypeInt 32 1 -%v4int = OpTypeVector %int 4 -%_ptr_Output_v4int = OpTypePointer Output %v4int -%iv2 = OpVariable %_ptr_Output_v4int Output -%ResType = OpTypeStruct %v4float %v4int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%Color = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs2_after = - R"(%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%int = OpTypeInt 32 1 -%v4int = OpTypeVector %int 4 -%_ptr_Output_v4int = OpTypePointer Output %v4int -%iv2 = OpVariable %_ptr_Output_v4int Output -%_ptr_Output_v4float = OpTypePointer Output %v4float -%Color = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %11 -%20 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%dv = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %v4float %BaseColor -OpStore %v %21 -%22 = OpLoad %v4float %Dead -%23 = OpExtInst %v4float %1 Frexp %22 %iv2 -OpStore %dv %23 -%24 = OpLoad %v4float %v -OpStore %Color %24 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %11 -%20 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %v4float %BaseColor -OpStore %v %21 -%22 = OpLoad %v4float %Dead -%23 = OpExtInst %v4float %1 Frexp %22 %iv2 -%24 = OpLoad %v4float %v -OpStore %Color %24 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2_before + func_before, - predefs1 + names_after + predefs2_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateDecorate) { - // Note: The SPIR-V was hand-edited to add the OpDecorate - // - // #version 140 - // - // in vec4 BaseColor; - // in vec4 Dead; - // - // void main() - // { - // vec4 v = BaseColor; - // vec4 dv = Dead * 0.5; - // gl_FragColor = v; - // } - - const std::string predefs1 = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %8 RelaxedPrecision -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string predefs2_before = - R"(%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%float_0_5 = OpConstant %float 0.5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs2_after = - R"(%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %10 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%dv = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -%19 = OpLoad %v4float %Dead -%8 = OpVectorTimesScalar %v4float %19 %float_0_5 -OpStore %dv %8 -%20 = OpLoad %v4float %v -OpStore %gl_FragColor %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -%20 = OpLoad %v4float %v -OpStore %gl_FragColor %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2_before + func_before, - predefs1 + names_after + predefs2_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, Simple) { - // #version 140 - // - // in vec4 BaseColor; - // in vec4 Dead; - // - // void main() - // { - // vec4 v = BaseColor; - // vec4 dv = Dead; - // gl_FragColor = v; - // } - - const std::string predefs1 = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string predefs2 = - R"(%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%dv = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%17 = OpLoad %v4float %Dead -OpStore %dv %17 -%18 = OpLoad %v4float %v -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%18 = OpLoad %v4float %v -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2 + func_before, - predefs1 + names_after + predefs2 + func_after, true, true); -} - -TEST_F(AggressiveDCETest, OptWhitelistExtension) { - // #version 140 - // - // in vec4 BaseColor; - // in vec4 Dead; - // - // void main() - // { - // vec4 v = BaseColor; - // vec4 dv = Dead; - // gl_FragColor = v; - // } - - const std::string predefs1 = - R"(OpCapability Shader -OpExtension "SPV_AMD_gpu_shader_int16" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string predefs2 = - R"(%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%dv = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%17 = OpLoad %v4float %Dead -OpStore %dv %17 -%18 = OpLoad %v4float %v -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%18 = OpLoad %v4float %v -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2 + func_before, - predefs1 + names_after + predefs2 + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoOptBlacklistExtension) { - // #version 140 - // - // in vec4 BaseColor; - // in vec4 Dead; - // - // void main() - // { - // vec4 v = BaseColor; - // vec4 dv = Dead; - // gl_FragColor = v; - // } - - const std::string assembly = - R"(OpCapability Shader -OpExtension "SPV_KHR_variable_pointers" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %9 -%15 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%dv = OpVariable %_ptr_Function_v4float Function -%16 = OpLoad %v4float %BaseColor -OpStore %v %16 -%17 = OpLoad %v4float %Dead -OpStore %dv %17 -%18 = OpLoad %v4float %v -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, ElimWithCall) { - // This demonstrates that "dead" function calls are not eliminated. - // Also demonstrates that DCE will happen in presence of function call. - // #version 140 - // in vec4 i1; - // in vec4 i2; - // - // void nothing(vec4 v) - // { - // } - // - // void main() - // { - // vec4 v1 = i1; - // vec4 v2 = i2; - // nothing(v1); - // gl_FragColor = vec4(0.0); - // } - - const std::string defs_before = - R"( OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i1 %i2 %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %nothing_vf4_ "nothing(vf4;" -OpName %v "v" -OpName %v1 "v1" -OpName %i1 "i1" -OpName %v2 "v2" -OpName %i2 "i2" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%16 = OpTypeFunction %void %_ptr_Function_v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%i1 = OpVariable %_ptr_Input_v4float Input -%i2 = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%20 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -)"; - - const std::string defs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i1 %i2 %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %nothing_vf4_ "nothing(vf4;" -OpName %v "v" -OpName %v1 "v1" -OpName %i1 "i1" -OpName %i2 "i2" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%16 = OpTypeFunction %void %_ptr_Function_v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%i1 = OpVariable %_ptr_Input_v4float Input -%i2 = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%20 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %12 -%21 = OpLabel -%v1 = OpVariable %_ptr_Function_v4float Function -%v2 = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %i1 -OpStore %v1 %22 -%23 = OpLoad %v4float %i2 -OpStore %v2 %23 -%24 = OpLoad %v4float %v1 -OpStore %param %24 -%25 = OpFunctionCall %void %nothing_vf4_ %param -OpStore %gl_FragColor %20 -OpReturn -OpFunctionEnd -%nothing_vf4_ = OpFunction %void None %16 -%v = OpFunctionParameter %_ptr_Function_v4float -%26 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %12 -%21 = OpLabel -%v1 = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %i1 -OpStore %v1 %22 -%24 = OpLoad %v4float %v1 -OpStore %param %24 -%25 = OpFunctionCall %void %nothing_vf4_ %param -OpStore %gl_FragColor %20 -OpReturn -OpFunctionEnd -%nothing_vf4_ = OpFunction %void None %16 -%v = OpFunctionParameter %_ptr_Function_v4float -%26 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoParamElim) { - // This demonstrates that unused parameters are not eliminated, but - // dead uses of them are. - // #version 140 - // - // in vec4 BaseColor; - // - // vec4 foo(vec4 v1, vec4 v2) - // { - // vec4 t = -v1; - // return v2; - // } - // - // void main() - // { - // vec4 dead; - // gl_FragColor = foo(dead, BaseColor); - // } - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_vf4_ "foo(vf4;vf4;" -OpName %v1 "v1" -OpName %v2 "v2" -OpName %t "t" -OpName %gl_FragColor "gl_FragColor" -OpName %dead "dead" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %param_0 "param" -%void = OpTypeVoid -%13 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%17 = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %13 -%20 = OpLabel -%dead = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%param_0 = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %v4float %dead -OpStore %param %21 -%22 = OpLoad %v4float %BaseColor -OpStore %param_0 %22 -%23 = OpFunctionCall %v4float %foo_vf4_vf4_ %param %param_0 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string defs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_vf4_ "foo(vf4;vf4;" -OpName %v1 "v1" -OpName %v2 "v2" -OpName %gl_FragColor "gl_FragColor" -OpName %dead "dead" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %param_0 "param" -%void = OpTypeVoid -%13 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%17 = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %13 -%20 = OpLabel -%dead = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%param_0 = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %v4float %dead -OpStore %param %21 -%22 = OpLoad %v4float %BaseColor -OpStore %param_0 %22 -%23 = OpFunctionCall %v4float %foo_vf4_vf4_ %param %param_0 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string func_before = - R"(%foo_vf4_vf4_ = OpFunction %v4float None %17 -%v1 = OpFunctionParameter %_ptr_Function_v4float -%v2 = OpFunctionParameter %_ptr_Function_v4float -%24 = OpLabel -%t = OpVariable %_ptr_Function_v4float Function -%25 = OpLoad %v4float %v1 -%26 = OpFNegate %v4float %25 -OpStore %t %26 -%27 = OpLoad %v4float %v2 -OpReturnValue %27 -OpFunctionEnd -)"; - - const std::string func_after = - R"(%foo_vf4_vf4_ = OpFunction %v4float None %17 -%v1 = OpFunctionParameter %_ptr_Function_v4float -%v2 = OpFunctionParameter %_ptr_Function_v4float -%24 = OpLabel -%27 = OpLoad %v4float %v2 -OpReturnValue %27 -OpFunctionEnd -)"; - - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, ElimOpaque) { - // SPIR-V not representable from GLSL; not generatable from HLSL - // for the moment. - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpMemberName %S_t 2 "smp" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %s0 "s0" -OpName %texCoords "texCoords" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%14 = OpTypeImage %float 2D 0 0 0 1 Unknown -%15 = OpTypeSampledImage %14 -%S_t = OpTypeStruct %v2float %v2float %15 -%_ptr_Function_S_t = OpTypePointer Function %S_t -%17 = OpTypeFunction %void %_ptr_Function_S_t -%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 -%_ptr_Function_15 = OpTypePointer Function %15 -%sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string defs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %texCoords "texCoords" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%14 = OpTypeImage %float 2D 0 0 0 1 Unknown -%15 = OpTypeSampledImage %14 -%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 -%sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %9 -%25 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%26 = OpLoad %v2float %texCoords -%27 = OpLoad %S_t %s0 -%28 = OpCompositeInsert %S_t %26 %27 0 -%29 = OpLoad %15 %sampler15 -%30 = OpCompositeInsert %S_t %29 %28 2 -OpStore %s0 %30 -%31 = OpImageSampleImplicitLod %v4float %29 %26 -OpStore %outColor %31 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %9 -%25 = OpLabel -%26 = OpLoad %v2float %texCoords -%29 = OpLoad %15 %sampler15 -%31 = OpImageSampleImplicitLod %v4float %29 %26 -OpStore %outColor %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoParamStoreElim) { - // Should not eliminate stores to params - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void foo(in vec4 v1, out vec4 v2) - // { - // v2 = -v1; - // } - // - // void main() - // { - // foo(BaseColor, OutColor); - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %foo_vf4_vf4_ "foo(vf4;vf4;" -OpName %v1 "v1" -OpName %v2 "v2" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpName %param "param" -OpName %param_0 "param" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%15 = OpTypeFunction %void %_ptr_Function_v4float %_ptr_Function_v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %11 -%18 = OpLabel -%param = OpVariable %_ptr_Function_v4float Function -%param_0 = OpVariable %_ptr_Function_v4float Function -%19 = OpLoad %v4float %BaseColor -OpStore %param %19 -%20 = OpFunctionCall %void %foo_vf4_vf4_ %param %param_0 -%21 = OpLoad %v4float %param_0 -OpStore %OutColor %21 -OpReturn -OpFunctionEnd -%foo_vf4_vf4_ = OpFunction %void None %15 -%v1 = OpFunctionParameter %_ptr_Function_v4float -%v2 = OpFunctionParameter %_ptr_Function_v4float -%22 = OpLabel -%23 = OpLoad %v4float %v1 -%24 = OpFNegate %v4float %23 -OpStore %v2 %24 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, PrivateStoreElimInEntryNoCalls) { - // Eliminate stores to private in entry point with no calls - // Note: Not legal GLSL - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 1) in vec4 Dead; - // layout(location = 0) out vec4 OutColor; - // - // private vec4 dv; - // - // void main() - // { - // vec4 v = BaseColor; - // dv = Dead; - // OutColor = v; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %Dead Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Private_v4float = OpTypePointer Private %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%dv = OpVariable %_ptr_Private_v4float Private -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %Dead Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string main_before = - R"(%main = OpFunction %void None %9 -%16 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%17 = OpLoad %v4float %BaseColor -OpStore %v %17 -%18 = OpLoad %v4float %Dead -OpStore %dv %18 -%19 = OpLoad %v4float %v -%20 = OpFNegate %v4float %19 -OpStore %OutColor %20 -OpReturn -OpFunctionEnd -)"; - - const std::string main_after = - R"(%main = OpFunction %void None %9 -%16 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%17 = OpLoad %v4float %BaseColor -OpStore %v %17 -%19 = OpLoad %v4float %v -%20 = OpFNegate %v4float %19 -OpStore %OutColor %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + main_before, predefs_after + main_after, true, true); -} - -TEST_F(AggressiveDCETest, NoPrivateStoreElimIfLoad) { - // Should not eliminate stores to private when there is a load - // Note: Not legal GLSL - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // private vec4 pv; - // - // void main() - // { - // pv = BaseColor; - // OutColor = pv; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %pv "pv" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Private_v4float = OpTypePointer Private %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%pv = OpVariable %_ptr_Private_v4float Private -%main = OpFunction %void None %7 -%13 = OpLabel -%14 = OpLoad %v4float %BaseColor -OpStore %pv %14 -%15 = OpLoad %v4float %pv -%16 = OpFNegate %v4float %15 -OpStore %OutColor %16 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoPrivateStoreElimWithCall) { - // Should not eliminate stores to private when function contains call - // Note: Not legal GLSL - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // private vec4 v1; - // - // void foo() - // { - // OutColor = -v1; - // } - // - // void main() - // { - // v1 = BaseColor; - // foo(); - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %OutColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %foo_ "foo(" -OpName %OutColor "OutColor" -OpName %v1 "v1" -OpName %BaseColor "BaseColor" -OpDecorate %OutColor Location 0 -OpDecorate %BaseColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Private_v4float = OpTypePointer Private %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%v1 = OpVariable %_ptr_Private_v4float Private -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %8 -%14 = OpLabel -%15 = OpLoad %v4float %BaseColor -OpStore %v1 %15 -%16 = OpFunctionCall %void %foo_ -OpReturn -OpFunctionEnd -%foo_ = OpFunction %void None %8 -%17 = OpLabel -%18 = OpLoad %v4float %v1 -%19 = OpFNegate %v4float %18 -OpStore %OutColor %19 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoPrivateStoreElimInNonEntry) { - // Should not eliminate stores to private when function is not entry point - // Note: Not legal GLSL - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // private vec4 v1; - // - // void foo() - // { - // v1 = BaseColor; - // } - // - // void main() - // { - // foo(); - // OutColor = -v1; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %foo_ "foo(" -OpName %v1 "v1" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Private_v4float = OpTypePointer Private %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%v1 = OpVariable %_ptr_Private_v4float Private -%OutColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %8 -%14 = OpLabel -%15 = OpFunctionCall %void %foo_ -%16 = OpLoad %v4float %v1 -%17 = OpFNegate %v4float %16 -OpStore %OutColor %17 -OpReturn -OpFunctionEnd -%foo_ = OpFunction %void None %8 -%18 = OpLabel -%19 = OpLoad %v4float %BaseColor -OpStore %v1 %19 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, WorkgroupStoreElimInEntryNoCalls) { - // Eliminate stores to private in entry point with no calls - // Note: Not legal GLSL - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 1) in vec4 Dead; - // layout(location = 0) out vec4 OutColor; - // - // workgroup vec4 dv; - // - // void main() - // { - // vec4 v = BaseColor; - // dv = Dead; - // OutColor = v; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %dv "dv" -OpName %Dead "Dead" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %Dead Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Workgroup_v4float = OpTypePointer Workgroup %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%dv = OpVariable %_ptr_Workgroup_v4float Workgroup -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Dead "Dead" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %Dead Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%Dead = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string main_before = - R"(%main = OpFunction %void None %9 -%16 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%17 = OpLoad %v4float %BaseColor -OpStore %v %17 -%18 = OpLoad %v4float %Dead -OpStore %dv %18 -%19 = OpLoad %v4float %v -%20 = OpFNegate %v4float %19 -OpStore %OutColor %20 -OpReturn -OpFunctionEnd -)"; - - const std::string main_after = - R"(%main = OpFunction %void None %9 -%16 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%17 = OpLoad %v4float %BaseColor -OpStore %v %17 -%19 = OpLoad %v4float %v -%20 = OpFNegate %v4float %19 -OpStore %OutColor %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + main_before, predefs_after + main_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateDeadIfThenElse) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float d; - // if (BaseColor.x == 0) - // d = BaseColor.y; - // else - // d = BaseColor.z; - // OutColor = vec4(1.0,1.0,1.0,1.0); - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %d "d" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%21 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%21 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %7 -%22 = OpLabel -%d = OpVariable %_ptr_Function_float Function -%23 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%24 = OpLoad %float %23 -%25 = OpFOrdEqual %bool %24 %float_0 -OpSelectionMerge %26 None -OpBranchConditional %25 %27 %28 -%27 = OpLabel -%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%30 = OpLoad %float %29 -OpStore %d %30 -OpBranch %26 -%28 = OpLabel -%31 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2 -%32 = OpLoad %float %31 -OpStore %d %32 -OpBranch %26 -%26 = OpLabel -OpStore %OutColor %21 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%22 = OpLabel -OpBranch %26 -%26 = OpLabel -OpStore %OutColor %21 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateDeadIfThen) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float d; - // if (BaseColor.x == 0) - // d = BaseColor.y; - // OutColor = vec4(1.0,1.0,1.0,1.0); - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %d "d" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%20 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%20 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %7 -%21 = OpLabel -%d = OpVariable %_ptr_Function_float Function -%22 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%23 = OpLoad %float %22 -%24 = OpFOrdEqual %bool %23 %float_0 -OpSelectionMerge %25 None -OpBranchConditional %24 %26 %25 -%26 = OpLabel -%27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%28 = OpLoad %float %27 -OpStore %d %28 -OpBranch %25 -%25 = OpLabel -OpStore %OutColor %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%21 = OpLabel -OpBranch %25 -%25 = OpLabel -OpStore %OutColor %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateDeadSwitch) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 1) in flat int x; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float d; - // switch (x) { - // case 0: - // d = BaseColor.y; - // } - // OutColor = vec4(1.0,1.0,1.0,1.0); - // } - const std::string before = - R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %x %BaseColor %OutColor - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %x "x" - OpName %d "d" - OpName %BaseColor "BaseColor" - OpName %OutColor "OutColor" - OpDecorate %x Flat - OpDecorate %x Location 1 - OpDecorate %BaseColor Location 0 - OpDecorate %OutColor Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int - %x = OpVariable %_ptr_Input_int Input - %float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %BaseColor = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 -%_ptr_Input_float = OpTypePointer Input %float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %OutColor = OpVariable %_ptr_Output_v4float Output - %float_1 = OpConstant %float 1 - %27 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 - %main = OpFunction %void None %3 - %5 = OpLabel - %d = OpVariable %_ptr_Function_float Function - %9 = OpLoad %int %x - OpSelectionMerge %11 None - OpSwitch %9 %11 0 %10 - %10 = OpLabel - %21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 - %22 = OpLoad %float %21 - OpStore %d %22 - OpBranch %11 - %11 = OpLabel - OpStore %OutColor %27 - OpReturn - OpFunctionEnd)"; - - const std::string after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %x %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %x "x" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %x Flat -OpDecorate %x Location 1 -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%x = OpVariable %_ptr_Input_int Input -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%27 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%main = OpFunction %void None %3 -%5 = OpLabel -OpBranch %11 -%11 = OpLabel -OpStore %OutColor %27 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateDeadIfThenElseNested) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float d; - // if (BaseColor.x == 0) - // if (BaseColor.y == 0) - // d = 0.0; - // else - // d = 0.25; - // else - // if (BaseColor.y == 0) - // d = 0.5; - // else - // d = 0.75; - // OutColor = vec4(1.0,1.0,1.0,1.0); - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %d "d" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%uint_1 = OpConstant %uint 1 -%_ptr_Function_float = OpTypePointer Function %float -%float_0_25 = OpConstant %float 0.25 -%float_0_5 = OpConstant %float 0.5 -%float_0_75 = OpConstant %float 0.75 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_1 = OpConstant %float 1 -%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %7 -%24 = OpLabel -%d = OpVariable %_ptr_Function_float Function -%25 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%26 = OpLoad %float %25 -%27 = OpFOrdEqual %bool %26 %float_0 -OpSelectionMerge %28 None -OpBranchConditional %27 %29 %30 -%29 = OpLabel -%31 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%32 = OpLoad %float %31 -%33 = OpFOrdEqual %bool %32 %float_0 -OpSelectionMerge %34 None -OpBranchConditional %33 %35 %36 -%35 = OpLabel -OpStore %d %float_0 -OpBranch %34 -%36 = OpLabel -OpStore %d %float_0_25 -OpBranch %34 -%34 = OpLabel -OpBranch %28 -%30 = OpLabel -%37 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%38 = OpLoad %float %37 -%39 = OpFOrdEqual %bool %38 %float_0 -OpSelectionMerge %40 None -OpBranchConditional %39 %41 %42 -%41 = OpLabel -OpStore %d %float_0_5 -OpBranch %40 -%42 = OpLabel -OpStore %d %float_0_75 -OpBranch %40 -%40 = OpLabel -OpBranch %28 -%28 = OpLabel -OpStore %OutColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%24 = OpLabel -OpBranch %28 -%28 = OpLabel -OpStore %OutColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateLiveIfThenElse) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float t; - // if (BaseColor.x == 0) - // t = BaseColor.y; - // else - // t = BaseColor.z; - // OutColor = vec4(t); - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %t "t" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%20 = OpLabel -%t = OpVariable %_ptr_Function_float Function -%21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%22 = OpLoad %float %21 -%23 = OpFOrdEqual %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %26 -%25 = OpLabel -%27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%28 = OpLoad %float %27 -OpStore %t %28 -OpBranch %24 -%26 = OpLabel -%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2 -%30 = OpLoad %float %29 -OpStore %t %30 -OpBranch %24 -%24 = OpLabel -%31 = OpLoad %float %t -%32 = OpCompositeConstruct %v4float %31 %31 %31 %31 -OpStore %OutColor %32 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateLiveIfThenElseNested) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float t; - // if (BaseColor.x == 0) - // if (BaseColor.y == 0) - // t = 0.0; - // else - // t = 0.25; - // else - // if (BaseColor.y == 0) - // t = 0.5; - // else - // t = 0.75; - // OutColor = vec4(t); - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %t "t" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%uint_1 = OpConstant %uint 1 -%_ptr_Function_float = OpTypePointer Function %float -%float_0_25 = OpConstant %float 0.25 -%float_0_5 = OpConstant %float 0.5 -%float_0_75 = OpConstant %float 0.75 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%22 = OpLabel -%t = OpVariable %_ptr_Function_float Function -%23 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%24 = OpLoad %float %23 -%25 = OpFOrdEqual %bool %24 %float_0 -OpSelectionMerge %26 None -OpBranchConditional %25 %27 %28 -%27 = OpLabel -%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%30 = OpLoad %float %29 -%31 = OpFOrdEqual %bool %30 %float_0 -OpSelectionMerge %32 None -OpBranchConditional %31 %33 %34 -%33 = OpLabel -OpStore %t %float_0 -OpBranch %32 -%34 = OpLabel -OpStore %t %float_0_25 -OpBranch %32 -%32 = OpLabel -OpBranch %26 -%28 = OpLabel -%35 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%36 = OpLoad %float %35 -%37 = OpFOrdEqual %bool %36 %float_0 -OpSelectionMerge %38 None -OpBranchConditional %37 %39 %40 -%39 = OpLabel -OpStore %t %float_0_5 -OpBranch %38 -%40 = OpLabel -OpStore %t %float_0_75 -OpBranch %38 -%38 = OpLabel -OpBranch %26 -%26 = OpLabel -%41 = OpLoad %float %t -%42 = OpCompositeConstruct %v4float %41 %41 %41 %41 -OpStore %OutColor %42 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateIfWithPhi) { - // Note: Assembly hand-optimized from GLSL - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float t; - // if (BaseColor.x == 0) - // t = 0.0; - // else - // t = 1.0; - // OutColor = vec4(t); - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %6 -%17 = OpLabel -%18 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%19 = OpLoad %float %18 -%20 = OpFOrdEqual %bool %19 %float_0 -OpSelectionMerge %21 None -OpBranchConditional %20 %22 %23 -%22 = OpLabel -OpBranch %21 -%23 = OpLabel -OpBranch %21 -%21 = OpLabel -%24 = OpPhi %float %float_0 %22 %float_1 %23 -%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 -OpStore %OutColor %25 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateIfBreak) { - // Note: Assembly optimized from GLSL - // - // #version 450 - // - // layout(location=0) in vec4 InColor; - // layout(location=0) out vec4 OutColor; - // - // void main() - // { - // float f = 0.0; - // for (;;) { - // f += 2.0; - // if (f > 20.0) - // break; - // } - // - // OutColor = InColor / f; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %OutColor %InColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %f "f" -OpName %OutColor "OutColor" -OpName %InColor "InColor" -OpDecorate %OutColor Location 0 -OpDecorate %InColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%float_2 = OpConstant %float 2 -%float_20 = OpConstant %float 20 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%InColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %7 -%17 = OpLabel -%f = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpBranch %18 -%18 = OpLabel -OpLoopMerge %19 %20 None -OpBranch %21 -%21 = OpLabel -%22 = OpLoad %float %f -%23 = OpFAdd %float %22 %float_2 -OpStore %f %23 -%24 = OpLoad %float %f -%25 = OpFOrdGreaterThan %bool %24 %float_20 -OpSelectionMerge %26 None -OpBranchConditional %25 %27 %26 -%27 = OpLabel -OpBranch %19 -%26 = OpLabel -OpBranch %20 -%20 = OpLabel -OpBranch %18 -%19 = OpLabel -%28 = OpLoad %v4float %InColor -%29 = OpLoad %float %f -%30 = OpCompositeConstruct %v4float %29 %29 %29 %29 -%31 = OpFDiv %v4float %28 %30 -OpStore %OutColor %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateIfBreak2) { - // Do not eliminate break as conditional branch with merge instruction - // Note: SPIR-V edited to add merge instruction before break. - // - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) - // s += g_F[i]; - // o = s; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %10 -%25 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %26 -%26 = OpLabel -OpLoopMerge %27 %28 None -OpBranch %29 -%29 = OpLabel -%30 = OpLoad %int %i -%31 = OpSLessThan %bool %30 %int_10 -OpSelectionMerge %32 None -OpBranchConditional %31 %32 %27 -%32 = OpLabel -%33 = OpLoad %int %i -%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %33 -%35 = OpLoad %float %34 -%36 = OpLoad %float %s -%37 = OpFAdd %float %36 %35 -OpStore %s %37 -OpBranch %28 -%28 = OpLabel -%38 = OpLoad %int %i -%39 = OpIAdd %int %38 %int_1 -OpStore %i %39 -OpBranch %26 -%27 = OpLabel -%40 = OpLoad %float %s -OpStore %o %40 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, EliminateEntireUselessLoop) { - // #version 140 - // in vec4 BaseColor; - // - // layout(std140) uniform U_t - // { - // int g_I ; - // } ; - // - // void main() - // { - // vec4 v = BaseColor; - // float df = 0.0; - // int i = 0; - // while (i < g_I) { - // df = df * 0.5; - // i = i + 1; - // } - // gl_FragColor = v; - // } - - const std::string predefs1 = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %df "df" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_I" -OpName %_ "" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -)"; - - const std::string predefs2_before = - R"(OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t Block -OpDecorate %_ DescriptorSet 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%U_t = OpTypeStruct %int -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_int = OpTypePointer Uniform %int -%bool = OpTypeBool -%float_0_5 = OpConstant %float 0.5 -%int_1 = OpConstant %int 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs2_after = - R"(%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %11 -%27 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%df = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%28 = OpLoad %v4float %BaseColor -OpStore %v %28 -OpStore %df %float_0 -OpStore %i %int_0 -OpBranch %29 -%29 = OpLabel -OpLoopMerge %30 %31 None -OpBranch %32 -%32 = OpLabel -%33 = OpLoad %int %i -%34 = OpAccessChain %_ptr_Uniform_int %_ %int_0 -%35 = OpLoad %int %34 -%36 = OpSLessThan %bool %33 %35 -OpBranchConditional %36 %37 %30 -%37 = OpLabel -%38 = OpLoad %float %df -%39 = OpFMul %float %38 %float_0_5 -OpStore %df %39 -%40 = OpLoad %int %i -%41 = OpIAdd %int %40 %int_1 -OpStore %i %41 -OpBranch %31 -%31 = OpLabel -OpBranch %29 -%30 = OpLabel -%42 = OpLoad %v4float %v -OpStore %gl_FragColor %42 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %11 -%27 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%28 = OpLoad %v4float %BaseColor -OpStore %v %28 -OpBranch %29 -%29 = OpLabel -OpBranch %30 -%30 = OpLabel -%42 = OpLoad %v4float %v -OpStore %gl_FragColor %42 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2_before + func_before, - predefs1 + names_after + predefs2_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateBusyLoop) { - // Note: SPIR-V edited to replace AtomicAdd(i,0) with AtomicLoad(i) - // - // #version 450 - // - // layout(std430) buffer I_t - // { - // int g_I; - // int g_I2; - // }; - // - // layout(location = 0) out int o; - // - // void main(void) - // { - // while (atomicAdd(g_I, 0) == 0) {} - // o = g_I2; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %I_t "I_t" -OpMemberName %I_t 0 "g_I" -OpMemberName %I_t 1 "g_I2" -OpName %_ "" -OpName %o "o" -OpMemberDecorate %I_t 0 Offset 0 -OpMemberDecorate %I_t 1 Offset 4 -OpDecorate %I_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%I_t = OpTypeStruct %int %int -%_ptr_Uniform_I_t = OpTypePointer Uniform %I_t -%_ = OpVariable %_ptr_Uniform_I_t Uniform -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%_ptr_Uniform_int = OpTypePointer Uniform %int -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%_ptr_Output_int = OpTypePointer Output %int -%o = OpVariable %_ptr_Output_int Output -%main = OpFunction %void None %7 -%18 = OpLabel -OpBranch %19 -%19 = OpLabel -OpLoopMerge %20 %21 None -OpBranch %22 -%22 = OpLabel -%23 = OpAccessChain %_ptr_Uniform_int %_ %int_0 -%24 = OpAtomicLoad %int %23 %uint_1 %uint_0 -%25 = OpIEqual %bool %24 %int_0 -OpBranchConditional %25 %26 %20 -%26 = OpLabel -OpBranch %21 -%21 = OpLabel -OpBranch %19 -%20 = OpLabel -%27 = OpAccessChain %_ptr_Uniform_int %_ %int_1 -%28 = OpLoad %int %27 -OpStore %o %28 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateLiveLoop) { - // Note: SPIR-V optimized - // - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) - // s += g_F[i]; - // o = s; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %8 -%21 = OpLabel -OpBranch %22 -%22 = OpLabel -%23 = OpPhi %float %float_0 %21 %24 %25 -%26 = OpPhi %int %int_0 %21 %27 %25 -OpLoopMerge %28 %25 None -OpBranch %29 -%29 = OpLabel -%30 = OpSLessThan %bool %26 %int_10 -OpBranchConditional %30 %31 %28 -%31 = OpLabel -%32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %26 -%33 = OpLoad %float %32 -%24 = OpFAdd %float %23 %33 -OpBranch %25 -%25 = OpLabel -%27 = OpIAdd %int %26 %int_1 -OpBranch %22 -%28 = OpLabel -OpStore %o %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, EliminateEntireFunctionBody) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // float d; - // if (BaseColor.x == 0) - // d = BaseColor.y; - // else - // d = BaseColor.z; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %d "d" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %7 -%20 = OpLabel -%d = OpVariable %_ptr_Function_float Function -%21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 -%22 = OpLoad %float %21 -%23 = OpFOrdEqual %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %26 -%25 = OpLabel -%27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 -%28 = OpLoad %float %27 -OpStore %d %28 -OpBranch %24 -%26 = OpLabel -%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2 -%30 = OpLoad %float %29 -OpStore %d %30 -OpBranch %24 -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%20 = OpLabel -OpBranch %24 -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateUselessInnerLoop) { - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // for (int j=0; j<10; j++) { - // } - // s += g_F[i]; - // } - // o = s; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %j "j" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_1 = OpConstant %int 1 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_1 = OpConstant %int 1 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %11 -%26 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%j = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpSLessThan %bool %31 %int_10 -OpBranchConditional %32 %33 %28 -%33 = OpLabel -OpStore %j %int_0 -OpBranch %34 -%34 = OpLabel -OpLoopMerge %35 %36 None -OpBranch %37 -%37 = OpLabel -%38 = OpLoad %int %j -%39 = OpSLessThan %bool %38 %int_10 -OpBranchConditional %39 %40 %35 -%40 = OpLabel -OpBranch %36 -%36 = OpLabel -%41 = OpLoad %int %j -%42 = OpIAdd %int %41 %int_1 -OpStore %j %42 -OpBranch %34 -%35 = OpLabel -%43 = OpLoad %int %i -%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %43 -%45 = OpLoad %float %44 -%46 = OpLoad %float %s -%47 = OpFAdd %float %46 %45 -OpStore %s %47 -OpBranch %29 -%29 = OpLabel -%48 = OpLoad %int %i -%49 = OpIAdd %int %48 %int_1 -OpStore %i %49 -OpBranch %27 -%28 = OpLabel -%50 = OpLoad %float %s -OpStore %o %50 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %11 -%26 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpSLessThan %bool %31 %int_10 -OpBranchConditional %32 %33 %28 -%33 = OpLabel -OpBranch %34 -%34 = OpLabel -OpBranch %35 -%35 = OpLabel -%43 = OpLoad %int %i -%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %43 -%45 = OpLoad %float %44 -%46 = OpLoad %float %s -%47 = OpFAdd %float %46 %45 -OpStore %s %47 -OpBranch %29 -%29 = OpLabel -%48 = OpLoad %int %i -%49 = OpIAdd %int %48 %int_1 -OpStore %i %49 -OpBranch %27 -%28 = OpLabel -%50 = OpLoad %float %s -OpStore %o %50 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateUselessNestedLoopWithIf) { - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10][10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // for (int j=0; j<10; j++) { - // float t = g_F[i][j]; - // if (t > 0.0) - // s += t; - // } - // } - // o = 0.0; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %j "j" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpDecorate %_arr__arr_float_uint_10_uint_10 ArrayStride 40 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 -%U_t = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %o "o" -OpDecorate %o Location 0 -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %12 -%27 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%j = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %28 -%28 = OpLabel -OpLoopMerge %29 %30 None -OpBranch %31 -%31 = OpLabel -%32 = OpLoad %int %i -%33 = OpSLessThan %bool %32 %int_10 -OpBranchConditional %33 %34 %29 -%34 = OpLabel -OpStore %j %int_0 -OpBranch %35 -%35 = OpLabel -OpLoopMerge %36 %37 None -OpBranch %38 -%38 = OpLabel -%39 = OpLoad %int %j -%40 = OpSLessThan %bool %39 %int_10 -OpBranchConditional %40 %41 %36 -%41 = OpLabel -%42 = OpLoad %int %i -%43 = OpLoad %int %j -%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %42 %43 -%45 = OpLoad %float %44 -%46 = OpFOrdGreaterThan %bool %45 %float_0 -OpSelectionMerge %47 None -OpBranchConditional %46 %48 %47 -%48 = OpLabel -%49 = OpLoad %float %s -%50 = OpFAdd %float %49 %45 -OpStore %s %50 -OpBranch %47 -%47 = OpLabel -OpBranch %37 -%37 = OpLabel -%51 = OpLoad %int %j -%52 = OpIAdd %int %51 %int_1 -OpStore %j %52 -OpBranch %35 -%36 = OpLabel -OpBranch %30 -%30 = OpLabel -%53 = OpLoad %int %i -%54 = OpIAdd %int %53 %int_1 -OpStore %i %54 -OpBranch %28 -%29 = OpLabel -OpStore %o %float_0 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %12 -%27 = OpLabel -OpBranch %28 -%28 = OpLabel -OpBranch %29 -%29 = OpLabel -OpStore %o %float_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, EliminateEmptyIfBeforeContinue) { - // #version 430 - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // s += 1.0; - // if (i > s) {} - // } - // o = s; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %3 -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpName %main "main" -OpDecorate %3 Location 0 -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%3 = OpVariable %_ptr_Output_float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %3 -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpName %main "main" -OpDecorate %3 Location 0 -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%3 = OpVariable %_ptr_Output_float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %5 -%16 = OpLabel -OpBranch %17 -%17 = OpLabel -%18 = OpPhi %float %float_0 %16 %19 %20 -%21 = OpPhi %int %int_0 %16 %22 %20 -OpLoopMerge %23 %20 None -OpBranch %24 -%24 = OpLabel -%25 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %25 %26 %23 -%26 = OpLabel -%19 = OpFAdd %float %18 %float_1 -%27 = OpConvertFToS %int %19 -%28 = OpSGreaterThan %bool %21 %27 -OpSelectionMerge %20 None -OpBranchConditional %28 %29 %20 -%29 = OpLabel -OpBranch %20 -%20 = OpLabel -%22 = OpIAdd %int %21 %int_1 -OpBranch %17 -%23 = OpLabel -OpStore %3 %18 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %5 -%16 = OpLabel -OpBranch %17 -%17 = OpLabel -%18 = OpPhi %float %float_0 %16 %19 %20 -%21 = OpPhi %int %int_0 %16 %22 %20 -OpLoopMerge %23 %20 None -OpBranch %24 -%24 = OpLabel -%25 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %25 %26 %23 -%26 = OpLabel -%19 = OpFAdd %float %18 %float_1 -OpBranch %20 -%20 = OpLabel -%22 = OpIAdd %int %21 %int_1 -OpBranch %17 -%23 = OpLabel -OpStore %3 %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + func_before, predefs_after + func_after, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateLiveNestedLoopWithIf) { - // Note: SPIR-V optimized - // - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10][10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // for (int j=0; j<10; j++) { - // float t = g_F[i][j]; - // if (t > 0.0) - // s += t; - // } - // } - // o = s; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %j "j" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpDecorate %_arr__arr_float_uint_10_uint_10 ArrayStride 40 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 -%U_t = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %12 -%27 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%j = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %28 -%28 = OpLabel -OpLoopMerge %29 %30 None -OpBranch %31 -%31 = OpLabel -%32 = OpLoad %int %i -%33 = OpSLessThan %bool %32 %int_10 -OpBranchConditional %33 %34 %29 -%34 = OpLabel -OpStore %j %int_0 -OpBranch %35 -%35 = OpLabel -OpLoopMerge %36 %37 None -OpBranch %38 -%38 = OpLabel -%39 = OpLoad %int %j -%40 = OpSLessThan %bool %39 %int_10 -OpBranchConditional %40 %41 %36 -%41 = OpLabel -%42 = OpLoad %int %i -%43 = OpLoad %int %j -%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %42 %43 -%45 = OpLoad %float %44 -%46 = OpFOrdGreaterThan %bool %45 %float_0 -OpSelectionMerge %47 None -OpBranchConditional %46 %48 %47 -%48 = OpLabel -%49 = OpLoad %float %s -%50 = OpFAdd %float %49 %45 -OpStore %s %50 -OpBranch %47 -%47 = OpLabel -OpBranch %37 -%37 = OpLabel -%51 = OpLoad %int %j -%52 = OpIAdd %int %51 %int_1 -OpStore %j %52 -OpBranch %35 -%36 = OpLabel -OpBranch %30 -%30 = OpLabel -%53 = OpLoad %int %i -%54 = OpIAdd %int %53 %int_1 -OpStore %i %54 -OpBranch %28 -%29 = OpLabel -%55 = OpLoad %float %s -OpStore %o %55 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateIfContinue) { - // Do not eliminate continue embedded in if construct - // - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // if (i % 2 == 0) continue; - // s += g_F[i]; - // } - // o = s; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_2 = OpConstant %int 2 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %10 -%26 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpSLessThan %bool %31 %int_10 -OpBranchConditional %32 %33 %28 -%33 = OpLabel -%34 = OpLoad %int %i -%35 = OpSMod %int %34 %int_2 -%36 = OpIEqual %bool %35 %int_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %37 -%38 = OpLabel -OpBranch %29 -%37 = OpLabel -%39 = OpLoad %int %i -%40 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %39 -%41 = OpLoad %float %40 -%42 = OpLoad %float %s -%43 = OpFAdd %float %42 %41 -OpStore %s %43 -OpBranch %29 -%29 = OpLabel -%44 = OpLoad %int %i -%45 = OpIAdd %int %44 %int_1 -OpStore %i %45 -OpBranch %27 -%28 = OpLabel -%46 = OpLoad %float %s -OpStore %o %46 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateIfContinue2) { - // Do not eliminate continue not embedded in if construct - // - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // if (i % 2 == 0) continue; - // s += g_F[i]; - // } - // o = s; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_2 = OpConstant %int 2 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %10 -%26 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpSLessThan %bool %31 %int_10 -OpBranchConditional %32 %33 %28 -%33 = OpLabel -%34 = OpLoad %int %i -%35 = OpSMod %int %34 %int_2 -%36 = OpIEqual %bool %35 %int_0 -OpBranchConditional %36 %29 %37 -%37 = OpLabel -%38 = OpLoad %int %i -%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %38 -%40 = OpLoad %float %39 -%41 = OpLoad %float %s -%42 = OpFAdd %float %41 %40 -OpStore %s %42 -OpBranch %29 -%29 = OpLabel -%43 = OpLoad %int %i -%44 = OpIAdd %int %43 %int_1 -OpStore %i %44 -OpBranch %27 -%28 = OpLabel -%45 = OpLoad %float %s -OpStore %o %45 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(AggressiveDCETest, NoEliminateIfContinue3) { - // Do not eliminate continue as conditional branch with merge instruction - // Note: SPIR-V edited to add merge instruction before continue. - // - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // float s = 0.0; - // for (int i=0; i<10; i++) { - // if (i % 2 == 0) continue; - // s += g_F[i]; - // } - // o = s; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %s "s" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_2 = OpConstant %int 2 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %10 -%26 = OpLabel -%s = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %s %float_0 -OpStore %i %int_0 -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpSLessThan %bool %31 %int_10 -OpBranchConditional %32 %33 %28 -%33 = OpLabel -%34 = OpLoad %int %i -%35 = OpSMod %int %34 %int_2 -%36 = OpIEqual %bool %35 %int_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %29 %37 -%37 = OpLabel -%38 = OpLoad %int %i -%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %38 -%40 = OpLoad %float %39 -%41 = OpLoad %float %s -%42 = OpFAdd %float %41 %40 -OpStore %s %42 -OpBranch %29 -%29 = OpLabel -%43 = OpLoad %int %i -%44 = OpIAdd %int %43 %int_1 -OpStore %i %44 -OpBranch %27 -%28 = OpLabel -%45 = OpLoad %float %s -OpStore %o %45 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -// This is not valid input and ADCE does not support variable pointers and only -// supports shaders. -TEST_F(AggressiveDCETest, PointerVariable) { - // ADCE is able to handle code that contains a load whose base address - // comes from a load and not an OpVariable. I want to see an instruction - // removed to be sure that ADCE is not exiting early. - - const std::string before = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -OpDecorate %8 DescriptorSet 0 -OpDecorate %8 Binding 1 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%8 = OpVariable %_ptr_Uniform__struct_6 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%26 = OpLoad %_ptr_Uniform__struct_5 %24 -%27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%25 = OpLoad %_ptr_Uniform__struct_5 %24 -%26 = OpAccessChain %_ptr_Uniform_v4float %25 %int_0 %uint_0 %int_0 -%27 = OpLoad %v4float %26 -OpStore %2 %27 -OpReturn -OpFunctionEnd -)"; - - // The input is not valid and ADCE only supports shaders, but not variable - // pointers. Workaround this by enabling relaxed logical pointers in the - // validator. - ValidatorOptions()->relax_logical_pointer = true; - SinglePassRunAndCheck(before, after, true, true); -} - -// %dead is unused. Make sure we remove it along with its name. -TEST_F(AggressiveDCETest, RemoveUnreferenced) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %dead "dead" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%dead = OpVariable %_ptr_Private_float Private -%main = OpFunction %void None %5 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%main = OpFunction %void None %5 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -// Delete %dead because it is unreferenced. Then %initializer becomes -// unreferenced, so remove it as well. -TEST_F(AggressiveDCETest, RemoveUnreferencedWithInit1) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %dead "dead" -OpName %initializer "initializer" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%initializer = OpVariable %_ptr_Private_float Private -%dead = OpVariable %_ptr_Private_float Private %initializer -%main = OpFunction %void None %6 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%main = OpFunction %void None %6 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -// Keep %live because it is used, and its initializer. -TEST_F(AggressiveDCETest, KeepReferenced) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %output -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %live "live" -OpName %initializer "initializer" -OpName %output "output" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%initializer = OpConstant %float 0 -%live = OpVariable %_ptr_Private_float Private %initializer -%_ptr_Output_float = OpTypePointer Output %float -%output = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %6 -%9 = OpLabel -%10 = OpLoad %float %live -OpStore %output %10 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, before, true, true); -} - -// This test that the decoration associated with a variable are removed when the -// variable is removed. -TEST_F(AggressiveDCETest, RemoveVariableAndDecorations) { - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 450 -OpName %main "main" -OpName %B "B" -OpMemberName %B 0 "a" -OpName %Bdat "Bdat" -OpMemberDecorate %B 0 Offset 0 -OpDecorate %B BufferBlock -OpDecorate %Bdat DescriptorSet 0 -OpDecorate %Bdat Binding 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%B = OpTypeStruct %uint -%_ptr_Uniform_B = OpTypePointer Uniform %B -%Bdat = OpVariable %_ptr_Uniform_B Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%main = OpFunction %void None %6 -%13 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 450 -OpName %main "main" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%main = OpFunction %void None %6 -%13 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(AggressiveDCETest, DeadNestedSwitch) { - const std::string text = R"( -; CHECK: OpLabel -; CHECK: OpBranch [[block:%\w+]] -; CHECK-NOT: OpSwitch -; CHECK-NEXT: [[block]] = OpLabel -; CHECK: OpBranch [[block:%\w+]] -; CHECK-NOT: OpSwitch -; CHECK-NEXT: [[block]] = OpLabel -; CHECK-NEXT: OpStore -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" %x -OpExecutionMode %func OriginUpperLeft -OpName %func "func" -%void = OpTypeVoid -%1 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_ptr_Output = OpTypePointer Output %uint -%uint_ptr_Input = OpTypePointer Input %uint -%x = OpVariable %uint_ptr_Output Output -%a = OpVariable %uint_ptr_Input Input -%func = OpFunction %void None %1 -%entry = OpLabel -OpBranch %header -%header = OpLabel -%ld = OpLoad %uint %a -OpLoopMerge %merge %continue None -OpBranch %postheader -%postheader = OpLabel -; This switch doesn't require an OpSelectionMerge and is nested in the dead loop. -OpSwitch %ld %merge 0 %extra 1 %continue -%extra = OpLabel -OpBranch %continue -%continue = OpLabel -OpBranch %header -%merge = OpLabel -OpStore %x %uint_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, LiveNestedSwitch) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" %3 %10 -OpExecutionMode %func OriginUpperLeft -OpName %func "func" -%void = OpTypeVoid -%1 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%_ptr_Input_uint = OpTypePointer Input %uint -%3 = OpVariable %_ptr_Output_uint Output -%10 = OpVariable %_ptr_Input_uint Input -%func = OpFunction %void None %1 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -%13 = OpLoad %uint %10 -OpLoopMerge %14 %15 None -OpBranch %16 -%16 = OpLabel -OpSwitch %13 %14 0 %17 1 %15 -%17 = OpLabel -OpStore %3 %uint_1 -OpBranch %15 -%15 = OpLabel -OpBranch %12 -%14 = OpLabel -OpStore %3 %uint_0 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, text, false, true); -} - -TEST_F(AggressiveDCETest, BasicDeleteDeadFunction) { - // The function Dead should be removed because it is never called. - const std::vector common_code = { - // clang-format off - "OpCapability Shader", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\"", - "OpName %main \"main\"", - "OpName %Live \"Live\"", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%main = OpFunction %void None %7", - "%15 = OpLabel", - "%16 = OpFunctionCall %void %Live", - "%17 = OpFunctionCall %void %Live", - "OpReturn", - "OpFunctionEnd", - "%Live = OpFunction %void None %7", - "%20 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - const std::vector dead_function = { - // clang-format off - "%Dead = OpFunction %void None %7", - "%19 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - JoinAllInsts(Concat(common_code, dead_function)), - JoinAllInsts(common_code), /* skip_nop = */ true); -} - -TEST_F(AggressiveDCETest, BasicKeepLiveFunction) { - // Everything is reachable from an entry point, so no functions should be - // deleted. - const std::vector text = { - // clang-format off - "OpCapability Shader", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\"", - "OpName %main \"main\"", - "OpName %Live1 \"Live1\"", - "OpName %Live2 \"Live2\"", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%main = OpFunction %void None %7", - "%15 = OpLabel", - "%16 = OpFunctionCall %void %Live2", - "%17 = OpFunctionCall %void %Live1", - "OpReturn", - "OpFunctionEnd", - "%Live1 = OpFunction %void None %7", - "%19 = OpLabel", - "OpReturn", - "OpFunctionEnd", - "%Live2 = OpFunction %void None %7", - "%20 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - std::string assembly = JoinAllInsts(text); - auto result = SinglePassRunAndDisassemble( - assembly, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); - EXPECT_EQ(assembly, std::get<0>(result)); -} - -TEST_F(AggressiveDCETest, BasicRemoveDecorationsAndNames) { - // We want to remove the names and decorations associated with results that - // are removed. This test will check for that. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - OpName %Dead "Dead" - OpName %x "x" - OpName %y "y" - OpName %z "z" - OpDecorate %x RelaxedPrecision - OpDecorate %y RelaxedPrecision - OpDecorate %z RelaxedPrecision - OpDecorate %6 RelaxedPrecision - OpDecorate %7 RelaxedPrecision - OpDecorate %8 RelaxedPrecision - %void = OpTypeVoid - %10 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float - %float_1 = OpConstant %float 1 - %main = OpFunction %void None %10 - %14 = OpLabel - OpReturn - OpFunctionEnd - %Dead = OpFunction %void None %10 - %15 = OpLabel - %x = OpVariable %_ptr_Function_float Function - %y = OpVariable %_ptr_Function_float Function - %z = OpVariable %_ptr_Function_float Function - OpStore %x %float_1 - OpStore %y %float_1 - %6 = OpLoad %float %x - %7 = OpLoad %float %y - %8 = OpFAdd %float %6 %7 - OpStore %z %8 - OpReturn - OpFunctionEnd)"; - - const std::string expected_output = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -%void = OpTypeVoid -%10 = OpTypeFunction %void -%main = OpFunction %void None %10 -%14 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, expected_output, - /* skip_nop = */ true); -} - -TEST_F(AggressiveDCETest, BasicAllDeadConstants) { - const std::string text = R"( - ; CHECK-NOT: OpConstant - OpCapability Shader - OpCapability Float64 - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %false = OpConstantFalse %bool - %int = OpTypeInt 32 1 - %9 = OpConstant %int 1 - %uint = OpTypeInt 32 0 - %11 = OpConstant %uint 2 - %float = OpTypeFloat 32 - %13 = OpConstant %float 3.1415 - %double = OpTypeFloat 64 - %15 = OpConstant %double 3.14159265358979 - %main = OpFunction %void None %4 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, BasicNoneDeadConstants) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\" %btv %bfv %iv %uv %fv %dv", - "OpName %main \"main\"", - "OpName %btv \"btv\"", - "OpName %bfv \"bfv\"", - "OpName %iv \"iv\"", - "OpName %uv \"uv\"", - "OpName %fv \"fv\"", - "OpName %dv \"dv\"", - "%void = OpTypeVoid", - "%10 = OpTypeFunction %void", - "%bool = OpTypeBool", - "%_ptr_Output_bool = OpTypePointer Output %bool", - "%true = OpConstantTrue %bool", - "%false = OpConstantFalse %bool", - "%int = OpTypeInt 32 1", - "%_ptr_Output_int = OpTypePointer Output %int", - "%int_1 = OpConstant %int 1", - "%uint = OpTypeInt 32 0", - "%_ptr_Output_uint = OpTypePointer Output %uint", - "%uint_2 = OpConstant %uint 2", - "%float = OpTypeFloat 32", - "%_ptr_Output_float = OpTypePointer Output %float", - "%float_3_1415 = OpConstant %float 3.1415", - "%double = OpTypeFloat 64", - "%_ptr_Output_double = OpTypePointer Output %double", - "%double_3_14159265358979 = OpConstant %double 3.14159265358979", - "%btv = OpVariable %_ptr_Output_bool Output", - "%bfv = OpVariable %_ptr_Output_bool Output", - "%iv = OpVariable %_ptr_Output_int Output", - "%uv = OpVariable %_ptr_Output_uint Output", - "%fv = OpVariable %_ptr_Output_float Output", - "%dv = OpVariable %_ptr_Output_double Output", - "%main = OpFunction %void None %10", - "%27 = OpLabel", - "OpStore %btv %true", - "OpStore %bfv %false", - "OpStore %iv %int_1", - "OpStore %uv %uint_2", - "OpStore %fv %float_3_1415", - "OpStore %dv %double_3_14159265358979", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - // All constants are used, so none of them should be eliminated. - SinglePassRunAndCheck( - JoinAllInsts(text), JoinAllInsts(text), /* skip_nop = */ true); -} - -struct AggressiveEliminateDeadConstantTestCase { - // Type declarations and constants that should be kept. - std::vector used_consts; - // Instructions that refer to constants, this is added to create uses for - // some constants so they won't be treated as dead constants. - std::vector main_insts; - // Dead constants that should be removed. - std::vector dead_consts; - // Expectations - std::vector checks; -}; - -// All types that are potentially required in -// AggressiveEliminateDeadConstantTest. -const std::vector CommonTypes = { - // clang-format off - // scalar types - "%bool = OpTypeBool", - "%uint = OpTypeInt 32 0", - "%int = OpTypeInt 32 1", - "%float = OpTypeFloat 32", - "%double = OpTypeFloat 64", - // vector types - "%v2bool = OpTypeVector %bool 2", - "%v2uint = OpTypeVector %uint 2", - "%v2int = OpTypeVector %int 2", - "%v3int = OpTypeVector %int 3", - "%v4int = OpTypeVector %int 4", - "%v2float = OpTypeVector %float 2", - "%v3float = OpTypeVector %float 3", - "%v2double = OpTypeVector %double 2", - // variable pointer types - "%_pf_bool = OpTypePointer Output %bool", - "%_pf_uint = OpTypePointer Output %uint", - "%_pf_int = OpTypePointer Output %int", - "%_pf_float = OpTypePointer Output %float", - "%_pf_double = OpTypePointer Output %double", - "%_pf_v2int = OpTypePointer Output %v2int", - "%_pf_v3int = OpTypePointer Output %v3int", - "%_pf_v2float = OpTypePointer Output %v2float", - "%_pf_v3float = OpTypePointer Output %v3float", - "%_pf_v2double = OpTypePointer Output %v2double", - // struct types - "%inner_struct = OpTypeStruct %bool %int %float %double", - "%outer_struct = OpTypeStruct %inner_struct %int %double", - "%flat_struct = OpTypeStruct %bool %int %float %double", - // clang-format on -}; - -using AggressiveEliminateDeadConstantTest = - PassTest<::testing::TestWithParam>; - -TEST_P(AggressiveEliminateDeadConstantTest, Custom) { - auto& tc = GetParam(); - AssemblyBuilder builder; - builder.AppendTypesConstantsGlobals(CommonTypes) - .AppendTypesConstantsGlobals(tc.used_consts) - .AppendInMain(tc.main_insts); - const std::string expected = builder.GetCode(); - builder.AppendTypesConstantsGlobals(tc.dead_consts); - builder.PrependPreamble(tc.checks); - const std::string assembly_with_dead_const = builder.GetCode(); - - // Do not enable validation. As the input code is invalid from the base - // tests (ported from other passes). - SinglePassRunAndMatch(assembly_with_dead_const, false); -} - -INSTANTIATE_TEST_SUITE_P( - ScalarTypeConstants, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Scalar type constants, one dead constant and one used constant. - { - /* .used_consts = */ - { - "%used_const_int = OpConstant %int 1", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "OpStore %int_var %used_const_int", - }, - /* .dead_consts = */ - { - "%dead_const_int = OpConstant %int 1", - }, - /* .checks = */ - { - "; CHECK: [[const:%\\w+]] = OpConstant %int 1", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - { - /* .used_consts = */ - { - "%used_const_uint = OpConstant %uint 1", - }, - /* .main_insts = */ - { - "%uint_var = OpVariable %_pf_uint Output", - "OpStore %uint_var %used_const_uint", - }, - /* .dead_consts = */ - { - "%dead_const_uint = OpConstant %uint 1", - }, - /* .checks = */ - { - "; CHECK: [[const:%\\w+]] = OpConstant %uint 1", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - { - /* .used_consts = */ - { - "%used_const_float = OpConstant %float 3.1415", - }, - /* .main_insts = */ - { - "%float_var = OpVariable %_pf_float Output", - "OpStore %float_var %used_const_float", - }, - /* .dead_consts = */ - { - "%dead_const_float = OpConstant %float 3.1415", - }, - /* .checks = */ - { - "; CHECK: [[const:%\\w+]] = OpConstant %float 3.1415", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - { - /* .used_consts = */ - { - "%used_const_double = OpConstant %double 3.14", - }, - /* .main_insts = */ - { - "%double_var = OpVariable %_pf_double Output", - "OpStore %double_var %used_const_double", - }, - /* .dead_consts = */ - { - "%dead_const_double = OpConstant %double 3.14", - }, - /* .checks = */ - { - "; CHECK: [[const:%\\w+]] = OpConstant %double 3.14", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - VectorTypeConstants, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Tests eliminating dead constant type ivec2. One dead constant vector - // and one used constant vector, each built from its own group of - // scalar constants. - { - /* .used_consts = */ - { - "%used_int_x = OpConstant %int 1", - "%used_int_y = OpConstant %int 2", - "%used_v2int = OpConstantComposite %v2int %used_int_x %used_int_y", - }, - /* .main_insts = */ - { - "%v2int_var = OpVariable %_pf_v2int Output", - "OpStore %v2int_var %used_v2int", - }, - /* .dead_consts = */ - { - "%dead_int_x = OpConstant %int 1", - "%dead_int_y = OpConstant %int 2", - "%dead_v2int = OpConstantComposite %v2int %dead_int_x %dead_int_y", - }, - /* .checks = */ - { - "; CHECK: [[constx:%\\w+]] = OpConstant %int 1", - "; CHECK: [[consty:%\\w+]] = OpConstant %int 2", - "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2int [[constx]] [[consty]]", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - // Tests eliminating dead constant ivec3. One dead constant vector and - // one used constant vector. But both built from a same group of - // scalar constants. - { - /* .used_consts = */ - { - "%used_int_x = OpConstant %int 1", - "%used_int_y = OpConstant %int 2", - "%used_int_z = OpConstant %int 3", - "%used_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z", - }, - /* .main_insts = */ - { - "%v3int_var = OpVariable %_pf_v3int Output", - "OpStore %v3int_var %used_v3int", - }, - /* .dead_consts = */ - { - "%dead_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z", - }, - /* .checks = */ - { - "; CHECK: [[constx:%\\w+]] = OpConstant %int 1", - "; CHECK: [[consty:%\\w+]] = OpConstant %int 2", - "; CHECK: [[constz:%\\w+]] = OpConstant %int 3", - "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3int [[constx]] [[consty]] [[constz]]", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - // Tests eliminating dead constant vec2. One dead constant vector and - // one used constant vector. Each built from its own group of scalar - // constants. - { - /* .used_consts = */ - { - "%used_float_x = OpConstant %float 3.1415", - "%used_float_y = OpConstant %float 4.13", - "%used_v2float = OpConstantComposite %v2float %used_float_x %used_float_y", - }, - /* .main_insts = */ - { - "%v2float_var = OpVariable %_pf_v2float Output", - "OpStore %v2float_var %used_v2float", - }, - /* .dead_consts = */ - { - "%dead_float_x = OpConstant %float 3.1415", - "%dead_float_y = OpConstant %float 4.13", - "%dead_v2float = OpConstantComposite %v2float %dead_float_x %dead_float_y", - }, - /* .checks = */ - { - "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415", - "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.13", - "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2float [[constx]] [[consty]]", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - // Tests eliminating dead constant vec3. One dead constant vector and - // one used constant vector. Both built from a same group of scalar - // constants. - { - /* .used_consts = */ - { - "%used_float_x = OpConstant %float 3.1415", - "%used_float_y = OpConstant %float 4.25", - "%used_float_z = OpConstant %float 4.75", - "%used_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z", - }, - /* .main_insts = */ - { - "%v3float_var = OpVariable %_pf_v3float Output", - "OpStore %v3float_var %used_v3float", - }, - /* .dead_consts = */ - { - "%dead_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z", - }, - /* .checks = */ - { - "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415", - "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.25", - "; CHECK: [[constz:%\\w+]] = OpConstant %float 4.75", - "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3float [[constx]] [[consty]]", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[const]]", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - StructTypeConstants, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // A plain struct type dead constants. All of its components are dead - // constants too. - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_int = OpConstant %int 1", - "%dead_float = OpConstant %float 2.5", - "%dead_double = OpConstant %double 3.14159265358979", - "%dead_struct = OpConstantComposite %flat_struct %dead_bool %dead_int %dead_float %dead_double", - }, - /* .checks = */ - { - "; CHECK-NOT: OpConstant", - }, - }, - // A plain struct type dead constants. Some of its components are dead - // constants while others are not. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 1", - "%used_double = OpConstant %double 3.14159265358979", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "OpStore %int_var %used_int", - "%double_var = OpVariable %_pf_double Output", - "OpStore %double_var %used_double", - }, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_float = OpConstant %float 2.5", - "%dead_struct = OpConstantComposite %flat_struct %dead_bool %used_int %dead_float %used_double", - }, - /* .checks = */ - { - "; CHECK: [[int:%\\w+]] = OpConstant %int 1", - "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[int]]", - "; CHECK: OpStore {{%\\w+}} [[double]]", - }, - }, - // A nesting struct type dead constants. All components of both outer - // and inner structs are dead and should be removed after dead constant - // elimination. - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_int = OpConstant %int 1", - "%dead_float = OpConstant %float 2.5", - "%dead_double = OpConstant %double 3.1415926535", - "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %dead_int %dead_float %dead_double", - "%dead_int2 = OpConstant %int 2", - "%dead_double2 = OpConstant %double 1.428571428514", - "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int2 %dead_double2", - }, - /* .checks = */ - { - "; CHECK-NOT: OpConstant", - }, - }, - // A nesting struct type dead constants. Some of its components are - // dead constants while others are not. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 1", - "%used_double = OpConstant %double 3.14159265358979", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "OpStore %int_var %used_int", - "%double_var = OpVariable %_pf_double Output", - "OpStore %double_var %used_double", - }, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_float = OpConstant %float 2.5", - "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %used_int %dead_float %used_double", - "%dead_int = OpConstant %int 2", - "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int %used_double", - }, - /* .checks = */ - { - "; CHECK: [[int:%\\w+]] = OpConstant %int 1", - "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[int]]", - "; CHECK: OpStore {{%\\w+}} [[double]]", - }, - }, - // A nesting struct case. The inner struct is used while the outer struct is not - { - /* .used_const = */ - { - "%used_bool = OpConstantTrue %bool", - "%used_int = OpConstant %int 1", - "%used_float = OpConstant %float 1.23", - "%used_double = OpConstant %double 1.2345678901234", - "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", - }, - /* .main_insts = */ - { - "%bool_var = OpVariable %_pf_bool Output", - "%bool_from_inner_struct = OpCompositeExtract %bool %used_inner_struct 0", - "OpStore %bool_var %bool_from_inner_struct", - }, - /* .dead_consts = */ - { - "%dead_int = OpConstant %int 2", - "%dead_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %dead_int %used_double" - }, - /* .checks = */ - { - "; CHECK: [[bool:%\\w+]] = OpConstantTrue", - "; CHECK: [[int:%\\w+]] = OpConstant %int 1", - "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23", - "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234", - "; CHECK: [[struct:%\\w+]] = OpConstantComposite %inner_struct [[bool]] [[int]] [[float]] [[double]]", - "; CHECK-NOT: OpConstant", - "; CHECK: OpCompositeExtract %bool [[struct]]", - } - }, - // A nesting struct case. The outer struct is used, so the inner struct should not - // be removed even though it is not used anywhere. - { - /* .used_const = */ - { - "%used_bool = OpConstantTrue %bool", - "%used_int = OpConstant %int 1", - "%used_float = OpConstant %float 1.23", - "%used_double = OpConstant %double 1.2345678901234", - "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", - "%used_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double" - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "%int_from_outer_struct = OpCompositeExtract %int %used_outer_struct 1", - "OpStore %int_var %int_from_outer_struct", - }, - /* .dead_consts = */ {}, - /* .checks = */ - { - "; CHECK: [[bool:%\\w+]] = OpConstantTrue %bool", - "; CHECK: [[int:%\\w+]] = OpConstant %int 1", - "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23", - "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234", - "; CHECK: [[inner_struct:%\\w+]] = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", - "; CHECK: [[outer_struct:%\\w+]] = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double", - "; CHECK: OpCompositeExtract %int [[outer_struct]]", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - ScalarTypeSpecConstants, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // All scalar type spec constants. - { - /* .used_consts = */ - { - "%used_bool = OpSpecConstantTrue %bool", - "%used_uint = OpSpecConstant %uint 2", - "%used_int = OpSpecConstant %int 2", - "%used_float = OpSpecConstant %float 2.5", - "%used_double = OpSpecConstant %double 1.428571428514", - }, - /* .main_insts = */ - { - "%bool_var = OpVariable %_pf_bool Output", - "%uint_var = OpVariable %_pf_uint Output", - "%int_var = OpVariable %_pf_int Output", - "%float_var = OpVariable %_pf_float Output", - "%double_var = OpVariable %_pf_double Output", - "OpStore %bool_var %used_bool", - "OpStore %uint_var %used_uint", - "OpStore %int_var %used_int", - "OpStore %float_var %used_float", - "OpStore %double_var %used_double", - }, - /* .dead_consts = */ - { - "%dead_bool = OpSpecConstantTrue %bool", - "%dead_uint = OpSpecConstant %uint 2", - "%dead_int = OpSpecConstant %int 2", - "%dead_float = OpSpecConstant %float 2.5", - "%dead_double = OpSpecConstant %double 1.428571428514", - }, - /* .checks = */ - { - "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool", - "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 2", - "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 2", - "; CHECK: [[float:%\\w+]] = OpSpecConstant %float 2.5", - "; CHECK: [[double:%\\w+]] = OpSpecConstant %double 1.428571428514", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[bool]]", - "; CHECK: OpStore {{%\\w+}} [[uint]]", - "; CHECK: OpStore {{%\\w+}} [[int]]", - "; CHECK: OpStore {{%\\w+}} [[float]]", - "; CHECK: OpStore {{%\\w+}} [[double]]", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - VectorTypeSpecConstants, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Bool vector type spec constants. One vector has all component dead, - // another vector has one dead boolean and one used boolean. - { - /* .used_consts = */ - { - "%used_bool = OpSpecConstantTrue %bool", - }, - /* .main_insts = */ - { - "%bool_var = OpVariable %_pf_bool Output", - "OpStore %bool_var %used_bool", - }, - /* .dead_consts = */ - { - "%dead_bool = OpSpecConstantFalse %bool", - "%dead_bool_vec1 = OpSpecConstantComposite %v2bool %dead_bool %dead_bool", - "%dead_bool_vec2 = OpSpecConstantComposite %v2bool %dead_bool %used_bool", - }, - /* .checks = */ - { - "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[bool]]", - }, - }, - - // Uint vector type spec constants. One vector has all component dead, - // another vector has one dead unsigend integer and one used unsigned - // integer. - { - /* .used_consts = */ - { - "%used_uint = OpSpecConstant %uint 3", - }, - /* .main_insts = */ - { - "%uint_var = OpVariable %_pf_uint Output", - "OpStore %uint_var %used_uint", - }, - /* .dead_consts = */ - { - "%dead_uint = OpSpecConstant %uint 1", - "%dead_uint_vec1 = OpSpecConstantComposite %v2uint %dead_uint %dead_uint", - "%dead_uint_vec2 = OpSpecConstantComposite %v2uint %dead_uint %used_uint", - }, - /* .checks = */ - { - "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 3", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[uint]]", - }, - }, - - // Int vector type spec constants. One vector has all component dead, - // another vector has one dead integer and one used integer. - { - /* .used_consts = */ - { - "%used_int = OpSpecConstant %int 3", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "OpStore %int_var %used_int", - }, - /* .dead_consts = */ - { - "%dead_int = OpSpecConstant %int 1", - "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_int %dead_int", - "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_int %used_int", - }, - /* .checks = */ - { - "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 3", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[int]]", - }, - }, - - // Int vector type spec constants built with both spec constants and - // front-end constants. - { - /* .used_consts = */ - { - "%used_spec_int = OpSpecConstant %int 3", - "%used_front_end_int = OpConstant %int 3", - }, - /* .main_insts = */ - { - "%int_var1 = OpVariable %_pf_int Output", - "OpStore %int_var1 %used_spec_int", - "%int_var2 = OpVariable %_pf_int Output", - "OpStore %int_var2 %used_front_end_int", - }, - /* .dead_consts = */ - { - "%dead_spec_int = OpSpecConstant %int 1", - "%dead_front_end_int = OpConstant %int 1", - // Dead front-end and dead spec constants - "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_spec_int %dead_front_end_int", - // Used front-end and dead spec constants - "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_spec_int %used_front_end_int", - // Dead front-end and used spec constants - "%dead_int_vec3 = OpSpecConstantComposite %v2int %dead_front_end_int %used_spec_int", - }, - /* .checks = */ - { - "; CHECK: [[int1:%\\w+]] = OpSpecConstant %int 3", - "; CHECK: [[int2:%\\w+]] = OpConstant %int 3", - "; CHECK-NOT: OpSpecConstant", - "; CHECK-NOT: OpConstant", - "; CHECK: OpStore {{%\\w+}} [[int1]]", - "; CHECK: OpStore {{%\\w+}} [[int2]]", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - SpecConstantOp, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Cast operations: uint <-> int <-> bool - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - // Assistant constants, only used in dead spec constant - // operations. - "%signed_zero = OpConstant %int 0", - "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", - "%unsigned_zero = OpConstant %uint 0", - "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - "%signed_one = OpConstant %int 1", - "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one", - "%unsigned_one = OpConstant %uint 1", - "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - - // Spec constants that support casting to each other. - "%dead_bool = OpSpecConstantTrue %bool", - "%dead_uint = OpSpecConstant %uint 1", - "%dead_int = OpSpecConstant %int 2", - "%dead_bool_vec = OpSpecConstantComposite %v2bool %dead_bool %dead_bool", - "%dead_uint_vec = OpSpecConstantComposite %v2uint %dead_uint %dead_uint", - "%dead_int_vec = OpSpecConstantComposite %v2int %dead_int %dead_int", - - // Scalar cast to boolean spec constant. - "%int_to_bool = OpSpecConstantOp %bool INotEqual %dead_int %signed_zero", - "%uint_to_bool = OpSpecConstantOp %bool INotEqual %dead_uint %unsigned_zero", - - // Vector cast to boolean spec constant. - "%int_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_int_vec %signed_zero_vec", - "%uint_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_uint_vec %unsigned_zero_vec", - - // Scalar cast to int spec constant. - "%bool_to_int = OpSpecConstantOp %int Select %dead_bool %signed_one %signed_zero", - "%uint_to_int = OpSpecConstantOp %uint IAdd %dead_uint %unsigned_zero", - - // Vector cast to int spec constant. - "%bool_to_int_vec = OpSpecConstantOp %v2int Select %dead_bool_vec %signed_one_vec %signed_zero_vec", - "%uint_to_int_vec = OpSpecConstantOp %v2uint IAdd %dead_uint_vec %unsigned_zero_vec", - - // Scalar cast to uint spec constant. - "%bool_to_uint = OpSpecConstantOp %uint Select %dead_bool %unsigned_one %unsigned_zero", - "%int_to_uint_vec = OpSpecConstantOp %uint IAdd %dead_int %signed_zero", - - // Vector cast to uint spec constant. - "%bool_to_uint_vec = OpSpecConstantOp %v2uint Select %dead_bool_vec %unsigned_one_vec %unsigned_zero_vec", - "%int_to_uint = OpSpecConstantOp %v2uint IAdd %dead_int_vec %signed_zero_vec", - }, - /* .checks = */ - { - "; CHECK-NOT: OpConstant", - "; CHECK-NOT: OpSpecConstant", - }, - }, - - // Add, sub, mul, div, rem. - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - "%dead_spec_int_a = OpSpecConstant %int 1", - "%dead_spec_int_a_vec = OpSpecConstantComposite %v2int %dead_spec_int_a %dead_spec_int_a", - - "%dead_spec_int_b = OpSpecConstant %int 2", - "%dead_spec_int_b_vec = OpSpecConstantComposite %v2int %dead_spec_int_b %dead_spec_int_b", - - "%dead_const_int_c = OpConstant %int 3", - "%dead_const_int_c_vec = OpConstantComposite %v2int %dead_const_int_c %dead_const_int_c", - - // Add - "%add_a_b = OpSpecConstantOp %int IAdd %dead_spec_int_a %dead_spec_int_b", - "%add_a_b_vec = OpSpecConstantOp %v2int IAdd %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Sub - "%sub_a_b = OpSpecConstantOp %int ISub %dead_spec_int_a %dead_spec_int_b", - "%sub_a_b_vec = OpSpecConstantOp %v2int ISub %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Mul - "%mul_a_b = OpSpecConstantOp %int IMul %dead_spec_int_a %dead_spec_int_b", - "%mul_a_b_vec = OpSpecConstantOp %v2int IMul %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Div - "%div_a_b = OpSpecConstantOp %int SDiv %dead_spec_int_a %dead_spec_int_b", - "%div_a_b_vec = OpSpecConstantOp %v2int SDiv %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Bitwise Xor - "%xor_a_b = OpSpecConstantOp %int BitwiseXor %dead_spec_int_a %dead_spec_int_b", - "%xor_a_b_vec = OpSpecConstantOp %v2int BitwiseXor %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Scalar Comparison - "%less_a_b = OpSpecConstantOp %bool SLessThan %dead_spec_int_a %dead_spec_int_b", - }, - /* .checks = */ - { - "; CHECK-NOT: OpConstant", - "; CHECK-NOT: OpSpecConstant", - }, - }, - - // Vectors without used swizzles should be removed. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 3", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "OpStore %int_var %used_int", - }, - /* .dead_consts = */ - { - "%dead_int = OpConstant %int 3", - - "%dead_spec_int_a = OpSpecConstant %int 1", - "%vec_a = OpSpecConstantComposite %v4int %dead_spec_int_a %dead_spec_int_a %dead_int %dead_int", - - "%dead_spec_int_b = OpSpecConstant %int 2", - "%vec_b = OpSpecConstantComposite %v4int %dead_spec_int_b %dead_spec_int_b %used_int %used_int", - - // Extract scalar - "%a_x = OpSpecConstantOp %int CompositeExtract %vec_a 0", - "%b_x = OpSpecConstantOp %int CompositeExtract %vec_b 0", - - // Extract vector - "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1", - "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1", - }, - /* .checks = */ - { - "; CHECK: [[int:%\\w+]] = OpConstant %int 3", - "; CHECK-NOT: OpConstant", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[int]]", - }, - }, - // Vectors with used swizzles should not be removed. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 3", - "%used_spec_int_a = OpSpecConstant %int 1", - "%used_spec_int_b = OpSpecConstant %int 2", - // Create vectors - "%vec_a = OpSpecConstantComposite %v4int %used_spec_int_a %used_spec_int_a %used_int %used_int", - "%vec_b = OpSpecConstantComposite %v4int %used_spec_int_b %used_spec_int_b %used_int %used_int", - // Extract vector - "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1", - "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1", - }, - /* .main_insts = */ - { - "%v2int_var_a = OpVariable %_pf_v2int Output", - "%v2int_var_b = OpVariable %_pf_v2int Output", - "OpStore %v2int_var_a %a_xy", - "OpStore %v2int_var_b %b_xy", - }, - /* .dead_consts = */ {}, - /* .checks = */ - { - "; CHECK: [[int:%\\w+]] = OpConstant %int 3", - "; CHECK: [[a:%\\w+]] = OpSpecConstant %int 1", - "; CHECK: [[b:%\\w+]] = OpSpecConstant %int 2", - "; CHECK: [[veca:%\\w+]] = OpSpecConstantComposite %v4int [[a]] [[a]] [[int]] [[int]]", - "; CHECK: [[vecb:%\\w+]] = OpSpecConstantComposite %v4int [[b]] [[b]] [[int]] [[int]]", - "; CHECK: [[exa:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[veca]] [[veca]] 0 1", - "; CHECK: [[exb:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[vecb]] [[vecb]] 0 1", - "; CHECK-NOT: OpConstant", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[exa]]", - "; CHECK: OpStore {{%\\w+}} [[exb]]", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - LongDefUseChain, AggressiveEliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Long Def-Use chain with binary operations. - { - /* .used_consts = */ - { - "%array_size = OpConstant %int 4", - "%type_arr_int_4 = OpTypeArray %int %array_size", - "%used_int_0 = OpConstant %int 100", - "%used_int_1 = OpConstant %int 1", - "%used_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_1", - "%used_int_3 = OpSpecConstantOp %int ISub %used_int_0 %used_int_2", - "%used_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_3", - "%used_int_5 = OpSpecConstantOp %int ISub %used_int_0 %used_int_4", - "%used_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_5", - "%used_int_7 = OpSpecConstantOp %int ISub %used_int_0 %used_int_6", - "%used_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_7", - "%used_int_9 = OpSpecConstantOp %int ISub %used_int_0 %used_int_8", - "%used_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_9", - "%used_int_11 = OpSpecConstantOp %int ISub %used_int_0 %used_int_10", - "%used_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_11", - "%used_int_13 = OpSpecConstantOp %int ISub %used_int_0 %used_int_12", - "%used_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_13", - "%used_int_15 = OpSpecConstantOp %int ISub %used_int_0 %used_int_14", - "%used_int_16 = OpSpecConstantOp %int ISub %used_int_0 %used_int_15", - "%used_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_16", - "%used_int_18 = OpSpecConstantOp %int ISub %used_int_0 %used_int_17", - "%used_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_18", - "%used_int_20 = OpSpecConstantOp %int ISub %used_int_0 %used_int_19", - "%used_vec_a = OpSpecConstantComposite %v2int %used_int_18 %used_int_19", - "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a", - "%used_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0", - "%used_array = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Output", - "%used_array_2 = OpCompositeExtract %int %used_array 2", - "OpStore %int_var %used_array_2", - }, - /* .dead_consts = */ - { - "%dead_int_1 = OpConstant %int 2", - "%dead_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_1", - "%dead_int_3 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_2", - "%dead_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_3", - "%dead_int_5 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_4", - "%dead_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_5", - "%dead_int_7 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_6", - "%dead_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_7", - "%dead_int_9 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_8", - "%dead_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_9", - "%dead_int_11 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_10", - "%dead_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_11", - "%dead_int_13 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_12", - "%dead_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_13", - "%dead_int_15 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_14", - "%dead_int_16 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_15", - "%dead_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_16", - "%dead_int_18 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_17", - "%dead_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_18", - "%dead_int_20 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_19", - "%dead_vec_a = OpSpecConstantComposite %v2int %dead_int_18 %dead_int_19", - "%dead_vec_b = OpSpecConstantOp %v2int IMul %dead_vec_a %dead_vec_a", - "%dead_int_21 = OpSpecConstantOp %int CompositeExtract %dead_vec_b 0", - "%dead_array = OpConstantComposite %type_arr_int_4 %dead_int_20 %used_int_20 %dead_int_19 %used_int_19", - }, - /* .checks = */ - { - "; CHECK: OpConstant %int 4", - "; CHECK: [[array:%\\w+]] = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21", - "; CHECK-NOT: OpConstant", - "; CHECK-NOT: OpSpecConstant", - "; CHECK: OpStore {{%\\w+}} [[array]]", - }, - }, - // Long Def-Use chain with swizzle - // clang-format on - }))); - -TEST_F(AggressiveDCETest, DeadDecorationGroup) { - // The decoration group should be eliminated because the target of group - // decorate is dead. - const std::string text = R"( -; CHECK-NOT: OpDecorat -; CHECK-NOT: OpGroupDecorate -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Restrict -OpDecorate %1 Aliased -%1 = OpDecorationGroup -OpGroupDecorate %1 %var -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%uint_ptr = OpTypePointer Function %uint -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %uint_ptr Function -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, DeadDecorationGroupAndValidDecorationMgr) { - // The decoration group should be eliminated because the target of group - // decorate is dead. - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Restrict -OpDecorate %1 Aliased -%1 = OpDecorationGroup -OpGroupDecorate %1 %var -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%uint_ptr = OpTypePointer Function %uint -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %uint_ptr Function -OpReturn -OpFunctionEnd - )"; - - auto pass = MakeUnique(); - auto consumer = [](spv_message_level_t, const char*, const spv_position_t&, - const char* message) { - std::cerr << message << std::endl; - }; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer, text); - - // Build the decoration manager before the pass. - context->get_decoration_mgr(); - - const auto status = pass->Run(context.get()); - EXPECT_EQ(status, Pass::Status::SuccessWithChange); -} - -TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroup) { - const std::string text = R"( -; CHECK: OpDecorate [[grp:%\w+]] Restrict -; CHECK: [[grp]] = OpDecorationGroup -; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]] -; CHECK: [[output]] = OpVariable {{%\w+}} Output -; CHECK-NOT: OpVariable {{%\w+}} Function -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %output -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Restrict -%1 = OpDecorationGroup -OpGroupDecorate %1 %var %output -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%uint_ptr_Function = OpTypePointer Function %uint -%uint_ptr_Output = OpTypePointer Output %uint -%uint_0 = OpConstant %uint 0 -%output = OpVariable %uint_ptr_Output Output -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %uint_ptr_Function Function -OpStore %output %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroupDifferentGroupDecorate) { - const std::string text = R"( -; CHECK: OpDecorate [[grp:%\w+]] Restrict -; CHECK: [[grp]] = OpDecorationGroup -; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]] -; CHECK-NOT: OpGroupDecorate -; CHECK: [[output]] = OpVariable {{%\w+}} Output -; CHECK-NOT: OpVariable {{%\w+}} Function -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %output -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Restrict -%1 = OpDecorationGroup -OpGroupDecorate %1 %output -OpGroupDecorate %1 %var -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%uint_ptr_Function = OpTypePointer Function %uint -%uint_ptr_Output = OpTypePointer Output %uint -%uint_0 = OpConstant %uint 0 -%output = OpVariable %uint_ptr_Output Output -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %uint_ptr_Function Function -OpStore %output %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, DeadGroupMemberDecorate) { - const std::string text = R"( -; CHECK-NOT: OpDec -; CHECK-NOT: OpGroup -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Offset 0 -OpDecorate %1 Uniform -%1 = OpDecorationGroup -OpGroupMemberDecorate %1 %var 0 -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint %uint -%struct_ptr = OpTypePointer Function %struct -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct_ptr Function -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, PartiallyDeadGroupMemberDecorate) { - const std::string text = R"( -; CHECK: OpDecorate [[grp:%\w+]] Offset 0 -; CHECK: OpDecorate [[grp]] RelaxedPrecision -; CHECK: [[grp]] = OpDecorationGroup -; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1 -; CHECK: [[output]] = OpTypeStruct -; CHECK-NOT: OpTypeStruct -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %output -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Offset 0 -OpDecorate %1 RelaxedPrecision -%1 = OpDecorationGroup -OpGroupMemberDecorate %1 %var_struct 0 %output_struct 1 -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%var_struct = OpTypeStruct %uint %uint -%output_struct = OpTypeStruct %uint %uint -%struct_ptr_Function = OpTypePointer Function %var_struct -%struct_ptr_Output = OpTypePointer Output %output_struct -%uint_ptr_Output = OpTypePointer Output %uint -%output = OpVariable %struct_ptr_Output Output -%uint_0 = OpConstant %uint 0 -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct_ptr_Function Function -%3 = OpAccessChain %uint_ptr_Output %output %uint_0 -OpStore %3 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AggressiveDCETest, - PartiallyDeadGroupMemberDecorateDifferentGroupDecorate) { - const std::string text = R"( -; CHECK: OpDecorate [[grp:%\w+]] Offset 0 -; CHECK: OpDecorate [[grp]] RelaxedPrecision -; CHECK: [[grp]] = OpDecorationGroup -; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1 -; CHECK-NOT: OpGroupMemberDecorate -; CHECK: [[output]] = OpTypeStruct -; CHECK-NOT: OpTypeStruct -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %output -OpExecutionMode %main OriginUpperLeft -OpDecorate %1 Offset 0 -OpDecorate %1 RelaxedPrecision -%1 = OpDecorationGroup -OpGroupMemberDecorate %1 %var_struct 0 -OpGroupMemberDecorate %1 %output_struct 1 -%void = OpTypeVoid -%func = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%var_struct = OpTypeStruct %uint %uint -%output_struct = OpTypeStruct %uint %uint -%struct_ptr_Function = OpTypePointer Function %var_struct -%struct_ptr_Output = OpTypePointer Output %output_struct -%uint_ptr_Output = OpTypePointer Output %uint -%output = OpVariable %struct_ptr_Output Output -%uint_0 = OpConstant %uint 0 -%main = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct_ptr_Function Function -%3 = OpAccessChain %uint_ptr_Output %output %uint_0 -OpStore %3 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -// Test for #1404 -TEST_F(AggressiveDCETest, DontRemoveWorkgroupSize) { - const std::string text = R"( -; CHECK: OpDecorate [[wgs:%\w+]] BuiltIn WorkgroupSize -; CHECK: [[wgs]] = OpSpecConstantComposite -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" -OpExecutionMode %func LocalSize 1 1 1 -OpDecorate %1 BuiltIn WorkgroupSize -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%functy = OpTypeFunction %void -%v3int = OpTypeVector %int 3 -%2 = OpSpecConstant %int 1 -%1 = OpSpecConstantComposite %v3int %2 %2 %2 -%func = OpFunction %void None %functy -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -// Test for #1214 -TEST_F(AggressiveDCETest, LoopHeaderIsAlsoAnotherLoopMerge) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" %2 -OpExecutionMode %1 OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%uint_0 = OpConstant %uint 0 -%9 = OpTypeFunction %void -%1 = OpFunction %void None %9 -%10 = OpLabel -OpBranch %11 -%11 = OpLabel -OpLoopMerge %12 %13 None -OpBranchConditional %true %14 %13 -%14 = OpLabel -OpStore %2 %uint_0 -OpLoopMerge %15 %16 None -OpBranchConditional %true %15 %16 -%16 = OpLabel -OpBranch %14 -%15 = OpLabel -OpBranchConditional %true %12 %13 -%13 = OpLabel -OpBranch %11 -%12 = OpLabel -%17 = OpPhi %uint %uint_0 %15 %uint_0 %18 -OpStore %2 %17 -OpLoopMerge %19 %18 None -OpBranchConditional %true %19 %18 -%18 = OpLabel -OpBranch %12 -%19 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(AggressiveDCETest, BreaksDontVisitPhis) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" %var -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int = OpTypeInt 32 0 -%int_ptr_Output = OpTypePointer Output %int -%var = OpVariable %int_ptr_Output Output -%int0 = OpConstant %int 0 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpBranch %outer_header -%outer_header = OpLabel -OpLoopMerge %outer_merge %outer_continue None -OpBranchConditional %true %inner_header %outer_continue -%inner_header = OpLabel -%phi = OpPhi %int %int0 %outer_header %int0 %inner_continue -OpStore %var %phi -OpLoopMerge %inner_merge %inner_continue None -OpBranchConditional %true %inner_merge %inner_continue -%inner_continue = OpLabel -OpBranch %inner_header -%inner_merge = OpLabel -OpBranch %outer_continue -%outer_continue = OpLabel -%p = OpPhi %int %int0 %outer_header %int0 %inner_merge -OpStore %var %p -OpBranch %outer_header -%outer_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, - std::get<1>(SinglePassRunAndDisassemble( - text, false, true))); -} - -// Test for #1212 -TEST_F(AggressiveDCETest, ConstStoreInnerLoop) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "main" %2 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%_ptr_Output_float = OpTypePointer Output %float -%2 = OpVariable %_ptr_Output_float Output -%float_3 = OpConstant %float 3 -%1 = OpFunction %void None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -OpLoopMerge %15 %16 None -OpBranchConditional %true %17 %15 -%17 = OpLabel -OpStore %2 %float_3 -OpLoopMerge %18 %17 None -OpBranchConditional %true %18 %17 -%18 = OpLabel -OpBranch %15 -%16 = OpLabel -OpBranch %14 -%15 = OpLabel -OpBranch %20 -%20 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, text, true, true); -} - -// Test for #1212 -TEST_F(AggressiveDCETest, InnerLoopCopy) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "main" %2 %3 -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%_ptr_Output_float = OpTypePointer Output %float -%_ptr_Input_float = OpTypePointer Input %float -%2 = OpVariable %_ptr_Output_float Output -%3 = OpVariable %_ptr_Input_float Input -%1 = OpFunction %void None %5 -%14 = OpLabel -OpBranch %15 -%15 = OpLabel -OpLoopMerge %16 %17 None -OpBranchConditional %true %18 %16 -%18 = OpLabel -%19 = OpLoad %float %3 -OpStore %2 %19 -OpLoopMerge %20 %18 None -OpBranchConditional %true %20 %18 -%20 = OpLabel -OpBranch %16 -%17 = OpLabel -OpBranch %15 -%16 = OpLabel -OpBranch %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(AggressiveDCETest, AtomicAdd) { - const std::string text = R"(OpCapability SampledBuffer -OpCapability StorageImageExtendedFormats -OpCapability ImageBuffer -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID -OpExecutionMode %2 LocalSize 64 1 1 -OpSource HLSL 600 -OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId -OpDecorate %4 DescriptorSet 4 -OpDecorate %4 Binding 70 -%uint = OpTypeInt 32 0 -%6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui -%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6 -%_ptr_Private_6 = OpTypePointer Private %6 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%_ptr_Image_uint = OpTypePointer Image %uint -%4 = OpVariable %_ptr_UniformConstant_6 UniformConstant -%16 = OpVariable %_ptr_Private_6 Private -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%2 = OpFunction %void None %10 -%17 = OpLabel -%18 = OpLoad %6 %4 -OpStore %16 %18 -%19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0 -%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(AggressiveDCETest, SafelyRemoveDecorateString) { - const std::string preamble = R"(OpCapability Shader -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -)"; - - const std::string body_before = - R"(OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "FOOBAR" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer -%1 = OpFunction %void None %4 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string body_after = R"(%void = OpTypeVoid -%4 = OpTypeFunction %void -%1 = OpFunction %void None %4 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(preamble + body_before, - preamble + body_after, true, true); -} - -TEST_F(AggressiveDCETest, CopyMemoryToGlobal) { - // |local| is loaded in an OpCopyMemory instruction. So the store must be - // kept alive. - const std::string test = - R"(OpCapability Geometry -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" %global -OpExecutionMode %main Triangles -OpExecutionMode %main Invocations 1 -OpExecutionMode %main OutputTriangleStrip -OpExecutionMode %main OutputVertices 5 -OpSource GLSL 440 -OpName %main "main" -OpName %local "local" -OpName %global "global" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%12 = OpConstantNull %v4float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%global = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%19 = OpLabel -%local = OpVariable %_ptr_Function_v4float Function -OpStore %local %12 -OpCopyMemory %global %local -OpEndPrimitive -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, true, true); -} - -TEST_F(AggressiveDCETest, CopyMemoryToLocal) { - // Make sure the store to |local2| using OpCopyMemory is kept and keeps - // |local1| alive. - const std::string test = - R"(OpCapability Geometry -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" %global -OpExecutionMode %main Triangles -OpExecutionMode %main Invocations 1 -OpExecutionMode %main OutputTriangleStrip -OpExecutionMode %main OutputVertices 5 -OpSource GLSL 440 -OpName %main "main" -OpName %local1 "local1" -OpName %local2 "local2" -OpName %global "global" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%12 = OpConstantNull %v4float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%global = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%19 = OpLabel -%local1 = OpVariable %_ptr_Function_v4float Function -%local2 = OpVariable %_ptr_Function_v4float Function -OpStore %local1 %12 -OpCopyMemory %local2 %local1 -OpCopyMemory %global %local2 -OpEndPrimitive -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, true, true); -} - -TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal) { - // Test that we remove function scope variables that are stored to using - // OpCopyMemory, but are never loaded. We can remove both |local1| and - // |local2|. - const std::string test = - R"(OpCapability Geometry -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" %global -OpExecutionMode %main Triangles -OpExecutionMode %main Invocations 1 -OpExecutionMode %main OutputTriangleStrip -OpExecutionMode %main OutputVertices 5 -OpSource GLSL 440 -OpName %main "main" -OpName %local1 "local1" -OpName %local2 "local2" -OpName %global "global" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%12 = OpConstantNull %v4float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%global = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%19 = OpLabel -%local1 = OpVariable %_ptr_Function_v4float Function -%local2 = OpVariable %_ptr_Function_v4float Function -OpStore %local1 %12 -OpCopyMemory %local2 %local1 -OpEndPrimitive -OpReturn -OpFunctionEnd -)"; - - const std::string result = - R"(OpCapability Geometry -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" %global -OpExecutionMode %main Triangles -OpExecutionMode %main Invocations 1 -OpExecutionMode %main OutputTriangleStrip -OpExecutionMode %main OutputVertices 5 -OpSource GLSL 440 -OpName %main "main" -OpName %global "global" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%global = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%19 = OpLabel -OpEndPrimitive -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, result, true, true); -} - -TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal2) { - // We are able to remove "local2" because it is not loaded, but have to keep - // the stores to "local1". - const std::string test = - R"(OpCapability Geometry -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" %global -OpExecutionMode %main Triangles -OpExecutionMode %main Invocations 1 -OpExecutionMode %main OutputTriangleStrip -OpExecutionMode %main OutputVertices 5 -OpSource GLSL 440 -OpName %main "main" -OpName %local1 "local1" -OpName %local2 "local2" -OpName %global "global" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%12 = OpConstantNull %v4float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%global = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%19 = OpLabel -%local1 = OpVariable %_ptr_Function_v4float Function -%local2 = OpVariable %_ptr_Function_v4float Function -OpStore %local1 %12 -OpCopyMemory %local2 %local1 -OpCopyMemory %global %local1 -OpEndPrimitive -OpReturn -OpFunctionEnd -)"; - - const std::string result = - R"(OpCapability Geometry -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" %global -OpExecutionMode %main Triangles -OpExecutionMode %main Invocations 1 -OpExecutionMode %main OutputTriangleStrip -OpExecutionMode %main OutputVertices 5 -OpSource GLSL 440 -OpName %main "main" -OpName %local1 "local1" -OpName %global "global" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%12 = OpConstantNull %v4float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%global = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %7 -%19 = OpLabel -%local1 = OpVariable %_ptr_Function_v4float Function -OpStore %local1 %12 -OpCopyMemory %global %local1 -OpEndPrimitive -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, result, true, true); -} - -TEST_F(AggressiveDCETest, StructuredIfWithConditionalExit) { - // We are able to remove "local2" because it is not loaded, but have to keep - // the stores to "local1". - const std::string test = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpName %main "main" -OpName %a "a" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Uniform_int = OpTypePointer Uniform %int -%int_0 = OpConstant %int 0 -%bool = OpTypeBool -%int_100 = OpConstant %int 100 -%int_1 = OpConstant %int 1 -%a = OpVariable %_ptr_Uniform_int Uniform -%main = OpFunction %void None %5 -%12 = OpLabel -%13 = OpLoad %int %a -%14 = OpSGreaterThan %bool %13 %int_0 -OpSelectionMerge %15 None -OpBranchConditional %14 %16 %15 -%16 = OpLabel -%17 = OpLoad %int %a -%18 = OpSLessThan %bool %17 %int_100 -OpBranchConditional %18 %19 %15 -%19 = OpLabel -OpStore %a %int_1 -OpBranch %15 -%15 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, true, true); -} - -TEST_F(AggressiveDCETest, CountingLoopNotEliminated) { - // #version 310 es - // - // precision highp float; - // precision highp int; - // - // layout(location = 0) out vec4 _GLF_color; - // - // void main() - // { - // float data[1]; - // for (int c = 0; c < 1; c++) { - // if (true) { - // do { - // for (int i = 0; i < 1; i++) { - // data[i] = 1.0; - // } - // } while (false); - // } - // } - // _GLF_color = vec4(data[0], 0.0, 0.0, 1.0); - // } - const std::string test = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_GLF_color -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -OpName %c "c" -OpName %i "i" -OpName %data "data" -OpName %_GLF_color "_GLF_color" -OpDecorate %_GLF_color Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%bool = OpTypeBool -%float = OpTypeFloat 32 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1 -%float_1 = OpConstant %float 1 -%_ptr_Function_float = OpTypePointer Function %float -%false = OpConstantFalse %bool -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_GLF_color = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%main = OpFunction %void None %8 -%26 = OpLabel -%c = OpVariable %_ptr_Function_int Function -%i = OpVariable %_ptr_Function_int Function -%data = OpVariable %_ptr_Function__arr_float_uint_1 Function -OpStore %c %int_0 -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -%31 = OpLoad %int %c -%32 = OpSLessThan %bool %31 %int_1 -OpBranchConditional %32 %33 %28 -%33 = OpLabel -OpBranch %34 -%34 = OpLabel -OpBranch %35 -%35 = OpLabel -OpLoopMerge %36 %37 None -OpBranch %38 -%38 = OpLabel -OpStore %i %int_0 -OpBranch %39 -%39 = OpLabel -OpLoopMerge %40 %41 None -OpBranch %42 -%42 = OpLabel -%43 = OpLoad %int %i -%44 = OpSLessThan %bool %43 %int_1 -OpBranchConditional %44 %46 %40 -%46 = OpLabel -%47 = OpLoad %int %i -%48 = OpAccessChain %_ptr_Function_float %data %47 -OpStore %48 %float_1 -OpBranch %41 -%41 = OpLabel -%49 = OpLoad %int %i -%50 = OpIAdd %int %49 %int_1 -OpStore %i %50 -OpBranch %39 -%40 = OpLabel -OpBranch %37 -%37 = OpLabel -OpBranchConditional %false %35 %36 -%36 = OpLabel -OpBranch %45 -%45 = OpLabel -OpBranch %29 -%29 = OpLabel -%51 = OpLoad %int %c -%52 = OpIAdd %int %51 %int_1 -OpStore %c %52 -OpBranch %27 -%28 = OpLabel -%53 = OpAccessChain %_ptr_Function_float %data %int_0 -%54 = OpLoad %float %53 -%55 = OpCompositeConstruct %v4float %54 %float_0 %float_0 %float_1 -OpStore %_GLF_color %55 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, true, true); -} - -TEST_F(AggressiveDCETest, EliminateLoopWithUnreachable) { - // #version 430 - // - // layout(std430) buffer U_t - // { - // float g_F[10]; - // float g_S; - // }; - // - // layout(location = 0)out float o; - // - // void main(void) - // { - // // Useless loop - // for (int i = 0; i<10; i++) { - // if (g_F[i] == 0.0) - // break; - // else - // break; - // // Unreachable merge block created here. - // // Need to edit SPIR-V to change to OpUnreachable - // } - // o = g_S; - // } - - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %i "i" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpMemberName %U_t 1 "g_S" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpMemberDecorate %U_t 1 Offset 40 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%float = OpTypeFloat 32 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 %float -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%float_0 = OpConstant %float 0 -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %9 -%23 = OpLabel -%i = OpVariable %_ptr_Function_int Function -OpStore %i %int_0 -OpBranch %24 -%24 = OpLabel -OpLoopMerge %25 %26 None -OpBranch %27 -%27 = OpLabel -%28 = OpLoad %int %i -%29 = OpSLessThan %bool %28 %int_10 -OpBranchConditional %29 %30 %25 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %31 -%33 = OpLoad %float %32 -%34 = OpFOrdEqual %bool %33 %float_0 -OpSelectionMerge %35 None -OpBranchConditional %34 %36 %37 -%36 = OpLabel -OpBranch %25 -%37 = OpLabel -OpBranch %25 -%35 = OpLabel -OpUnreachable -%26 = OpLabel -%38 = OpLoad %int %i -%39 = OpIAdd %int %38 %int_1 -OpStore %i %39 -OpBranch %24 -%25 = OpLabel -%40 = OpAccessChain %_ptr_Uniform_float %_ %int_1 -%41 = OpLoad %float %40 -OpStore %o %41 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %o -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_F" -OpMemberName %U_t 1 "g_S" -OpName %_ "" -OpName %o "o" -OpDecorate %_arr_float_uint_10 ArrayStride 4 -OpMemberDecorate %U_t 0 Offset 0 -OpMemberDecorate %U_t 1 Offset 40 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpDecorate %o Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%float = OpTypeFloat 32 -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%U_t = OpTypeStruct %_arr_float_uint_10 %float -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%o = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %9 -%23 = OpLabel -OpBranch %24 -%24 = OpLabel -OpBranch %25 -%25 = OpLabel -%40 = OpAccessChain %_ptr_Uniform_float %_ %int_1 -%41 = OpLoad %float %40 -OpStore %o %41 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(AggressiveDCETest, DeadHlslCounterBufferGOOGLE) { - // We are able to remove "local2" because it is not loaded, but have to keep - // the stores to "local1". - const std::string test = - R"( -; CHECK-NOT: OpDecorateId -; CHECK: [[var:%\w+]] = OpVariable -; CHECK-NOT: OpVariable -; CHECK: [[ac:%\w+]] = OpAccessChain {{%\w+}} [[var]] -; CHECK: OpStore [[ac]] - OpCapability Shader - OpExtension "SPV_GOOGLE_hlsl_functionality1" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 32 1 1 - OpSource HLSL 600 - OpDecorate %_runtimearr_v2float ArrayStride 8 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_struct_3 BufferBlock - OpMemberDecorate %_struct_4 0 Offset 0 - OpDecorate %_struct_4 BufferBlock - OpDecorateId %5 HlslCounterBufferGOOGLE %6 - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %6 DescriptorSet 0 - OpDecorate %6 Binding 1 - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 -%_runtimearr_v2float = OpTypeRuntimeArray %v2float - %_struct_3 = OpTypeStruct %_runtimearr_v2float -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 - %int = OpTypeInt 32 1 - %_struct_4 = OpTypeStruct %int -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 - %void = OpTypeVoid - %13 = OpTypeFunction %void - %19 = OpConstantNull %v2float - %int_0 = OpConstant %int 0 -%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float - %5 = OpVariable %_ptr_Uniform__struct_3 Uniform - %6 = OpVariable %_ptr_Uniform__struct_4 Uniform - %1 = OpFunction %void None %13 - %22 = OpLabel - %23 = OpAccessChain %_ptr_Uniform_v2float %5 %int_0 %int_0 - OpStore %23 %19 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(test, true); -} - -TEST_F(AggressiveDCETest, Dead) { - // We are able to remove "local2" because it is not loaded, but have to keep - // the stores to "local1". - const std::string test = - R"( -; CHECK: OpCapability -; CHECK-NOT: OpMemberDecorateStringGOOGLE -; CHECK: OpFunctionEnd - OpCapability Shader - OpExtension "SPV_GOOGLE_hlsl_functionality1" - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %VSMain "VSMain" - OpSource HLSL 500 - OpName %VSMain "VSMain" - OpName %PSInput "PSInput" - OpMemberName %PSInput 0 "Pos" - OpMemberName %PSInput 1 "uv" - OpMemberDecorateStringGOOGLE %PSInput 0 HlslSemanticGOOGLE "SV_POSITION" - OpMemberDecorateStringGOOGLE %PSInput 1 HlslSemanticGOOGLE "TEX_COORD" - %void = OpTypeVoid - %5 = OpTypeFunction %void - %float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%PSInput = OpTypeStruct %v4float %v2float - %VSMain = OpFunction %void None %5 - %9 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(test, true); -} - -TEST_F(AggressiveDCETest, DeadInfiniteLoop) { - const std::string test = R"( -; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpBranch [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpBranch [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpReturn - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeFloat 32 - %9 = OpTypeVector %8 3 - %10 = OpTypeFunction %9 - %11 = OpConstant %8 1 - %12 = OpConstantComposite %9 %11 %11 %11 - %13 = OpTypeInt 32 1 - %32 = OpUndef %13 - %2 = OpFunction %6 None %7 - %33 = OpLabel - OpBranch %34 - %34 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpFunctionCall %9 %39 - OpSelectionMerge %40 None - OpSwitch %32 %40 14 %41 58 %42 - %42 = OpLabel - OpBranch %43 - %43 = OpLabel - OpLoopMerge %44 %45 None - OpBranch %45 - %45 = OpLabel - OpBranch %43 - %44 = OpLabel - OpUnreachable - %41 = OpLabel - OpBranch %36 - %40 = OpLabel - OpBranch %36 - %36 = OpLabel - OpBranch %34 - %35 = OpLabel - OpReturn - OpFunctionEnd - %39 = OpFunction %9 None %10 - %46 = OpLabel - OpReturnValue %12 - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(test, true); -} - -TEST_F(AggressiveDCETest, DeadInfiniteLoopReturnValue) { - const std::string test = R"( -; CHECK: [[vec3:%\w+]] = OpTypeVector -; CHECK: [[undef:%\w+]] = OpUndef [[vec3]] -; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpBranch [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpBranch [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpReturnValue [[undef]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeFloat 32 - %9 = OpTypeVector %8 3 - %10 = OpTypeFunction %9 - %11 = OpConstant %8 1 - %12 = OpConstantComposite %9 %11 %11 %11 - %13 = OpTypeInt 32 1 - %32 = OpUndef %13 - %2 = OpFunction %6 None %7 - %entry = OpLabel - %call = OpFunctionCall %9 %func - OpReturn - OpFunctionEnd - %func = OpFunction %9 None %10 - %33 = OpLabel - OpBranch %34 - %34 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpFunctionCall %9 %39 - OpSelectionMerge %40 None - OpSwitch %32 %40 14 %41 58 %42 - %42 = OpLabel - OpBranch %43 - %43 = OpLabel - OpLoopMerge %44 %45 None - OpBranch %45 - %45 = OpLabel - OpBranch %43 - %44 = OpLabel - OpUnreachable - %41 = OpLabel - OpBranch %36 - %40 = OpLabel - OpBranch %36 - %36 = OpLabel - OpBranch %34 - %35 = OpLabel - OpReturnValue %12 - OpFunctionEnd - %39 = OpFunction %9 None %10 - %46 = OpLabel - OpReturnValue %12 - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(test, true); -} - -TEST_F(AggressiveDCETest, TestVariablePointer) { - const std::string before = - R"(OpCapability Shader -OpCapability VariablePointers -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "main" -OpExecutionMode %2 LocalSize 1 1 1 -OpSource GLSL 450 -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_struct_3 Block -OpDecorate %4 DescriptorSet 0 -OpDecorate %4 Binding 0 -OpDecorate %_ptr_StorageBuffer_int ArrayStride 4 -OpDecorate %_arr_int_int_128 ArrayStride 4 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%int_128 = OpConstant %int 128 -%_arr_int_int_128 = OpTypeArray %int %int_128 -%_struct_3 = OpTypeStruct %_arr_int_int_128 -%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3 -%4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int -%2 = OpFunction %void None %8 -%16 = OpLabel -%17 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0 -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %_ptr_StorageBuffer_int %17 %16 %20 %21 -OpLoopMerge %22 %21 None -OpBranchConditional %true %23 %22 -%23 = OpLabel -OpStore %19 %int_0 -OpBranch %21 -%21 = OpLabel -%20 = OpPtrAccessChain %_ptr_StorageBuffer_int %19 %int_1 -OpBranch %18 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, before, true, true); -} - -TEST_F(AggressiveDCETest, DeadInputInterfaceV13) { - const std::string spirv = R"( -; CHECK: OpEntryPoint GLCompute %main "main" [[var:%\w+]] -; CHECK: [[var]] = OpVariable -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %dead -OpExecutionMode %main LocalSize 1 1 1 -OpName %main "main" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_input_int = OpTypePointer Input %int -%dead = OpVariable %ptr_input_int Input -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_3); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(AggressiveDCETest, DeadInputInterfaceV14) { - const std::string spirv = R"( -; CHECK: OpEntryPoint GLCompute %main "main" [[var:%\w+]] -; CHECK: [[var]] = OpVariable -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %dead -OpExecutionMode %main LocalSize 1 1 1 -OpName %main "main" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_input_int = OpTypePointer Input %int -%dead = OpVariable %ptr_input_int Input -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(AggressiveDCETest, DeadInterfaceV14) { - const std::string spirv = R"( -; CHECK-NOT: OpEntryPoint GLCompute %main "main" % -; CHECK: OpEntryPoint GLCompute %main "main" -; CHECK-NOT: OpVariable -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %dead -OpExecutionMode %main LocalSize 1 1 1 -OpName %main "main" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_private_int = OpTypePointer Private %int -%dead = OpVariable %ptr_private_int Private -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(AggressiveDCETest, DeadInterfacesV14) { - const std::string spirv = R"( -; CHECK: OpEntryPoint GLCompute %main "main" %live1 %live2 -; CHECK-NOT: %dead -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %live1 %dead1 %dead2 %live2 -OpExecutionMode %main LocalSize 1 1 1 -OpName %main "main" -OpName %live1 "live1" -OpName %live2 "live2" -OpName %dead1 "dead1" -OpName %dead2 "dead2" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%live1 = OpVariable %ptr_ssbo_int StorageBuffer -%live2 = OpVariable %ptr_ssbo_int StorageBuffer -%dead1 = OpVariable %ptr_ssbo_int StorageBuffer -%dead2 = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpStore %live1 %int0 -OpStore %live2 %int0 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(AggressiveDCETest, PreserveBindings) { - const std::string spirv = R"( -; CHECK: OpDecorate %unusedSampler DescriptorSet 0 -; CHECK: OpDecorate %unusedSampler Binding 0 -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %unusedSampler "unusedSampler" -OpDecorate %unusedSampler DescriptorSet 0 -OpDecorate %unusedSampler Binding 0 -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%7 = OpTypeImage %float 2D 0 0 0 1 Unknown -%8 = OpTypeSampledImage %7 -%_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8 -%unusedSampler = OpVariable %_ptr_UniformConstant_8 UniformConstant -%main = OpFunction %void None %5 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - - OptimizerOptions()->preserve_bindings_ = true; - - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(AggressiveDCETest, PreserveSpecConstants) { - const std::string spirv = R"( -; CHECK: OpName %specConstant "specConstant" -; CHECK: %specConstant = OpSpecConstant %int 0 -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %specConstant "specConstant" -OpDecorate %specConstant SpecId 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%specConstant = OpSpecConstant %int 0 -%main = OpFunction %void None %3 -%5 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - - OptimizerOptions()->preserve_spec_constants_ = true; - - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(AggressiveDCETest, LiveDecorateId) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" %2 -OpExecutionMode %1 LocalSize 8 1 1 -OpDecorate %2 DescriptorSet 0 -OpDecorate %2 Binding 0 -OpDecorateId %3 UniformId %uint_2 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_2 = OpConstant %uint 2 -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer -%8 = OpTypeFunction %void -%1 = OpFunction %void None %8 -%9 = OpLabel -%3 = OpLoad %uint %2 -OpStore %2 %3 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - OptimizerOptions()->preserve_spec_constants_ = true; - SinglePassRunAndCheck(spirv, spirv, true); -} - -TEST_F(AggressiveDCETest, LiveDecorateIdOnGroup) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" %2 -OpExecutionMode %1 LocalSize 8 1 1 -OpDecorate %2 DescriptorSet 0 -OpDecorate %2 Binding 0 -OpDecorateId %3 UniformId %uint_2 -%3 = OpDecorationGroup -OpGroupDecorate %3 %5 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_2 = OpConstant %uint 2 -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer -%9 = OpTypeFunction %void -%1 = OpFunction %void None %9 -%10 = OpLabel -%5 = OpLoad %uint %2 -OpStore %2 %5 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - OptimizerOptions()->preserve_spec_constants_ = true; - SinglePassRunAndCheck(spirv, spirv, true); -} - -TEST_F(AggressiveDCETest, NoEliminateForwardPointer) { - // clang-format off - // - // #version 450 - // #extension GL_EXT_buffer_reference : enable - // - // // forward reference - // layout(buffer_reference) buffer blockType; - // - // layout(buffer_reference, std430, buffer_reference_align = 16) buffer blockType { - // int x; - // blockType next; - // }; - // - // layout(std430) buffer rootBlock { - // blockType root; - // } r; - // - // void main() - // { - // blockType b = r.root; - // b = b.next; - // b.x = 531; - // } - // - // clang-format on - - const std::string predefs1 = - R"(OpCapability Shader -OpCapability PhysicalStorageBufferAddresses -OpExtension "SPV_EXT_physical_storage_buffer" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_buffer_reference" -)"; - - const std::string names_before = - R"(OpName %main "main" -OpName %blockType "blockType" -OpMemberName %blockType 0 "x" -OpMemberName %blockType 1 "next" -OpName %b "b" -OpName %rootBlock "rootBlock" -OpMemberName %rootBlock 0 "root" -OpName %r "r" -OpMemberDecorate %blockType 0 Offset 0 -OpMemberDecorate %blockType 1 Offset 8 -OpDecorate %blockType Block -OpDecorate %b AliasedPointer -OpMemberDecorate %rootBlock 0 Offset 0 -OpDecorate %rootBlock Block -OpDecorate %r DescriptorSet 0 -OpDecorate %r Binding 0 -)"; - - const std::string names_after = - R"(OpName %main "main" -OpName %blockType "blockType" -OpMemberName %blockType 0 "x" -OpMemberName %blockType 1 "next" -OpName %rootBlock "rootBlock" -OpMemberName %rootBlock 0 "root" -OpName %r "r" -OpMemberDecorate %blockType 0 Offset 0 -OpMemberDecorate %blockType 1 Offset 8 -OpDecorate %blockType Block -OpMemberDecorate %rootBlock 0 Offset 0 -OpDecorate %rootBlock Block -OpDecorate %r DescriptorSet 0 -OpDecorate %r Binding 0 -)"; - - const std::string predefs2_before = - R"(%void = OpTypeVoid -%3 = OpTypeFunction %void -OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer -%int = OpTypeInt 32 1 -%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType -%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType -%_ptr_Function__ptr_PhysicalStorageBuffer_blockType = OpTypePointer Function %_ptr_PhysicalStorageBuffer_blockType -%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType -%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock -%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_1 = OpConstant %int 1 -%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_531 = OpConstant %int 531 -%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int -)"; - - const std::string predefs2_after = - R"(%void = OpTypeVoid -%8 = OpTypeFunction %void -OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer -%int = OpTypeInt 32 1 -%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType -%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType -%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType -%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock -%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_1 = OpConstant %int 1 -%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_531 = OpConstant %int 531 -%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%b = OpVariable %_ptr_Function__ptr_PhysicalStorageBuffer_blockType Function -%16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0 -%17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16 -%21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1 -%22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8 -OpStore %b %22 -%26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0 -OpStore %26 %int_531 Aligned 16 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %8 -%19 = OpLabel -%20 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0 -%21 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %20 -%22 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %21 %int_1 -%23 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %22 Aligned 8 -%24 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %23 %int_0 -OpStore %24 %int_531 Aligned 16 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs1 + names_before + predefs2_before + func_before, - predefs1 + names_after + predefs2_after + func_after, true, true); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// Check that logical addressing required -// Check that function calls inhibit optimization -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/amd_ext_to_khr.cpp b/3rdparty/spirv-tools/test/opt/amd_ext_to_khr.cpp deleted file mode 100644 index d943d3425..000000000 --- a/3rdparty/spirv-tools/test/opt/amd_ext_to_khr.cpp +++ /dev/null @@ -1,918 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "gmock/gmock.h" - -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using AmdExtToKhrTest = PassTest<::testing::Test>; - -using ::testing::HasSubstr; - -std::string GetTest(std::string op_code, std::string new_op_code) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot" -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[undef:%\w+]] = OpUndef %uint -; CHECK-NEXT: )" + new_op_code + - R"( %uint %uint_3 Reduce [[undef]] - OpCapability Shader - OpCapability Groups - OpExtension "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %uint - %8 = )" + op_code + - R"( %uint %uint_3 Reduce %7 - OpReturn - OpFunctionEnd - -)"; - return text; -} - -TEST_F(AmdExtToKhrTest, ReplaceGroupIAddNonUniformAMD) { - std::string text = - GetTest("OpGroupIAddNonUniformAMD", "OpGroupNonUniformIAdd"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupFAddNonUniformAMD) { - std::string text = - GetTest("OpGroupFAddNonUniformAMD", "OpGroupNonUniformFAdd"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupUMinNonUniformAMD) { - std::string text = - GetTest("OpGroupUMinNonUniformAMD", "OpGroupNonUniformUMin"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupSMinNonUniformAMD) { - std::string text = - GetTest("OpGroupSMinNonUniformAMD", "OpGroupNonUniformSMin"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupFMinNonUniformAMD) { - std::string text = - GetTest("OpGroupFMinNonUniformAMD", "OpGroupNonUniformFMin"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupUMaxNonUniformAMD) { - std::string text = - GetTest("OpGroupUMaxNonUniformAMD", "OpGroupNonUniformUMax"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupSMaxNonUniformAMD) { - std::string text = - GetTest("OpGroupSMaxNonUniformAMD", "OpGroupNonUniformSMax"); - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceGroupFMaxNonUniformAMD) { - std::string text = - GetTest("OpGroupFMaxNonUniformAMD", "OpGroupNonUniformFMax"); - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceMbcntAMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot" -; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLtMask -; CHECK: [[var]] = OpVariable %_ptr_Input_v4uint Input -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[ld:%\w+]] = OpLoad %v4uint [[var]] -; CHECK-NEXT: [[shuffle:%\w+]] = OpVectorShuffle %v2uint [[ld]] [[ld]] 0 1 -; CHECK-NEXT: [[bitcast:%\w+]] = OpBitcast %ulong [[shuffle]] -; CHECK-NEXT: [[and:%\w+]] = OpBitwiseAnd %ulong [[bitcast]] %ulong_0 -; CHECK-NEXT: [[result:%\w+]] = OpBitCount %uint [[and]] - OpCapability Shader - OpCapability Int64 - OpExtension "SPV_AMD_shader_ballot" - %1 = OpExtInstImport "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "func" - OpExecutionMode %2 OriginUpperLeft - %void = OpTypeVoid - %4 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %ulong = OpTypeInt 64 0 - %ulong_0 = OpConstant %ulong 0 - %2 = OpFunction %void None %4 - %8 = OpLabel - %9 = OpExtInst %uint %1 MbcntAMD %ulong_0 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceSwizzleInvocationsAMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot" -; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLocalInvocationId -; CHECK: [[subgroup:%\w+]] = OpConstant %uint 3 -; CHECK: [[offset:%\w+]] = OpConstantComposite %v4uint -; CHECK: [[var]] = OpVariable %_ptr_Input_uint Input -; CHECK: [[uint_max:%\w+]] = OpConstant %uint 4294967295 -; CHECK: [[ballot_value:%\w+]] = OpConstantComposite %v4uint [[uint_max]] [[uint_max]] [[uint_max]] [[uint_max]] -; CHECK: [[null:%\w+]] = OpConstantNull [[type:%\w+]] -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[data:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[id:%\w+]] = OpLoad %uint [[var]] -; CHECK-NEXT: [[quad_idx:%\w+]] = OpBitwiseAnd %uint [[id]] %uint_3 -; CHECK-NEXT: [[quad_ldr:%\w+]] = OpBitwiseXor %uint [[id]] [[quad_idx]] -; CHECK-NEXT: [[my_offset:%\w+]] = OpVectorExtractDynamic %uint [[offset]] [[quad_idx]] -; CHECK-NEXT: [[target_inv:%\w+]] = OpIAdd %uint [[quad_ldr]] [[my_offset]] -; CHECK-NEXT: [[is_active:%\w+]] = OpGroupNonUniformBallotBitExtract %bool [[subgroup]] [[ballot_value]] [[target_inv]] -; CHECK-NEXT: [[shuffle:%\w+]] = OpGroupNonUniformShuffle [[type]] [[subgroup]] [[data]] [[target_inv]] -; CHECK-NEXT: [[result:%\w+]] = OpSelect [[type]] [[is_active]] [[shuffle]] [[null]] - OpCapability Shader - OpExtension "SPV_AMD_shader_ballot" - %ext = OpExtInstImport "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_x = OpConstant %uint 1 - %uint_y = OpConstant %uint 2 - %uint_z = OpConstant %uint 3 - %uint_w = OpConstant %uint 0 - %v4uint = OpTypeVector %uint 4 - %offset = OpConstantComposite %v4uint %uint_x %uint_y %uint_z %uint_x - %1 = OpFunction %void None %3 - %6 = OpLabel - %data = OpUndef %uint - %9 = OpExtInst %uint %ext SwizzleInvocationsAMD %data %offset - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} -TEST_F(AmdExtToKhrTest, ReplaceSwizzleInvocationsMaskedAMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot" -; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLocalInvocationId -; CHECK: [[x:%\w+]] = OpConstant %uint 19 -; CHECK: [[y:%\w+]] = OpConstant %uint 12 -; CHECK: [[z:%\w+]] = OpConstant %uint 16 -; CHECK: [[var]] = OpVariable %_ptr_Input_uint Input -; CHECK: [[mask_extend:%\w+]] = OpConstant %uint 4294967264 -; CHECK: [[uint_max:%\w+]] = OpConstant %uint 4294967295 -; CHECK: [[subgroup:%\w+]] = OpConstant %uint 3 -; CHECK: [[ballot_value:%\w+]] = OpConstantComposite %v4uint [[uint_max]] [[uint_max]] [[uint_max]] [[uint_max]] -; CHECK: [[null:%\w+]] = OpConstantNull [[type:%\w+]] -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[data:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[id:%\w+]] = OpLoad %uint [[var]] -; CHECK-NEXT: [[and_mask:%\w+]] = OpBitwiseOr %uint [[x]] [[mask_extend]] -; CHECK-NEXT: [[and:%\w+]] = OpBitwiseAnd %uint [[id]] [[and_mask]] -; CHECK-NEXT: [[or:%\w+]] = OpBitwiseOr %uint [[and]] [[y]] -; CHECK-NEXT: [[target_inv:%\w+]] = OpBitwiseXor %uint [[or]] [[z]] -; CHECK-NEXT: [[is_active:%\w+]] = OpGroupNonUniformBallotBitExtract %bool [[subgroup]] [[ballot_value]] [[target_inv]] -; CHECK-NEXT: [[shuffle:%\w+]] = OpGroupNonUniformShuffle [[type]] [[subgroup]] [[data]] [[target_inv]] -; CHECK-NEXT: [[result:%\w+]] = OpSelect [[type]] [[is_active]] [[shuffle]] [[null]] - OpCapability Shader - OpExtension "SPV_AMD_shader_ballot" - %ext = OpExtInstImport "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_x = OpConstant %uint 19 - %uint_y = OpConstant %uint 12 - %uint_z = OpConstant %uint 16 - %v3uint = OpTypeVector %uint 3 - %mask = OpConstantComposite %v3uint %uint_x %uint_y %uint_z - %1 = OpFunction %void None %3 - %6 = OpLabel - %data = OpUndef %uint - %9 = OpExtInst %uint %ext SwizzleInvocationsMaskedAMD %data %mask - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceWriteInvocationAMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot" -; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLocalInvocationId -; CHECK: [[var]] = OpVariable %_ptr_Input_uint Input -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[input_val:%\w+]] = OpUndef %uint -; CHECK-NEXT: [[write_val:%\w+]] = OpUndef %uint -; CHECK-NEXT: [[ld:%\w+]] = OpLoad %uint [[var]] -; CHECK-NEXT: [[cmp:%\w+]] = OpIEqual %bool [[ld]] %uint_3 -; CHECK-NEXT: [[result:%\w+]] = OpSelect %uint [[cmp]] [[write_val]] [[input_val]] - OpCapability Shader - OpExtension "SPV_AMD_shader_ballot" - %ext = OpExtInstImport "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %uint - %8 = OpUndef %uint - %9 = OpExtInst %uint %ext WriteInvocationAMD %7 %8 %uint_3 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceFMin3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeFloat 32 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] FMin [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] FMin [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %float - %8 = OpUndef %float - %9 = OpUndef %float - %10 = OpExtInst %float %ext FMin3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceSMin3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeInt 32 1 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] SMin [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] SMin [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %int - %8 = OpUndef %int - %9 = OpUndef %int - %10 = OpExtInst %int %ext SMin3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceUMin3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeInt 32 0 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %uint - %8 = OpUndef %uint - %9 = OpUndef %uint - %10 = OpExtInst %uint %ext UMin3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceFMax3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeFloat 32 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] FMax [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] FMax [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %float - %8 = OpUndef %float - %9 = OpUndef %float - %10 = OpExtInst %float %ext FMax3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceSMax3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeInt 32 1 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] SMax [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] SMax [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %int - %8 = OpUndef %int - %9 = OpUndef %int - %10 = OpExtInst %int %ext SMax3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceUMax3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeInt 32 0 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %uint - %8 = OpUndef %uint - %9 = OpUndef %uint - %10 = OpExtInst %uint %ext UMax3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceVecUMax3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeVector -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[x]] [[y]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[temp]] [[z]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %vec = OpTypeVector %uint 4 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %vec - %8 = OpUndef %vec - %9 = OpUndef %vec - %10 = OpExtInst %vec %ext UMax3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceFMid3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeFloat 32 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] FMin [[y]] [[z]] -; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] FMax [[y]] [[z]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] FClamp [[x]] [[min]] [[max]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %float - %8 = OpUndef %float - %9 = OpUndef %float - %10 = OpExtInst %float %ext FMid3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceSMid3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeInt 32 1 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] SMin [[y]] [[z]] -; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] SMax [[y]] [[z]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] SClamp [[x]] [[min]] [[max]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %int - %8 = OpUndef %int - %9 = OpUndef %int - %10 = OpExtInst %int %ext SMid3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceUMid3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeInt 32 0 -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[y]] [[z]] -; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[y]] [[z]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UClamp [[x]] [[min]] [[max]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %uint - %8 = OpUndef %uint - %9 = OpUndef %uint - %10 = OpExtInst %uint %ext UMid3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceVecUMid3AMD) { - const std::string text = R"( -; CHECK: OpCapability Shader -; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax" -; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax" -; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450" -; CHECK: [[type:%\w+]] = OpTypeVector -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]] -; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[y]] [[z]] -; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[y]] [[z]] -; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UClamp [[x]] [[min]] [[max]] - OpCapability Shader - OpExtension "SPV_AMD_shader_trinary_minmax" - %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "func" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %vec = OpTypeVector %uint 3 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %uint_3 = OpConstant %uint 3 - %1 = OpFunction %void None %3 - %6 = OpLabel - %7 = OpUndef %vec - %8 = OpUndef %vec - %9 = OpUndef %vec - %10 = OpExtInst %vec %ext UMid3AMD %7 %8 %9 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceCubeFaceCoordAMD) { - // Sorry for the Check test. The code sequence is so long, I do not think - // that a match test would be anymore legible. This tests the replacement of - // the CubeFaceCoordAMD instruction. - const std::string before = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpExtension "SPV_AMD_gcn_shader" - %1 = OpExtInstImport "SPV_AMD_gcn_shader" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 1 1 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %v3float = OpTypeVector %float 3 - %2 = OpFunction %void None %4 - %8 = OpLabel - %9 = OpUndef %v3float - %10 = OpExtInst %v2float %1 CubeFaceCoordAMD %9 - OpReturn - OpFunctionEnd -)"; - - const std::string after = R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%12 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "main" -OpExecutionMode %2 LocalSize 1 1 1 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v3float = OpTypeVector %float 3 -%bool = OpTypeBool -%float_0 = OpConstant %float 0 -%float_2 = OpConstant %float 2 -%float_0_5 = OpConstant %float 0.5 -%16 = OpConstantComposite %v2float %float_0_5 %float_0_5 -%2 = OpFunction %void None %4 -%8 = OpLabel -%9 = OpUndef %v3float -%17 = OpCompositeExtract %float %9 0 -%18 = OpCompositeExtract %float %9 1 -%19 = OpCompositeExtract %float %9 2 -%20 = OpFNegate %float %17 -%21 = OpFNegate %float %18 -%22 = OpFNegate %float %19 -%23 = OpExtInst %float %12 FAbs %17 -%24 = OpExtInst %float %12 FAbs %18 -%25 = OpExtInst %float %12 FAbs %19 -%26 = OpFOrdLessThan %bool %19 %float_0 -%27 = OpFOrdLessThan %bool %18 %float_0 -%28 = OpFOrdLessThan %bool %17 %float_0 -%29 = OpExtInst %float %12 FMax %23 %24 -%30 = OpExtInst %float %12 FMax %25 %29 -%31 = OpFMul %float %float_2 %30 -%32 = OpFOrdGreaterThanEqual %bool %25 %29 -%33 = OpLogicalNot %bool %32 -%34 = OpFOrdGreaterThanEqual %bool %24 %23 -%35 = OpLogicalAnd %bool %33 %34 -%36 = OpSelect %float %26 %20 %17 -%37 = OpSelect %float %28 %19 %22 -%38 = OpSelect %float %35 %17 %37 -%39 = OpSelect %float %32 %36 %38 -%40 = OpSelect %float %27 %22 %19 -%41 = OpSelect %float %35 %40 %21 -%42 = OpCompositeConstruct %v2float %39 %41 -%43 = OpCompositeConstruct %v2float %31 %31 -%44 = OpFDiv %v2float %42 %43 -%10 = OpFAdd %v2float %44 %16 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true); -} - -TEST_F(AmdExtToKhrTest, ReplaceCubeFaceIndexAMD) { - // Sorry for the Check test. The code sequence is so long, I do not think - // that a match test would be anymore legible. This tests the replacement of - // the CubeFaceIndexAMD instruction. - const std::string before = R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_AMD_gcn_shader" -%1 = OpExtInstImport "SPV_AMD_gcn_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "main" -OpExecutionMode %2 LocalSize 1 1 1 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%2 = OpFunction %void None %4 -%7 = OpLabel -%8 = OpUndef %v3float -%9 = OpExtInst %float %1 CubeFaceIndexAMD %8 -OpReturn -OpFunctionEnd -)"; - - const std::string after = R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%11 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "main" -OpExecutionMode %2 LocalSize 1 1 1 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%bool = OpTypeBool -%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_5 = OpConstant %float 5 -%2 = OpFunction %void None %4 -%7 = OpLabel -%8 = OpUndef %v3float -%18 = OpCompositeExtract %float %8 0 -%19 = OpCompositeExtract %float %8 1 -%20 = OpCompositeExtract %float %8 2 -%21 = OpExtInst %float %11 FAbs %18 -%22 = OpExtInst %float %11 FAbs %19 -%23 = OpExtInst %float %11 FAbs %20 -%24 = OpFOrdLessThan %bool %20 %float_0 -%25 = OpFOrdLessThan %bool %19 %float_0 -%26 = OpFOrdLessThan %bool %18 %float_0 -%27 = OpExtInst %float %11 FMax %21 %22 -%28 = OpFOrdGreaterThanEqual %bool %23 %27 -%29 = OpFOrdGreaterThanEqual %bool %22 %21 -%30 = OpSelect %float %24 %float_5 %float_4 -%31 = OpSelect %float %25 %float_3 %float_2 -%32 = OpSelect %float %26 %float_1 %float_0 -%33 = OpSelect %float %29 %31 %32 -%9 = OpSelect %float %28 %30 %33 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true); -} - -TEST_F(AmdExtToKhrTest, SetVersion) { - const std::string text = R"( - OpCapability Shader - OpCapability Int64 - OpExtension "SPV_AMD_shader_ballot" - %1 = OpExtInstImport "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "func" - OpExecutionMode %2 OriginUpperLeft - %void = OpTypeVoid - %4 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %ulong = OpTypeInt 64 0 - %ulong_0 = OpConstant %ulong 0 - %2 = OpFunction %void None %4 - %8 = OpLabel - %9 = OpExtInst %uint %1 MbcntAMD %ulong_0 - OpReturn - OpFunctionEnd -)"; - - // Set the version to 1.1 and make sure it is upgraded to 1.3. - SetTargetEnv(SPV_ENV_UNIVERSAL_1_1); - SetDisassembleOptions(0); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* skip_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); - const std::string& output = std::get<0>(result); - EXPECT_THAT(output, HasSubstr("Version: 1.3")); -} - -TEST_F(AmdExtToKhrTest, SetVersion1) { - const std::string text = R"( - OpCapability Shader - OpCapability Int64 - OpExtension "SPV_AMD_shader_ballot" - %1 = OpExtInstImport "SPV_AMD_shader_ballot" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "func" - OpExecutionMode %2 OriginUpperLeft - %void = OpTypeVoid - %4 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %ulong = OpTypeInt 64 0 - %ulong_0 = OpConstant %ulong 0 - %2 = OpFunction %void None %4 - %8 = OpLabel - %9 = OpExtInst %uint %1 MbcntAMD %ulong_0 - OpReturn - OpFunctionEnd -)"; - - // Set the version to 1.4 and make sure it is stays the same. - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SetDisassembleOptions(0); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* skip_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); - const std::string& output = std::get<0>(result); - EXPECT_THAT(output, HasSubstr("Version: 1.4")); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/assembly_builder.h b/3rdparty/spirv-tools/test/opt/assembly_builder.h deleted file mode 100644 index 1673c092b..000000000 --- a/3rdparty/spirv-tools/test/opt/assembly_builder.h +++ /dev/null @@ -1,266 +0,0 @@ -// 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. - -#ifndef TEST_OPT_ASSEMBLY_BUILDER_H_ -#define TEST_OPT_ASSEMBLY_BUILDER_H_ - -#include -#include -#include -#include -#include -#include - -namespace spvtools { -namespace opt { - -// A simple SPIR-V assembly code builder for test uses. It builds an SPIR-V -// assembly module from vectors of assembly strings. It allows users to add -// instructions to the main function and the type-constants-globals section -// directly. It relies on OpName instructions and friendly-name disassembling -// to keep the ID names unchanged after assembling. -// -// An assembly module is divided into several sections, matching with the -// SPIR-V Logical Layout: -// Global Preamble: -// OpCapability instructions; -// OpExtension instructions and OpExtInstImport instructions; -// OpMemoryModel instruction; -// OpEntryPoint and OpExecutionMode instruction; -// OpString, OpSourceExtension, OpSource and OpSourceContinued instructions. -// Names: -// OpName instructions. -// Annotations: -// OpDecorate, OpMemberDecorate, OpGroupDecorate, OpGroupMemberDecorate and -// OpDecorationGroup. -// Types, Constants and Global variables: -// Types, constants and global variables declaration instructions. -// Main Function: -// Main function instructions. -// Main Function Postamble: -// The return and function end instructions. -// -// The assembly code is built by concatenating all the strings in the above -// sections. -// -// Users define the contents in section -// and
. The section is to hold the names for IDs to -// keep them unchanged before and after assembling. All defined IDs to be added -// to this code builder will be assigned with a global name through OpName -// instruction. The name is extracted from the definition instruction. -// E.g. adding instruction: %var_a = OpConstant %int 2, will also add an -// instruction: OpName %var_a, "var_a". -// -// Note that the name must not be used on more than one defined IDs and -// friendly-name disassembling must be enabled so that OpName instructions will -// be respected. -class AssemblyBuilder { - // The base ID value for spec constants. - static const uint32_t SPEC_ID_BASE = 200; - - public: - // Initalize a minimal SPIR-V assembly code as the template. The minimal - // module contains an empty main function and some predefined names for the - // main function. - AssemblyBuilder() - : spec_id_counter_(SPEC_ID_BASE), - global_preamble_({ - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - // clang-format on - }), - names_(), - annotations_(), - types_consts_globals_(), - main_func_(), - main_func_postamble_({ - "OpReturn", - "OpFunctionEnd", - }) { - AppendTypesConstantsGlobals({ - "%void = OpTypeVoid", - "%main_func_type = OpTypeFunction %void", - }); - AppendInMain({ - "%main = OpFunction %void None %main_func_type", - "%main_func_entry_block = OpLabel", - }); - } - - // Appends OpName instructions to this builder. Instrcution strings that do - // not start with 'OpName ' will be skipped. Returns the references of this - // assembly builder. - AssemblyBuilder& AppendNames(const std::vector& vec_asm_code) { - for (auto& inst_str : vec_asm_code) { - if (inst_str.find("OpName ") == 0) { - names_.push_back(inst_str); - } - } - return *this; - } - - // Appends instructions to the types-constants-globals section and returns - // the reference of this assembly builder. IDs defined in the given code will - // be added to the Names section and then be registered with OpName - // instruction. Corresponding decoration instruction will be added for spec - // constants defined with opcode: 'OpSpecConstant'. - AssemblyBuilder& AppendTypesConstantsGlobals( - const std::vector& vec_asm_code) { - AddNamesForResultIDsIn(vec_asm_code); - // Check spec constants defined with OpSpecConstant. - for (auto& inst_str : vec_asm_code) { - if (inst_str.find("= OpSpecConstant ") != std::string::npos || - inst_str.find("= OpSpecConstantTrue ") != std::string::npos || - inst_str.find("= OpSpecConstantFalse ") != std::string::npos) { - AddSpecIDFor(GetResultIDName(inst_str)); - } - } - types_consts_globals_.insert(types_consts_globals_.end(), - vec_asm_code.begin(), vec_asm_code.end()); - return *this; - } - - // Appends instructions to the main function block, which is already labelled - // with "main_func_entry_block". Returns the reference of this assembly - // builder. IDs defined in the given code will be added to the Names section - // and then be registered with OpName instruction. - AssemblyBuilder& AppendInMain(const std::vector& vec_asm_code) { - AddNamesForResultIDsIn(vec_asm_code); - main_func_.insert(main_func_.end(), vec_asm_code.begin(), - vec_asm_code.end()); - return *this; - } - - // Appends annotation instructions to the annotation section, and returns the - // reference of this assembly builder. - AssemblyBuilder& AppendAnnotations( - const std::vector& vec_annotations) { - annotations_.insert(annotations_.end(), vec_annotations.begin(), - vec_annotations.end()); - return *this; - } - - // Pre-pends string to the preamble of the module. Useful for EFFCEE checks. - AssemblyBuilder& PrependPreamble(const std::vector& preamble) { - preamble_.insert(preamble_.end(), preamble.begin(), preamble.end()); - return *this; - } - - // Get the SPIR-V assembly code as string. - std::string GetCode() const { - std::ostringstream ss; - for (const auto& line : preamble_) { - ss << line << std::endl; - } - for (const auto& line : global_preamble_) { - ss << line << std::endl; - } - for (const auto& line : names_) { - ss << line << std::endl; - } - for (const auto& line : annotations_) { - ss << line << std::endl; - } - for (const auto& line : types_consts_globals_) { - ss << line << std::endl; - } - for (const auto& line : main_func_) { - ss << line << std::endl; - } - for (const auto& line : main_func_postamble_) { - ss << line << std::endl; - } - return ss.str(); - } - - private: - // Adds a given name to the Name section with OpName. If the given name has - // been added before, does nothing. - void AddOpNameIfNotExist(const std::string& id_name) { - if (!used_names_.count(id_name)) { - std::stringstream opname_inst; - opname_inst << "OpName " - << "%" << id_name << " \"" << id_name << "\""; - names_.emplace_back(opname_inst.str()); - used_names_.insert(id_name); - } - } - - // Adds the names in a vector of assembly code strings to the Names section. - // If a '=' sign is found in an instruction, this instruction will be treated - // as an ID defining instruction. The ID name used in the instruction will be - // extracted and added to the Names section. - void AddNamesForResultIDsIn(const std::vector& vec_asm_code) { - for (const auto& line : vec_asm_code) { - std::string name = GetResultIDName(line); - if (!name.empty()) { - AddOpNameIfNotExist(name); - } - } - } - - // Adds an OpDecorate SpecId instruction for the given ID name. - void AddSpecIDFor(const std::string& id_name) { - std::stringstream decorate_inst; - decorate_inst << "OpDecorate " - << "%" << id_name << " SpecId " << spec_id_counter_; - spec_id_counter_ += 1; - annotations_.emplace_back(decorate_inst.str()); - } - - // Extracts the ID name from a SPIR-V assembly instruction string. If the - // instruction is an ID-defining instruction (has result ID), returns the - // name of the result ID in string. If the instruction does not have result - // ID, returns an empty string. - std::string GetResultIDName(const std::string inst_str) { - std::string name; - if (inst_str.find('=') != std::string::npos) { - size_t assign_sign = inst_str.find('='); - name = inst_str.substr(0, assign_sign); - name.erase(remove_if(name.begin(), name.end(), - [](char c) { return c == ' ' || c == '%'; }), - name.end()); - } - return name; - } - - uint32_t spec_id_counter_; - // User-defined preamble. - std::vector preamble_; - // The vector that contains common preambles shared across all test SPIR-V - // code. - std::vector global_preamble_; - // The vector that contains OpName instructions. - std::vector names_; - // The vector that contains annotation instructions. - std::vector annotations_; - // The vector that contains the code to declare types, constants and global - // variables (aka. the Types-Constants-Globals section). - std::vector types_consts_globals_; - // The vector that contains the code in main function's entry block. - std::vector main_func_; - // The vector that contains the postamble of main function body. - std::vector main_func_postamble_; - // All of the defined variable names. - std::unordered_set used_names_; -}; - -} // namespace opt -} // namespace spvtools - -#endif // TEST_OPT_ASSEMBLY_BUILDER_H_ diff --git a/3rdparty/spirv-tools/test/opt/assembly_builder_test.cpp b/3rdparty/spirv-tools/test/opt/assembly_builder_test.cpp deleted file mode 100644 index 55fbbe904..000000000 --- a/3rdparty/spirv-tools/test/opt/assembly_builder_test.cpp +++ /dev/null @@ -1,283 +0,0 @@ -// 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 "test/opt/assembly_builder.h" - -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using AssemblyBuilderTest = PassTest<::testing::Test>; - -TEST_F(AssemblyBuilderTest, MinimalShader) { - AssemblyBuilder builder; - std::vector expected = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %void \"void\"", - "OpName %main_func_type \"main_func_type\"", - "OpName %main \"main\"", - "OpName %main_func_entry_block \"main_func_entry_block\"", - "%void = OpTypeVoid", - "%main_func_type = OpTypeFunction %void", - "%main = OpFunction %void None %main_func_type", -"%main_func_entry_block = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - SinglePassRunAndCheck(builder.GetCode(), JoinAllInsts(expected), - /* skip_nop = */ false); -} - -TEST_F(AssemblyBuilderTest, ShaderWithConstants) { - AssemblyBuilder builder; - builder - .AppendTypesConstantsGlobals({ - // clang-format off - "%bool = OpTypeBool", - "%_PF_bool = OpTypePointer Function %bool", - "%bt = OpConstantTrue %bool", - "%bf = OpConstantFalse %bool", - "%int = OpTypeInt 32 1", - "%_PF_int = OpTypePointer Function %int", - "%si = OpConstant %int 1", - "%uint = OpTypeInt 32 0", - "%_PF_uint = OpTypePointer Function %uint", - "%ui = OpConstant %uint 2", - "%float = OpTypeFloat 32", - "%_PF_float = OpTypePointer Function %float", - "%f = OpConstant %float 3.1415", - "%double = OpTypeFloat 64", - "%_PF_double = OpTypePointer Function %double", - "%d = OpConstant %double 3.14159265358979", - // clang-format on - }) - .AppendInMain({ - // clang-format off - "%btv = OpVariable %_PF_bool Function", - "%bfv = OpVariable %_PF_bool Function", - "%iv = OpVariable %_PF_int Function", - "%uv = OpVariable %_PF_uint Function", - "%fv = OpVariable %_PF_float Function", - "%dv = OpVariable %_PF_double Function", - "OpStore %btv %bt", - "OpStore %bfv %bf", - "OpStore %iv %si", - "OpStore %uv %ui", - "OpStore %fv %f", - "OpStore %dv %d", - // clang-format on - }); - - std::vector expected = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %void \"void\"", - "OpName %main_func_type \"main_func_type\"", - "OpName %main \"main\"", - "OpName %main_func_entry_block \"main_func_entry_block\"", - "OpName %bool \"bool\"", - "OpName %_PF_bool \"_PF_bool\"", - "OpName %bt \"bt\"", - "OpName %bf \"bf\"", - "OpName %int \"int\"", - "OpName %_PF_int \"_PF_int\"", - "OpName %si \"si\"", - "OpName %uint \"uint\"", - "OpName %_PF_uint \"_PF_uint\"", - "OpName %ui \"ui\"", - "OpName %float \"float\"", - "OpName %_PF_float \"_PF_float\"", - "OpName %f \"f\"", - "OpName %double \"double\"", - "OpName %_PF_double \"_PF_double\"", - "OpName %d \"d\"", - "OpName %btv \"btv\"", - "OpName %bfv \"bfv\"", - "OpName %iv \"iv\"", - "OpName %uv \"uv\"", - "OpName %fv \"fv\"", - "OpName %dv \"dv\"", - "%void = OpTypeVoid", -"%main_func_type = OpTypeFunction %void", - "%bool = OpTypeBool", - "%_PF_bool = OpTypePointer Function %bool", - "%bt = OpConstantTrue %bool", - "%bf = OpConstantFalse %bool", - "%int = OpTypeInt 32 1", - "%_PF_int = OpTypePointer Function %int", - "%si = OpConstant %int 1", - "%uint = OpTypeInt 32 0", - "%_PF_uint = OpTypePointer Function %uint", - "%ui = OpConstant %uint 2", - "%float = OpTypeFloat 32", - "%_PF_float = OpTypePointer Function %float", - "%f = OpConstant %float 3.1415", - "%double = OpTypeFloat 64", - "%_PF_double = OpTypePointer Function %double", - "%d = OpConstant %double 3.14159265358979", - "%main = OpFunction %void None %main_func_type", -"%main_func_entry_block = OpLabel", - "%btv = OpVariable %_PF_bool Function", - "%bfv = OpVariable %_PF_bool Function", - "%iv = OpVariable %_PF_int Function", - "%uv = OpVariable %_PF_uint Function", - "%fv = OpVariable %_PF_float Function", - "%dv = OpVariable %_PF_double Function", - "OpStore %btv %bt", - "OpStore %bfv %bf", - "OpStore %iv %si", - "OpStore %uv %ui", - "OpStore %fv %f", - "OpStore %dv %d", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck(builder.GetCode(), JoinAllInsts(expected), - /* skip_nop = */ false); -} - -TEST_F(AssemblyBuilderTest, SpecConstants) { - AssemblyBuilder builder; - builder.AppendTypesConstantsGlobals({ - "%bool = OpTypeBool", - "%uint = OpTypeInt 32 0", - "%int = OpTypeInt 32 1", - "%float = OpTypeFloat 32", - "%double = OpTypeFloat 64", - "%v2int = OpTypeVector %int 2", - - "%spec_true = OpSpecConstantTrue %bool", - "%spec_false = OpSpecConstantFalse %bool", - "%spec_uint = OpSpecConstant %uint 1", - "%spec_int = OpSpecConstant %int 1", - "%spec_float = OpSpecConstant %float 1.25", - "%spec_double = OpSpecConstant %double 1.2345678", - - // Spec constants defined below should not have SpecID. - "%spec_add_op = OpSpecConstantOp %int IAdd %spec_int %spec_int", - "%spec_vec = OpSpecConstantComposite %v2int %spec_int %spec_int", - "%spec_vec_x = OpSpecConstantOp %int CompositeExtract %spec_vec 0", - }); - std::vector expected = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %void \"void\"", - "OpName %main_func_type \"main_func_type\"", - "OpName %main \"main\"", - "OpName %main_func_entry_block \"main_func_entry_block\"", - "OpName %bool \"bool\"", - "OpName %uint \"uint\"", - "OpName %int \"int\"", - "OpName %float \"float\"", - "OpName %double \"double\"", - "OpName %v2int \"v2int\"", - "OpName %spec_true \"spec_true\"", - "OpName %spec_false \"spec_false\"", - "OpName %spec_uint \"spec_uint\"", - "OpName %spec_int \"spec_int\"", - "OpName %spec_float \"spec_float\"", - "OpName %spec_double \"spec_double\"", - "OpName %spec_add_op \"spec_add_op\"", - "OpName %spec_vec \"spec_vec\"", - "OpName %spec_vec_x \"spec_vec_x\"", - "OpDecorate %spec_true SpecId 200", - "OpDecorate %spec_false SpecId 201", - "OpDecorate %spec_uint SpecId 202", - "OpDecorate %spec_int SpecId 203", - "OpDecorate %spec_float SpecId 204", - "OpDecorate %spec_double SpecId 205", - "%void = OpTypeVoid", - "%main_func_type = OpTypeFunction %void", - "%bool = OpTypeBool", - "%uint = OpTypeInt 32 0", - "%int = OpTypeInt 32 1", - "%float = OpTypeFloat 32", - "%double = OpTypeFloat 64", - "%v2int = OpTypeVector %int 2", - "%spec_true = OpSpecConstantTrue %bool", - "%spec_false = OpSpecConstantFalse %bool", - "%spec_uint = OpSpecConstant %uint 1", - "%spec_int = OpSpecConstant %int 1", - "%spec_float = OpSpecConstant %float 1.25", - "%spec_double = OpSpecConstant %double 1.2345678", - "%spec_add_op = OpSpecConstantOp %int IAdd %spec_int %spec_int", - "%spec_vec = OpSpecConstantComposite %v2int %spec_int %spec_int", - "%spec_vec_x = OpSpecConstantOp %int CompositeExtract %spec_vec 0", - "%main = OpFunction %void None %main_func_type", -"%main_func_entry_block = OpLabel", - "OpReturn", - "OpFunctionEnd", - - // clang-format on - }; - - SinglePassRunAndCheck(builder.GetCode(), JoinAllInsts(expected), - /* skip_nop = */ false); -} - -TEST_F(AssemblyBuilderTest, AppendNames) { - AssemblyBuilder builder; - builder.AppendNames({ - "OpName %void \"another_name_for_void\"", - "I am an invalid OpName instruction and should not be added", - "OpName %main \"another name for main\"", - }); - std::vector expected = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %void \"void\"", - "OpName %main_func_type \"main_func_type\"", - "OpName %main \"main\"", - "OpName %main_func_entry_block \"main_func_entry_block\"", - "OpName %void \"another_name_for_void\"", - "OpName %main \"another name for main\"", - "%void = OpTypeVoid", - "%main_func_type = OpTypeFunction %void", - "%main = OpFunction %void None %main_func_type", -"%main_func_entry_block = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - SinglePassRunAndCheck(builder.GetCode(), JoinAllInsts(expected), - /* skip_nop = */ false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/block_merge_test.cpp b/3rdparty/spirv-tools/test/opt/block_merge_test.cpp deleted file mode 100644 index 11fba736c..000000000 --- a/3rdparty/spirv-tools/test/opt/block_merge_test.cpp +++ /dev/null @@ -1,976 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using BlockMergeTest = PassTest<::testing::Test>; - -TEST_F(BlockMergeTest, Simple) { - // Note: SPIR-V hand edited to insert block boundary - // between two statements in main. - // - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpBranch %15 -%15 = OpLabel -%16 = OpLoad %v4float %v -OpStore %gl_FragColor %16 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -%16 = OpLoad %v4float %v -OpStore %gl_FragColor %16 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(BlockMergeTest, EmptyBlock) { - // Note: SPIR-V hand edited to insert empty block - // after two statements in main. - // - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpBranch %15 -%15 = OpLabel -%16 = OpLoad %v4float %v -OpStore %gl_FragColor %16 -OpBranch %17 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -%16 = OpLoad %v4float %v -OpStore %gl_FragColor %16 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(BlockMergeTest, NestedInControlFlow) { - // Note: SPIR-V hand edited to insert block boundary - // between OpFMul and OpStore in then-part. - // - // #version 140 - // in vec4 BaseColor; - // - // layout(std140) uniform U_t - // { - // bool g_B ; - // } ; - // - // void main() - // { - // vec4 v = BaseColor; - // if (g_B) - // vec4 v = v * 0.25; - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_B" -OpName %_ "" -OpName %v_0 "v" -OpName %gl_FragColor "gl_FragColor" -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t Block -OpDecorate %_ DescriptorSet 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%U_t = OpTypeStruct %uint -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_0_25 = OpConstant %float 0.25 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%24 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%v_0 = OpVariable %_ptr_Function_v4float Function -%25 = OpLoad %v4float %BaseColor -OpStore %v %25 -%26 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%27 = OpLoad %uint %26 -%28 = OpINotEqual %bool %27 %uint_0 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -%31 = OpLoad %v4float %v -%32 = OpVectorTimesScalar %v4float %31 %float_0_25 -OpBranch %33 -%33 = OpLabel -OpStore %v_0 %32 -OpBranch %29 -%29 = OpLabel -%34 = OpLoad %v4float %v -OpStore %gl_FragColor %34 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%24 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%v_0 = OpVariable %_ptr_Function_v4float Function -%25 = OpLoad %v4float %BaseColor -OpStore %v %25 -%26 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%27 = OpLoad %uint %26 -%28 = OpINotEqual %bool %27 %uint_0 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -%31 = OpLoad %v4float %v -%32 = OpVectorTimesScalar %v4float %31 %float_0_25 -OpStore %v_0 %32 -OpBranch %29 -%29 = OpLabel -%34 = OpLoad %v4float %v -OpStore %gl_FragColor %34 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(BlockMergeTest, PhiInSuccessorOfMergedBlock) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[then:%\w+]] [[else:%\w+]] -; CHECK: [[then]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[else]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpPhi {{%\w+}} %true [[then]] %false [[else]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpSelectionMerge %merge None -OpBranchConditional %true %then %else -%then = OpLabel -OpBranch %then_next -%then_next = OpLabel -OpBranch %merge -%else = OpLabel -OpBranch %merge -%merge = OpLabel -%phi = OpPhi %bool %true %then_next %false %else -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, UpdateMergeInstruction) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[then:%\w+]] [[else:%\w+]] -; CHECK: [[then]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[else]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpSelectionMerge %real_merge None -OpBranchConditional %true %then %else -%then = OpLabel -OpBranch %merge -%else = OpLabel -OpBranch %merge -%merge = OpLabel -OpBranch %real_merge -%real_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, TwoMergeBlocksCannotBeMerged) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[outer_merge:%\w+]] None -; CHECK: OpSelectionMerge [[inner_merge:%\w+]] None -; CHECK: [[inner_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[outer_merge]] -; CHECK: [[outer_merge]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpSelectionMerge %outer_merge None -OpBranchConditional %true %then %else -%then = OpLabel -OpBranch %inner_header -%else = OpLabel -OpBranch %inner_header -%inner_header = OpLabel -OpSelectionMerge %inner_merge None -OpBranchConditional %true %inner_then %inner_else -%inner_then = OpLabel -OpBranch %inner_merge -%inner_else = OpLabel -OpBranch %inner_merge -%inner_merge = OpLabel -OpBranch %outer_merge -%outer_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, MergeContinue) { - const std::string text = R"( -; CHECK: OpBranch [[header:%\w+]] -; CHECK: [[header]] = OpLabel -; CHECK-NEXT: OpLogicalAnd -; CHECK-NEXT: OpLoopMerge {{%\w+}} [[header]] None -; CHECK-NEXT: OpBranch [[header]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpBranch %header -%header = OpLabel -OpLoopMerge %merge %continue None -OpBranch %continue -%continue = OpLabel -%op = OpLogicalAnd %bool %true %false -OpBranch %header -%merge = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, TwoHeadersCannotBeMerged) { - const std::string text = R"( -; CHECK: OpBranch [[loop_header:%\w+]] -; CHECK: [[loop_header]] = OpLabel -; CHECK-NEXT: OpLoopMerge -; CHECK-NEXT: OpBranch [[if_header:%\w+]] -; CHECK: [[if_header]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpBranch %header -%header = OpLabel -OpLoopMerge %merge %continue None -OpBranch %inner_header -%inner_header = OpLabel -OpSelectionMerge %if_merge None -OpBranchConditional %true %then %if_merge -%then = OpLabel -OpBranch %continue -%if_merge = OpLabel -OpBranch %continue -%continue = OpLabel -OpBranchConditional %false %merge %header -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, CannotMergeContinue) { - const std::string text = R"( -; CHECK: OpBranch [[loop_header:%\w+]] -; CHECK: [[loop_header]] = OpLabel -; CHECK-NEXT: OpLoopMerge {{%\w+}} [[continue:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_header:%\w+]] -; CHECK: [[if_header]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK: [[continue]] = OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpBranch %header -%header = OpLabel -OpLoopMerge %merge %continue None -OpBranchConditional %true %inner_header %merge -%inner_header = OpLabel -OpSelectionMerge %if_merge None -OpBranchConditional %true %then %if_merge -%then = OpLabel -OpBranch %continue -%if_merge = OpLabel -OpBranch %continue -%continue = OpLabel -OpBranchConditional %false %merge %header -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, RemoveStructuredDeclaration) { - // Note: SPIR-V hand edited remove dead branch and add block - // before continue block - // - // #version 140 - // in vec4 BaseColor; - // - // void main() - // { - // while (true) { - // break; - // } - // gl_FragColor = BaseColor; - // } - - const std::string assembly = - R"( -; CHECK: OpLabel -; CHECK: [[header:%\w+]] = OpLabel -; CHECK-NOT: OpLoopMerge -; CHECK: OpReturn -; CHECK: [[continue:%\w+]] = OpLabel -; CHECK-NEXT: OpBranch [[block:%\w+]] -; CHECK: [[block]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %gl_FragColor "gl_FragColor" -OpName %BaseColor "BaseColor" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %6 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -OpLoopMerge %15 %16 None -OpBranch %17 -%17 = OpLabel -OpBranch %15 -%18 = OpLabel -OpBranch %16 -%16 = OpLabel -OpBranch %14 -%15 = OpLabel -%19 = OpLoad %v4float %BaseColor -OpStore %gl_FragColor %19 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(assembly, true); -} - -TEST_F(BlockMergeTest, DontMergeKill) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK: [[ret:%\w+]] = OpLabel -; CHECK-NEXT: OpKill -; CHECK-DAG: [[cont]] = OpLabel -; CHECK-DAG: [[merge]] = OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %5 -%5 = OpLabel -OpKill -%4 = OpLabel -OpBranch %2 -%3 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, DontMergeUnreachable) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK: [[ret:%\w+]] = OpLabel -; CHECK-NEXT: OpUnreachable -; CHECK-DAG: [[cont]] = OpLabel -; CHECK-DAG: [[merge]] = OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %5 -%5 = OpLabel -OpUnreachable -%4 = OpLabel -OpBranch %2 -%3 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(BlockMergeTest, DontMergeReturn) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK: [[ret:%\w+]] = OpLabel -; CHECK-NEXT: OpReturn -; CHECK-DAG: [[cont]] = OpLabel -; CHECK-DAG: [[merge]] = OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %5 -%5 = OpLabel -OpReturn -%4 = OpLabel -OpBranch %2 -%3 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, DontMergeSwitch) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK: [[ret:%\w+]] = OpLabel -; CHECK-NEXT: OpSwitch -; CHECK-DAG: [[cont]] = OpLabel -; CHECK-DAG: [[merge]] = OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %5 -%5 = OpLabel -OpSwitch %int_0 %6 -%6 = OpLabel -OpReturn -%4 = OpLabel -OpBranch %2 -%3 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, DontMergeReturnValue) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK: [[ret:%\w+]] = OpLabel -; CHECK-NEXT: OpReturn -; CHECK-DAG: [[cont]] = OpLabel -; CHECK-DAG: [[merge]] = OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%functy = OpTypeFunction %void -%otherfuncty = OpTypeFunction %bool -%true = OpConstantTrue %bool -%func = OpFunction %void None %functy -%1 = OpLabel -%2 = OpFunctionCall %bool %3 -OpReturn -OpFunctionEnd -%3 = OpFunction %bool None %otherfuncty -%4 = OpLabel -OpBranch %5 -%5 = OpLabel -OpLoopMerge %6 %7 None -OpBranch %8 -%8 = OpLabel -OpReturnValue %true -%7 = OpLabel -OpBranch %5 -%6 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, MergeHeaders) { - // Merge two headers when the second is the merge block of the first. - const std::string text = R"( -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpBranch [[header:%\w+]] -; CHECK-NEXT: [[header]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHEKC: OpReturn -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%functy = OpTypeFunction %void -%otherfuncty = OpTypeFunction %bool -%true = OpConstantTrue %bool -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %5 -%5 = OpLabel -OpLoopMerge %8 %7 None -OpBranch %8 -%7 = OpLabel -OpBranch %5 -%8 = OpLabel -OpSelectionMerge %m None -OpBranchConditional %true %a %m -%a = OpLabel -OpBranch %m -%m = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(BlockMergeTest, OpPhiInSuccessor) { - // Checks that when merging blocks A and B, the OpPhi at the start of B is - // removed and uses of its definition are replaced appropriately. - const std::string prefix = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -OpName %x "x" -OpName %y "y" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%main = OpFunction %void None %6 -%10 = OpLabel -%x = OpVariable %_ptr_Function_int Function -%y = OpVariable %_ptr_Function_int Function -OpStore %x %int_1 -%11 = OpLoad %int %x -)"; - - const std::string suffix_before = - R"(OpBranch %12 -%12 = OpLabel -%13 = OpPhi %int %11 %10 -OpStore %y %13 -OpReturn -OpFunctionEnd -)"; - - const std::string suffix_after = - R"(OpStore %y %11 -OpReturn -OpFunctionEnd -)"; - SinglePassRunAndCheck(prefix + suffix_before, - prefix + suffix_after, true, true); -} - -TEST_F(BlockMergeTest, MultipleOpPhisInSuccessor) { - // Checks that when merging blocks A and B, the OpPhis at the start of B are - // removed and uses of their definitions are replaced appropriately. - const std::string prefix = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -OpName %S "S" -OpMemberName %S 0 "x" -OpMemberName %S 1 "f" -OpName %s "s" -OpName %g "g" -OpName %y "y" -OpName %t "t" -OpName %z "z" -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%float = OpTypeFloat 32 -%S = OpTypeStruct %int %float -%_ptr_Function_S = OpTypePointer Function %S -%int_1 = OpConstant %int 1 -%float_2 = OpConstant %float 2 -%16 = OpConstantComposite %S %int_1 %float_2 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Function_int = OpTypePointer Function %int -%int_3 = OpConstant %int 3 -%int_0 = OpConstant %int 0 -%main = OpFunction %void None %10 -%21 = OpLabel -%s = OpVariable %_ptr_Function_S Function -%g = OpVariable %_ptr_Function_float Function -%y = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_S Function -%z = OpVariable %_ptr_Function_float Function -OpStore %s %16 -OpStore %g %float_2 -OpStore %y %int_3 -%22 = OpLoad %S %s -OpStore %t %22 -%23 = OpAccessChain %_ptr_Function_float %s %int_1 -%24 = OpLoad %float %23 -%25 = OpLoad %float %g -)"; - - const std::string suffix_before = - R"(OpBranch %26 -%26 = OpLabel -%27 = OpPhi %float %24 %21 -%28 = OpPhi %float %25 %21 -%29 = OpFAdd %float %27 %28 -%30 = OpAccessChain %_ptr_Function_int %s %int_0 -%31 = OpLoad %int %30 -OpBranch %32 -%32 = OpLabel -%33 = OpPhi %float %29 %26 -%34 = OpPhi %int %31 %26 -%35 = OpConvertSToF %float %34 -OpBranch %36 -%36 = OpLabel -%37 = OpPhi %float %35 %32 -%38 = OpFSub %float %33 %37 -%39 = OpLoad %int %y -OpBranch %40 -%40 = OpLabel -%41 = OpPhi %float %38 %36 -%42 = OpPhi %int %39 %36 -%43 = OpConvertSToF %float %42 -%44 = OpFAdd %float %41 %43 -OpStore %z %44 -OpReturn -OpFunctionEnd -)"; - - const std::string suffix_after = - R"(%29 = OpFAdd %float %24 %25 -%30 = OpAccessChain %_ptr_Function_int %s %int_0 -%31 = OpLoad %int %30 -%35 = OpConvertSToF %float %31 -%38 = OpFSub %float %29 %35 -%39 = OpLoad %int %y -%43 = OpConvertSToF %float %39 -%44 = OpFAdd %float %38 %43 -OpStore %z %44 -OpReturn -OpFunctionEnd -)"; - SinglePassRunAndCheck(prefix + suffix_before, - prefix + suffix_after, true, true); -} - -TEST_F(BlockMergeTest, UnreachableLoop) { - const std::string spirv = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%bool = OpTypeBool -%false = OpConstantFalse %bool -%main = OpFunction %void None %4 -%9 = OpLabel -OpBranch %10 -%11 = OpLabel -OpLoopMerge %12 %13 None -OpBranchConditional %false %13 %14 -%13 = OpLabel -OpSelectionMerge %15 None -OpBranchConditional %false %16 %17 -%16 = OpLabel -OpBranch %15 -%17 = OpLabel -OpBranch %15 -%15 = OpLabel -OpBranch %11 -%14 = OpLabel -OpReturn -%12 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(spirv, spirv, true, true); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// More complex control flow -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/ccp_test.cpp b/3rdparty/spirv-tools/test/opt/ccp_test.cpp deleted file mode 100644 index 920c0f4d5..000000000 --- a/3rdparty/spirv-tools/test/opt/ccp_test.cpp +++ /dev/null @@ -1,930 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/ccp_pass.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using CCPTest = PassTest<::testing::Test>; - -TEST_F(CCPTest, PropagateThroughPhis) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %x %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %x "x" - OpName %outparm "outparm" - OpDecorate %x Flat - OpDecorate %x Location 0 - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool -%_ptr_Function_int = OpTypePointer Function %int - %int_4 = OpConstant %int 4 - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 -%_ptr_Input_int = OpTypePointer Input %int - %x = OpVariable %_ptr_Input_int Input -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %3 - %4 = OpLabel - %5 = OpLoad %int %x - %9 = OpIAdd %int %int_1 %int_3 - %6 = OpSGreaterThan %bool %5 %int_3 - OpSelectionMerge %25 None - OpBranchConditional %6 %22 %23 - %22 = OpLabel - -; CHECK: OpCopyObject %int %int_4 - %7 = OpCopyObject %int %9 - - OpBranch %25 - %23 = OpLabel - %8 = OpCopyObject %int %int_4 - OpBranch %25 - %25 = OpLabel - -; %int_4 should have propagated to both OpPhi operands. -; CHECK: OpPhi %int %int_4 {{%\d+}} %int_4 {{%\d+}} - %35 = OpPhi %int %7 %22 %8 %23 - -; This function always returns 4. DCE should get rid of everything else. -; CHECK OpStore %outparm %int_4 - OpStore %outparm %35 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, SimplifyConditionals) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %outparm "outparm" - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool -%_ptr_Function_int = OpTypePointer Function %int - %int_4 = OpConstant %int 4 - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %3 - %4 = OpLabel - %9 = OpIAdd %int %int_4 %int_3 - %6 = OpSGreaterThan %bool %9 %int_3 - OpSelectionMerge %25 None -; CHECK: OpBranchConditional %true [[bb_taken:%\d+]] [[bb_not_taken:%\d+]] - OpBranchConditional %6 %22 %23 -; CHECK: [[bb_taken]] = OpLabel - %22 = OpLabel -; CHECK: OpCopyObject %int %int_7 - %7 = OpCopyObject %int %9 - OpBranch %25 -; CHECK: [[bb_not_taken]] = OpLabel - %23 = OpLabel -; CHECK: [[id_not_evaluated:%\d+]] = OpCopyObject %int %int_4 - %8 = OpCopyObject %int %int_4 - OpBranch %25 - %25 = OpLabel - -; %int_7 should have propagated to the first OpPhi operand. But the else branch -; is not executable (conditional is always true), so no values should be -; propagated there and the value of the OpPhi should always be %int_7. -; CHECK: OpPhi %int %int_7 [[bb_taken]] [[id_not_evaluated]] [[bb_not_taken]] - %35 = OpPhi %int %7 %22 %8 %23 - -; Only the true path of the conditional is ever executed. The output of this -; function is always %int_7. -; CHECK: OpStore %outparm %int_7 - OpStore %outparm %35 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, SimplifySwitches) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %outparm "outparm" - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %6 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_23 = OpConstant %int 23 - %int_42 = OpConstant %int 42 - %int_14 = OpConstant %int 14 - %int_15 = OpConstant %int 15 - %int_4 = OpConstant %int 4 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %6 - %15 = OpLabel - OpSelectionMerge %17 None - OpSwitch %int_23 %17 10 %18 13 %19 23 %20 - %18 = OpLabel - OpBranch %17 - %19 = OpLabel - OpBranch %17 - %20 = OpLabel - OpBranch %17 - %17 = OpLabel - %24 = OpPhi %int %int_23 %15 %int_42 %18 %int_14 %19 %int_15 %20 - -; The switch will always jump to label %20, which carries the value %int_15. -; CHECK: OpIAdd %int %int_15 %int_4 - %22 = OpIAdd %int %24 %int_4 - -; Consequently, the return value will always be %int_19. -; CHECK: OpStore %outparm %int_19 - OpStore %outparm %22 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, SimplifySwitchesDefaultBranch) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %outparm "outparm" - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %6 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_42 = OpConstant %int 42 - %int_4 = OpConstant %int 4 - %int_1 = OpConstant %int 1 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %6 - %13 = OpLabel - %15 = OpIAdd %int %int_42 %int_4 - OpSelectionMerge %16 None - -; CHECK: OpSwitch %int_46 {{%\d+}} 10 {{%\d+}} - OpSwitch %15 %17 10 %18 - %18 = OpLabel - OpBranch %16 - %17 = OpLabel - OpBranch %16 - %16 = OpLabel - %22 = OpPhi %int %int_42 %18 %int_1 %17 - -; The switch will always jump to the default label %17. This carries the value -; %int_1. -; CHECK: OpIAdd %int %int_1 %int_4 - %20 = OpIAdd %int %22 %int_4 - -; Resulting in a return value of %int_5. -; CHECK: OpStore %outparm %int_5 - OpStore %outparm %20 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, SimplifyIntVector) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %OutColor - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %v "v" - OpName %OutColor "OutColor" - OpDecorate %OutColor Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %v4int = OpTypeVector %int 4 -%_ptr_Function_v4int = OpTypePointer Function %v4int - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %int_3 = OpConstant %int 3 - %int_4 = OpConstant %int 4 - %14 = OpConstantComposite %v4int %int_1 %int_2 %int_3 %int_4 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Output_v4int = OpTypePointer Output %v4int - %OutColor = OpVariable %_ptr_Output_v4int Output - %main = OpFunction %void None %3 - %5 = OpLabel - %v = OpVariable %_ptr_Function_v4int Function - OpStore %v %14 - %18 = OpAccessChain %_ptr_Function_int %v %uint_0 - %19 = OpLoad %int %18 - -; The constant folder does not see through access chains. To get this, the -; vector would have to be scalarized. -; CHECK: [[result_id:%\d+]] = OpIAdd %int {{%\d+}} %int_1 - %20 = OpIAdd %int %19 %int_1 - %21 = OpAccessChain %_ptr_Function_int %v %uint_0 - -; CHECK: OpStore {{%\d+}} [[result_id]] - OpStore %21 %20 - %24 = OpLoad %v4int %v - OpStore %OutColor %24 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, BadSimplifyFloatVector) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %OutColor - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %v "v" - OpName %OutColor "OutColor" - OpDecorate %OutColor Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %float_1 = OpConstant %float 1 - %float_2 = OpConstant %float 2 - %float_3 = OpConstant %float 3 - %float_4 = OpConstant %float 4 - %14 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %OutColor = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %3 - %5 = OpLabel - %v = OpVariable %_ptr_Function_v4float Function - OpStore %v %14 - %18 = OpAccessChain %_ptr_Function_float %v %uint_0 - %19 = OpLoad %float %18 - -; NOTE: This test should start failing once floating point folding is -; implemented (https://github.com/KhronosGroup/SPIRV-Tools/issues/943). -; This should be checking that we are adding %float_1 + %float_1. -; CHECK: [[result_id:%\d+]] = OpFAdd %float {{%\d+}} %float_1 - %20 = OpFAdd %float %19 %float_1 - %21 = OpAccessChain %_ptr_Function_float %v %uint_0 - -; This should be checkint that we are storing %float_2 instead of result_it. -; CHECK: OpStore {{%\d+}} [[result_id]] - OpStore %21 %20 - %24 = OpLoad %v4float %v - OpStore %OutColor %24 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, NoLoadStorePropagation) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %x "x" - OpName %outparm "outparm" - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_23 = OpConstant %int 23 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %3 - %5 = OpLabel - %x = OpVariable %_ptr_Function_int Function - OpStore %x %int_23 - -; int_23 should not propagate into this load. -; CHECK: [[load_id:%\d+]] = OpLoad %int %x - %12 = OpLoad %int %x - -; Nor into this copy operation. -; CHECK: [[copy_id:%\d+]] = OpCopyObject %int [[load_id]] - %13 = OpCopyObject %int %12 - -; Likewise here. -; CHECK: OpStore %outparm [[copy_id]] - OpStore %outparm %13 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, HandleAbortInstructions) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 500 - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool -; CHECK: %true = OpConstantTrue %bool - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %4 = OpLabel - %9 = OpIAdd %int %int_3 %int_1 - %6 = OpSGreaterThan %bool %9 %int_3 - OpSelectionMerge %23 None -; CHECK: OpBranchConditional %true {{%\d+}} {{%\d+}} - OpBranchConditional %6 %22 %23 - %22 = OpLabel - OpKill - %23 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, SSAWebCycles) { - // Test reduced from https://github.com/KhronosGroup/SPIRV-Tools/issues/1159 - // When there is a cycle in the SSA def-use web, the propagator was getting - // into an infinite loop. SSA edges for Phi instructions should not be - // added to the edges to simulate. - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_4 = OpConstant %int 4 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 -%_ptr_Output_int = OpTypePointer Output %int - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %11 - %11 = OpLabel - %29 = OpPhi %int %int_0 %5 %22 %14 - %30 = OpPhi %int %int_0 %5 %25 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %bool %30 %int_4 -; CHECK: OpBranchConditional %true {{%\d+}} {{%\d+}} - OpBranchConditional %19 %12 %13 - %12 = OpLabel -; CHECK: OpIAdd %int %int_0 %int_0 - %22 = OpIAdd %int %29 %30 - OpBranch %14 - %14 = OpLabel -; CHECK: OpPhi %int %int_0 {{%\d+}} - %25 = OpPhi %int %30 %12 - OpBranch %11 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, LoopInductionVariables) { - // Test reduced from https://github.com/KhronosGroup/SPIRV-Tools/issues/1143 - // We are failing to properly consider the induction variable for this loop - // as Varying. - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpName %main "main" - %void = OpTypeVoid - %5 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %5 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - -; This Phi should not have all constant arguments: -; CHECK: [[phi_id:%\d+]] = OpPhi %int %int_0 {{%\d+}} {{%\d+}} {{%\d+}} - %22 = OpPhi %int %int_0 %12 %21 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - -; The Phi should never be considered to have the value %int_0. -; CHECK: [[branch_selector:%\d+]] = OpSLessThan %bool [[phi_id]] %int_10 - %18 = OpSLessThan %bool %22 %int_10 - -; This conditional was wrongly converted into an always-true jump due to the -; bad meet evaluation of %22. -; CHECK: OpBranchConditional [[branch_selector]] {{%\d+}} {{%\d+}} - OpBranchConditional %18 %19 %14 - %19 = OpLabel - OpBranch %15 - %15 = OpLabel -; CHECK: OpIAdd %int [[phi_id]] %int_1 - %21 = OpIAdd %int %22 %int_1 - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(CCPTest, HandleCompositeWithUndef) { - // Check to make sure that CCP does not crash when given a "constant" struct - // with an undef. If at a later time CCP is enhanced to optimize this case, - // it is not wrong. - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 500 - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool - %_struct_7 = OpTypeStruct %int %int - %int_1 = OpConstant %int 1 - %9 = OpUndef %int - %10 = OpConstantComposite %_struct_7 %int_1 %9 - %main = OpFunction %void None %4 - %11 = OpLabel - %12 = OpCompositeExtract %int %10 0 - %13 = OpCopyObject %int %12 - OpReturn - OpFunctionEnd - )"; - - auto res = SinglePassRunToBinary(spv_asm, true); - EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange); -} - -TEST_F(CCPTest, SkipSpecConstantInstrucitons) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 500 - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %10 = OpSpecConstantFalse %bool - %main = OpFunction %void None %4 - %11 = OpLabel - OpBranchConditional %10 %L1 %L2 - %L1 = OpLabel - OpReturn - %L2 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto res = SinglePassRunToBinary(spv_asm, true); - EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange); -} - -TEST_F(CCPTest, UpdateSubsequentPhisToVarying) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" %in -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 1 -%false = OpConstantFalse %bool -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%int6 = OpConstant %int 6 -%int_ptr_Input = OpTypePointer Input %int -%in = OpVariable %int_ptr_Input Input -%undef = OpUndef %int -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -%outer_phi = OpPhi %int %int0 %1 %outer_add %15 -%cond1 = OpSLessThanEqual %bool %outer_phi %int6 -OpLoopMerge %3 %15 None -OpBranchConditional %cond1 %4 %3 -%4 = OpLabel -%ld = OpLoad %int %in -%cond2 = OpSGreaterThanEqual %bool %int1 %ld -OpSelectionMerge %10 None -OpBranchConditional %cond2 %8 %9 -%8 = OpLabel -OpBranch %10 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -%extra_phi = OpPhi %int %outer_phi %8 %outer_phi %9 -OpBranch %11 -%11 = OpLabel -%inner_phi = OpPhi %int %int0 %10 %inner_add %13 -%cond3 = OpSLessThanEqual %bool %inner_phi %int6 -OpLoopMerge %14 %13 None -OpBranchConditional %cond3 %12 %14 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%inner_add = OpIAdd %int %inner_phi %int1 -OpBranch %11 -%14 = OpLabel -OpBranch %15 -%15 = OpLabel -%outer_add = OpIAdd %int %extra_phi %int1 -OpBranch %2 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - auto res = SinglePassRunToBinary(text, true); - EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange); -} - -TEST_F(CCPTest, UndefInPhi) { - const std::string text = R"( -; CHECK: [[uint1:%\w+]] = OpConstant {{%\w+}} 1 -; CHECK: [[phi:%\w+]] = OpPhi -; CHECK: OpIAdd {{%\w+}} [[phi]] [[uint1]] - OpCapability Kernel - OpCapability Linkage - OpMemoryModel Logical OpenCL - OpDecorate %1 LinkageAttributes "func" Export - %void = OpTypeVoid - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %7 = OpUndef %uint - %8 = OpTypeFunction %void %bool - %1 = OpFunction %void None %8 - %9 = OpFunctionParameter %bool - %10 = OpLabel - OpBranchConditional %9 %11 %12 - %11 = OpLabel - OpBranch %13 - %12 = OpLabel - OpBranch %14 - %14 = OpLabel - OpBranchConditional %9 %13 %15 - %15 = OpLabel - OpBranch %13 - %13 = OpLabel - %16 = OpPhi %uint %uint_0 %11 %7 %14 %uint_1 %15 - %17 = OpIAdd %uint %16 %uint_1 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -// Just test to make sure the constant fold rules are being used. Will rely on -// the folding test for specific testing of specific rules. -TEST_F(CCPTest, UseConstantFoldingRules) { - const std::string text = R"( -; CHECK: [[float1:%\w+]] = OpConstant {{%\w+}} 1 -; CHECK: OpReturnValue [[float1]] - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %1 LinkageAttributes "func" Export - %void = OpTypeVoid - %bool = OpTypeBool - %float = OpTypeFloat 32 - %float_0 = OpConstant %float 0 - %float_1 = OpConstant %float 1 - %8 = OpTypeFunction %float - %1 = OpFunction %float None %8 - %10 = OpLabel - %17 = OpFAdd %float %float_0 %float_1 - OpReturnValue %17 - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -// Test for #1300. Previously value for %5 would not settle during simulation. -TEST_F(CCPTest, SettlePhiLatticeValue) { - const std::string text = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranchConditional %true %2 %3 -%3 = OpLabel -OpBranch %2 -%2 = OpLabel -%5 = OpPhi %bool %true %1 %false %3 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunToBinary(text, true); -} - -TEST_F(CCPTest, NullBranchCondition) { - const std::string text = R"( -; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 -; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 1 -%null = OpConstantNull %bool -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpSelectionMerge %2 None -OpBranchConditional %null %2 %3 -%3 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %int %int_1 %1 %int_2 %3 -%add = OpIAdd %int %int_1 %phi -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CCPTest, UndefBranchCondition) { - const std::string text = R"( -; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 -; CHECK: [[phi:%\w+]] = OpPhi -; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 1 -%undef = OpUndef %bool -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpSelectionMerge %2 None -OpBranchConditional %undef %2 %3 -%3 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %int %int_1 %1 %int_2 %3 -%add = OpIAdd %int %int_1 %phi -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CCPTest, NullSwitchCondition) { - const std::string text = R"( -; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 -; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 1 -%null = OpConstantNull %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpSelectionMerge %2 None -OpSwitch %null %2 0 %3 -%3 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %int %int_1 %1 %int_2 %3 -%add = OpIAdd %int %int_1 %phi -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CCPTest, UndefSwitchCondition) { - const std::string text = R"( -; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 -; CHECK: [[phi:%\w+]] = OpPhi -; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 1 -%undef = OpUndef %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpSelectionMerge %2 None -OpSwitch %undef %2 0 %3 -%3 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %int %int_1 %1 %int_2 %3 -%add = OpIAdd %int %int_1 %phi -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -// Test for #1361. -TEST_F(CCPTest, CompositeConstructOfGlobalValue) { - const std::string text = R"( -; CHECK: [[phi:%\w+]] = OpPhi -; CHECK-NEXT: OpCompositeExtract {{%\w+}} [[phi]] 0 -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" %in -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 1 -%bool = OpTypeBool -%functy = OpTypeFunction %void -%ptr_int_Input = OpTypePointer Input %int -%in = OpVariable %ptr_int_Input Input -%struct = OpTypeStruct %ptr_int_Input %ptr_int_Input -%struct_null = OpConstantNull %struct -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %struct %struct_null %1 %5 %4 -%extract = OpCompositeExtract %ptr_int_Input %phi 0 -OpLoopMerge %3 %4 None -OpBranch %4 -%4 = OpLabel -%5 = OpCompositeConstruct %struct %in %in -OpBranch %2 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CCPTest, FoldWithDecoration) { - const std::string text = R"( -; CHECK: OpCapability -; CHECK-NOT: OpDecorate -; CHECK: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpDecorate %3 RelaxedPrecision - %void = OpTypeVoid - %5 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %float_0 = OpConstant %float 0 - %v4float = OpTypeVector %float 4 - %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 - %2 = OpFunction %void None %5 - %11 = OpLabel - %3 = OpVectorShuffle %v3float %10 %10 0 1 2 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/cfg_cleanup_test.cpp b/3rdparty/spirv-tools/test/opt/cfg_cleanup_test.cpp deleted file mode 100644 index 3498f00bb..000000000 --- a/3rdparty/spirv-tools/test/opt/cfg_cleanup_test.cpp +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright (c) 2017 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using CFGCleanupTest = PassTest<::testing::Test>; - -TEST_F(CFGCleanupTest, RemoveUnreachableBlocks) { - const std::string declarations = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %inf %outf4 -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %inf "inf" -OpName %outf4 "outf4" -OpDecorate %inf Location 0 -OpDecorate %outf4 Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Input_float = OpTypePointer Input %float -%inf = OpVariable %_ptr_Input_float Input -%float_2 = OpConstant %float 2 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outf4 = OpVariable %_ptr_Output_v4float Output -%float_n0_5 = OpConstant %float -0.5 -)"; - - const std::string body_before = R"(%main = OpFunction %void None %6 -%14 = OpLabel -OpBranch %18 -%19 = OpLabel -%20 = OpLoad %float %inf -%21 = OpCompositeConstruct %v4float %20 %20 %20 %20 -OpStore %outf4 %21 -OpBranch %17 -%18 = OpLabel -%22 = OpLoad %float %inf -%23 = OpFAdd %float %22 %float_n0_5 -%24 = OpCompositeConstruct %v4float %23 %23 %23 %23 -OpStore %outf4 %24 -OpBranch %17 -%17 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string body_after = R"(%main = OpFunction %void None %6 -%14 = OpLabel -OpBranch %15 -%15 = OpLabel -%20 = OpLoad %float %inf -%21 = OpFAdd %float %20 %float_n0_5 -%22 = OpCompositeConstruct %v4float %21 %21 %21 %21 -OpStore %outf4 %22 -OpBranch %19 -%19 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(declarations + body_before, - declarations + body_after, true, true); -} - -TEST_F(CFGCleanupTest, RemoveDecorations) { - const std::string before = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpName %main "main" - OpName %x "x" - OpName %dead "dead" - OpDecorate %x RelaxedPrecision - OpDecorate %dead RelaxedPrecision - %void = OpTypeVoid - %6 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float - %float_2 = OpConstant %float 2 - %float_4 = OpConstant %float 4 - - %main = OpFunction %void None %6 - %14 = OpLabel - %x = OpVariable %_ptr_Function_float Function - OpBranch %18 - %19 = OpLabel - %dead = OpVariable %_ptr_Function_float Function - OpStore %dead %float_2 - OpBranch %17 - %18 = OpLabel - OpStore %x %float_4 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd -)"; - - const std::string after = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpName %main "main" -OpName %x "x" -OpDecorate %x RelaxedPrecision -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_2 = OpConstant %float 2 -%float_4 = OpConstant %float 4 -%main = OpFunction %void None %6 -%11 = OpLabel -%x = OpVariable %_ptr_Function_float Function -OpBranch %12 -%12 = OpLabel -OpStore %x %float_4 -OpBranch %14 -%14 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(CFGCleanupTest, UpdatePhis) { - const std::string before = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %y %outparm - OpExecutionMode %main OriginUpperLeft - OpName %main "main" - OpName %y "y" - OpName %outparm "outparm" - OpDecorate %y Flat - OpDecorate %y Location 0 - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_int = OpTypePointer Input %int - %y = OpVariable %_ptr_Input_int Input - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_42 = OpConstant %int 42 - %int_23 = OpConstant %int 23 - %int_5 = OpConstant %int 5 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %3 - %5 = OpLabel - %11 = OpLoad %int %y - OpBranch %21 - %16 = OpLabel - %20 = OpIAdd %int %11 %int_42 - OpBranch %17 - %21 = OpLabel - %24 = OpISub %int %11 %int_23 - OpBranch %17 - %17 = OpLabel - %31 = OpPhi %int %20 %16 %24 %21 - %27 = OpIAdd %int %31 %int_5 - OpStore %outparm %27 - OpReturn - OpFunctionEnd -)"; - - const std::string after = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %y %outparm -OpExecutionMode %main OriginUpperLeft -OpName %main "main" -OpName %y "y" -OpName %outparm "outparm" -OpDecorate %y Flat -OpDecorate %y Location 0 -OpDecorate %outparm Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_int = OpTypePointer Input %int -%y = OpVariable %_ptr_Input_int Input -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_42 = OpConstant %int 42 -%int_23 = OpConstant %int 23 -%int_5 = OpConstant %int 5 -%_ptr_Output_int = OpTypePointer Output %int -%outparm = OpVariable %_ptr_Output_int Output -%main = OpFunction %void None %6 -%16 = OpLabel -%17 = OpLoad %int %y -OpBranch %18 -%18 = OpLabel -%22 = OpISub %int %17 %int_23 -OpBranch %21 -%21 = OpLabel -%23 = OpPhi %int %22 %18 -%24 = OpIAdd %int %23 %int_5 -OpStore %outparm %24 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(CFGCleanupTest, RemoveNamedLabels) { - const std::string before = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 430 - OpName %main "main" - OpName %dead "dead" - %void = OpTypeVoid - %5 = OpTypeFunction %void - %main = OpFunction %void None %5 - %6 = OpLabel - OpReturn - %dead = OpLabel - OpReturn - OpFunctionEnd)"; - - const std::string after = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 430 -OpName %main "main" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%main = OpFunction %void None %5 -%6 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(CFGCleanupTest, RemovePhiArgsFromFarBlocks) { - const std::string before = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %y %outparm - OpExecutionMode %main OriginUpperLeft - OpName %main "main" - OpName %y "y" - OpName %outparm "outparm" - OpDecorate %y Flat - OpDecorate %y Location 0 - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_int = OpTypePointer Input %int - %y = OpVariable %_ptr_Input_int Input - %int_42 = OpConstant %int 42 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %int_14 = OpConstant %int 14 - %int_15 = OpConstant %int 15 - %int_5 = OpConstant %int 5 - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %40 - %41 = OpLabel - %11 = OpLoad %int %y - OpBranch %40 - %40 = OpLabel - %12 = OpLoad %int %y - OpSelectionMerge %16 None - OpSwitch %12 %16 10 %13 13 %14 18 %15 - %13 = OpLabel - OpBranch %16 - %14 = OpLabel - OpStore %outparm %int_14 - OpBranch %16 - %15 = OpLabel - OpStore %outparm %int_15 - OpBranch %16 - %16 = OpLabel - %30 = OpPhi %int %11 %40 %int_42 %13 %11 %14 %11 %15 - %28 = OpIAdd %int %30 %int_5 - OpStore %outparm %28 - OpReturn - OpFunctionEnd)"; - - const std::string after = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %y %outparm -OpExecutionMode %main OriginUpperLeft -OpName %main "main" -OpName %y "y" -OpName %outparm "outparm" -OpDecorate %y Flat -OpDecorate %y Location 0 -OpDecorate %outparm Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_int = OpTypePointer Input %int -%y = OpVariable %_ptr_Input_int Input -%int_42 = OpConstant %int 42 -%_ptr_Output_int = OpTypePointer Output %int -%outparm = OpVariable %_ptr_Output_int Output -%int_14 = OpConstant %int 14 -%int_15 = OpConstant %int 15 -%int_5 = OpConstant %int 5 -%26 = OpUndef %int -%main = OpFunction %void None %6 -%15 = OpLabel -OpBranch %16 -%16 = OpLabel -%19 = OpLoad %int %y -OpSelectionMerge %20 None -OpSwitch %19 %20 10 %21 13 %22 18 %23 -%21 = OpLabel -OpBranch %20 -%22 = OpLabel -OpStore %outparm %int_14 -OpBranch %20 -%23 = OpLabel -OpStore %outparm %int_15 -OpBranch %20 -%20 = OpLabel -%24 = OpPhi %int %26 %16 %int_42 %21 %26 %22 %26 %23 -%25 = OpIAdd %int %24 %int_5 -OpStore %outparm %25 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(CFGCleanupTest, RemovePhiConstantArgs) { - const std::string before = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %y %outparm - OpExecutionMode %main OriginUpperLeft - OpName %main "main" - OpName %y "y" - OpName %outparm "outparm" - OpDecorate %y Flat - OpDecorate %y Location 0 - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int - %y = OpVariable %_ptr_Input_int Input - %int_10 = OpConstant %int 10 - %bool = OpTypeBool -%_ptr_Function_int = OpTypePointer Function %int - %int_23 = OpConstant %int 23 - %int_5 = OpConstant %int 5 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %24 = OpUndef %int - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %14 - %40 = OpLabel - %9 = OpLoad %int %y - %12 = OpSGreaterThan %bool %9 %int_10 - OpSelectionMerge %14 None - OpBranchConditional %12 %13 %14 - %13 = OpLabel - OpBranch %14 - %14 = OpLabel - %25 = OpPhi %int %24 %5 %int_23 %13 - %20 = OpIAdd %int %25 %int_5 - OpStore %outparm %20 - OpReturn - OpFunctionEnd)"; - - const std::string after = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %y %outparm -OpExecutionMode %main OriginUpperLeft -OpName %main "main" -OpName %y "y" -OpName %outparm "outparm" -OpDecorate %y Flat -OpDecorate %y Location 0 -OpDecorate %outparm Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%y = OpVariable %_ptr_Input_int Input -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%_ptr_Function_int = OpTypePointer Function %int -%int_23 = OpConstant %int 23 -%int_5 = OpConstant %int 5 -%_ptr_Output_int = OpTypePointer Output %int -%outparm = OpVariable %_ptr_Output_int Output -%15 = OpUndef %int -%main = OpFunction %void None %6 -%16 = OpLabel -OpBranch %17 -%17 = OpLabel -%22 = OpPhi %int %15 %16 -%23 = OpIAdd %int %22 %int_5 -OpStore %outparm %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/cfg_test.cpp b/3rdparty/spirv-tools/test/opt/cfg_test.cpp deleted file mode 100644 index 2cfc9f374..000000000 --- a/3rdparty/spirv-tools/test/opt/cfg_test.cpp +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/ir_context.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::ContainerEq; - -using CFGTest = PassTest<::testing::Test>; - -TEST_F(CFGTest, ForEachBlockInPostOrderIf) { - const std::string test = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -%bool = OpTypeBool -%true = OpConstantTrue %bool -%void = OpTypeVoid -%4 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%5 = OpConstant %uint 5 -%main = OpFunction %void None %4 -%8 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %true %9 %10 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, test, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - CFG* cfg = context->cfg(); - Module* module = context->module(); - Function* function = &*module->begin(); - std::vector order; - cfg->ForEachBlockInPostOrder(&*function->begin(), [&order](BasicBlock* bb) { - order.push_back(bb->id()); - }); - - std::vector expected_result = {10, 9, 8}; - EXPECT_THAT(order, ContainerEq(expected_result)); -} - -TEST_F(CFGTest, ForEachBlockInPostOrderLoop) { - const std::string test = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -%bool = OpTypeBool -%true = OpConstantTrue %bool -%void = OpTypeVoid -%4 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%5 = OpConstant %uint 5 -%main = OpFunction %void None %4 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %11 %10 None -OpBranchConditional %true %11 %10 -%10 = OpLabel -OpBranch %9 -%11 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, test, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - CFG* cfg = context->cfg(); - Module* module = context->module(); - Function* function = &*module->begin(); - std::vector order; - cfg->ForEachBlockInPostOrder(&*function->begin(), [&order](BasicBlock* bb) { - order.push_back(bb->id()); - }); - - std::vector expected_result1 = {10, 11, 9, 8}; - std::vector expected_result2 = {11, 10, 9, 8}; - EXPECT_THAT(order, AnyOf(ContainerEq(expected_result1), - ContainerEq(expected_result2))); -} - -TEST_F(CFGTest, ForEachBlockInReversePostOrderIf) { - const std::string test = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -%bool = OpTypeBool -%true = OpConstantTrue %bool -%void = OpTypeVoid -%4 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%5 = OpConstant %uint 5 -%main = OpFunction %void None %4 -%8 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %true %9 %10 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, test, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - CFG* cfg = context->cfg(); - Module* module = context->module(); - Function* function = &*module->begin(); - std::vector order; - cfg->ForEachBlockInReversePostOrder( - &*function->begin(), - [&order](BasicBlock* bb) { order.push_back(bb->id()); }); - - std::vector expected_result = {8, 9, 10}; - EXPECT_THAT(order, ContainerEq(expected_result)); -} - -TEST_F(CFGTest, ForEachBlockInReversePostOrderLoop) { - const std::string test = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -%bool = OpTypeBool -%true = OpConstantTrue %bool -%void = OpTypeVoid -%4 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%5 = OpConstant %uint 5 -%main = OpFunction %void None %4 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %11 %10 None -OpBranchConditional %true %11 %10 -%10 = OpLabel -OpBranch %9 -%11 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, test, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - CFG* cfg = context->cfg(); - Module* module = context->module(); - Function* function = &*module->begin(); - std::vector order; - cfg->ForEachBlockInReversePostOrder( - &*function->begin(), - [&order](BasicBlock* bb) { order.push_back(bb->id()); }); - - std::vector expected_result1 = {8, 9, 10, 11}; - std::vector expected_result2 = {8, 9, 11, 10}; - EXPECT_THAT(order, AnyOf(ContainerEq(expected_result1), - ContainerEq(expected_result2))); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/code_sink_test.cpp b/3rdparty/spirv-tools/test/opt/code_sink_test.cpp deleted file mode 100644 index f1bd12756..000000000 --- a/3rdparty/spirv-tools/test/opt/code_sink_test.cpp +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using CodeSinkTest = PassTest<::testing::Test>; - -TEST_F(CodeSinkTest, MoveToNextBlock) { - const std::string text = R"( -;CHECK: OpFunction -;CHECK: OpLabel -;CHECK: OpLabel -;CHECK: [[ac:%\w+]] = OpAccessChain -;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]] -;CHECK: OpCopyObject %uint [[ld]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %9 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %10 = OpTypeFunction %void - %1 = OpFunction %void None %10 - %11 = OpLabel - %12 = OpAccessChain %_ptr_Uniform_uint %9 %uint_0 - %13 = OpLoad %uint %12 - OpBranch %14 - %14 = OpLabel - %15 = OpCopyObject %uint %13 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CodeSinkTest, MovePastSelection) { - const std::string text = R"( -;CHECK: OpFunction -;CHECK: OpLabel -;CHECK: OpSelectionMerge [[merge_bb:%\w+]] -;CHECK: [[merge_bb]] = OpLabel -;CHECK: [[ac:%\w+]] = OpAccessChain -;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]] -;CHECK: OpCopyObject %uint [[ld]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %16 - %17 = OpLabel - OpBranch %16 - %16 = OpLabel - %18 = OpCopyObject %uint %15 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CodeSinkTest, MoveIntoSelection) { - const std::string text = R"( -;CHECK: OpFunction -;CHECK: OpLabel -;CHECK: OpSelectionMerge [[merge_bb:%\w+]] -;CHECK-NEXT: OpBranchConditional %true [[bb:%\w+]] [[merge_bb]] -;CHECK: [[bb]] = OpLabel -;CHECK-NEXT: [[ac:%\w+]] = OpAccessChain -;CHECK-NEXT: [[ld:%\w+]] = OpLoad %uint [[ac]] -;CHECK-NEXT: OpCopyObject %uint [[ld]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CodeSinkTest, LeaveBeforeSelection) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - %19 = OpCopyObject %uint %15 - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, LeaveAloneUseInSameBlock) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - %cond = OpIEqual %bool %15 %uint_0 - OpSelectionMerge %16 None - OpBranchConditional %cond %17 %16 - %17 = OpLabel - OpBranch %16 - %16 = OpLabel - %19 = OpCopyObject %uint %15 - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DontMoveIntoLoop) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpBranch %17 - %17 = OpLabel - OpLoopMerge %merge %cont None - OpBranch %cont - %cont = OpLabel - %cond = OpIEqual %bool %15 %uint_0 - OpBranchConditional %cond %merge %17 - %merge = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DontMoveIntoLoop2) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %16 - %17 = OpLabel - OpLoopMerge %merge %cont None - OpBranch %cont - %cont = OpLabel - %cond = OpIEqual %bool %15 %uint_0 - OpBranchConditional %cond %merge %17 - %merge = OpLabel - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DontMoveSelectionUsedInBothSides) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - %19 = OpCopyObject %uint %15 - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DontMoveBecauseOfStore) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpStore %14 %15 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, MoveReadOnlyLoadWithSync) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%mem_semantics = OpConstant %uint 0x42 ; Uniform memeory arquire -%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpMemoryBarrier %uint_4 %mem_semantics - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DontMoveBecauseOfSync) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpDecorate %_arr_uint_uint_4 BufferBlock - OpMemberDecorate %_arr_uint_uint_4 0 Offset 0 - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%mem_semantics = OpConstant %uint 0x42 ; Uniform memeory arquire -%_arr_uint_uint_4 = OpTypeStruct %uint -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - OpMemoryBarrier %uint_4 %mem_semantics - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DontMoveBecauseOfAtomicWithSync) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpDecorate %_arr_uint_uint_4 BufferBlock - OpMemberDecorate %_arr_uint_uint_4 0 Offset 0 - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%mem_semantics = OpConstant %uint 0x42 ; Uniform memeory arquire -%_arr_uint_uint_4 = OpTypeStruct %uint -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - %al = OpAtomicLoad %uint %14 %uint_4 %mem_semantics - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, MoveWithAtomicWithoutSync) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpDecorate %_arr_uint_uint_4 BufferBlock - OpMemberDecorate %_arr_uint_uint_4 0 Offset 0 - %void = OpTypeVoid - %bool = OpTypeBool - %true = OpConstantTrue %bool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_4 = OpConstant %uint 4 -%_arr_uint_uint_4 = OpTypeStruct %uint -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 - %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform - %12 = OpTypeFunction %void - %1 = OpFunction %void None %12 - %13 = OpLabel - %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 - %15 = OpLoad %uint %14 - %al = OpAtomicLoad %uint %14 %uint_4 %uint_0 - OpSelectionMerge %16 None - OpBranchConditional %true %17 %20 - %20 = OpLabel - OpBranch %16 - %17 = OpLabel - %18 = OpCopyObject %uint %15 - OpBranch %16 - %16 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); -} - -TEST_F(CodeSinkTest, DecorationOnLoad) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" %2 - OpDecorate %3 RelaxedPrecision - %void = OpTypeVoid - %5 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Input_float = OpTypePointer Input %float - %2 = OpVariable %_ptr_Input_float Input - %1 = OpFunction %void None %5 - %8 = OpLabel - %3 = OpLoad %float %2 - OpReturn - OpFunctionEnd -)"; - - // We just want to make sure the code does not crash. - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/combine_access_chains_test.cpp b/3rdparty/spirv-tools/test/opt/combine_access_chains_test.cpp deleted file mode 100644 index aed14c9de..000000000 --- a/3rdparty/spirv-tools/test/opt/combine_access_chains_test.cpp +++ /dev/null @@ -1,773 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using CombineAccessChainsTest = PassTest<::testing::Test>; - -TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainConstant) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpAccessChain %ptr_Workgroup_uint %var %uint_0 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, PtrAccessChainFromInBoundsAccessChainConstant) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpInBoundsAccessChain %ptr_Workgroup_uint %var %uint_0 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainCombineConstant) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2 -; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int2]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpAccessChain %ptr_Workgroup_uint %var %uint_1 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_1 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainNonConstant) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[ld1:%\w+]] = OpLoad -; CHECK: [[ld2:%\w+]] = OpLoad -; CHECK: [[add:%\w+]] = OpIAdd [[int]] [[ld1]] [[ld2]] -; CHECK: OpAccessChain [[ptr_int]] [[var]] [[add]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Function_uint = OpTypePointer Function %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%local_var = OpVariable %ptr_Function_uint Function -%ld1 = OpLoad %uint %local_var -%gep = OpAccessChain %ptr_Workgroup_uint %var %ld1 -%ld2 = OpLoad %uint %local_var -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %ld2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainExtraIndices) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int1:%\w+]] = OpConstant [[int]] 1 -; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int1]] [[int2]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%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_array_4 = OpTypeArray %uint %uint_4 -%uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4 -%uint_array_4_array_4_array_4 = OpTypeArray %uint_array_4_array_4 %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Function_uint = OpTypePointer Function %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4 -%ptr_Workgroup_uint_array_4_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4_array_4_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpAccessChain %ptr_Workgroup_uint_array_4 %var %uint_1 %uint_0 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_2 %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, - PtrAccessChainFromPtrAccessChainCombineElementOperand) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6 -; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int6]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3 %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, - PtrAccessChainFromPtrAccessChainOnlyElementOperand) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4 -; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]] -; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6 -; CHECK: OpPtrAccessChain [[ptr_array]] [[var]] [[int6]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, - PtrAccessChainFromPtrAccessCombineNonElementIndex) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int3]] [[int3]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Function_uint = OpTypePointer Function %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 %uint_0 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3 %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, - AccessChainFromPtrAccessChainOnlyElementOperand) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int3]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 -%gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, AccessChainFromPtrAccessChainAppend) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int1:%\w+]] = OpConstant [[int]] 1 -; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2 -; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int1]] [[int2]] [[int3]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%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_array_4 = OpTypeArray %uint %uint_4 -%uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_1 %uint_2 -%gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, AccessChainFromAccessChainAppend) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int1:%\w+]] = OpConstant [[int]] 1 -; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2 -; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int1]] [[int2]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%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_array_4 = OpTypeArray %uint %uint_4 -%uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%ptr_gep = OpAccessChain %ptr_Workgroup_uint_array_4 %var %uint_1 -%gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, NonConstantStructSlide) { - const std::string text = R"( -; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[ld:%\w+]] = OpLoad -; CHECK: OpPtrAccessChain {{%\w+}} [[var]] [[ld]] [[int0]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%struct = OpTypeStruct %uint %uint -%ptr_Workgroup_struct = OpTypePointer Workgroup %struct -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Function_uint = OpTypePointer Function %uint -%wg_var = OpVariable %ptr_Workgroup_struct Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%1 = OpLabel -%func_var = OpVariable %ptr_Function_uint Function -%ld = OpLoad %uint %func_var -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_struct %wg_var %ld -%gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, DontCombineNonConstantStructSlide) { - const std::string text = R"( -; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[ld:%\w+]] = OpLoad -; CHECK: [[gep:%\w+]] = OpAccessChain -; CHECK: OpPtrAccessChain {{%\w+}} [[gep]] [[ld]] [[int0]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_4 = OpConstant %uint 4 -%struct = OpTypeStruct %uint %uint -%struct_array_4 = OpTypeArray %struct %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Function_uint = OpTypePointer Function %uint -%ptr_Workgroup_struct = OpTypePointer Workgroup %struct -%ptr_Workgroup_struct_array_4 = OpTypePointer Workgroup %struct_array_4 -%wg_var = OpVariable %ptr_Workgroup_struct_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%1 = OpLabel -%func_var = OpVariable %ptr_Function_uint Function -%ld = OpLoad %uint %func_var -%gep = OpAccessChain %ptr_Workgroup_struct %wg_var %uint_0 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %ld %uint_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, CombineNonConstantStructSlideElement) { - const std::string text = R"( -; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[ld:%\w+]] = OpLoad -; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]] [[ld]] -; CHECK: OpPtrAccessChain {{%\w+}} [[var]] [[add]] [[int0]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_4 = OpConstant %uint 4 -%struct = OpTypeStruct %uint %uint -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Function_uint = OpTypePointer Function %uint -%ptr_Workgroup_struct = OpTypePointer Workgroup %struct -%wg_var = OpVariable %ptr_Workgroup_struct Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%1 = OpLabel -%func_var = OpVariable %ptr_Function_uint Function -%ld = OpLoad %uint %func_var -%gep = OpPtrAccessChain %ptr_Workgroup_struct %wg_var %ld -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %ld %uint_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, PtrAccessChainFromInBoundsPtrAccessChain) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4 -; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]] -; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6 -; CHECK: OpPtrAccessChain [[ptr_array]] [[var]] [[int6]] -OpCapability Shader -OpCapability VariablePointers -OpCapability Addresses -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 -%ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, InBoundsPtrAccessChainFromPtrAccessChain) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4 -; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]] -; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6 -; CHECK: OpPtrAccessChain [[ptr_array]] [[var]] [[int6]] -OpCapability Shader -OpCapability VariablePointers -OpCapability Addresses -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 -%ptr_gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, - InBoundsPtrAccessChainFromInBoundsPtrAccessChain) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4 -; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]] -; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]] -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup -; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6 -; CHECK: OpInBoundsPtrAccessChain [[ptr_array]] [[var]] [[int6]] -OpCapability Shader -OpCapability VariablePointers -OpCapability Addresses -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_array_4 = OpTypeArray %uint %uint_4 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4 -%var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -%gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 -%ptr_gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, NoIndexAccessChains) { - const std::string text = R"( -; CHECK: [[var:%\w+]] = OpVariable -; CHECK-NOT: OpConstant -; CHECK: [[gep:%\w+]] = OpAccessChain {{%\w+}} [[var]] -; CHECK: OpAccessChain {{%\w+}} [[var]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%var = OpVariable %ptr_Workgroup_uint Workgroup -%void_func = OpTypeFunction %void -%func = OpFunction %void None %void_func -%1 = OpLabel -%gep1 = OpAccessChain %ptr_Workgroup_uint %var -%gep2 = OpAccessChain %ptr_Workgroup_uint %gep1 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, NoIndexPtrAccessChains) { - const std::string text = R"( -; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: [[gep:%\w+]] = OpPtrAccessChain {{%\w+}} [[var]] [[int0]] -; CHECK: OpCopyObject {{%\w+}} [[gep]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%var = OpVariable %ptr_Workgroup_uint Workgroup -%void_func = OpTypeFunction %void -%func = OpFunction %void None %void_func -%1 = OpLabel -%gep1 = OpPtrAccessChain %ptr_Workgroup_uint %var %uint_0 -%gep2 = OpAccessChain %ptr_Workgroup_uint %gep1 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, NoIndexPtrAccessChains2) { - const std::string text = R"( -; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: OpPtrAccessChain {{%\w+}} [[var]] [[int0]] -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%var = OpVariable %ptr_Workgroup_uint Workgroup -%void_func = OpTypeFunction %void -%func = OpFunction %void None %void_func -%1 = OpLabel -%gep1 = OpAccessChain %ptr_Workgroup_uint %var -%gep2 = OpPtrAccessChain %ptr_Workgroup_uint %gep1 %uint_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(CombineAccessChainsTest, CombineMixedSign) { - const std::string text = R"( -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: [[uint2:%\w+]] = OpConstant [[uint]] 2 -; CHECK: OpInBoundsPtrAccessChain {{%\w+}} [[var]] [[uint2]] -OpCapability Shader -OpCapability VariablePointers -OpCapability Addresses -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%int = OpTypeInt 32 1 -%uint_1 = OpConstant %uint 1 -%int_1 = OpConstant %int 1 -%ptr_Workgroup_uint = OpTypePointer Workgroup %uint -%var = OpVariable %ptr_Workgroup_uint Workgroup -%void_func = OpTypeFunction %void -%func = OpFunction %void None %void_func -%1 = OpLabel -%gep1 = OpInBoundsPtrAccessChain %ptr_Workgroup_uint %var %uint_1 -%gep2 = OpInBoundsPtrAccessChain %ptr_Workgroup_uint %gep1 %int_1 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/compact_ids_test.cpp b/3rdparty/spirv-tools/test/opt/compact_ids_test.cpp deleted file mode 100644 index b1e4b2cbb..000000000 --- a/3rdparty/spirv-tools/test/opt/compact_ids_test.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "spirv-tools/libspirv.hpp" -#include "spirv-tools/optimizer.hpp" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using CompactIdsTest = PassTest<::testing::Test>; - -TEST_F(CompactIdsTest, PassOff) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -%99 = OpTypeInt 32 0 -%10 = OpTypeVector %99 2 -%20 = OpConstant %99 2 -%30 = OpTypeArray %99 %20 -)"; - - const std::string after = before; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, false); -} - -TEST_F(CompactIdsTest, PassOn) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %3 "simple_kernel" -%99 = OpTypeInt 32 0 -%10 = OpTypeVector %99 2 -%20 = OpConstant %99 2 -%30 = OpTypeArray %99 %20 -%40 = OpTypeVoid -%50 = OpTypeFunction %40 - %3 = OpFunction %40 None %50 -%70 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %1 "simple_kernel" -%2 = OpTypeInt 32 0 -%3 = OpTypeVector %2 2 -%4 = OpConstant %2 2 -%5 = OpTypeArray %2 %4 -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%1 = OpFunction %6 None %7 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, false); -} - -TEST(CompactIds, InstructionResultIsUpdated) { - // For https://github.com/KhronosGroup/SPIRV-Tools/issues/827 - // In that bug, the compact Ids pass was directly updating the result Id - // word for an OpFunction instruction, but not updating the cached - // result_id_ in that Instruction object. - // - // This test is a bit cheesy. We don't expose internal interfaces enough - // to see the inconsistency. So reproduce the original scenario, with - // compact ids followed by a pass that trips up on the inconsistency. - - const std::string input(R"(OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %100 "main" -%200 = OpTypeVoid -%300 = OpTypeFunction %200 -%100 = OpFunction %200 None %300 -%400 = OpLabel -OpReturn -OpFunctionEnd -)"); - - std::vector binary; - const spv_target_env env = SPV_ENV_UNIVERSAL_1_0; - spvtools::SpirvTools tools(env); - auto assembled = tools.Assemble( - input, &binary, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_TRUE(assembled); - - spvtools::Optimizer optimizer(env); - optimizer.RegisterPass(CreateCompactIdsPass()); - // The exhaustive inliner will use the result_id - optimizer.RegisterPass(CreateInlineExhaustivePass()); - - // This should not crash! - optimizer.Run(binary.data(), binary.size(), &binary); - - std::string disassembly; - tools.Disassemble(binary, &disassembly, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - const std::string expected(R"(OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %1 "main" -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%1 = OpFunction %2 None %3 -%4 = OpLabel -OpReturn -OpFunctionEnd -)"); - - EXPECT_THAT(disassembly, ::testing::Eq(expected)); -} - -TEST(CompactIds, HeaderIsUpdated) { - const std::string input(R"(OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %100 "main" -%200 = OpTypeVoid -%300 = OpTypeFunction %200 -%100 = OpFunction %200 None %300 -%400 = OpLabel -OpReturn -OpFunctionEnd -)"); - - std::vector binary; - const spv_target_env env = SPV_ENV_UNIVERSAL_1_0; - spvtools::SpirvTools tools(env); - auto assembled = tools.Assemble( - input, &binary, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_TRUE(assembled); - - spvtools::Optimizer optimizer(env); - optimizer.RegisterPass(CreateCompactIdsPass()); - // The exhaustive inliner will use the result_id - optimizer.RegisterPass(CreateInlineExhaustivePass()); - - // This should not crash! - optimizer.Run(binary.data(), binary.size(), &binary); - - std::string disassembly; - tools.Disassemble(binary, &disassembly, SPV_BINARY_TO_TEXT_OPTION_NONE); - - const std::string expected(R"(; SPIR-V -; Version: 1.0 -; Generator: Khronos SPIR-V Tools Assembler; 0 -; Bound: 5 -; Schema: 0 -OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %1 "main" -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%1 = OpFunction %2 None %3 -%4 = OpLabel -OpReturn -OpFunctionEnd -)"); - - EXPECT_THAT(disassembly, ::testing::Eq(expected)); -} - -// Test context consistency check after invalidating -// CFG and others by compact IDs Pass. -// Uses a GLSL shader with named labels for variety -TEST(CompactIds, ConsistentCheck) { - const std::string input(R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_A %out_var_SV_TARGET -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %main "main" -OpName %in_var_A "in.var.A" -OpName %out_var_SV_TARGET "out.var.SV_TARGET" -OpDecorate %in_var_A Location 0 -OpDecorate %out_var_SV_TARGET Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%in_var_A = OpVariable %_ptr_Input_v4float Input -%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %3 -%5 = OpLabel -%12 = OpLoad %v4float %in_var_A -%23 = OpVectorShuffle %v4float %12 %12 0 0 0 1 -OpStore %out_var_SV_TARGET %23 -OpReturn -OpFunctionEnd -)"); - - spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(context, nullptr); - - CompactIdsPass compact_id_pass; - context->BuildInvalidAnalyses(compact_id_pass.GetPreservedAnalyses()); - const auto status = compact_id_pass.Run(context.get()); - ASSERT_NE(status, Pass::Status::Failure); - EXPECT_TRUE(context->IsConsistent()); - - // Test output just in case - std::vector binary; - context->module()->ToBinary(&binary, false); - std::string disassembly; - tools.Disassemble(binary, &disassembly, - SpirvTools::kDefaultDisassembleOption); - - const std::string expected(R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_A %out_var_SV_TARGET -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %main "main" -OpName %in_var_A "in.var.A" -OpName %out_var_SV_TARGET "out.var.SV_TARGET" -OpDecorate %in_var_A Location 0 -OpDecorate %out_var_SV_TARGET Location 0 -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%in_var_A = OpVariable %_ptr_Input_v4float Input -%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %5 -%10 = OpLabel -%11 = OpLoad %v4float %in_var_A -%12 = OpVectorShuffle %v4float %11 %11 0 0 0 1 -OpStore %out_var_SV_TARGET %12 -OpReturn -OpFunctionEnd -)"); - - EXPECT_THAT(disassembly, ::testing::Eq(expected)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/constant_manager_test.cpp b/3rdparty/spirv-tools/test/opt/constant_manager_test.cpp deleted file mode 100644 index 14e14ec20..000000000 --- a/3rdparty/spirv-tools/test/opt/constant_manager_test.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/constants.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { -namespace analysis { -namespace { - -using ConstantManagerTest = ::testing::Test; - -TEST_F(ConstantManagerTest, GetDefiningInstruction) { - const std::string text = R"( -%int = OpTypeInt 32 0 -%1 = OpTypeStruct %int -%2 = OpTypeStruct %int - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(context, nullptr); - - Type* struct_type_1 = context->get_type_mgr()->GetType(1); - StructConstant struct_const_1(struct_type_1->AsStruct()); - Instruction* const_inst_1 = - context->get_constant_mgr()->GetDefiningInstruction(&struct_const_1, 1); - EXPECT_EQ(const_inst_1->type_id(), 1); - - Type* struct_type_2 = context->get_type_mgr()->GetType(2); - StructConstant struct_const_2(struct_type_2->AsStruct()); - Instruction* const_inst_2 = - context->get_constant_mgr()->GetDefiningInstruction(&struct_const_2, 2); - EXPECT_EQ(const_inst_2->type_id(), 2); -} - -TEST_F(ConstantManagerTest, GetDefiningInstruction2) { - const std::string text = R"( -%int = OpTypeInt 32 0 -%1 = OpTypeStruct %int -%2 = OpTypeStruct %int -%3 = OpConstantNull %1 -%4 = OpConstantNull %2 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(context, nullptr); - - Type* struct_type_1 = context->get_type_mgr()->GetType(1); - NullConstant struct_const_1(struct_type_1->AsStruct()); - Instruction* const_inst_1 = - context->get_constant_mgr()->GetDefiningInstruction(&struct_const_1, 1); - EXPECT_EQ(const_inst_1->type_id(), 1); - EXPECT_EQ(const_inst_1->result_id(), 3); - - Type* struct_type_2 = context->get_type_mgr()->GetType(2); - NullConstant struct_const_2(struct_type_2->AsStruct()); - Instruction* const_inst_2 = - context->get_constant_mgr()->GetDefiningInstruction(&struct_const_2, 2); - EXPECT_EQ(const_inst_2->type_id(), 2); - EXPECT_EQ(const_inst_2->result_id(), 4); -} - -TEST_F(ConstantManagerTest, GetDefiningInstructionIdOverflow) { - const std::string text = R"( -%1 = OpTypeInt 32 0 -%3 = OpConstant %1 1 -%4 = OpConstant %1 2 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(context, nullptr); - - // Set the id bound to the max, so the new constant cannot be generated. - context->module()->SetIdBound(context->max_id_bound()); - - Type* int_type = context->get_type_mgr()->GetType(1); - IntConstant int_constant(int_type->AsInteger(), {3}); - Instruction* inst = - context->get_constant_mgr()->GetDefiningInstruction(&int_constant, 1); - EXPECT_EQ(inst, nullptr); -} - -} // namespace -} // namespace analysis -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/constants_test.cpp b/3rdparty/spirv-tools/test/opt/constants_test.cpp deleted file mode 100644 index 55c92a513..000000000 --- a/3rdparty/spirv-tools/test/opt/constants_test.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/opt/constants.h" - -#include - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/types.h" - -namespace spvtools { -namespace opt { -namespace analysis { -namespace { - -using ConstantTest = ::testing::Test; -using ::testing::ValuesIn; - -template -struct GetExtendedValueCase { - bool is_signed; - int width; - std::vector words; - T expected_value; -}; - -using GetSignExtendedValueCase = GetExtendedValueCase; -using GetZeroExtendedValueCase = GetExtendedValueCase; - -using GetSignExtendedValueTest = - ::testing::TestWithParam; -using GetZeroExtendedValueTest = - ::testing::TestWithParam; - -TEST_P(GetSignExtendedValueTest, Case) { - Integer type(GetParam().width, GetParam().is_signed); - IntConstant value(&type, GetParam().words); - - EXPECT_EQ(GetParam().expected_value, value.GetSignExtendedValue()); -} - -TEST_P(GetZeroExtendedValueTest, Case) { - Integer type(GetParam().width, GetParam().is_signed); - IntConstant value(&type, GetParam().words); - - EXPECT_EQ(GetParam().expected_value, value.GetZeroExtendedValue()); -} - -const uint32_t k32ones = ~uint32_t(0); -const uint64_t k64ones = ~uint64_t(0); -const int64_t kSBillion = 1000 * 1000 * 1000; -const uint64_t kUBillion = 1000 * 1000 * 1000; - -INSTANTIATE_TEST_SUITE_P(AtMost32Bits, GetSignExtendedValueTest, - ValuesIn(std::vector{ - // 4 bits - {false, 4, {0}, 0}, - {false, 4, {7}, 7}, - {false, 4, {15}, 15}, - {true, 4, {0}, 0}, - {true, 4, {7}, 7}, - {true, 4, {0xfffffff8}, -8}, - {true, 4, {k32ones}, -1}, - // 16 bits - {false, 16, {0}, 0}, - {false, 16, {32767}, 32767}, - {false, 16, {32768}, 32768}, - {false, 16, {65000}, 65000}, - {true, 16, {0}, 0}, - {true, 16, {32767}, 32767}, - {true, 16, {0xfffffff8}, -8}, - {true, 16, {k32ones}, -1}, - // 32 bits - {false, 32, {0}, 0}, - {false, 32, {1000000}, 1000000}, - {true, 32, {0xfffffff8}, -8}, - {true, 32, {k32ones}, -1}, - })); - -INSTANTIATE_TEST_SUITE_P(AtMost64Bits, GetSignExtendedValueTest, - ValuesIn(std::vector{ - // 48 bits - {false, 48, {0, 0}, 0}, - {false, 48, {5, 0}, 5}, - {false, 48, {0xfffffff8, k32ones}, -8}, - {false, 48, {k32ones, k32ones}, -1}, - {false, 48, {0xdcd65000, 1}, 8 * kSBillion}, - {true, 48, {0xfffffff8, k32ones}, -8}, - {true, 48, {k32ones, k32ones}, -1}, - {true, 48, {0xdcd65000, 1}, 8 * kSBillion}, - - // 64 bits - {false, 64, {12, 0}, 12}, - {false, 64, {0xdcd65000, 1}, 8 * kSBillion}, - {false, 48, {0xfffffff8, k32ones}, -8}, - {false, 64, {k32ones, k32ones}, -1}, - {true, 64, {12, 0}, 12}, - {true, 64, {0xdcd65000, 1}, 8 * kSBillion}, - {true, 48, {0xfffffff8, k32ones}, -8}, - {true, 64, {k32ones, k32ones}, -1}, - })); - -INSTANTIATE_TEST_SUITE_P(AtMost32Bits, GetZeroExtendedValueTest, - ValuesIn(std::vector{ - // 4 bits - {false, 4, {0}, 0}, - {false, 4, {7}, 7}, - {false, 4, {15}, 15}, - {true, 4, {0}, 0}, - {true, 4, {7}, 7}, - {true, 4, {0xfffffff8}, 0xfffffff8}, - {true, 4, {k32ones}, k32ones}, - // 16 bits - {false, 16, {0}, 0}, - {false, 16, {32767}, 32767}, - {false, 16, {32768}, 32768}, - {false, 16, {65000}, 65000}, - {true, 16, {0}, 0}, - {true, 16, {32767}, 32767}, - {true, 16, {0xfffffff8}, 0xfffffff8}, - {true, 16, {k32ones}, k32ones}, - // 32 bits - {false, 32, {0}, 0}, - {false, 32, {1000000}, 1000000}, - {true, 32, {0xfffffff8}, 0xfffffff8}, - {true, 32, {k32ones}, k32ones}, - })); - -INSTANTIATE_TEST_SUITE_P(AtMost64Bits, GetZeroExtendedValueTest, - ValuesIn(std::vector{ - // 48 bits - {false, 48, {0, 0}, 0}, - {false, 48, {5, 0}, 5}, - {false, 48, {0xfffffff8, k32ones}, uint64_t(-8)}, - {false, 48, {k32ones, k32ones}, uint64_t(-1)}, - {false, 48, {0xdcd65000, 1}, 8 * kUBillion}, - {true, 48, {0xfffffff8, k32ones}, uint64_t(-8)}, - {true, 48, {k32ones, k32ones}, uint64_t(-1)}, - {true, 48, {0xdcd65000, 1}, 8 * kUBillion}, - - // 64 bits - {false, 64, {12, 0}, 12}, - {false, 64, {0xdcd65000, 1}, 8 * kUBillion}, - {false, 48, {0xfffffff8, k32ones}, uint64_t(-8)}, - {false, 64, {k32ones, k32ones}, k64ones}, - {true, 64, {12, 0}, 12}, - {true, 64, {0xdcd65000, 1}, 8 * kUBillion}, - {true, 48, {0xfffffff8, k32ones}, uint64_t(-8)}, - {true, 64, {k32ones, k32ones}, k64ones}, - })); - -} // namespace -} // namespace analysis -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/convert_relaxed_to_half_test.cpp b/3rdparty/spirv-tools/test/opt/convert_relaxed_to_half_test.cpp deleted file mode 100644 index 3ac80099f..000000000 --- a/3rdparty/spirv-tools/test/opt/convert_relaxed_to_half_test.cpp +++ /dev/null @@ -1,1227 +0,0 @@ -// Copyright (c) 2019 Valve Corporation -// Copyright (c) 2019 LunarG 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. - -// Convert Relaxed to Half tests - -#include -#include - -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ConvertToHalfTest = PassTest<::testing::Test>; - -TEST_F(ConvertToHalfTest, ConvertToHalfBasic) { - // The resulting SPIR-V was processed with --relax-float-ops. - // - // clang-format off - // - // SamplerState g_sSamp : register(s0); - // uniform Texture1D g_tTex1df4 : register(t0); - // - // struct PS_INPUT - // { - // float Tex0 : TEXCOORD0; - // }; - // - // struct PS_OUTPUT - // { - // float4 Color : SV_Target0; - // }; - // - // cbuffer cbuff{ - // float c; - // } - // - // PS_OUTPUT main(PS_INPUT i) - // { - // PS_OUTPUT psout; - // psout.Color = g_tTex1df4.Sample(g_sSamp, i.Tex0) * c; - // return psout; - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "c" -OpName %_ "" -OpName %i_Tex0 "i.Tex0" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 Offset 0 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %i_Tex0 Location 0 -OpDecorate %_entryPointOutput_Color Location 0 -OpDecorate %48 RelaxedPrecision -OpDecorate %63 RelaxedPrecision -OpDecorate %65 RelaxedPrecision -OpDecorate %66 RelaxedPrecision -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%19 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_19 UniformConstant -%23 = OpTypeSampler -%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 -%g_sSamp = OpVariable %_ptr_UniformConstant_23 UniformConstant -%27 = OpTypeSampledImage %19 -%cbuff = OpTypeStruct %float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpCapability Float16 -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "c" -OpName %_ "" -OpName %i_Tex0 "i.Tex0" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 Offset 0 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %i_Tex0 Location 0 -OpDecorate %_entryPointOutput_Color Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%19 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_19 UniformConstant -%23 = OpTypeSampler -%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 -%g_sSamp = OpVariable %_ptr_UniformConstant_23 UniformConstant -%27 = OpTypeSampledImage %19 -%cbuff = OpTypeStruct %float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%half = OpTypeFloat 16 -%v4half = OpTypeVector %half 4 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%48 = OpLoad %float %i_Tex0 -%58 = OpLoad %19 %g_tTex1df4 -%59 = OpLoad %23 %g_sSamp -%60 = OpSampledImage %27 %58 %59 -%63 = OpImageSampleImplicitLod %v4float %60 %48 -%64 = OpAccessChain %_ptr_Uniform_float %_ %int_0 -%65 = OpLoad %float %64 -%66 = OpVectorTimesScalar %v4float %63 %65 -OpStore %_entryPointOutput_Color %66 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%48 = OpLoad %float %i_Tex0 -%58 = OpLoad %19 %g_tTex1df4 -%59 = OpLoad %23 %g_sSamp -%60 = OpSampledImage %27 %58 %59 -%63 = OpImageSampleImplicitLod %v4float %60 %48 -%64 = OpAccessChain %_ptr_Uniform_float %_ %int_0 -%65 = OpLoad %float %64 -%69 = OpFConvert %v4half %63 -%70 = OpFConvert %half %65 -%66 = OpVectorTimesScalar %v4half %69 %70 -%71 = OpFConvert %v4float %66 -OpStore %_entryPointOutput_Color %71 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(ConvertToHalfTest, ConvertToHalfWithDrefSample) { - // The resulting SPIR-V was processed with --relax-float-ops. - // - // clang-format off - // - // SamplerComparisonState g_sSamp : register(s0); - // uniform Texture1D g_tTex1df4 : register(t0); - // - // cbuffer cbuff{ - // float c1; - // float c2; - // }; - // - // struct PS_INPUT - // { - // float Tex0 : TEXCOORD0; - // float Tex1 : TEXCOORD1; - // }; - // - // struct PS_OUTPUT - // { - // float Color : SV_Target0; - // }; - // - // PS_OUTPUT main(PS_INPUT i) - // { - // PS_OUTPUT psout; - // float txval10 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex0 * 0.1, c1 + 0.1); - // float txval11 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex1 * 0.2, c2 + 0.2); - // float t = txval10 + txval11; - // float t2 = t / 2.0; - // psout.Color = t2; - // return psout; - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "c1" -OpMemberName %cbuff 1 "c2" -OpName %_ "" -OpName %i_Tex0 "i.Tex0" -OpName %i_Tex1 "i.Tex1" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 Offset 0 -OpMemberDecorate %cbuff 1 Offset 4 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %i_Tex0 Location 0 -OpDecorate %i_Tex1 Location 1 -OpDecorate %_entryPointOutput_Color Location 0 -OpDecorate %100 RelaxedPrecision -OpDecorate %76 RelaxedPrecision -OpDecorate %79 RelaxedPrecision -OpDecorate %98 RelaxedPrecision -OpDecorate %101 RelaxedPrecision -OpDecorate %110 RelaxedPrecision -OpDecorate %102 RelaxedPrecision -OpDecorate %112 RelaxedPrecision -OpDecorate %104 RelaxedPrecision -OpDecorate %113 RelaxedPrecision -OpDecorate %114 RelaxedPrecision -OpDecorate %116 RelaxedPrecision -OpDecorate %119 RelaxedPrecision -OpDecorate %121 RelaxedPrecision -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%16 = OpTypeImage %float 1D 1 0 0 1 Unknown -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_16 UniformConstant -%20 = OpTypeSampler -%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 -%g_sSamp = OpVariable %_ptr_UniformConstant_20 UniformConstant -%24 = OpTypeSampledImage %16 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%float_0_100000001 = OpConstant %float 0.100000001 -%cbuff = OpTypeStruct %float %float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%v2float = OpTypeVector %float 2 -%int_1 = OpConstant %int 1 -%float_0_200000003 = OpConstant %float 0.200000003 -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%i_Tex1 = OpVariable %_ptr_Input_float Input -%_ptr_Output_float = OpTypePointer Output %float -%_entryPointOutput_Color = OpVariable %_ptr_Output_float Output -%float_0_5 = OpConstant %float 0.5 -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpCapability Float16 -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "c1" -OpMemberName %cbuff 1 "c2" -OpName %_ "" -OpName %i_Tex0 "i.Tex0" -OpName %i_Tex1 "i.Tex1" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 Offset 0 -OpMemberDecorate %cbuff 1 Offset 4 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %i_Tex0 Location 0 -OpDecorate %i_Tex1 Location 1 -OpDecorate %_entryPointOutput_Color Location 0 -%void = OpTypeVoid -%25 = OpTypeFunction %void -%float = OpTypeFloat 32 -%27 = OpTypeImage %float 1D 1 0 0 1 Unknown -%_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_27 UniformConstant -%29 = OpTypeSampler -%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 -%g_sSamp = OpVariable %_ptr_UniformConstant_29 UniformConstant -%31 = OpTypeSampledImage %27 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%float_0_100000001 = OpConstant %float 0.100000001 -%cbuff = OpTypeStruct %float %float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%v2float = OpTypeVector %float 2 -%int_1 = OpConstant %int 1 -%float_0_200000003 = OpConstant %float 0.200000003 -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%i_Tex1 = OpVariable %_ptr_Input_float Input -%_ptr_Output_float = OpTypePointer Output %float -%_entryPointOutput_Color = OpVariable %_ptr_Output_float Output -%float_0_5 = OpConstant %float 0.5 -%half = OpTypeFloat 16 -%v2half = OpTypeVector %half 2 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%76 = OpLoad %float %i_Tex0 -%79 = OpLoad %float %i_Tex1 -%93 = OpLoad %16 %g_tTex1df4 -%94 = OpLoad %20 %g_sSamp -%95 = OpSampledImage %24 %93 %94 -%98 = OpFMul %float %76 %float_0_100000001 -%99 = OpAccessChain %_ptr_Uniform_float %_ %int_0 -%100 = OpLoad %float %99 -%101 = OpFAdd %float %100 %float_0_100000001 -%102 = OpCompositeConstruct %v2float %98 %101 -%104 = OpImageSampleDrefImplicitLod %float %95 %102 %101 -%105 = OpLoad %16 %g_tTex1df4 -%106 = OpLoad %20 %g_sSamp -%107 = OpSampledImage %24 %105 %106 -%110 = OpFMul %float %79 %float_0_200000003 -%111 = OpAccessChain %_ptr_Uniform_float %_ %int_1 -%112 = OpLoad %float %111 -%113 = OpFAdd %float %112 %float_0_200000003 -%114 = OpCompositeConstruct %v2float %110 %113 -%116 = OpImageSampleDrefImplicitLod %float %107 %114 %113 -%119 = OpFAdd %float %104 %116 -%121 = OpFMul %float %119 %float_0_5 -OpStore %_entryPointOutput_Color %121 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %25 -%43 = OpLabel -%11 = OpLoad %float %i_Tex0 -%12 = OpLoad %float %i_Tex1 -%44 = OpLoad %27 %g_tTex1df4 -%45 = OpLoad %29 %g_sSamp -%46 = OpSampledImage %31 %44 %45 -%53 = OpFConvert %half %11 -%54 = OpFConvert %half %float_0_100000001 -%13 = OpFMul %half %53 %54 -%47 = OpAccessChain %_ptr_Uniform_float %_ %int_0 -%10 = OpLoad %float %47 -%55 = OpFConvert %half %10 -%56 = OpFConvert %half %float_0_100000001 -%14 = OpFAdd %half %55 %56 -%16 = OpCompositeConstruct %v2half %13 %14 -%58 = OpFConvert %float %14 -%18 = OpImageSampleDrefImplicitLod %float %46 %16 %58 -%48 = OpLoad %27 %g_tTex1df4 -%49 = OpLoad %29 %g_sSamp -%50 = OpSampledImage %31 %48 %49 -%59 = OpFConvert %half %12 -%60 = OpFConvert %half %float_0_200000003 -%15 = OpFMul %half %59 %60 -%51 = OpAccessChain %_ptr_Uniform_float %_ %int_1 -%17 = OpLoad %float %51 -%61 = OpFConvert %half %17 -%62 = OpFConvert %half %float_0_200000003 -%19 = OpFAdd %half %61 %62 -%20 = OpCompositeConstruct %v2half %15 %19 -%63 = OpFConvert %float %19 -%21 = OpImageSampleDrefImplicitLod %float %50 %20 %63 -%64 = OpFConvert %half %18 -%65 = OpFConvert %half %21 -%22 = OpFAdd %half %64 %65 -%66 = OpFConvert %half %float_0_5 -%23 = OpFMul %half %22 %66 -%67 = OpFConvert %float %23 -OpStore %_entryPointOutput_Color %67 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(ConvertToHalfTest, ConvertToHalfWithVectorMatrixMult) { - // The resulting SPIR-V was processed with --relax-float-ops. - // - // clang-format off - // - // SamplerState g_sSamp : register(s0); - // uniform Texture1D g_tTex1df4 : register(t0); - // - // struct PS_OUTPUT - // { - // float4 Color : SV_Target0; - // }; - // - // cbuffer cbuff{ - // float4x4 M; - // } - // - // PS_OUTPUT main() - // { - // PS_OUTPUT psout; - // float4 txval10 = g_tTex1df4.Sample(g_sSamp, 0.1); - // float4 t = mul(txval10, M); - // psout.Color = t; - // return psout; - //} - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "M" -OpName %_ "" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 RowMajor -OpMemberDecorate %cbuff 0 Offset 0 -OpMemberDecorate %cbuff 0 MatrixStride 16 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %_entryPointOutput_Color Location 0 -OpDecorate %56 RelaxedPrecision -OpDecorate %58 RelaxedPrecision -OpDecorate %60 RelaxedPrecision -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%14 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant -%18 = OpTypeSampler -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant -%22 = OpTypeSampledImage %14 -%float_0_100000001 = OpConstant %float 0.100000001 -%mat4v4float = OpTypeMatrix %v4float 4 -%cbuff = OpTypeStruct %mat4v4float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpCapability Float16 -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "M" -OpName %_ "" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 RowMajor -OpMemberDecorate %cbuff 0 Offset 0 -OpMemberDecorate %cbuff 0 MatrixStride 16 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %_entryPointOutput_Color Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%14 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant -%18 = OpTypeSampler -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant -%22 = OpTypeSampledImage %14 -%float_0_100000001 = OpConstant %float 0.100000001 -%mat4v4float = OpTypeMatrix %v4float 4 -%cbuff = OpTypeStruct %mat4v4float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%half = OpTypeFloat 16 -%v4half = OpTypeVector %half 4 -%mat4v4half = OpTypeMatrix %v4half 4 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %14 %g_tTex1df4 -%54 = OpLoad %18 %g_sSamp -%55 = OpSampledImage %22 %53 %54 -%56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001 -%57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0 -%58 = OpLoad %mat4v4float %57 -%60 = OpMatrixTimesVector %v4float %58 %56 -OpStore %_entryPointOutput_Color %60 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %14 %g_tTex1df4 -%54 = OpLoad %18 %g_sSamp -%55 = OpSampledImage %22 %53 %54 -%56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001 -%57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0 -%58 = OpLoad %mat4v4float %57 -%67 = OpCompositeExtract %v4float %58 0 -%68 = OpFConvert %v4half %67 -%69 = OpCompositeExtract %v4float %58 1 -%70 = OpFConvert %v4half %69 -%71 = OpCompositeExtract %v4float %58 2 -%72 = OpFConvert %v4half %71 -%73 = OpCompositeExtract %v4float %58 3 -%74 = OpFConvert %v4half %73 -%75 = OpCompositeConstruct %mat4v4half %68 %70 %72 %74 -%64 = OpCopyObject %mat4v4float %58 -%65 = OpFConvert %v4half %56 -%60 = OpMatrixTimesVector %v4half %75 %65 -%66 = OpFConvert %v4float %60 -OpStore %_entryPointOutput_Color %66 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(ConvertToHalfTest, ConvertToHalfWithPhi) { - // The resulting SPIR-V was processed with --relax-float-ops. - // - // clang-format off - // - // SamplerState g_sSamp : register(s0); - // uniform Texture1D g_tTex1df4 : register(t0); - // - // struct PS_OUTPUT - // { - // float4 Color : SV_Target0; - // }; - // - // cbuffer cbuff{ - // bool b; - // float4x4 M; - // } - // - // PS_OUTPUT main() - // { - // PS_OUTPUT psout; - // float4 t; - // - // if (b) - // t = g_tTex1df4.Sample(g_sSamp, 0.1); - // else - // t = float4(0.0, 0.0, 0.0, 0.0); - // - // float4 t2 = t * 2.0; - // psout.Color = t2; - // return psout; - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "b" -OpMemberName %cbuff 1 "M" -OpName %_ "" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpMemberDecorate %cbuff 0 Offset 0 -OpMemberDecorate %cbuff 1 RowMajor -OpMemberDecorate %cbuff 1 Offset 16 -OpMemberDecorate %cbuff 1 MatrixStride 16 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpDecorate %_entryPointOutput_Color Location 0 -OpDecorate %72 RelaxedPrecision -OpDecorate %85 RelaxedPrecision -OpDecorate %74 RelaxedPrecision -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%mat4v4float = OpTypeMatrix %v4float 4 -%cbuff = OpTypeStruct %uint %mat4v4float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%29 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant -%33 = OpTypeSampler -%_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33 -%g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant -%37 = OpTypeSampledImage %29 -%float_0_100000001 = OpConstant %float 0.100000001 -%float_0 = OpConstant %float 0 -%43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_2 = OpConstant %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpCapability Float16 -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "b" -OpMemberName %cbuff 1 "M" -OpName %_ "" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpMemberDecorate %cbuff 0 Offset 0 -OpMemberDecorate %cbuff 1 RowMajor -OpMemberDecorate %cbuff 1 Offset 16 -OpMemberDecorate %cbuff 1 MatrixStride 16 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpDecorate %_entryPointOutput_Color Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%mat4v4float = OpTypeMatrix %v4float 4 -%cbuff = OpTypeStruct %uint %mat4v4float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%29 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant -%33 = OpTypeSampler -%_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33 -%g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant -%37 = OpTypeSampledImage %29 -%float_0_100000001 = OpConstant %float 0.100000001 -%float_0 = OpConstant %float 0 -%43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_2 = OpConstant %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%half = OpTypeFloat 16 -%v4half = OpTypeVector %half 4 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpINotEqual %bool %64 %uint_0 -OpSelectionMerge %66 None -OpBranchConditional %65 %67 %68 -%67 = OpLabel -%69 = OpLoad %29 %g_tTex1df4 -%70 = OpLoad %33 %g_sSamp -%71 = OpSampledImage %37 %69 %70 -%72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001 -OpBranch %66 -%68 = OpLabel -OpBranch %66 -%66 = OpLabel -%85 = OpPhi %v4float %72 %67 %43 %68 -%74 = OpVectorTimesScalar %v4float %85 %float_2 -OpStore %_entryPointOutput_Color %74 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpINotEqual %bool %64 %uint_0 -OpSelectionMerge %66 None -OpBranchConditional %65 %67 %68 -%67 = OpLabel -%69 = OpLoad %29 %g_tTex1df4 -%70 = OpLoad %33 %g_sSamp -%71 = OpSampledImage %37 %69 %70 -%72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001 -%88 = OpFConvert %v4half %72 -OpBranch %66 -%68 = OpLabel -%89 = OpFConvert %v4half %43 -OpBranch %66 -%66 = OpLabel -%85 = OpPhi %v4half %88 %67 %89 %68 -%90 = OpFConvert %half %float_2 -%74 = OpVectorTimesScalar %v4half %85 %90 -%91 = OpFConvert %v4float %74 -OpStore %_entryPointOutput_Color %91 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(ConvertToHalfTest, ConvertToHalfWithLoopAndFConvert) { - // The resulting SPIR-V was processed with --relax-float-ops. - // - // The loop causes an FConvert to be generated at the bottom of the loop - // for the Phi. The FConvert is later processed and turned into a (dead) - // copy. - // - // clang-format off - // - // struct PS_OUTPUT - // { - // float4 Color : SV_Target0; - // }; - // - // cbuffer cbuff{ - // float4 a[10]; - // } - // - // PS_OUTPUT main() - // { - // PS_OUTPUT psout; - // float4 t = 0.0;; - // - // for (int i = 0; i<10; ++i) - // t = t + a[i]; - // - // float4 t2 = t / 10.0; - // psout.Color = t2; - // return psout; - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "a" -OpName %_ "" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %_arr_v4float_uint_10 ArrayStride 16 -OpMemberDecorate %cbuff 0 Offset 0 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %_entryPointOutput_Color Location 0 -OpDecorate %96 RelaxedPrecision -OpDecorate %81 RelaxedPrecision -OpDecorate %75 RelaxedPrecision -OpDecorate %76 RelaxedPrecision -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%float_0 = OpConstant %float 0 -%15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10 -%cbuff = OpTypeStruct %_arr_v4float_uint_10 -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%int_1 = OpConstant %int 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%float_0_100000001 = OpConstant %float 0.100000001 -%94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001 -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Float16 -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "a" -OpName %_ "" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %_arr_v4float_uint_10 ArrayStride 16 -OpMemberDecorate %cbuff 0 Offset 0 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %_entryPointOutput_Color Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%float_0 = OpConstant %float 0 -%15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_10 = OpConstant %uint 10 -%_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10 -%cbuff = OpTypeStruct %_arr_v4float_uint_10 -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%int_1 = OpConstant %int 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%float_0_100000001 = OpConstant %float 0.100000001 -%94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001 -%half = OpTypeFloat 16 -%v4half = OpTypeVector %half 4 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -OpBranch %65 -%65 = OpLabel -%96 = OpPhi %v4float %15 %5 %76 %71 -%95 = OpPhi %int %int_0 %5 %78 %71 -%70 = OpSLessThan %bool %95 %int_10 -OpLoopMerge %66 %71 None -OpBranchConditional %70 %71 %66 -%71 = OpLabel -%74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95 -%75 = OpLoad %v4float %74 -%76 = OpFAdd %v4float %96 %75 -%78 = OpIAdd %int %95 %int_1 -OpBranch %65 -%66 = OpLabel -%81 = OpFMul %v4float %96 %94 -OpStore %_entryPointOutput_Color %81 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%99 = OpFConvert %v4half %15 -OpBranch %65 -%65 = OpLabel -%96 = OpPhi %v4half %99 %5 %76 %71 -%95 = OpPhi %int %int_0 %5 %78 %71 -%70 = OpSLessThan %bool %95 %int_10 -OpLoopMerge %66 %71 None -OpBranchConditional %70 %71 %66 -%71 = OpLabel -%74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95 -%75 = OpLoad %v4float %74 -%103 = OpFConvert %v4half %75 -%76 = OpFAdd %v4half %96 %103 -%78 = OpIAdd %int %95 %int_1 -%100 = OpCopyObject %v4half %76 -OpBranch %65 -%66 = OpLabel -%101 = OpFConvert %v4half %94 -%81 = OpFMul %v4half %96 %101 -%102 = OpFConvert %v4float %81 -OpStore %_entryPointOutput_Color %102 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -TEST_F(ConvertToHalfTest, ConvertToHalfWithExtracts) { - // The resulting SPIR-V was processed with --relax-float-ops. - // - // The extra converts in the func_after can be DCE'd. - // - // clang-format off - // - // SamplerState g_sSamp : register(s0); - // uniform Texture1D g_tTex1df4 : register(t0); - // - // struct PS_INPUT - // { - // float Tex0 : TEXCOORD0; - // }; - // - // struct PS_OUTPUT - // { - // float4 Color : SV_Target0; - // }; - // - // cbuffer cbuff{ - // float c; - // } - // - // PS_OUTPUT main(PS_INPUT i) - // { - // PS_OUTPUT psout; - // float4 tx = g_tTex1df4.Sample(g_sSamp, i.Tex0); - // float4 t = float4(tx.y, tx.z, tx.x, tx.w) * c; - // psout.Color = t; - // return psout; - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "c" -OpName %_ "" -OpName %i_Tex0 "i.Tex0" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 Offset 0 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %i_Tex0 Location 0 -OpDecorate %_entryPointOutput_Color Location 0 -OpDecorate %65 RelaxedPrecision -OpDecorate %82 RelaxedPrecision -OpDecorate %84 RelaxedPrecision -OpDecorate %86 RelaxedPrecision -OpDecorate %88 RelaxedPrecision -OpDecorate %90 RelaxedPrecision -OpDecorate %91 RelaxedPrecision -OpDecorate %93 RelaxedPrecision -OpDecorate %94 RelaxedPrecision -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%17 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant -%21 = OpTypeSampler -%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 -%g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant -%25 = OpTypeSampledImage %17 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%cbuff = OpTypeStruct %float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpCapability Float16 -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %cbuff "cbuff" -OpMemberName %cbuff 0 "c" -OpName %_ "" -OpName %i_Tex0 "i.Tex0" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpMemberDecorate %cbuff 0 Offset 0 -OpDecorate %cbuff Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 1 -OpDecorate %i_Tex0 Location 0 -OpDecorate %_entryPointOutput_Color Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%17 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant -%21 = OpTypeSampler -%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 -%g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant -%25 = OpTypeSampledImage %17 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%cbuff = OpTypeStruct %float -%_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff -%_ = OpVariable %_ptr_Uniform_cbuff Uniform -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%half = OpTypeFloat 16 -%v4half = OpTypeVector %half 4 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%65 = OpLoad %float %i_Tex0 -%77 = OpLoad %17 %g_tTex1df4 -%78 = OpLoad %21 %g_sSamp -%79 = OpSampledImage %25 %77 %78 -%82 = OpImageSampleImplicitLod %v4float %79 %65 -%84 = OpCompositeExtract %float %82 1 -%86 = OpCompositeExtract %float %82 2 -%88 = OpCompositeExtract %float %82 0 -%90 = OpCompositeExtract %float %82 3 -%91 = OpCompositeConstruct %v4float %84 %86 %88 %90 -%92 = OpAccessChain %_ptr_Uniform_float %_ %int_0 -%93 = OpLoad %float %92 -%94 = OpVectorTimesScalar %v4float %91 %93 -OpStore %_entryPointOutput_Color %94 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%65 = OpLoad %float %i_Tex0 -%77 = OpLoad %17 %g_tTex1df4 -%78 = OpLoad %21 %g_sSamp -%79 = OpSampledImage %25 %77 %78 -%82 = OpImageSampleImplicitLod %v4float %79 %65 -%97 = OpFConvert %v4half %82 -%84 = OpCompositeExtract %half %97 1 -%98 = OpFConvert %v4half %82 -%86 = OpCompositeExtract %half %98 2 -%99 = OpFConvert %v4half %82 -%88 = OpCompositeExtract %half %99 0 -%100 = OpFConvert %v4half %82 -%90 = OpCompositeExtract %half %100 3 -%91 = OpCompositeConstruct %v4half %84 %86 %88 %90 -%92 = OpAccessChain %_ptr_Uniform_float %_ %int_0 -%93 = OpLoad %float %92 -%101 = OpFConvert %half %93 -%94 = OpVectorTimesScalar %v4half %91 %101 -%102 = OpFConvert %v4float %94 -OpStore %_entryPointOutput_Color %102 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(defs_before + func_before, - defs_after + func_after, true, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/copy_prop_array_test.cpp b/3rdparty/spirv-tools/test/opt/copy_prop_array_test.cpp deleted file mode 100644 index 1afee9cf9..000000000 --- a/3rdparty/spirv-tools/test/opt/copy_prop_array_test.cpp +++ /dev/null @@ -1,1627 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using CopyPropArrayPassTest = PassTest<::testing::Test>; - -TEST_F(CopyPropArrayPassTest, BasicPropagateArray) { - const std::string before = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK: OpVariable -; CHECK: OpAccessChain -; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[new_address]] %24 -; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]] -; CHECK: OpStore %out_var_SV_Target [[load]] -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%28 = OpCompositeExtract %v4float %26 1 -%29 = OpCompositeExtract %v4float %26 2 -%30 = OpCompositeExtract %v4float %26 3 -%31 = OpCompositeExtract %v4float %26 4 -%32 = OpCompositeExtract %v4float %26 5 -%33 = OpCompositeExtract %v4float %26 6 -%34 = OpCompositeExtract %v4float %26 7 -%35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34 -OpStore %23 %35 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(before, false); -} - -TEST_F(CopyPropArrayPassTest, BasicPropagateArrayWithName) { - const std::string before = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %local "local" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK: OpVariable -; CHECK: OpAccessChain -; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[new_address]] %24 -; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]] -; CHECK: OpStore %out_var_SV_Target [[load]] -%main = OpFunction %void None %13 -%22 = OpLabel -%local = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%28 = OpCompositeExtract %v4float %26 1 -%29 = OpCompositeExtract %v4float %26 2 -%30 = OpCompositeExtract %v4float %26 3 -%31 = OpCompositeExtract %v4float %26 4 -%32 = OpCompositeExtract %v4float %26 5 -%33 = OpCompositeExtract %v4float %26 6 -%34 = OpCompositeExtract %v4float %26 7 -%35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34 -OpStore %local %35 -%36 = OpAccessChain %_ptr_Function_v4float %local %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(before, false); -} - -// Propagate 2d array. This test identifying a copy through multiple levels. -// Also has to traverse multiple OpAccessChains. -TEST_F(CopyPropArrayPassTest, Propagate2DArray) { - const std::string text = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_2 ArrayStride 16 -OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_2 = OpConstant %uint 2 -%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 -%_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2 -%type_MyCBuffer = OpTypeStruct %_arr__arr_v4float_uint_2_uint_2 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%14 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_2_0 = OpTypeArray %v4float %uint_2 -%_arr__arr_v4float_uint_2_0_uint_2 = OpTypeArray %_arr_v4float_uint_2_0 %uint_2 -%_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 = OpTypePointer Function %_arr__arr_v4float_uint_2_0_uint_2 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_v4float_uint_2_uint_2 -%_ptr_Function__arr_v4float_uint_2_0 = OpTypePointer Function %_arr_v4float_uint_2_0 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK: OpVariable -; CHECK: OpVariable -; CHECK: OpAccessChain -; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0 -%main = OpFunction %void None %14 -%25 = OpLabel -%26 = OpVariable %_ptr_Function__arr_v4float_uint_2_0 Function -%27 = OpVariable %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 Function -%28 = OpLoad %int %in_var_INDEX -%29 = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0 -%30 = OpLoad %_arr__arr_v4float_uint_2_uint_2 %29 -%31 = OpCompositeExtract %_arr_v4float_uint_2 %30 0 -%32 = OpCompositeExtract %v4float %31 0 -%33 = OpCompositeExtract %v4float %31 1 -%34 = OpCompositeConstruct %_arr_v4float_uint_2_0 %32 %33 -%35 = OpCompositeExtract %_arr_v4float_uint_2 %30 1 -%36 = OpCompositeExtract %v4float %35 0 -%37 = OpCompositeExtract %v4float %35 1 -%38 = OpCompositeConstruct %_arr_v4float_uint_2_0 %36 %37 -%39 = OpCompositeConstruct %_arr__arr_v4float_uint_2_0_uint_2 %34 %38 -; CHECK: OpStore -OpStore %27 %39 -%40 = OpAccessChain %_ptr_Function__arr_v4float_uint_2_0 %27 %28 -%42 = OpAccessChain %_ptr_Function_v4float %40 %28 -%43 = OpLoad %v4float %42 -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_2 [[new_address]] %28 -; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[ac1]] %28 -; CHECK: [[load:%\w+]] = OpLoad %v4float [[ac2]] -; CHECK: OpStore %out_var_SV_Target [[load]] -OpStore %out_var_SV_Target %43 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(text, false); -} - -// Propagate 2d array. This test identifying a copy through multiple levels. -// Also has to traverse multiple OpAccessChains. -TEST_F(CopyPropArrayPassTest, Propagate2DArrayWithMultiLevelExtract) { - const std::string text = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_2 ArrayStride 16 -OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_2 = OpConstant %uint 2 -%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 -%_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2 -%type_MyCBuffer = OpTypeStruct %_arr__arr_v4float_uint_2_uint_2 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%14 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_2_0 = OpTypeArray %v4float %uint_2 -%_arr__arr_v4float_uint_2_0_uint_2 = OpTypeArray %_arr_v4float_uint_2_0 %uint_2 -%_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 = OpTypePointer Function %_arr__arr_v4float_uint_2_0_uint_2 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_v4float_uint_2_uint_2 -%_ptr_Function__arr_v4float_uint_2_0 = OpTypePointer Function %_arr_v4float_uint_2_0 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK: OpVariable -; CHECK: OpVariable -; CHECK: OpAccessChain -; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0 -%main = OpFunction %void None %14 -%25 = OpLabel -%26 = OpVariable %_ptr_Function__arr_v4float_uint_2_0 Function -%27 = OpVariable %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 Function -%28 = OpLoad %int %in_var_INDEX -%29 = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0 -%30 = OpLoad %_arr__arr_v4float_uint_2_uint_2 %29 -%32 = OpCompositeExtract %v4float %30 0 0 -%33 = OpCompositeExtract %v4float %30 0 1 -%34 = OpCompositeConstruct %_arr_v4float_uint_2_0 %32 %33 -%36 = OpCompositeExtract %v4float %30 1 0 -%37 = OpCompositeExtract %v4float %30 1 1 -%38 = OpCompositeConstruct %_arr_v4float_uint_2_0 %36 %37 -%39 = OpCompositeConstruct %_arr__arr_v4float_uint_2_0_uint_2 %34 %38 -; CHECK: OpStore -OpStore %27 %39 -%40 = OpAccessChain %_ptr_Function__arr_v4float_uint_2_0 %27 %28 -%42 = OpAccessChain %_ptr_Function_v4float %40 %28 -%43 = OpLoad %v4float %42 -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_2 [[new_address]] %28 -; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[ac1]] %28 -; CHECK: [[load:%\w+]] = OpLoad %v4float [[ac2]] -; CHECK: OpStore %out_var_SV_Target [[load]] -OpStore %out_var_SV_Target %43 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(text, false); -} - -// Test decomposing an object when we need to "rewrite" a store. -TEST_F(CopyPropArrayPassTest, DecomposeObjectForArrayStore) { - const std::string text = - R"( OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpName %type_MyCBuffer "type.MyCBuffer" - OpMemberName %type_MyCBuffer 0 "Data" - OpName %MyCBuffer "MyCBuffer" - OpName %main "main" - OpName %in_var_INDEX "in.var.INDEX" - OpName %out_var_SV_Target "out.var.SV_Target" - OpDecorate %_arr_v4float_uint_2 ArrayStride 16 - OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32 - OpMemberDecorate %type_MyCBuffer 0 Offset 0 - OpDecorate %type_MyCBuffer Block - OpDecorate %in_var_INDEX Flat - OpDecorate %in_var_INDEX Location 0 - OpDecorate %out_var_SV_Target Location 0 - OpDecorate %MyCBuffer DescriptorSet 0 - OpDecorate %MyCBuffer Binding 0 - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 -%_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2 -%type_MyCBuffer = OpTypeStruct %_arr__arr_v4float_uint_2_uint_2 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer - %void = OpTypeVoid - %14 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_2_0 = OpTypeArray %v4float %uint_2 -%_arr__arr_v4float_uint_2_0_uint_2 = OpTypeArray %_arr_v4float_uint_2_0 %uint_2 -%_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 = OpTypePointer Function %_arr__arr_v4float_uint_2_0_uint_2 - %int_0 = OpConstant %int 0 -%_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_v4float_uint_2_uint_2 -%_ptr_Function__arr_v4float_uint_2_0 = OpTypePointer Function %_arr_v4float_uint_2_0 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %14 - %25 = OpLabel - %26 = OpVariable %_ptr_Function__arr_v4float_uint_2_0 Function - %27 = OpVariable %_ptr_Function__arr__arr_v4float_uint_2_0_uint_2 Function - %28 = OpLoad %int %in_var_INDEX - %29 = OpAccessChain %_ptr_Uniform__arr__arr_v4float_uint_2_uint_2 %MyCBuffer %int_0 - %30 = OpLoad %_arr__arr_v4float_uint_2_uint_2 %29 - %31 = OpCompositeExtract %_arr_v4float_uint_2 %30 0 - %32 = OpCompositeExtract %v4float %31 0 - %33 = OpCompositeExtract %v4float %31 1 - %34 = OpCompositeConstruct %_arr_v4float_uint_2_0 %32 %33 - %35 = OpCompositeExtract %_arr_v4float_uint_2 %30 1 - %36 = OpCompositeExtract %v4float %35 0 - %37 = OpCompositeExtract %v4float %35 1 - %38 = OpCompositeConstruct %_arr_v4float_uint_2_0 %36 %37 - %39 = OpCompositeConstruct %_arr__arr_v4float_uint_2_0_uint_2 %34 %38 - OpStore %27 %39 -; CHECK: [[access_chain:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_2 - %40 = OpAccessChain %_ptr_Function__arr_v4float_uint_2_0 %27 %28 -; CHECK: [[load:%\w+]] = OpLoad %_arr_v4float_uint_2 [[access_chain]] - %41 = OpLoad %_arr_v4float_uint_2_0 %40 -; CHECK: [[extract1:%\w+]] = OpCompositeExtract %v4float [[load]] 0 -; CHECK: [[extract2:%\w+]] = OpCompositeExtract %v4float [[load]] 1 -; CHECK: [[construct:%\w+]] = OpCompositeConstruct %_arr_v4float_uint_2_0 [[extract1]] [[extract2]] -; CHECK: OpStore %26 [[construct]] - OpStore %26 %41 - %42 = OpAccessChain %_ptr_Function_v4float %26 %28 - %43 = OpLoad %v4float %42 - OpStore %out_var_SV_Target %43 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(text, false); -} - -// Test decomposing an object when we need to "rewrite" a store. -TEST_F(CopyPropArrayPassTest, DecomposeObjectForStructStore) { - const std::string text = - R"( OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpName %type_MyCBuffer "type.MyCBuffer" - OpMemberName %type_MyCBuffer 0 "Data" - OpName %MyCBuffer "MyCBuffer" - OpName %main "main" - OpName %in_var_INDEX "in.var.INDEX" - OpName %out_var_SV_Target "out.var.SV_Target" - OpMemberDecorate %type_MyCBuffer 0 Offset 0 - OpDecorate %type_MyCBuffer Block - OpDecorate %in_var_INDEX Flat - OpDecorate %in_var_INDEX Location 0 - OpDecorate %out_var_SV_Target Location 0 - OpDecorate %MyCBuffer DescriptorSet 0 - OpDecorate %MyCBuffer Binding 0 -; CHECK: OpDecorate [[decorated_type:%\w+]] GLSLPacked - OpDecorate %struct GLSLPacked - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -; CHECK: [[decorated_type]] = OpTypeStruct -%struct = OpTypeStruct %float %uint -%_arr_struct_uint_2 = OpTypeArray %struct %uint_2 -%type_MyCBuffer = OpTypeStruct %_arr_struct_uint_2 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer - %void = OpTypeVoid - %14 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -; CHECK: [[struct:%\w+]] = OpTypeStruct %float %uint -%struct_0 = OpTypeStruct %float %uint -%_arr_struct_0_uint_2 = OpTypeArray %struct_0 %uint_2 -%_ptr_Function__arr_struct_0_uint_2 = OpTypePointer Function %_arr_struct_0_uint_2 - %int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_struct_uint_2 = OpTypePointer Uniform %_arr_struct_uint_2 -; CHECK: [[decorated_ptr:%\w+]] = OpTypePointer Uniform [[decorated_type]] -%_ptr_Function_struct_0 = OpTypePointer Function %struct_0 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %14 - %25 = OpLabel - %26 = OpVariable %_ptr_Function_struct_0 Function - %27 = OpVariable %_ptr_Function__arr_struct_0_uint_2 Function - %28 = OpLoad %int %in_var_INDEX - %29 = OpAccessChain %_ptr_Uniform__arr_struct_uint_2 %MyCBuffer %int_0 - %30 = OpLoad %_arr_struct_uint_2 %29 - %31 = OpCompositeExtract %struct %30 0 - %32 = OpCompositeExtract %v4float %31 0 - %33 = OpCompositeExtract %v4float %31 1 - %34 = OpCompositeConstruct %struct_0 %32 %33 - %35 = OpCompositeExtract %struct %30 1 - %36 = OpCompositeExtract %float %35 0 - %37 = OpCompositeExtract %uint %35 1 - %38 = OpCompositeConstruct %struct_0 %36 %37 - %39 = OpCompositeConstruct %_arr_struct_0_uint_2 %34 %38 - OpStore %27 %39 -; CHECK: [[access_chain:%\w+]] = OpAccessChain [[decorated_ptr]] - %40 = OpAccessChain %_ptr_Function_struct_0 %27 %28 -; CHECK: [[load:%\w+]] = OpLoad [[decorated_type]] [[access_chain]] - %41 = OpLoad %struct_0 %40 -; CHECK: [[extract1:%\w+]] = OpCompositeExtract %float [[load]] 0 -; CHECK: [[extract2:%\w+]] = OpCompositeExtract %uint [[load]] 1 -; CHECK: [[construct:%\w+]] = OpCompositeConstruct [[struct]] [[extract1]] [[extract2]] -; CHECK: OpStore %26 [[construct]] - OpStore %26 %41 - %42 = OpAccessChain %_ptr_Function_v4float %26 %28 - %43 = OpLoad %v4float %42 - OpStore %out_var_SV_Target %43 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(text, false); -} - -TEST_F(CopyPropArrayPassTest, CopyViaInserts) { - const std::string before = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK: OpVariable -; CHECK: OpAccessChain -; CHECK: [[new_address:%\w+]] = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -; CHECK: [[element_ptr:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[new_address]] %24 -; CHECK: [[load:%\w+]] = OpLoad %v4float [[element_ptr]] -; CHECK: OpStore %out_var_SV_Target [[load]] -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%undef = OpUndef %_arr_v4float_uint_8_0 -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%i0 = OpCompositeInsert %_arr_v4float_uint_8_0 %27 %undef 0 -%28 = OpCompositeExtract %v4float %26 1 -%i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %i0 1 -%29 = OpCompositeExtract %v4float %26 2 -%i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 2 -%30 = OpCompositeExtract %v4float %26 3 -%i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3 -%31 = OpCompositeExtract %v4float %26 4 -%i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4 -%32 = OpCompositeExtract %v4float %26 5 -%i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5 -%33 = OpCompositeExtract %v4float %26 6 -%i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6 -%34 = OpCompositeExtract %v4float %26 7 -%i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7 -OpStore %23 %i7 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(before, false); -} - -TEST_F(CopyPropArrayPassTest, IsomorphicTypes1) { - const std::string before = - R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[s1:%\w+]] = OpTypeStruct [[int]] -; CHECK: [[s2:%\w+]] = OpTypeStruct [[s1]] -; CHECK: [[a1:%\w+]] = OpTypeArray [[s2]] -; CHECK: [[s3:%\w+]] = OpTypeStruct [[a1]] -; CHECK: [[p_s3:%\w+]] = OpTypePointer Uniform [[s3]] -; CHECK: [[global_var:%\w+]] = OpVariable [[p_s3]] Uniform -; CHECK: [[p_a1:%\w+]] = OpTypePointer Uniform [[a1]] -; CHECK: [[p_s2:%\w+]] = OpTypePointer Uniform [[s2]] -; CHECK: [[ac1:%\w+]] = OpAccessChain [[p_a1]] [[global_var]] %uint_0 -; CHECK: [[ac2:%\w+]] = OpAccessChain [[p_s2]] [[ac1]] %uint_0 -; CHECK: [[ld:%\w+]] = OpLoad [[s2]] [[ac2]] -; CHECK: [[ex:%\w+]] = OpCompositeExtract [[s1]] [[ld]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "PS_main" - OpExecutionMode %2 OriginUpperLeft - OpSource HLSL 600 - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 101 - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 - %s1 = OpTypeStruct %uint - %s2 = OpTypeStruct %s1 -%a1 = OpTypeArray %s2 %uint_1 - %s3 = OpTypeStruct %a1 - %s1_1 = OpTypeStruct %uint -%_ptr_Uniform_uint = OpTypePointer Uniform %uint - %void = OpTypeVoid - %13 = OpTypeFunction %void - %uint_0 = OpConstant %uint 0 - %s1_0 = OpTypeStruct %uint - %s2_0 = OpTypeStruct %s1_0 -%a1_0 = OpTypeArray %s2_0 %uint_1 - %s3_0 = OpTypeStruct %a1_0 -%p_s3 = OpTypePointer Uniform %s3 -%p_s3_0 = OpTypePointer Function %s3_0 - %3 = OpVariable %p_s3 Uniform -%p_a1_0 = OpTypePointer Function %a1_0 -%p_s2_0 = OpTypePointer Function %s2_0 - %2 = OpFunction %void None %13 - %20 = OpLabel - %21 = OpVariable %p_a1_0 Function - %22 = OpLoad %s3 %3 - %23 = OpCompositeExtract %a1 %22 0 - %24 = OpCompositeExtract %s2 %23 0 - %25 = OpCompositeExtract %s1 %24 0 - %26 = OpCompositeExtract %uint %25 0 - %27 = OpCompositeConstruct %s1_0 %26 - %32 = OpCompositeConstruct %s2_0 %27 - %28 = OpCompositeConstruct %a1_0 %32 - OpStore %21 %28 - %29 = OpAccessChain %p_s2_0 %21 %uint_0 - %30 = OpLoad %s2 %29 - %31 = OpCompositeExtract %s1 %30 0 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(before, false); -} - -TEST_F(CopyPropArrayPassTest, IsomorphicTypes2) { - const std::string before = - R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[s1:%\w+]] = OpTypeStruct [[int]] -; CHECK: [[s2:%\w+]] = OpTypeStruct [[s1]] -; CHECK: [[a1:%\w+]] = OpTypeArray [[s2]] -; CHECK: [[s3:%\w+]] = OpTypeStruct [[a1]] -; CHECK: [[p_s3:%\w+]] = OpTypePointer Uniform [[s3]] -; CHECK: [[global_var:%\w+]] = OpVariable [[p_s3]] Uniform -; CHECK: [[p_s2:%\w+]] = OpTypePointer Uniform [[s2]] -; CHECK: [[p_s1:%\w+]] = OpTypePointer Uniform [[s1]] -; CHECK: [[ac1:%\w+]] = OpAccessChain [[p_s2]] [[global_var]] %uint_0 %uint_0 -; CHECK: [[ac2:%\w+]] = OpAccessChain [[p_s1]] [[ac1]] %uint_0 -; CHECK: [[ld:%\w+]] = OpLoad [[s1]] [[ac2]] -; CHECK: [[ex:%\w+]] = OpCompositeExtract [[int]] [[ld]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "PS_main" - OpExecutionMode %2 OriginUpperLeft - OpSource HLSL 600 - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 101 - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 - %_struct_6 = OpTypeStruct %uint - %_struct_7 = OpTypeStruct %_struct_6 -%_arr__struct_7_uint_1 = OpTypeArray %_struct_7 %uint_1 - %_struct_9 = OpTypeStruct %_arr__struct_7_uint_1 - %_struct_10 = OpTypeStruct %uint -%_ptr_Uniform_uint = OpTypePointer Uniform %uint - %void = OpTypeVoid - %13 = OpTypeFunction %void - %uint_0 = OpConstant %uint 0 - %_struct_15 = OpTypeStruct %uint -%_arr__struct_15_uint_1 = OpTypeArray %_struct_15 %uint_1 -%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 - %3 = OpVariable %_ptr_Uniform__struct_9 Uniform -%_ptr_Function__arr__struct_15_uint_1 = OpTypePointer Function %_arr__struct_15_uint_1 - %2 = OpFunction %void None %13 - %20 = OpLabel - %21 = OpVariable %_ptr_Function__arr__struct_15_uint_1 Function - %22 = OpLoad %_struct_9 %3 - %23 = OpCompositeExtract %_arr__struct_7_uint_1 %22 0 - %24 = OpCompositeExtract %_struct_7 %23 0 - %25 = OpCompositeExtract %_struct_6 %24 0 - %26 = OpCompositeExtract %uint %25 0 - %27 = OpCompositeConstruct %_struct_15 %26 - %28 = OpCompositeConstruct %_arr__struct_15_uint_1 %27 - OpStore %21 %28 - %29 = OpAccessChain %_ptr_Function__struct_15 %21 %uint_0 - %30 = OpLoad %_struct_15 %29 - %31 = OpCompositeExtract %uint %30 0 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(before, false); -} - -TEST_F(CopyPropArrayPassTest, IsomorphicTypes3) { - const std::string before = - R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[s1:%\w+]] = OpTypeStruct [[int]] -; CHECK: [[s2:%\w+]] = OpTypeStruct [[s1]] -; CHECK: [[a1:%\w+]] = OpTypeArray [[s2]] -; CHECK: [[s3:%\w+]] = OpTypeStruct [[a1]] -; CHECK: [[s1_1:%\w+]] = OpTypeStruct [[int]] -; CHECK: [[p_s3:%\w+]] = OpTypePointer Uniform [[s3]] -; CHECK: [[p_s1_1:%\w+]] = OpTypePointer Function [[s1_1]] -; CHECK: [[global_var:%\w+]] = OpVariable [[p_s3]] Uniform -; CHECK: [[p_s2:%\w+]] = OpTypePointer Uniform [[s2]] -; CHECK: [[p_s1:%\w+]] = OpTypePointer Uniform [[s1]] -; CHECK: [[var:%\w+]] = OpVariable [[p_s1_1]] Function -; CHECK: [[ac1:%\w+]] = OpAccessChain [[p_s2]] [[global_var]] %uint_0 %uint_0 -; CHECK: [[ac2:%\w+]] = OpAccessChain [[p_s1]] [[ac1]] %uint_0 -; CHECK: [[ld:%\w+]] = OpLoad [[s1]] [[ac2]] -; CHECK: [[ex:%\w+]] = OpCompositeExtract [[int]] [[ld]] -; CHECK: [[copy:%\w+]] = OpCompositeConstruct [[s1_1]] [[ex]] -; CHECK: OpStore [[var]] [[copy]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "PS_main" - OpExecutionMode %2 OriginUpperLeft - OpSource HLSL 600 - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 101 - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 - %_struct_6 = OpTypeStruct %uint - %_struct_7 = OpTypeStruct %_struct_6 -%_arr__struct_7_uint_1 = OpTypeArray %_struct_7 %uint_1 - %_struct_9 = OpTypeStruct %_arr__struct_7_uint_1 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint - %void = OpTypeVoid - %13 = OpTypeFunction %void - %uint_0 = OpConstant %uint 0 - %_struct_15 = OpTypeStruct %uint - %_struct_10 = OpTypeStruct %uint -%_arr__struct_15_uint_1 = OpTypeArray %_struct_15 %uint_1 -%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 - %3 = OpVariable %_ptr_Uniform__struct_9 Uniform -%_ptr_Function__arr__struct_15_uint_1 = OpTypePointer Function %_arr__struct_15_uint_1 - %2 = OpFunction %void None %13 - %20 = OpLabel - %21 = OpVariable %_ptr_Function__arr__struct_15_uint_1 Function - %var = OpVariable %_ptr_Function__struct_15 Function - %22 = OpLoad %_struct_9 %3 - %23 = OpCompositeExtract %_arr__struct_7_uint_1 %22 0 - %24 = OpCompositeExtract %_struct_7 %23 0 - %25 = OpCompositeExtract %_struct_6 %24 0 - %26 = OpCompositeExtract %uint %25 0 - %27 = OpCompositeConstruct %_struct_15 %26 - %28 = OpCompositeConstruct %_arr__struct_15_uint_1 %27 - OpStore %21 %28 - %29 = OpAccessChain %_ptr_Function__struct_15 %21 %uint_0 - %30 = OpLoad %_struct_15 %29 - OpStore %var %30 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(before, false); -} - -TEST_F(CopyPropArrayPassTest, BadMergingTwoObjects) { - // The second element in the |OpCompositeConstruct| is from a different - // object. - const std::string text = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpName %type_ConstBuf "type.ConstBuf" -OpMemberName %type_ConstBuf 0 "TexSizeU" -OpMemberName %type_ConstBuf 1 "TexSizeV" -OpName %ConstBuf "ConstBuf" -OpName %main "main" -OpMemberDecorate %type_ConstBuf 0 Offset 0 -OpMemberDecorate %type_ConstBuf 1 Offset 8 -OpDecorate %type_ConstBuf Block -OpDecorate %ConstBuf DescriptorSet 0 -OpDecorate %ConstBuf Binding 2 -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%type_ConstBuf = OpTypeStruct %v2float %v2float -%_ptr_Uniform_type_ConstBuf = OpTypePointer Uniform %type_ConstBuf -%void = OpTypeVoid -%9 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%int_0 = OpConstant %uint 0 -%uint_2 = OpConstant %uint 2 -%_arr_v2float_uint_2 = OpTypeArray %v2float %uint_2 -%_ptr_Function__arr_v2float_uint_2 = OpTypePointer Function %_arr_v2float_uint_2 -%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float -%ConstBuf = OpVariable %_ptr_Uniform_type_ConstBuf Uniform -%main = OpFunction %void None %9 -%24 = OpLabel -%25 = OpVariable %_ptr_Function__arr_v2float_uint_2 Function -%27 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf %int_0 -%28 = OpLoad %v2float %27 -%29 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf %int_0 -%30 = OpLoad %v2float %29 -%31 = OpFNegate %v2float %30 -%37 = OpCompositeConstruct %_arr_v2float_uint_2 %28 %31 -OpStore %25 %37 -OpReturn -OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CopyPropArrayPassTest, SecondElementNotContained) { - // The second element in the |OpCompositeConstruct| is not a memory object. - // Make sure no change happends. - const std::string text = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpName %type_ConstBuf "type.ConstBuf" -OpMemberName %type_ConstBuf 0 "TexSizeU" -OpMemberName %type_ConstBuf 1 "TexSizeV" -OpName %ConstBuf "ConstBuf" -OpName %main "main" -OpMemberDecorate %type_ConstBuf 0 Offset 0 -OpMemberDecorate %type_ConstBuf 1 Offset 8 -OpDecorate %type_ConstBuf Block -OpDecorate %ConstBuf DescriptorSet 0 -OpDecorate %ConstBuf Binding 2 -OpDecorate %ConstBuf2 DescriptorSet 1 -OpDecorate %ConstBuf2 Binding 2 -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%type_ConstBuf = OpTypeStruct %v2float %v2float -%_ptr_Uniform_type_ConstBuf = OpTypePointer Uniform %type_ConstBuf -%void = OpTypeVoid -%9 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%int_0 = OpConstant %uint 0 -%int_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%_arr_v2float_uint_2 = OpTypeArray %v2float %uint_2 -%_ptr_Function__arr_v2float_uint_2 = OpTypePointer Function %_arr_v2float_uint_2 -%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float -%ConstBuf = OpVariable %_ptr_Uniform_type_ConstBuf Uniform -%ConstBuf2 = OpVariable %_ptr_Uniform_type_ConstBuf Uniform -%main = OpFunction %void None %9 -%24 = OpLabel -%25 = OpVariable %_ptr_Function__arr_v2float_uint_2 Function -%27 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf %int_0 -%28 = OpLoad %v2float %27 -%29 = OpAccessChain %_ptr_Uniform_v2float %ConstBuf2 %int_1 -%30 = OpLoad %v2float %29 -%37 = OpCompositeConstruct %_arr_v2float_uint_2 %28 %30 -OpStore %25 %37 -OpReturn -OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} -// This test will place a load before the store. We cannot propagate in this -// case. -TEST_F(CopyPropArrayPassTest, LoadBeforeStore) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%38 = OpAccessChain %_ptr_Function_v4float %23 %24 -%39 = OpLoad %v4float %36 -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%28 = OpCompositeExtract %v4float %26 1 -%29 = OpCompositeExtract %v4float %26 2 -%30 = OpCompositeExtract %v4float %26 3 -%31 = OpCompositeExtract %v4float %26 4 -%32 = OpCompositeExtract %v4float %26 5 -%33 = OpCompositeExtract %v4float %26 6 -%34 = OpCompositeExtract %v4float %26 7 -%35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34 -OpStore %23 %35 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// This test will place a load where it is not dominated by the store. We -// cannot propagate in this case. -TEST_F(CopyPropArrayPassTest, LoadNotDominated) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -OpSelectionMerge %merge None -OpBranchConditional %true %if %else -%if = OpLabel -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%28 = OpCompositeExtract %v4float %26 1 -%29 = OpCompositeExtract %v4float %26 2 -%30 = OpCompositeExtract %v4float %26 3 -%31 = OpCompositeExtract %v4float %26 4 -%32 = OpCompositeExtract %v4float %26 5 -%33 = OpCompositeExtract %v4float %26 6 -%34 = OpCompositeExtract %v4float %26 7 -%35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34 -OpStore %23 %35 -%38 = OpAccessChain %_ptr_Function_v4float %23 %24 -%39 = OpLoad %v4float %36 -OpBranch %merge -%else = OpLabel -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpBranch %merge -%merge = OpLabel -%phi = OpPhi %out_var_SV_Target %39 %if %37 %else -OpStore %out_var_SV_Target %phi -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// This test has a partial store to the variable. We cannot propagate in this -// case. -TEST_F(CopyPropArrayPassTest, PartialStore) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%f0 = OpConstant %float 0 -%v4const = OpConstantComposite %v4float %f0 %f0 %f0 %f0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%28 = OpCompositeExtract %v4float %26 1 -%29 = OpCompositeExtract %v4float %26 2 -%30 = OpCompositeExtract %v4float %26 3 -%31 = OpCompositeExtract %v4float %26 4 -%32 = OpCompositeExtract %v4float %26 5 -%33 = OpCompositeExtract %v4float %26 6 -%34 = OpCompositeExtract %v4float %26 7 -%35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34 -OpStore %23 %35 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 - OpStore %36 %v4const -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// This test does not have a proper copy of an object. We cannot propagate in -// this case. -TEST_F(CopyPropArrayPassTest, NotACopy) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%f0 = OpConstant %float 0 -%v4const = OpConstantComposite %v4float %f0 %f0 %f0 %f0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%28 = OpCompositeExtract %v4float %26 0 -%29 = OpCompositeExtract %v4float %26 2 -%30 = OpCompositeExtract %v4float %26 3 -%31 = OpCompositeExtract %v4float %26 4 -%32 = OpCompositeExtract %v4float %26 5 -%33 = OpCompositeExtract %v4float %26 6 -%34 = OpCompositeExtract %v4float %26 7 -%35 = OpCompositeConstruct %_arr_v4float_uint_8_0 %27 %28 %29 %30 %31 %32 %33 %34 -OpStore %23 %35 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CopyPropArrayPassTest, BadCopyViaInserts1) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%undef = OpUndef %_arr_v4float_uint_8_0 -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%i0 = OpCompositeInsert %_arr_v4float_uint_8_0 %27 %undef 0 -%28 = OpCompositeExtract %v4float %26 1 -%i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %i0 1 -%29 = OpCompositeExtract %v4float %26 2 -%i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 3 -%30 = OpCompositeExtract %v4float %26 3 -%i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3 -%31 = OpCompositeExtract %v4float %26 4 -%i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4 -%32 = OpCompositeExtract %v4float %26 5 -%i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5 -%33 = OpCompositeExtract %v4float %26 6 -%i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6 -%34 = OpCompositeExtract %v4float %26 7 -%i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7 -OpStore %23 %i7 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CopyPropArrayPassTest, BadCopyViaInserts2) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%undef = OpUndef %_arr_v4float_uint_8_0 -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%27 = OpCompositeExtract %v4float %26 0 -%i0 = OpCompositeInsert %_arr_v4float_uint_8_0 %27 %undef 0 -%28 = OpCompositeExtract %v4float %26 1 -%i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %i0 1 -%29 = OpCompositeExtract %v4float %26 3 -%i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 2 -%30 = OpCompositeExtract %v4float %26 3 -%i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3 -%31 = OpCompositeExtract %v4float %26 4 -%i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4 -%32 = OpCompositeExtract %v4float %26 5 -%i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5 -%33 = OpCompositeExtract %v4float %26 6 -%i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6 -%34 = OpCompositeExtract %v4float %26 7 -%i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7 -OpStore %23 %i7 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CopyPropArrayPassTest, BadCopyViaInserts3) { - const std::string text = - R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %in_var_INDEX %out_var_SV_Target -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 600 -OpName %type_MyCBuffer "type.MyCBuffer" -OpMemberName %type_MyCBuffer 0 "Data" -OpName %MyCBuffer "MyCBuffer" -OpName %main "main" -OpName %in_var_INDEX "in.var.INDEX" -OpName %out_var_SV_Target "out.var.SV_Target" -OpDecorate %_arr_v4float_uint_8 ArrayStride 16 -OpMemberDecorate %type_MyCBuffer 0 Offset 0 -OpDecorate %type_MyCBuffer Block -OpDecorate %in_var_INDEX Flat -OpDecorate %in_var_INDEX Location 0 -OpDecorate %out_var_SV_Target Location 0 -OpDecorate %MyCBuffer DescriptorSet 0 -OpDecorate %MyCBuffer Binding 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8 -%type_MyCBuffer = OpTypeStruct %_arr_v4float_uint_8 -%_ptr_Uniform_type_MyCBuffer = OpTypePointer Uniform %type_MyCBuffer -%void = OpTypeVoid -%13 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v4float_uint_8_0 = OpTypeArray %v4float %uint_8 -%_ptr_Function__arr_v4float_uint_8_0 = OpTypePointer Function %_arr_v4float_uint_8_0 -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_v4float_uint_8 = OpTypePointer Uniform %_arr_v4float_uint_8 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%MyCBuffer = OpVariable %_ptr_Uniform_type_MyCBuffer Uniform -%in_var_INDEX = OpVariable %_ptr_Input_int Input -%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %13 -%22 = OpLabel -%23 = OpVariable %_ptr_Function__arr_v4float_uint_8_0 Function -%undef = OpUndef %_arr_v4float_uint_8_0 -%24 = OpLoad %int %in_var_INDEX -%25 = OpAccessChain %_ptr_Uniform__arr_v4float_uint_8 %MyCBuffer %int_0 -%26 = OpLoad %_arr_v4float_uint_8 %25 -%28 = OpCompositeExtract %v4float %26 1 -%i1 = OpCompositeInsert %_arr_v4float_uint_8_0 %28 %undef 1 -%29 = OpCompositeExtract %v4float %26 2 -%i2 = OpCompositeInsert %_arr_v4float_uint_8_0 %29 %i1 2 -%30 = OpCompositeExtract %v4float %26 3 -%i3 = OpCompositeInsert %_arr_v4float_uint_8_0 %30 %i2 3 -%31 = OpCompositeExtract %v4float %26 4 -%i4 = OpCompositeInsert %_arr_v4float_uint_8_0 %31 %i3 4 -%32 = OpCompositeExtract %v4float %26 5 -%i5 = OpCompositeInsert %_arr_v4float_uint_8_0 %32 %i4 5 -%33 = OpCompositeExtract %v4float %26 6 -%i6 = OpCompositeInsert %_arr_v4float_uint_8_0 %33 %i5 6 -%34 = OpCompositeExtract %v4float %26 7 -%i7 = OpCompositeInsert %_arr_v4float_uint_8_0 %34 %i6 7 -OpStore %23 %i7 -%36 = OpAccessChain %_ptr_Function_v4float %23 %24 -%37 = OpLoad %v4float %36 -OpStore %out_var_SV_Target %37 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(CopyPropArrayPassTest, AtomicAdd) { - const std::string before = R"(OpCapability SampledBuffer -OpCapability StorageImageExtendedFormats -OpCapability ImageBuffer -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID -OpExecutionMode %2 LocalSize 64 1 1 -OpSource HLSL 600 -OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId -OpDecorate %4 DescriptorSet 4 -OpDecorate %4 Binding 70 -%uint = OpTypeInt 32 0 -%6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui -%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6 -%_ptr_Function_6 = OpTypePointer Function %6 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%_ptr_Image_uint = OpTypePointer Image %uint -%4 = OpVariable %_ptr_UniformConstant_6 UniformConstant -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%2 = OpFunction %void None %10 -%17 = OpLabel -%16 = OpVariable %_ptr_Function_6 Function -%18 = OpLoad %6 %4 -OpStore %16 %18 -%19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0 -%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1 -OpReturn -OpFunctionEnd -)"; - - const std::string after = R"(OpCapability SampledBuffer -OpCapability StorageImageExtendedFormats -OpCapability ImageBuffer -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID -OpExecutionMode %2 LocalSize 64 1 1 -OpSource HLSL 600 -OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId -OpDecorate %4 DescriptorSet 4 -OpDecorate %4 Binding 70 -%uint = OpTypeInt 32 0 -%6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui -%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6 -%_ptr_Function_6 = OpTypePointer Function %6 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%_ptr_Image_uint = OpTypePointer Image %uint -%4 = OpVariable %_ptr_UniformConstant_6 UniformConstant -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%2 = OpFunction %void None %10 -%17 = OpLabel -%16 = OpVariable %_ptr_Function_6 Function -%18 = OpLoad %6 %4 -OpStore %16 %18 -%19 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0 -%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(CopyPropArrayPassTest, IndexIsNullConstnat) { - const std::string text = R"( -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform -; CHECK: [[null:%\w+]] = OpConstantNull %uint -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_uint_uint_1 [[var]] %uint_0 %uint_0 -; CHECK: OpAccessChain %_ptr_Uniform_uint [[ac1]] [[null]] -; CHECK-NEXT: OpReturn - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpDecorate %myCBuffer DescriptorSet 0 - OpDecorate %myCBuffer Binding 0 - OpDecorate %_arr_v4float_uint_1 ArrayStride 16 - OpMemberDecorate %MyConstantBuffer 0 Offset 0 - OpMemberDecorate %type_myCBuffer 0 Offset 0 - OpDecorate %type_myCBuffer Block - %uint = OpTypeInt 32 0 - %int_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 -%_arr_v4float_uint_1 = OpTypeArray %uint %uint_1 -%MyConstantBuffer = OpTypeStruct %_arr_v4float_uint_1 -%type_myCBuffer = OpTypeStruct %MyConstantBuffer -%_ptr_Uniform_type_myCBuffer = OpTypePointer Uniform %type_myCBuffer -%_arr_v4float_uint_1_0 = OpTypeArray %uint %uint_1 - %void = OpTypeVoid - %19 = OpTypeFunction %void -%_ptr_Function_v4float = OpTypePointer Function %uint -%_ptr_Uniform_MyConstantBuffer = OpTypePointer Uniform %MyConstantBuffer - %myCBuffer = OpVariable %_ptr_Uniform_type_myCBuffer Uniform -%_ptr_Function__arr_v4float_uint_1_0 = OpTypePointer Function %_arr_v4float_uint_1_0 - %23 = OpConstantNull %uint - %main = OpFunction %void None %19 - %24 = OpLabel - %25 = OpVariable %_ptr_Function__arr_v4float_uint_1_0 Function - %26 = OpAccessChain %_ptr_Uniform_MyConstantBuffer %myCBuffer %int_0 - %27 = OpLoad %MyConstantBuffer %26 - %28 = OpCompositeExtract %_arr_v4float_uint_1 %27 0 - %29 = OpCompositeExtract %uint %28 0 - %30 = OpCompositeConstruct %_arr_v4float_uint_1_0 %29 - OpStore %25 %30 - %31 = OpAccessChain %_ptr_Function_v4float %25 %23 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(text, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dead_branch_elim_test.cpp b/3rdparty/spirv-tools/test/opt/dead_branch_elim_test.cpp deleted file mode 100644 index e61286762..000000000 --- a/3rdparty/spirv-tools/test/opt/dead_branch_elim_test.cpp +++ /dev/null @@ -1,3171 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DeadBranchElimTest = PassTest<::testing::Test>; - -TEST_F(DeadBranchElimTest, IfThenElseTrue) { - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v; - // if (true) - // v = vec4(0.0,0.0,0.0,0.0); - // else - // v = vec4(1.0,1.0,1.0,1.0); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %gl_FragColor "gl_FragColor" -OpName %BaseColor "BaseColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -OpSelectionMerge %20 None -OpBranchConditional %true %21 %22 -%21 = OpLabel -OpStore %v %14 -OpBranch %20 -%22 = OpLabel -OpStore %v %16 -OpBranch %20 -%20 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -OpBranch %21 -%21 = OpLabel -OpStore %v %14 -OpBranch %20 -%20 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, IfThenElseFalse) { - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v; - // if (false) - // v = vec4(0.0,0.0,0.0,0.0); - // else - // v = vec4(1.0,1.0,1.0,1.0); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %gl_FragColor "gl_FragColor" -OpName %BaseColor "BaseColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%bool = OpTypeBool -%false = OpConstantFalse %bool -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -OpSelectionMerge %20 None -OpBranchConditional %false %21 %22 -%21 = OpLabel -OpStore %v %14 -OpBranch %20 -%22 = OpLabel -OpStore %v %16 -OpBranch %20 -%20 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -OpBranch %22 -%22 = OpLabel -OpStore %v %16 -OpBranch %20 -%20 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, IfThenTrue) { - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // if (true) - // v = v * vec4(0.5,0.5,0.5,0.5); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float_0_5 = OpConstant %float 0.5 -%15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -OpSelectionMerge %19 None -OpBranchConditional %true %20 %19 -%20 = OpLabel -%21 = OpLoad %v4float %v -%22 = OpFMul %v4float %21 %15 -OpStore %v %22 -OpBranch %19 -%19 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -OpBranch %20 -%20 = OpLabel -%21 = OpLoad %v4float %v -%22 = OpFMul %v4float %21 %15 -OpStore %v %22 -OpBranch %19 -%19 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, IfThenFalse) { - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // if (false) - // v = v * vec4(0.5,0.5,0.5,0.5); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%bool = OpTypeBool -%false = OpConstantFalse %bool -%float_0_5 = OpConstant %float 0.5 -%15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -OpSelectionMerge %19 None -OpBranchConditional %false %20 %19 -%20 = OpLabel -%21 = OpLoad %v4float %v -%22 = OpFMul %v4float %21 %15 -OpStore %v %22 -OpBranch %19 -%19 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -OpBranch %19 -%19 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, IfThenElsePhiTrue) { - // Test handling of phi in merge block after dead branch elimination. - // Note: The SPIR-V has had store/load elimination and phi insertion - // - // #version 140 - // - // void main() - // { - // vec4 v; - // if (true) - // v = vec4(0.0,0.0,0.0,0.0); - // else - // v = vec4(1.0,1.0,1.0,1.0); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -)"; - - const std::string before = - R"(%main = OpFunction %void None %5 -%17 = OpLabel -OpSelectionMerge %18 None -OpBranchConditional %true %19 %20 -%19 = OpLabel -OpBranch %18 -%20 = OpLabel -OpBranch %18 -%18 = OpLabel -%21 = OpPhi %v4float %12 %19 %14 %20 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %5 -%17 = OpLabel -OpBranch %19 -%19 = OpLabel -OpBranch %18 -%18 = OpLabel -OpStore %gl_FragColor %12 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, IfThenElsePhiFalse) { - // Test handling of phi in merge block after dead branch elimination. - // Note: The SPIR-V has had store/load elimination and phi insertion - // - // #version 140 - // - // void main() - // { - // vec4 v; - // if (true) - // v = vec4(0.0,0.0,0.0,0.0); - // else - // v = vec4(1.0,1.0,1.0,1.0); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%bool = OpTypeBool -%false = OpConstantFalse %bool -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -)"; - - const std::string before = - R"(%main = OpFunction %void None %5 -%17 = OpLabel -OpSelectionMerge %18 None -OpBranchConditional %false %19 %20 -%19 = OpLabel -OpBranch %18 -%20 = OpLabel -OpBranch %18 -%18 = OpLabel -%21 = OpPhi %v4float %12 %19 %14 %20 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %5 -%17 = OpLabel -OpBranch %20 -%20 = OpLabel -OpBranch %18 -%18 = OpLabel -OpStore %gl_FragColor %14 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, CompoundIfThenElseFalse) { - // #version 140 - // - // layout(std140) uniform U_t - // { - // bool g_B ; - // } ; - // - // void main() - // { - // vec4 v; - // if (false) { - // if (g_B) - // v = vec4(0.0,0.0,0.0,0.0); - // else - // v = vec4(1.0,1.0,1.0,1.0); - // } else { - // if (g_B) - // v = vec4(1.0,1.0,1.0,1.0); - // else - // v = vec4(0.0,0.0,0.0,0.0); - // } - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_B" -OpName %_ "" -OpName %v "v" -OpName %gl_FragColor "gl_FragColor" -OpMemberDecorate %U_t 0 Offset 0 -OpDecorate %U_t Block -OpDecorate %_ DescriptorSet 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%bool = OpTypeBool -%false = OpConstantFalse %bool -%uint = OpTypeInt 32 0 -%U_t = OpTypeStruct %uint -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%uint_0 = OpConstant %uint 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%25 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -OpSelectionMerge %26 None -OpBranchConditional %false %27 %28 -%27 = OpLabel -%29 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%30 = OpLoad %uint %29 -%31 = OpINotEqual %bool %30 %uint_0 -OpSelectionMerge %32 None -OpBranchConditional %31 %33 %34 -%33 = OpLabel -OpStore %v %21 -OpBranch %32 -%34 = OpLabel -OpStore %v %23 -OpBranch %32 -%32 = OpLabel -OpBranch %26 -%28 = OpLabel -%35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%36 = OpLoad %uint %35 -%37 = OpINotEqual %bool %36 %uint_0 -OpSelectionMerge %38 None -OpBranchConditional %37 %39 %40 -%39 = OpLabel -OpStore %v %23 -OpBranch %38 -%40 = OpLabel -OpStore %v %21 -OpBranch %38 -%38 = OpLabel -OpBranch %26 -%26 = OpLabel -%41 = OpLoad %v4float %v -OpStore %gl_FragColor %41 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%25 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -OpBranch %28 -%28 = OpLabel -%35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%36 = OpLoad %uint %35 -%37 = OpINotEqual %bool %36 %uint_0 -OpSelectionMerge %38 None -OpBranchConditional %37 %39 %40 -%40 = OpLabel -OpStore %v %21 -OpBranch %38 -%39 = OpLabel -OpStore %v %23 -OpBranch %38 -%38 = OpLabel -OpBranch %26 -%26 = OpLabel -%41 = OpLoad %v4float %v -OpStore %gl_FragColor %41 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, PreventOrphanMerge) { - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float_0_5 = OpConstant %float 0.5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%16 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%17 = OpLoad %v4float %BaseColor -OpStore %v %17 -OpSelectionMerge %18 None -OpBranchConditional %true %19 %20 -%19 = OpLabel -OpKill -%20 = OpLabel -%21 = OpLoad %v4float %v -%22 = OpVectorTimesScalar %v4float %21 %float_0_5 -OpStore %v %22 -OpBranch %18 -%18 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%16 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%17 = OpLoad %v4float %BaseColor -OpStore %v %17 -OpBranch %19 -%19 = OpLabel -OpKill -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, HandleOrphanMerge) { - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_ "foo(" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %gl_FragColor Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%9 = OpTypeFunction %v4float -%bool = OpTypeBool -%true = OpConstantTrue %bool -%float_0 = OpConstant %float 0 -%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%15 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %6 -%17 = OpLabel -%18 = OpFunctionCall %v4float %foo_ -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%foo_ = OpFunction %v4float None %9 -%19 = OpLabel -OpSelectionMerge %20 None -OpBranchConditional %true %21 %22 -%21 = OpLabel -OpReturnValue %13 -%22 = OpLabel -OpReturnValue %15 -%20 = OpLabel -%23 = OpUndef %v4float -OpReturnValue %23 -OpFunctionEnd -)"; - - const std::string after = - R"(%foo_ = OpFunction %v4float None %9 -%19 = OpLabel -OpBranch %21 -%21 = OpLabel -OpReturnValue %13 -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, KeepContinueTargetWhenKillAfterMerge) { - // #version 450 - // void main() { - // bool c; - // bool d; - // while(c) { - // if(d) { - // continue; - // } - // if(false) { - // continue; - // } - // discard; - // } - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %c "c" -OpName %d "d" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool -%false = OpConstantFalse %bool -)"; - - const std::string before = - R"(%main = OpFunction %void None %6 -%10 = OpLabel -%c = OpVariable %_ptr_Function_bool Function -%d = OpVariable %_ptr_Function_bool Function -OpBranch %11 -%11 = OpLabel -OpLoopMerge %12 %13 None -OpBranch %14 -%14 = OpLabel -%15 = OpLoad %bool %c -OpBranchConditional %15 %16 %12 -%16 = OpLabel -%17 = OpLoad %bool %d -OpSelectionMerge %18 None -OpBranchConditional %17 %19 %18 -%19 = OpLabel -OpBranch %13 -%18 = OpLabel -OpSelectionMerge %20 None -OpBranchConditional %false %21 %20 -%21 = OpLabel -OpBranch %13 -%20 = OpLabel -OpKill -%13 = OpLabel -OpBranch %11 -%12 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %6 -%10 = OpLabel -%c = OpVariable %_ptr_Function_bool Function -%d = OpVariable %_ptr_Function_bool Function -OpBranch %11 -%11 = OpLabel -OpLoopMerge %12 %13 None -OpBranch %14 -%14 = OpLabel -%15 = OpLoad %bool %c -OpBranchConditional %15 %16 %12 -%16 = OpLabel -%17 = OpLoad %bool %d -OpSelectionMerge %18 None -OpBranchConditional %17 %19 %18 -%19 = OpLabel -OpBranch %13 -%18 = OpLabel -OpBranch %20 -%20 = OpLabel -OpKill -%13 = OpLabel -OpBranch %11 -%12 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, DecorateDeleted) { - // Note: SPIR-V hand-edited to add decoration - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // if (false) - // v = v * vec4(0.5,0.5,0.5,0.5); - // gl_FragColor = v; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %22 RelaxedPrecision -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%bool = OpTypeBool -%false = OpConstantFalse %bool -%float_0_5 = OpConstant %float 0.5 -%15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%bool = OpTypeBool -%false = OpConstantFalse %bool -%float_0_5 = OpConstant %float 0.5 -%16 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -OpSelectionMerge %19 None -OpBranchConditional %false %20 %19 -%20 = OpLabel -%21 = OpLoad %v4float %v -%22 = OpFMul %v4float %21 %15 -OpStore %v %22 -OpBranch %19 -%19 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%18 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%19 = OpLoad %v4float %BaseColor -OpStore %v %19 -OpBranch %20 -%20 = OpLabel -%23 = OpLoad %v4float %v -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs_before + before, - predefs_after + after, true, true); -} - -TEST_F(DeadBranchElimTest, LoopInDeadBranch) { - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // vec4 v = BaseColor; - // if (false) - // for (int i=0; i<3; i++) - // v = v * 0.5; - // OutColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %i "i" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%bool = OpTypeBool -%false = OpConstantFalse %bool -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_3 = OpConstant %int 3 -%float_0_5 = OpConstant %float 0.5 -%int_1 = OpConstant %int 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%i = OpVariable %_ptr_Function_int Function -%23 = OpLoad %v4float %BaseColor -OpStore %v %23 -OpSelectionMerge %24 None -OpBranchConditional %false %25 %24 -%25 = OpLabel -OpStore %i %int_0 -OpBranch %26 -%26 = OpLabel -OpLoopMerge %27 %28 None -OpBranch %29 -%29 = OpLabel -%30 = OpLoad %int %i -%31 = OpSLessThan %bool %30 %int_3 -OpBranchConditional %31 %32 %27 -%32 = OpLabel -%33 = OpLoad %v4float %v -%34 = OpVectorTimesScalar %v4float %33 %float_0_5 -OpStore %v %34 -OpBranch %28 -%28 = OpLabel -%35 = OpLoad %int %i -%36 = OpIAdd %int %35 %int_1 -OpStore %i %36 -OpBranch %26 -%27 = OpLabel -OpBranch %24 -%24 = OpLabel -%37 = OpLoad %v4float %v -OpStore %OutColor %37 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%i = OpVariable %_ptr_Function_int Function -%23 = OpLoad %v4float %BaseColor -OpStore %v %23 -OpBranch %24 -%24 = OpLabel -%37 = OpLoad %v4float %v -OpStore %OutColor %37 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, SwitchLiveCase) { - // #version 450 - // - // layout (location=0) in vec4 BaseColor; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // switch (1) { - // case 0: - // OutColor = vec4(0.0,0.0,0.0,0.0); - // break; - // case 1: - // OutColor = vec4(0.125,0.125,0.125,0.125); - // break; - // case 2: - // OutColor = vec4(0.25,0.25,0.25,0.25); - // break; - // default: - // OutColor = vec4(1.0,1.0,1.0,1.0); - // } - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %OutColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %OutColor "OutColor" -OpName %BaseColor "BaseColor" -OpDecorate %OutColor Location 0 -OpDecorate %BaseColor Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_0_125 = OpConstant %float 0.125 -%15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125 -%float_0_25 = OpConstant %float 0.25 -%17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25 -%float_1 = OpConstant %float 1 -%19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %6 -%21 = OpLabel -OpSelectionMerge %22 None -OpSwitch %int_1 %23 0 %24 1 %25 2 %26 -%23 = OpLabel -OpStore %OutColor %19 -OpBranch %22 -%24 = OpLabel -OpStore %OutColor %13 -OpBranch %22 -%25 = OpLabel -OpStore %OutColor %15 -OpBranch %22 -%26 = OpLabel -OpStore %OutColor %17 -OpBranch %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %6 -%21 = OpLabel -OpBranch %25 -%25 = OpLabel -OpStore %OutColor %15 -OpBranch %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, SwitchLiveDefault) { - // #version 450 - // - // layout (location=0) in vec4 BaseColor; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // switch (7) { - // case 0: - // OutColor = vec4(0.0,0.0,0.0,0.0); - // break; - // case 1: - // OutColor = vec4(0.125,0.125,0.125,0.125); - // break; - // case 2: - // OutColor = vec4(0.25,0.25,0.25,0.25); - // break; - // default: - // OutColor = vec4(1.0,1.0,1.0,1.0); - // } - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %OutColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %OutColor "OutColor" -OpName %BaseColor "BaseColor" -OpDecorate %OutColor Location 0 -OpDecorate %BaseColor Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%int_7 = OpConstant %int 7 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_0_125 = OpConstant %float 0.125 -%15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125 -%float_0_25 = OpConstant %float 0.25 -%17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25 -%float_1 = OpConstant %float 1 -%19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %6 -%21 = OpLabel -OpSelectionMerge %22 None -OpSwitch %int_7 %23 0 %24 1 %25 2 %26 -%23 = OpLabel -OpStore %OutColor %19 -OpBranch %22 -%24 = OpLabel -OpStore %OutColor %13 -OpBranch %22 -%25 = OpLabel -OpStore %OutColor %15 -OpBranch %22 -%26 = OpLabel -OpStore %OutColor %17 -OpBranch %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %6 -%21 = OpLabel -OpBranch %23 -%23 = OpLabel -OpStore %OutColor %19 -OpBranch %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, SwitchLiveCaseBreakFromLoop) { - // This sample does not directly translate to GLSL/HLSL as - // direct breaks from a loop cannot be made from a switch. - // This construct is currently formed by inlining a function - // containing early returns from the cases of a switch. The - // function is wrapped in a one-trip loop and returns are - // translated to branches to the loop's merge block. - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %OutColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %oc "oc" -OpName %OutColor "OutColor" -OpName %BaseColor "BaseColor" -OpDecorate %OutColor Location 0 -OpDecorate %BaseColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_0_125 = OpConstant %float 0.125 -%19 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125 -%float_0_25 = OpConstant %float 0.25 -%21 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25 -%float_1 = OpConstant %float 1 -%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%26 = OpLabel -%oc = OpVariable %_ptr_Function_v4float Function -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -OpSelectionMerge %31 None -OpSwitch %int_1 %31 0 %32 1 %33 2 %34 -%32 = OpLabel -OpStore %oc %17 -OpBranch %28 -%33 = OpLabel -OpStore %oc %19 -OpBranch %28 -%34 = OpLabel -OpStore %oc %21 -OpBranch %28 -%31 = OpLabel -OpStore %oc %23 -OpBranch %28 -%29 = OpLabel -OpBranchConditional %false %27 %28 -%28 = OpLabel -%35 = OpLoad %v4float %oc -OpStore %OutColor %35 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%26 = OpLabel -%oc = OpVariable %_ptr_Function_v4float Function -OpBranch %27 -%27 = OpLabel -OpLoopMerge %28 %29 None -OpBranch %30 -%30 = OpLabel -OpBranch %33 -%33 = OpLabel -OpStore %oc %19 -OpBranch %28 -%29 = OpLabel -OpBranch %27 -%28 = OpLabel -%35 = OpLoad %v4float %oc -OpStore %OutColor %35 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(DeadBranchElimTest, LeaveContinueBackedge) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None -; CHECK: [[continue]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} {{%\w+}} [[merge]] -; CHECK-NEXT: [[merge]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%bool = OpTypeBool -%false = OpConstantFalse %bool -%void = OpTypeVoid -%funcTy = OpTypeFunction %void -%func = OpFunction %void None %funcTy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %4 -%4 = OpLabel -; Be careful we don't remove the backedge to %2 despite never taking it. -OpBranchConditional %false %2 %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} -TEST_F(DeadBranchElimTest, LeaveContinueBackedgeExtraBlock) { - const std::string text = R"( -; CHECK: OpBranch [[header:%\w+]] -; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None -; CHECK-NEXT: OpBranch [[continue]] -; CHECK-NEXT: [[continue]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[extra:%\w+]] [[merge]] -; CHECK-NEXT: [[extra]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -; CHECK-NEXT: [[merge]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%bool = OpTypeBool -%false = OpConstantFalse %bool -%void = OpTypeVoid -%funcTy = OpTypeFunction %void -%func = OpFunction %void None %funcTy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %4 -%4 = OpLabel -; Be careful we don't remove the backedge to %2 despite never taking it. -OpBranchConditional %false %5 %3 -; This block remains live despite being unreachable. -%5 = OpLabel -OpBranch %2 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, RemovePhiWithUnreachableContinue) { - const std::string text = R"( -; CHECK: [[entry:%\w+]] = OpLabel -; CHECK-NEXT: OpBranch [[header:%\w+]] -; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK-NEXT: [[ret]] = OpLabel -; CHECK-NEXT: OpReturn -; CHECK: [[continue]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpUnreachable -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%void = OpTypeVoid -%funcTy = OpTypeFunction %void -%func = OpFunction %void None %funcTy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %bool %false %1 %true %continue -OpLoopMerge %merge %continue None -OpBranch %3 -%3 = OpLabel -OpReturn -%continue = OpLabel -OpBranch %2 -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, UnreachableLoopMergeAndContinueTargets) { - const std::string text = R"( -; CHECK: [[undef:%\w+]] = OpUndef %bool -; CHECK: OpSelectionMerge [[header:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_lab:%\w+]] [[else_lab:%\w+]] -; CHECK: OpPhi %bool %false [[if_lab]] %false [[else_lab]] [[undef]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK-NEXT: OpBranch [[ret:%\w+]] -; CHECK-NEXT: [[ret]] = OpLabel -; CHECK-NEXT: OpReturn -; CHECK: [[continue]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpUnreachable -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%void = OpTypeVoid -%funcTy = OpTypeFunction %void -%func = OpFunction %void None %funcTy -%1 = OpLabel -%c = OpUndef %bool -OpSelectionMerge %2 None -OpBranchConditional %c %if %else -%if = OpLabel -OpBranch %2 -%else = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %bool %false %if %false %else %true %continue -OpLoopMerge %merge %continue None -OpBranch %3 -%3 = OpLabel -OpReturn -%continue = OpLabel -OpBranch %2 -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} -TEST_F(DeadBranchElimTest, EarlyReconvergence) { - const std::string text = R"( -; CHECK-NOT: OpBranchConditional -; CHECK: [[logical:%\w+]] = OpLogicalOr -; CHECK-NOT: OpPhi -; CHECK: OpLogicalAnd {{%\w+}} {{%\w+}} [[logical]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpSelectionMerge %2 None -OpBranchConditional %false %3 %4 -%3 = OpLabel -%12 = OpLogicalNot %bool %true -OpBranch %2 -%4 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %false %5 %6 -%5 = OpLabel -%10 = OpLogicalAnd %bool %true %false -OpBranch %7 -%6 = OpLabel -%11 = OpLogicalOr %bool %true %false -OpBranch %7 -%7 = OpLabel -; This phi is in a block preceeding the merge %14! -%8 = OpPhi %bool %10 %5 %11 %6 -OpBranch %14 -%14 = OpLabel -OpBranch %2 -%2 = OpLabel -%9 = OpPhi %bool %12 %3 %8 %14 -%13 = OpLogicalAnd %bool %true %9 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloating) { - const std::string text = R"( -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpReturn -; CHECK-NEXT: OpFunctionEnd -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%1 = OpTypeFunction %void -%func = OpFunction %void None %1 -%2 = OpLabel -OpReturn -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloatingJoin) { - const std::string text = R"( -; CHECK: OpFunction -; CHECK-NEXT: OpFunctionParameter -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpReturn -; CHECK-NEXT: OpFunctionEnd -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%1 = OpTypeFunction %void %bool -%func = OpFunction %void None %1 -%bool_param = OpFunctionParameter %bool -%2 = OpLabel -OpReturn -%3 = OpLabel -OpSelectionMerge %6 None -OpBranchConditional %bool_param %4 %5 -%4 = OpLabel -OpBranch %6 -%5 = OpLabel -OpBranch %6 -%6 = OpLabel -%7 = OpPhi %bool %true %4 %false %6 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksDeadPhi) { - const std::string text = R"( -; CHECK: OpFunction -; CHECK-NEXT: OpFunctionParameter -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpBranch [[label:%\w+]] -; CHECK-NEXT: [[label]] = OpLabel -; CHECK-NEXT: OpLogicalNot %bool %true -; CHECK-NEXT: OpReturn -; CHECK-NEXT: OpFunctionEnd -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%1 = OpTypeFunction %void %bool -%func = OpFunction %void None %1 -%bool_param = OpFunctionParameter %bool -%2 = OpLabel -OpBranch %3 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -%5 = OpPhi %bool %true %2 %false %4 -%6 = OpLogicalNot %bool %5 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksPartiallyDeadPhi) { - const std::string text = R"( -; CHECK: OpFunction -; CHECK-NEXT: [[param:%\w+]] = OpFunctionParameter -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpBranchConditional [[param]] [[merge:%\w+]] [[br:%\w+]] -; CHECK-NEXT: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi %bool %true %2 %false [[br]] -; CHECK-NEXT: OpLogicalNot %bool [[phi]] -; CHECK-NEXT: OpReturn -; CHECK-NEXT: [[br]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK-NEXT: OpFunctionEnd -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%1 = OpTypeFunction %void %bool -%func = OpFunction %void None %1 -%bool_param = OpFunctionParameter %bool -%2 = OpLabel -OpBranchConditional %bool_param %3 %7 -%7 = OpLabel -OpBranch %3 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -%5 = OpPhi %bool %true %2 %false %7 %false %4 -%6 = OpLogicalNot %bool %5 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, LiveHeaderDeadPhi) { - const std::string text = R"( -; CHECK: OpLabel -; CHECK-NOT: OpBranchConditional -; CHECK-NOT: OpPhi -; CHECK: OpLogicalNot %bool %false -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %true %2 %3 -%2 = OpLabel -OpBranch %3 -%3 = OpLabel -%5 = OpPhi %bool %true %3 %false %2 -%6 = OpLogicalNot %bool %5 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, ExtraBackedgeBlocksLive) { - const std::string text = R"( -; CHECK: [[entry:%\w+]] = OpLabel -; CHECK-NOT: OpSelectionMerge -; CHECK: OpBranch [[header:%\w+]] -; CHECK-NEXT: [[header]] = OpLabel -; CHECK-NEXT: OpPhi %bool %true [[entry]] %false [[backedge:%\w+]] -; CHECK-NEXT: OpLoopMerge -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%func_ty = OpTypeFunction %void %bool -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %bool -%entry = OpLabel -OpSelectionMerge %if_merge None -; This dead branch is included to ensure the pass does work. -OpBranchConditional %false %if_merge %loop_header -%loop_header = OpLabel -; Both incoming edges are live, so the phi should be untouched. -%phi = OpPhi %bool %true %entry %false %backedge -OpLoopMerge %loop_merge %continue None -OpBranchConditional %param %loop_merge %continue -%continue = OpLabel -OpBranch %backedge -%backedge = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpBranch %if_merge -%if_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, ExtraBackedgeBlocksUnreachable) { - const std::string text = R"( -; CHECK: [[entry:%\w+]] = OpLabel -; CHECK-NEXT: OpBranch [[header:%\w+]] -; CHECK-NEXT: [[header]] = OpLabel -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None -; CHECK-NEXT: OpBranch [[merge]] -; CHECK-NEXT: [[merge]] = OpLabel -; CHECK-NEXT: OpReturn -; CHECK-NEXT: [[continue]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%func_ty = OpTypeFunction %void %bool -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %bool -%entry = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -; Since the continue is unreachable, %backedge will be removed. The phi will -; instead require an edge from %continue. -%phi = OpPhi %bool %true %entry %false %backedge -OpLoopMerge %merge %continue None -OpBranch %merge -%continue = OpLabel -OpBranch %backedge -%backedge = OpLabel -OpBranch %loop_header -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, NoUnnecessaryChanges) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef = OpUndef %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %4 %5 None -OpBranch %6 -%6 = OpLabel -OpReturn -%5 = OpLabel -OpBranch %2 -%4 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); -} - -TEST_F(DeadBranchElimTest, ExtraBackedgePartiallyDead) { - const std::string text = R"( -; CHECK: OpLabel -; CHECK: [[header:%\w+]] = OpLabel -; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None -; CHECK: [[merge]] = OpLabel -; CHECK: [[continue]] = OpLabel -; CHECK: OpBranch [[extra:%\w+]] -; CHECK: [[extra]] = OpLabel -; CHECK-NOT: OpSelectionMerge -; CHECK-NEXT: OpBranch [[else:%\w+]] -; CHECK-NEXT: [[else]] = OpLabel -; CHECK-NEXT: OpLogicalOr -; CHECK-NEXT: OpBranch [[backedge:%\w+]] -; CHECK-NEXT: [[backedge:%\w+]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpName %func "func" -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%func_ty = OpTypeFunction %void %bool -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %bool -%entry = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %continue None -OpBranchConditional %param %loop_merge %continue -%continue = OpLabel -OpBranch %extra -%extra = OpLabel -OpSelectionMerge %backedge None -OpBranchConditional %false %then %else -%then = OpLabel -%and = OpLogicalAnd %bool %true %false -OpBranch %backedge -%else = OpLabel -%or = OpLogicalOr %bool %true %false -OpBranch %backedge -%backedge = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, UnreachableContinuePhiInMerge) { - const std::string text = R"( -; CHECK: [[entry:%\w+]] = OpLabel -; CHECK-NEXT: OpBranch [[header:%\w+]] -; CHECK-NEXT: [[header]] = OpLabel -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None -; CHECK-NEXT: OpBranch [[label:%\w+]] -; CHECK-NEXT: [[label]] = OpLabel -; CHECK-NEXT: [[fadd:%\w+]] = OpFAdd -; CHECK-NEXT: OpBranch [[label:%\w+]] -; CHECK-NEXT: [[label]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK-NEXT: [[continue]] = OpLabel -; CHECK-NEXT: OpBranch [[header]] -; CHECK-NEXT: [[merge]] = OpLabel -; CHECK-NEXT: OpStore {{%\w+}} [[fadd]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %o - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %o "o" - OpName %S "S" - OpMemberName %S 0 "a" - OpName %U_t "U_t" - OpMemberName %U_t 0 "g_F" - OpMemberName %U_t 1 "g_F2" - OpDecorate %o Location 0 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %U_t 0 Volatile - OpMemberDecorate %U_t 0 Offset 0 - OpMemberDecorate %U_t 1 Offset 4 - OpDecorate %U_t BufferBlock - %void = OpTypeVoid - %7 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float - %float_0 = OpConstant %float 0 - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %float_1 = OpConstant %float 1 - %float_5 = OpConstant %float 5 - %int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float - %o = OpVariable %_ptr_Output_float Output - %S = OpTypeStruct %float - %U_t = OpTypeStruct %S %S -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t - %main = OpFunction %void None %7 - %22 = OpLabel - OpBranch %23 - %23 = OpLabel - %24 = OpPhi %float %float_0 %22 %25 %26 - %27 = OpPhi %int %int_0 %22 %28 %26 - OpLoopMerge %29 %26 None - OpBranch %40 - %40 = OpLabel - %25 = OpFAdd %float %24 %float_1 - OpSelectionMerge %30 None - OpBranchConditional %true %31 %30 - %31 = OpLabel - OpBranch %29 - %30 = OpLabel - OpBranch %26 - %26 = OpLabel - %28 = OpIAdd %int %27 %int_1 - %32 = OpSLessThan %bool %27 %int_10 -; continue block branches to the header or another none dead block. - OpBranchConditional %32 %23 %29 - %29 = OpLabel - %33 = OpPhi %float %24 %26 %25 %31 - OpStore %o %33 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, NonStructuredIf) { - const std::string text = R"( -; CHECK-NOT: OpBranchConditional -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpDecorate %func LinkageAttributes "func" Export -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpBranchConditional %true %then %else -%then = OpLabel -OpBranch %final -%else = OpLabel -OpBranch %final -%final = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, ReorderBlocks) { - const std::string text = R"( -; CHECK: OpLabel -; CHECK: OpBranch [[label:%\w+]] -; CHECK: [[label:%\w+]] = OpLabel -; CHECK-NEXT: OpLogicalNot -; CHECK-NEXT: OpBranch [[label:%\w+]] -; CHECK: [[label]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %true %2 %3 -%3 = OpLabel -OpReturn -%2 = OpLabel -%not = OpLogicalNot %bool %true -OpBranch %3 -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, ReorderBlocksMultiple) { - // Checks are not important. The validation post optimization is the - // important part. - const std::string text = R"( -; CHECK: OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %true %2 %3 -%3 = OpLabel -OpReturn -%2 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, ReorderBlocksMultiple2) { - // Checks are not important. The validation post optimization is the - // important part. - const std::string text = R"( -; CHECK: OpLabel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %true %2 %3 -%3 = OpLabel -OpBranch %5 -%5 = OpLabel -OpReturn -%2 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit1) { - // Checks that if a selection merge construct contains a conditional branch - // to the merge node, then the OpSelectionMerge instruction is positioned - // correctly. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"( -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpBranch [[taken_branch:%\w+]] -; CHECK-NEXT: [[taken_branch]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[merge]] {{%\w+}} -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpSelectionMerge %outer_merge None -OpBranchConditional %true %bb1 %bb3 -%bb1 = OpLabel -OpBranchConditional %undef_bool %outer_merge %bb2 -%bb2 = OpLabel -OpBranch %outer_merge -%bb3 = OpLabel -OpBranch %outer_merge -%outer_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit2) { - // Checks that if a selection merge construct contains a conditional branch - // to the merge node, then the OpSelectionMerge instruction is positioned - // correctly. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"( -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK-NEXT: [[bb1]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[inner_merge:%\w+]] -; CHECK: [[inner_merge]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[outer_merge:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[outer_merge]:%\w+]] {{%\w+}} -; CHECK: [[outer_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpSelectionMerge %outer_merge None -OpBranchConditional %true %bb1 %bb5 -%bb1 = OpLabel -OpSelectionMerge %inner_merge None -OpBranchConditional %undef_bool %bb2 %bb3 -%bb2 = OpLabel -OpBranch %inner_merge -%bb3 = OpLabel -OpBranch %inner_merge -%inner_merge = OpLabel -OpBranchConditional %undef_bool %outer_merge %bb4 -%bb4 = OpLabel -OpBranch %outer_merge -%bb5 = OpLabel -OpBranch %outer_merge -%outer_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithConditionalExit) { - // Checks that if a selection merge construct contains a conditional branch - // to the merge node, then we keep the OpSelectionMerge on that branch. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%undef_int = OpUndef %uint -)"; - - const std::string body = - R"( -; CHECK: OpLoopMerge [[loop_merge:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None -; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 1 [[bb3:%\w+]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpSwitch %undef_int %sel_merge 1 %bb3 -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop) { - // Checks that if a selection merge construct contains a conditional branch - // to a loop surrounding the selection merge, then we do not keep the - // OpSelectionMerge instruction. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"( -; CHECK: OpLoopMerge [[loop_merge:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_merge]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge:%\w+]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpBranchConditional %undef_bool %bb3 %loop_merge -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue) { - // Checks that if a selection merge construct contains a conditional branch - // to continue of a loop surrounding the selection merge, then we do not keep - // the OpSelectionMerge instruction. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"(; -; CHECK: OpLabel -; CHECK: [[loop_header:%\w+]] = OpLabel -; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge:%\w+]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_cont]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_header]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpBranchConditional %undef_bool %bb3 %cont -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop2) { - // Same as |SelectionMergeWithExitToLoop|, except the switch goes to the loop - // merge or the selection merge. In this case, we do not need an - // OpSelectionMerge either. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"( -; CHECK: OpLoopMerge [[loop_merge:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_merge]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpBranchConditional %undef_bool %sel_merge %loop_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue2) { - // Same as |SelectionMergeWithExitToLoopContinue|, except the branch goes to - // the loop continue or the selection merge. In this case, we do not need an - // OpSelectionMerge either. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"( -; CHECK: OpLabel -; CHECK: [[loop_header:%\w+]] = OpLabel -; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_cont]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_cont]] = OpLabel -; CHECK: OpBranch [[loop_header]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpBranchConditional %undef_bool %sel_merge %cont -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop3) { - // Checks that if a selection merge construct contains a conditional branch - // to the merge of a surrounding loop, the selection merge, and another block - // inside the selection merge, then we must keep the OpSelectionMerge - // instruction on that branch. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%undef_int = OpUndef %uint -)"; - - const std::string body = - R"( -; CHECK: OpLoopMerge [[loop_merge:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None -; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 0 [[loop_merge]] 1 [[bb3:%\w+]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpSwitch %undef_int %sel_merge 0 %loop_merge 1 %bb3 -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue3) { - // Checks that if a selection merge construct contains a conditional branch - // to the merge of a surrounding loop, the selection merge, and another block - // inside the selection merge, then we must keep the OpSelectionMerge - // instruction on that branch. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%undef_int = OpUndef %uint -)"; - - const std::string body = - R"( -; CHECK: OpLabel -; CHECK: [[loop_header:%\w+]] = OpLabel -; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_continue:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None -; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 0 [[loop_continue]] 1 [[bb3:%\w+]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_continue]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_header]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpSwitch %undef_int %sel_merge 0 %cont 1 %bb3 -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop4) { - // Same as |SelectionMergeWithExitToLoop|, except the branch in the selection - // construct is an |OpSwitch| instead of an |OpConditionalBranch|. The - // OpSelectionMerge instruction is not needed in this case either. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%undef_int = OpUndef %uint -)"; - - const std::string body = - R"( -; CHECK: OpLoopMerge [[loop_merge:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSwitch {{%\w+}} [[bb3:%\w+]] 0 [[loop_merge]] 1 [[bb3:%\w+]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge:%\w+]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpSwitch %undef_int %bb3 0 %loop_merge 1 %bb3 -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue4) { - // Same as |SelectionMergeWithExitToLoopContinue|, except the branch in the - // selection construct is an |OpSwitch| instead of an |OpConditionalBranch|. - // The OpSelectionMerge instruction is not needed in this case either. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%undef_int = OpUndef %uint -)"; - - const std::string body = - R"( -; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSwitch {{%\w+}} [[bb3:%\w+]] 0 [[loop_cont]] 1 [[bb3:%\w+]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[sel_merge:%\w+]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %sel_merge None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpSwitch %undef_int %bb3 0 %cont 1 %bb3 -%bb3 = OpLabel -OpBranch %sel_merge -%bb4 = OpLabel -OpBranch %sel_merge -%sel_merge = OpLabel -OpBranch %loop_merge -%cont = OpLabel -OpBranch %loop_header -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + body, true); -} - -TEST_F(DeadBranchElimTest, SelectionMergeSameAsLoopContinue) { - // Same as |SelectionMergeWithExitToLoopContinue|, except the branch in the - // selection construct is an |OpSwitch| instead of an |OpConditionalBranch|. - // The OpSelectionMerge instruction is not needed in this case either. - const std::string predefs = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -%void = OpTypeVoid -%func_type = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%undef_bool = OpUndef %bool -)"; - - const std::string body = - R"( -; CHECK: OpLabel -; CHECK: [[loop_header:%\w+]] = OpLabel -; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[loop_cont]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]] -; CHECK: [[bb3]] = OpLabel -; CHECK-NEXT: OpBranch [[loop_cont]] -; CHECK: [[loop_cont]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[loop_header]] [[loop_merge]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -%main = OpFunction %void None %func_type -%entry_bb = OpLabel -OpBranch %loop_header -%loop_header = OpLabel -OpLoopMerge %loop_merge %cont None -OpBranch %bb1 -%bb1 = OpLabel -OpSelectionMerge %cont None -OpBranchConditional %true %bb2 %bb4 -%bb2 = OpLabel -OpBranchConditional %undef_bool %bb3 %cont -%bb3 = OpLabel -OpBranch %cont -%bb4 = OpLabel -OpBranch %cont -%cont = OpLabel -OpBranchConditional %undef_bool %loop_header %loop_merge -%loop_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - // The selection merge in the loop naming the continue target as merge is - // invalid, but handled by this pass so validation is disabled. - SinglePassRunAndMatch(predefs + body, false); -} - -TEST_F(DeadBranchElimTest, SelectionMergeWithNestedLoop) { - const std::string body = - R"( -; CHECK: OpSelectionMerge [[merge1:%\w+]] -; CHECK: [[merge1]] = OpLabel -; CHECK-NEXT: OpBranch [[preheader:%\w+]] -; CHECK: [[preheader]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpBranch [[header:%\w+]] -; CHECK: [[header]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpLoopMerge [[merge2:%\w+]] -; CHECK: [[merge2]] = OpLabel -; CHECK-NEXT: OpUnreachable - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource ESSL 310 - OpName %main "main" - OpName %h "h" - OpName %i "i" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %bool = OpTypeBool - %_ptr_Function_bool = OpTypePointer Function %bool - %true = OpConstantTrue %bool - %int = OpTypeInt 32 1 - %_ptr_Function_int = OpTypePointer Function %int - %int_1 = OpConstant %int 1 - %int_0 = OpConstant %int 0 - %27 = OpUndef %bool - %main = OpFunction %void None %3 - %5 = OpLabel - %h = OpVariable %_ptr_Function_bool Function - %i = OpVariable %_ptr_Function_int Function - OpSelectionMerge %11 None - OpBranchConditional %27 %10 %11 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %true %13 %14 - %13 = OpLabel - OpStore %i %int_1 - OpBranch %19 - %19 = OpLabel - OpLoopMerge %21 %22 None - OpBranch %23 - %23 = OpLabel - %26 = OpSGreaterThan %bool %int_1 %int_0 - OpBranchConditional %true %20 %21 - %20 = OpLabel - OpBranch %22 - %22 = OpLabel - OpBranch %19 - %21 = OpLabel - OpBranch %14 - %14 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(body, true); -} - -TEST_F(DeadBranchElimTest, DontFoldBackedge) { - const std::string body = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -%void = OpTypeVoid -%4 = OpTypeFunction %void -%bool = OpTypeBool -%false = OpConstantFalse %bool -%2 = OpFunction %void None %4 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -OpLoopMerge %9 %10 None -OpBranch %11 -%11 = OpLabel -%12 = OpUndef %bool -OpSelectionMerge %10 None -OpBranchConditional %12 %13 %10 -%13 = OpLabel -OpBranch %9 -%10 = OpLabel -OpBranch %14 -%14 = OpLabel -OpBranchConditional %false %8 %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(body, body, true); -} - -TEST_F(DeadBranchElimTest, FoldBackedgeToHeader) { - const std::string body = - R"( -; CHECK: OpLabel -; CHECK: [[header:%\w+]] = OpLabel -; CHECK-NEXT: OpLoopMerge {{%\w+}} [[cont:%\w+]] -; CHECK: [[cont]] = OpLabel -; This branch may not be in the continue block, but must come after it. -; CHECK: OpBranch [[header]] -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -%void = OpTypeVoid -%4 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%2 = OpFunction %void None %4 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -OpLoopMerge %9 %10 None -OpBranch %11 -%11 = OpLabel -%12 = OpUndef %bool -OpSelectionMerge %10 None -OpBranchConditional %12 %13 %10 -%13 = OpLabel -OpBranch %9 -%10 = OpLabel -OpBranch %14 -%14 = OpLabel -OpBranchConditional %true %8 %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // The selection merge in the loop naming the continue target as merge is - // invalid, but handled by this pass so validation is disabled. - SinglePassRunAndMatch(body, false); -} - -TEST_F(DeadBranchElimTest, UnreachableMergeAndContinueSameBlock) { - const std::string spirv = R"( -; CHECK: OpLabel -; CHECK: [[outer:%\w+]] = OpLabel -; CHECK-NEXT: OpLoopMerge [[outer_merge:%\w+]] [[outer_cont:%\w+]] None -; CHECK-NEXT: OpBranch [[inner:%\w+]] -; CHECK: [[inner]] = OpLabel -; CHECK: OpLoopMerge [[outer_cont]] [[inner_cont:%\w+]] None -; CHECK: [[inner_cont]] = OpLabel -; CHECK-NEXT: OpBranch [[inner]] -; CHECK: [[outer_cont]] = OpLabel -; CHECK-NEXT: OpBranch [[outer]] -; CHECK: [[outer_merge]] = OpLabel -; CHECK-NEXT: OpUnreachable -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %outer_loop -%outer_loop = OpLabel -OpLoopMerge %outer_merge %outer_continue None -OpBranch %inner_loop -%inner_loop = OpLabel -OpLoopMerge %outer_continue %inner_continue None -OpBranch %inner_body -%inner_body = OpLabel -OpSelectionMerge %inner_continue None -OpBranchConditional %true %ret %inner_continue -%ret = OpLabel -OpReturn -%inner_continue = OpLabel -OpBranchConditional %true %outer_continue %inner_loop -%outer_continue = OpLabel -OpBranchConditional %true %outer_merge %outer_loop -%outer_merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(spirv, true); -} - -// Fold a switch with a nested break. The only case should be the default. -TEST_F(DeadBranchElimTest, FoldSwitchWithNestedBreak) { - const std::string spirv = R"( -; CHECK: OpSwitch %int_3 [[case_bb:%\w+]]{{[[:space:]]}} -; CHECK: [[case_bb]] = OpLabel -; CHECK-NEXT: OpUndef -; CHECK-NEXT: OpSelectionMerge - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %2 "main" - OpSource GLSL 450 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 - %bool = OpTypeBool - %2 = OpFunction %void None %4 - %10 = OpLabel - OpSelectionMerge %11 None - OpSwitch %int_3 %12 3 %13 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - %14 = OpUndef %bool - OpSelectionMerge %15 None - OpBranchConditional %14 %16 %15 - %16 = OpLabel - OpBranch %11 - %15 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(DeadBranchElimTest, FoldBranchWithBreakToSwitch) { - const std::string spirv = R"( -; CHECK: OpSelectionMerge [[sel_merge:%\w+]] -; CHECK-NEXT: OpSwitch {{%\w+}} {{%\w+}} 3 [[bb:%\w+]] -; CHECK: [[bb]] = OpLabel -; CHECK-NEXT: OpBranch [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NOT: OpSelectionMerge -; CHECK: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %2 "main" - OpSource GLSL 450 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %2 = OpFunction %void None %4 - %10 = OpLabel - %undef_int = OpUndef %int - OpSelectionMerge %11 None - OpSwitch %undef_int %12 3 %13 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpSelectionMerge %15 None - OpBranchConditional %true %16 %15 - %16 = OpLabel - %14 = OpUndef %bool - OpBranchConditional %14 %11 %17 - %17 = OpLabel - OpBranch %15 - %15 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(DeadBranchElimTest, IfInSwitch) { - // #version 310 es - // - // void main() - // { - // switch(0) - // { - // case 0: - // if(false) - // { - // } - // else - // { - // } - // } - // } - - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%bool = OpTypeBool -%false = OpConstantFalse %bool -%main = OpFunction %void None %3 -%5 = OpLabel -OpSelectionMerge %9 None -OpSwitch %int_0 %9 0 %8 -%8 = OpLabel -OpSelectionMerge %13 None -OpBranchConditional %false %12 %13 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%bool = OpTypeBool -%false = OpConstantFalse %bool -%main = OpFunction %void None %4 -%9 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, true, true); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// More complex control flow -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dead_insert_elim_test.cpp b/3rdparty/spirv-tools/test/opt/dead_insert_elim_test.cpp deleted file mode 100644 index 8ae6894d8..000000000 --- a/3rdparty/spirv-tools/test/opt/dead_insert_elim_test.cpp +++ /dev/null @@ -1,571 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DeadInsertElimTest = PassTest<::testing::Test>; - -TEST_F(DeadInsertElimTest, InsertAfterInsertElim) { - // With two insertions to the same offset, the first is dead. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in float In0; - // layout (location=1) in float In1; - // layout (location=2) in vec2 In2; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec2 v = In2; - // v.x = In0 + In1; // dead - // v.x = 0.0; - // OutColor = v.xyxy; - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In2 "In2" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %OutColor "OutColor" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_n" -OpName %_ "" -OpDecorate %In2 Location 2 -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %OutColor Location 0 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%In2 = OpVariable %_ptr_Input_v2float Input -%_ptr_Input_float = OpTypePointer Input %float -%In0 = OpVariable %_ptr_Input_float Input -%In1 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%int = OpTypeInt 32 1 -%_Globals_ = OpTypeStruct %uint %int -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In2 "In2" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %OutColor "OutColor" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_n" -OpName %_ "" -OpDecorate %In2 Location 2 -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %OutColor Location 0 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%In2 = OpVariable %_ptr_Input_v2float Input -%_ptr_Input_float = OpTypePointer Input %float -%In0 = OpVariable %_ptr_Input_float Input -%In1 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%int = OpTypeInt 32 1 -%_Globals_ = OpTypeStruct %uint %int -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -)"; - - const std::string before = - R"(%main = OpFunction %void None %11 -%25 = OpLabel -%26 = OpLoad %v2float %In2 -%27 = OpLoad %float %In0 -%28 = OpLoad %float %In1 -%29 = OpFAdd %float %27 %28 -%35 = OpCompositeInsert %v2float %29 %26 0 -%37 = OpCompositeInsert %v2float %float_0 %35 0 -%33 = OpVectorShuffle %v4float %37 %37 0 1 0 1 -OpStore %OutColor %33 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%23 = OpLabel -%24 = OpLoad %v2float %In2 -%29 = OpCompositeInsert %v2float %float_0 %24 0 -%30 = OpVectorShuffle %v4float %29 %29 0 1 0 1 -OpStore %OutColor %30 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -TEST_F(DeadInsertElimTest, DeadInsertInChainWithPhi) { - // Dead insert eliminated with phi in insertion chain. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in vec4 In0; - // layout (location=1) in float In1; - // layout (location=2) in float In2; - // layout (location=0) out vec4 OutColor; - // - // layout(std140, binding = 0 ) uniform _Globals_ - // { - // bool g_b; - // }; - // - // void main() - // { - // vec4 v = In0; - // v.z = In1 + In2; - // if (g_b) v.w = 1.0; - // OutColor = vec4(v.x,v.y,0.0,v.w); - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%_Globals_ = OpTypeStruct %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%_Globals_ = OpTypeStruct %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string before = - R"(%main = OpFunction %void None %11 -%31 = OpLabel -%32 = OpLoad %v4float %In0 -%33 = OpLoad %float %In1 -%34 = OpLoad %float %In2 -%35 = OpFAdd %float %33 %34 -%51 = OpCompositeInsert %v4float %35 %32 2 -%37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%38 = OpLoad %uint %37 -%39 = OpINotEqual %bool %38 %uint_0 -OpSelectionMerge %40 None -OpBranchConditional %39 %41 %40 -%41 = OpLabel -%53 = OpCompositeInsert %v4float %float_1 %51 3 -OpBranch %40 -%40 = OpLabel -%60 = OpPhi %v4float %51 %31 %53 %41 -%55 = OpCompositeExtract %float %60 0 -%57 = OpCompositeExtract %float %60 1 -%59 = OpCompositeExtract %float %60 3 -%49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59 -OpStore %OutColor %49 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%27 = OpLabel -%28 = OpLoad %v4float %In0 -%33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%34 = OpLoad %uint %33 -%35 = OpINotEqual %bool %34 %uint_0 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %36 -%37 = OpLabel -%38 = OpCompositeInsert %v4float %float_1 %28 3 -OpBranch %36 -%36 = OpLabel -%39 = OpPhi %v4float %28 %27 %38 %37 -%40 = OpCompositeExtract %float %39 0 -%41 = OpCompositeExtract %float %39 1 -%42 = OpCompositeExtract %float %39 3 -%43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42 -OpStore %OutColor %43 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -TEST_F(DeadInsertElimTest, DeadInsertTwoPasses) { - // Dead insert which requires two passes to eliminate - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in vec4 In0; - // layout (location=1) in float In1; - // layout (location=2) in float In2; - // layout (location=0) out vec4 OutColor; - // - // layout(std140, binding = 0 ) uniform _Globals_ - // { - // bool g_b; - // bool g_b2; - // }; - // - // void main() - // { - // vec4 v1, v2; - // v1 = In0; - // v1.y = In1 + In2; // dead, second pass - // if (g_b) v1.x = 1.0; - // v2.x = v1.x; - // v2.y = v1.y; // dead, first pass - // if (g_b2) v2.x = 0.0; - // OutColor = vec4(v2.x,v2.x,0.0,1.0); - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_b2" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_Globals_ = OpTypeStruct %uint %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%27 = OpUndef %v4float -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_b2" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_Globals_ = OpTypeStruct %uint %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%27 = OpUndef %v4float -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%28 = OpLabel -%29 = OpLoad %v4float %In0 -%30 = OpLoad %float %In1 -%31 = OpLoad %float %In2 -%32 = OpFAdd %float %30 %31 -%33 = OpCompositeInsert %v4float %32 %29 1 -%34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%35 = OpLoad %uint %34 -%36 = OpINotEqual %bool %35 %uint_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %37 -%38 = OpLabel -%39 = OpCompositeInsert %v4float %float_1 %33 0 -OpBranch %37 -%37 = OpLabel -%40 = OpPhi %v4float %33 %28 %39 %38 -%41 = OpCompositeExtract %float %40 0 -%42 = OpCompositeInsert %v4float %41 %27 0 -%43 = OpCompositeExtract %float %40 1 -%44 = OpCompositeInsert %v4float %43 %42 1 -%45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1 -%46 = OpLoad %uint %45 -%47 = OpINotEqual %bool %46 %uint_0 -OpSelectionMerge %48 None -OpBranchConditional %47 %49 %48 -%49 = OpLabel -%50 = OpCompositeInsert %v4float %float_0 %44 0 -OpBranch %48 -%48 = OpLabel -%51 = OpPhi %v4float %44 %37 %50 %49 -%52 = OpCompositeExtract %float %51 0 -%53 = OpCompositeExtract %float %51 0 -%54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1 -OpStore %OutColor %54 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%28 = OpLabel -%29 = OpLoad %v4float %In0 -%34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%35 = OpLoad %uint %34 -%36 = OpINotEqual %bool %35 %uint_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %37 -%38 = OpLabel -%39 = OpCompositeInsert %v4float %float_1 %29 0 -OpBranch %37 -%37 = OpLabel -%40 = OpPhi %v4float %29 %28 %39 %38 -%41 = OpCompositeExtract %float %40 0 -%42 = OpCompositeInsert %v4float %41 %27 0 -%45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1 -%46 = OpLoad %uint %45 -%47 = OpINotEqual %bool %46 %uint_0 -OpSelectionMerge %48 None -OpBranchConditional %47 %49 %48 -%49 = OpLabel -%50 = OpCompositeInsert %v4float %float_0 %42 0 -OpBranch %48 -%48 = OpLabel -%51 = OpPhi %v4float %42 %37 %50 %49 -%52 = OpCompositeExtract %float %51 0 -%53 = OpCompositeExtract %float %51 0 -%54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1 -OpStore %OutColor %54 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dead_variable_elim_test.cpp b/3rdparty/spirv-tools/test/opt/dead_variable_elim_test.cpp deleted file mode 100644 index a55ee62a5..000000000 --- a/3rdparty/spirv-tools/test/opt/dead_variable_elim_test.cpp +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (c) 2017 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DeadVariableElimTest = PassTest<::testing::Test>; - -// %dead is unused. Make sure we remove it along with its name. -TEST_F(DeadVariableElimTest, RemoveUnreferenced) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %dead "dead" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%dead = OpVariable %_ptr_Private_float Private -%main = OpFunction %void None %5 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%main = OpFunction %void None %5 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -// Since %dead is exported, make sure we keep it. It could be referenced -// somewhere else. -TEST_F(DeadVariableElimTest, KeepExported) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %dead "dead" -OpDecorate %dead LinkageAttributes "dead" Export -%void = OpTypeVoid -%5 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%dead = OpVariable %_ptr_Private_float Private -%main = OpFunction %void None %5 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, before, true, true); -} - -// Delete %dead because it is unreferenced. Then %initializer becomes -// unreferenced, so remove it as well. -TEST_F(DeadVariableElimTest, RemoveUnreferencedWithInit1) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %dead "dead" -OpName %initializer "initializer" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%initializer = OpVariable %_ptr_Private_float Private -%dead = OpVariable %_ptr_Private_float Private %initializer -%main = OpFunction %void None %6 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%main = OpFunction %void None %6 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -// Delete %dead because it is unreferenced. In this case, the initialized has -// another reference, and should not be removed. -TEST_F(DeadVariableElimTest, RemoveUnreferencedWithInit2) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %dead "dead" -OpName %initializer "initializer" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%initializer = OpVariable %_ptr_Private_float Private -%dead = OpVariable %_ptr_Private_float Private %initializer -%main = OpFunction %void None %6 -%9 = OpLabel -%10 = OpLoad %float %initializer -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %initializer "initializer" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%initializer = OpVariable %_ptr_Private_float Private -%main = OpFunction %void None %6 -%9 = OpLabel -%10 = OpLoad %float %initializer -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -// Keep %live because it is used, and its initializer. -TEST_F(DeadVariableElimTest, KeepReferenced) { - const std::string before = - R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 150 -OpName %main "main" -OpName %live "live" -OpName %initializer "initializer" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float -%initializer = OpConstant %float 0 -%live = OpVariable %_ptr_Private_float Private %initializer -%main = OpFunction %void None %6 -%9 = OpLabel -%10 = OpLoad %float %live -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, before, true, true); -} - -// This test that the decoration associated with a variable are removed when the -// variable is removed. -TEST_F(DeadVariableElimTest, RemoveVariableAndDecorations) { - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 450 -OpName %main "main" -OpName %B "B" -OpMemberName %B 0 "a" -OpName %Bdat "Bdat" -OpMemberDecorate %B 0 Offset 0 -OpDecorate %B BufferBlock -OpDecorate %Bdat DescriptorSet 0 -OpDecorate %Bdat Binding 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%B = OpTypeStruct %uint -%_ptr_Uniform_B = OpTypePointer Uniform %B -%Bdat = OpVariable %_ptr_Uniform_B Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%main = OpFunction %void None %6 -%13 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 450 -OpName %main "main" -OpName %B "B" -OpMemberName %B 0 "a" -OpMemberDecorate %B 0 Offset 0 -OpDecorate %B BufferBlock -%void = OpTypeVoid -%6 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%B = OpTypeStruct %uint -%_ptr_Uniform_B = OpTypePointer Uniform %B -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%main = OpFunction %void None %6 -%13 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, true, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/decompose_initialized_variables_test.cpp b/3rdparty/spirv-tools/test/opt/decompose_initialized_variables_test.cpp deleted file mode 100644 index 06ba59a58..000000000 --- a/3rdparty/spirv-tools/test/opt/decompose_initialized_variables_test.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DecomposeInitializedVariablesTest = PassTest<::testing::Test>; - -std::string single_entry_header = R"(OpCapability Shader -OpCapability VulkanMemoryModel -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical Vulkan -OpEntryPoint Vertex %1 "shader" -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%4 = OpConstantNull %uint -%void = OpTypeVoid -%6 = OpTypeFunction %void -)"; - -std::string GetFunctionTest(std::string body) { - auto result = single_entry_header; - result += "%_ptr_Function_uint = OpTypePointer Function %uint\n"; - result += "%1 = OpFunction %void None %6\n"; - result += "%8 = OpLabel\n"; - result += body + "\n"; - result += "OpReturn\n"; - result += "OpFunctionEnd\n"; - return result; -} - -TEST_F(DecomposeInitializedVariablesTest, FunctionChanged) { - std::string input = "%9 = OpVariable %_ptr_Function_uint Function %uint_1"; - std::string expected = R"(%9 = OpVariable %_ptr_Function_uint Function -OpStore %9 %uint_1)"; - - SinglePassRunAndCheck( - GetFunctionTest(input), GetFunctionTest(expected), - /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, FunctionUnchanged) { - std::string input = "%9 = OpVariable %_ptr_Function_uint Function"; - - SinglePassRunAndCheck( - GetFunctionTest(input), GetFunctionTest(input), /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, FunctionMultipleVariables) { - std::string input = R"(%9 = OpVariable %_ptr_Function_uint Function %uint_1 -%10 = OpVariable %_ptr_Function_uint Function %4)"; - std::string expected = R"(%9 = OpVariable %_ptr_Function_uint Function -%10 = OpVariable %_ptr_Function_uint Function -OpStore %9 %uint_1 -OpStore %10 %4)"; - - SinglePassRunAndCheck( - GetFunctionTest(input), GetFunctionTest(expected), - /* skip_nop = */ false); -} - -std::string GetGlobalTest(std::string storage_class, bool initialized, - bool decomposed) { - auto result = single_entry_header; - - result += "%_ptr_" + storage_class + "_uint = OpTypePointer " + - storage_class + " %uint\n"; - if (initialized) { - result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " + - storage_class + " %4\n"; - } else { - result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " + - storage_class + "\n"; - } - result += R"(%1 = OpFunction %void None %9 -%9 = OpLabel -)"; - if (decomposed) result += "OpStore %8 %4\n"; - result += R"(OpReturn -OpFunctionEnd -)"; - return result; -} - -TEST_F(DecomposeInitializedVariablesTest, PrivateChanged) { - std::string input = GetGlobalTest("Private", true, false); - std::string expected = GetGlobalTest("Private", false, true); - SinglePassRunAndCheck( - input, expected, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, PrivateUnchanged) { - std::string input = GetGlobalTest("Private", false, false); - SinglePassRunAndCheck( - input, input, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, OutputChanged) { - std::string input = GetGlobalTest("Output", true, false); - std::string expected = GetGlobalTest("Output", false, true); - SinglePassRunAndCheck( - input, expected, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, OutputUnchanged) { - std::string input = GetGlobalTest("Output", false, false); - SinglePassRunAndCheck( - input, input, /* skip_nop = */ false); -} - -std::string multiple_entry_header = R"(OpCapability Shader -OpCapability VulkanMemoryModel -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical Vulkan -OpEntryPoint Vertex %1 "vertex" -OpEntryPoint Fragment %2 "fragment" -%uint = OpTypeInt 32 0 -%4 = OpConstantNull %uint -%void = OpTypeVoid -%6 = OpTypeFunction %void -)"; - -std::string GetGlobalMultipleEntryTest(std::string storage_class, - bool initialized, bool decomposed) { - auto result = multiple_entry_header; - result += "%_ptr_" + storage_class + "_uint = OpTypePointer " + - storage_class + " %uint\n"; - if (initialized) { - result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " + - storage_class + " %4\n"; - } else { - result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " + - storage_class + "\n"; - } - result += R"(%1 = OpFunction %void None %9 -%9 = OpLabel -)"; - if (decomposed) result += "OpStore %8 %4\n"; - result += R"(OpReturn -OpFunctionEnd -%2 = OpFunction %void None %10 -%10 = OpLabel -)"; - if (decomposed) result += "OpStore %8 %4\n"; - result += R"(OpReturn -OpFunctionEnd -)"; - - return result; -} - -TEST_F(DecomposeInitializedVariablesTest, PrivateMultipleEntryChanged) { - std::string input = GetGlobalMultipleEntryTest("Private", true, false); - std::string expected = GetGlobalMultipleEntryTest("Private", false, true); - SinglePassRunAndCheck( - input, expected, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, PrivateMultipleEntryUnchanged) { - std::string input = GetGlobalMultipleEntryTest("Private", false, false); - SinglePassRunAndCheck( - input, input, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, OutputMultipleEntryChanged) { - std::string input = GetGlobalMultipleEntryTest("Output", true, false); - std::string expected = GetGlobalMultipleEntryTest("Output", false, true); - SinglePassRunAndCheck( - input, expected, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, OutputMultipleEntryUnchanged) { - std::string input = GetGlobalMultipleEntryTest("Output", false, false); - SinglePassRunAndCheck( - input, input, /* skip_nop = */ false); -} - -std::string GetGlobalWithNonEntryPointTest(std::string storage_class, - bool initialized, bool decomposed) { - auto result = single_entry_header; - result += "%_ptr_" + storage_class + "_uint = OpTypePointer " + - storage_class + " %uint\n"; - if (initialized) { - result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " + - storage_class + " %4\n"; - } else { - result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " + - storage_class + "\n"; - } - result += R"(%1 = OpFunction %void None %9 -%9 = OpLabel -)"; - if (decomposed) result += "OpStore %8 %4\n"; - result += R"(OpReturn -OpFunctionEnd -%10 = OpFunction %void None %11 -%11 = OpLabel -OpReturn -OpFunctionEnd -)"; - - return result; -} - -TEST_F(DecomposeInitializedVariablesTest, PrivateWithNonEntryPointChanged) { - std::string input = GetGlobalWithNonEntryPointTest("Private", true, false); - std::string expected = GetGlobalWithNonEntryPointTest("Private", false, true); - SinglePassRunAndCheck( - input, expected, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, PrivateWithNonEntryPointUnchanged) { - std::string input = GetGlobalWithNonEntryPointTest("Private", false, false); - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - input, input, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, OutputWithNonEntryPointChanged) { - std::string input = GetGlobalWithNonEntryPointTest("Output", true, false); - std::string expected = GetGlobalWithNonEntryPointTest("Output", false, true); - SinglePassRunAndCheck( - input, expected, /* skip_nop = */ false); -} - -TEST_F(DecomposeInitializedVariablesTest, OutputWithNonEntryPointUnchanged) { - std::string input = GetGlobalWithNonEntryPointTest("Output", false, false); - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - input, input, /* skip_nop = */ false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/decoration_manager_test.cpp b/3rdparty/spirv-tools/test/opt/decoration_manager_test.cpp deleted file mode 100644 index fcfbff060..000000000 --- a/3rdparty/spirv-tools/test/opt/decoration_manager_test.cpp +++ /dev/null @@ -1,1510 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/decoration_manager.h" -#include "source/opt/ir_context.h" -#include "source/spirv_constant.h" -#include "source/util/string_utils.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace opt { -namespace analysis { -namespace { - -using utils::MakeVector; - -class DecorationManagerTest : public ::testing::Test { - public: - DecorationManagerTest() - : tools_(SPV_ENV_UNIVERSAL_1_2), - context_(), - consumer_([this](spv_message_level_t level, const char*, - const spv_position_t& position, const char* message) { - if (!error_message_.empty()) error_message_ += "\n"; - switch (level) { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - error_message_ += "ERROR"; - break; - case SPV_MSG_WARNING: - error_message_ += "WARNING"; - break; - case SPV_MSG_INFO: - error_message_ += "INFO"; - break; - case SPV_MSG_DEBUG: - error_message_ += "DEBUG"; - break; - } - error_message_ += - ": " + std::to_string(position.index) + ": " + message; - }), - disassemble_options_(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER), - error_message_() { - tools_.SetMessageConsumer(consumer_); - } - - void TearDown() override { error_message_.clear(); } - - DecorationManager* GetDecorationManager(const std::string& text) { - context_ = BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer_, text); - if (context_.get()) - return context_->get_decoration_mgr(); - else - return nullptr; - } - - // Disassembles |binary| and outputs the result in |text|. If |text| is a - // null pointer, SPV_ERROR_INVALID_POINTER is returned. - spv_result_t Disassemble(const std::vector& binary, - std::string* text) { - if (!text) return SPV_ERROR_INVALID_POINTER; - return tools_.Disassemble(binary, text, disassemble_options_) - ? SPV_SUCCESS - : SPV_ERROR_INVALID_BINARY; - } - - // Returns the accumulated error messages for the test. - std::string GetErrorMessage() const { return error_message_; } - - std::string ToText(const std::vector& inst) { - std::vector binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u}; - for (const Instruction* i : inst) - i->ToBinaryWithoutAttachedDebugInsts(&binary); - std::string text; - Disassemble(binary, &text); - return text; - } - - std::string ModuleToText() { - std::vector binary; - context_->module()->ToBinary(&binary, false); - std::string text; - Disassemble(binary, &text); - return text; - } - - spvtools::MessageConsumer GetConsumer() { return consumer_; } - - private: - // An instance for calling SPIRV-Tools functionalities. - spvtools::SpirvTools tools_; - std::unique_ptr context_; - spvtools::MessageConsumer consumer_; - uint32_t disassemble_options_; - std::string error_message_; -}; - -TEST_F(DecorationManagerTest, - ComparingDecorationsWithDiffOpcodesDecorateDecorateId) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // This parameter can be interprated both as { SpvDecorationConstant } - // and also as a list of IDs: { 22 } - const std::vector param{SpvDecorationConstant}; - // OpDecorate %1 Constant - Instruction inst1( - &ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, param}}); - // OpDecorateId %1 %22 ; 'Constant' is decoration number 22 - Instruction inst2( - &ir_context, SpvOpDecorateId, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, param}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, - ComparingDecorationsWithDiffOpcodesDecorateDecorateString) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // This parameter can be interprated both as { SpvDecorationConstant } - // and also as a null-terminated string with a single character with value 22. - const std::vector param{SpvDecorationConstant}; - // OpDecorate %1 Constant - Instruction inst1( - &ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, param}}); - // OpDecorateStringGOOGLE %1 !22 - Instruction inst2( - &ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_LITERAL_STRING, param}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateParam) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpDecorate %1 Constant - Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - // OpDecorate %1 Restrict - Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationRestrict}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateIdParam) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpDecorate %1 Constant - Instruction inst1( - &ir_context, SpvOpDecorateId, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, {555}}}); - // OpDecorate %1 Restrict - Instruction inst2( - &ir_context, SpvOpDecorateId, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, {666}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateStringParam) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpDecorate %1 Constant - Instruction inst1(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("Hello!")}}); - // OpDecorate %1 Restrict - Instruction inst2(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("Hellx")}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, ComparingSameDecorationsOnDiffTargetAllowed) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpDecorate %1 Constant - Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - // OpDecorate %2 Constant - Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {2u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, ComparingSameDecorationIdsOnDiffTargetAllowed) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - Instruction inst1( - &ir_context, SpvOpDecorateId, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, {44}}}); - Instruction inst2( - &ir_context, SpvOpDecorateId, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {2u}}, {SPV_OPERAND_TYPE_DECORATION, {44}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, - ComparingSameDecorationStringsOnDiffTargetAllowed) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - Instruction inst1(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("hello")}}); - Instruction inst2(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {2u}}, - {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("hello")}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, ComparingSameDecorationsOnDiffTargetDisallowed) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpDecorate %1 Constant - Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - // OpDecorate %2 Constant - Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {2u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, false)); -} - -TEST_F(DecorationManagerTest, ComparingMemberDecorationsOnSameTypeDiffMember) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpMemberDecorate %1 0 Constant - Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - // OpMemberDecorate %1 1 Constant - Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, - ComparingSameMemberDecorationsOnDiffTargetAllowed) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpMemberDecorate %1 0 Constant - Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - // OpMemberDecorate %2 0 Constant - Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {2u}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true)); -} - -TEST_F(DecorationManagerTest, - ComparingSameMemberDecorationsOnDiffTargetDisallowed) { - IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer()); - // OpMemberDecorate %1 0 Constant - Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {1u}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - // OpMemberDecorate %2 0 Constant - Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u, - {{SPV_OPERAND_TYPE_ID, {2u}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}}, - {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}}); - DecorationManager* decoManager = ir_context.get_decoration_mgr(); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, false)); -} - -TEST_F(DecorationManagerTest, RemoveDecorationFromVariable) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 %3 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Uniform -%3 = OpVariable %4 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - decoManager->RemoveDecorationsFrom(1u); - auto decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - decorations = decoManager->GetDecorationsFor(3u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - const std::string expected_decorations = R"(OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %3 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Uniform -%3 = OpVariable %4 Uniform -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, RemoveDecorationStringFromVariable) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello world" -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 %3 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Uniform -%3 = OpVariable %4 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - decoManager->RemoveDecorationsFrom(1u); - auto decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - decorations = decoManager->GetDecorationsFor(3u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - const std::string expected_decorations = R"(OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %3 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Uniform -%3 = OpVariable %4 Uniform -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, RemoveDecorationFromDecorationGroup) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 %3 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Uniform -%3 = OpVariable %4 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - decoManager->RemoveDecorationsFrom(2u); - auto decorations = decoManager->GetDecorationsFor(2u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - const std::string expected_decorations = R"(OpDecorate %1 Constant -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - decorations = decoManager->GetDecorationsFor(3u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_THAT(ToText(decorations), ""); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -%2 = OpDecorationGroup -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Uniform -%3 = OpVariable %4 Uniform -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, - RemoveDecorationFromDecorationGroupKeepDeadDecorations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 -%3 = OpTypeInt 32 0 -%1 = OpVariable %3 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - decoManager->RemoveDecorationsFrom(1u); - auto decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - decorations = decoManager->GetDecorationsFor(2u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - const std::string expected_decorations = R"(OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %2 Restrict -%2 = OpDecorationGroup -%3 = OpTypeInt 32 0 -%1 = OpVariable %3 Uniform -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, RemoveAllDecorationsAppliedByGroup) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 -OpDecorate %3 BuiltIn VertexId -%3 = OpDecorationGroup -OpGroupDecorate %3 %1 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Input -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - decoManager->RemoveDecorationsFrom(1u, [](const Instruction& inst) { - return inst.opcode() == SpvOpDecorate && - inst.GetSingleWordInOperand(0u) == 3u; - }); - auto decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - std::string expected_decorations = R"(OpDecorate %1 Constant -OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - decorations = decoManager->GetDecorationsFor(2u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - expected_decorations = R"(OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 -OpDecorate %3 BuiltIn VertexId -%3 = OpDecorationGroup -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Input -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, RemoveSomeDecorationsAppliedByGroup) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 -OpDecorate %3 BuiltIn VertexId -OpDecorate %3 Invariant -%3 = OpDecorationGroup -OpGroupDecorate %3 %1 -%uint = OpTypeInt 32 0 -%1 = OpVariable %uint Input -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - decoManager->RemoveDecorationsFrom(1u, [](const Instruction& inst) { - return inst.opcode() == SpvOpDecorate && - inst.GetSingleWordInOperand(0u) == 3u && - inst.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn; - }); - auto decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - std::string expected_decorations = R"(OpDecorate %1 Constant -OpDecorate %1 Invariant -OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - decorations = decoManager->GetDecorationsFor(2u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - expected_decorations = R"(OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 -OpDecorate %3 BuiltIn VertexId -OpDecorate %3 Invariant -%3 = OpDecorationGroup -OpDecorate %1 Invariant -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Input -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, RemoveDecorationDecorate) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %1 Restrict -%2 = OpTypeInt 32 0 -%1 = OpVariable %2 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - auto decorations = decoManager->GetDecorationsFor(1u, false); - decoManager->RemoveDecoration(decorations.front()); - decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - const std::string expected_decorations = R"(OpDecorate %1 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); -} - -TEST_F(DecorationManagerTest, RemoveDecorationStringDecorate) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "foobar" -OpDecorate %1 Restrict -%2 = OpTypeInt 32 0 -%1 = OpVariable %2 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - auto decorations = decoManager->GetDecorationsFor(1u, false); - decoManager->RemoveDecoration(decorations.front()); - decorations = decoManager->GetDecorationsFor(1u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - const std::string expected_decorations = R"(OpDecorate %1 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); -} - -TEST_F(DecorationManagerTest, CloneDecorations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 -OpDecorate %3 BuiltIn VertexId -OpDecorate %3 Invariant -%3 = OpDecorationGroup -OpGroupDecorate %3 %1 -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Input -%5 = OpVariable %4 Input -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - - // Check cloning OpDecorate including group decorations. - auto decorations = decoManager->GetDecorationsFor(5u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - - decoManager->CloneDecorations(1u, 5u); - decorations = decoManager->GetDecorationsFor(5u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - std::string expected_decorations = R"(OpDecorate %5 Constant -OpDecorate %2 Restrict -OpDecorate %3 BuiltIn VertexId -OpDecorate %3 Invariant -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - // Check that bookkeeping for ID 2 remains the same. - decorations = decoManager->GetDecorationsFor(2u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - expected_decorations = R"(OpDecorate %2 Restrict -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %2 %1 %5 -OpDecorate %3 BuiltIn VertexId -OpDecorate %3 Invariant -%3 = OpDecorationGroup -OpGroupDecorate %3 %1 %5 -OpDecorate %5 Constant -%4 = OpTypeInt 32 0 -%1 = OpVariable %4 Input -%5 = OpVariable %4 Input -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, CloneDecorationsStringAndId) { - const std::string spirv = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "blah" -OpDecorateId %1 HlslCounterBufferGOOGLE %2 -OpDecorate %1 Aliased -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Uniform %3 -%1 = OpVariable %4 Uniform -%2 = OpVariable %4 Uniform -%5 = OpVariable %4 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - - // Check cloning OpDecorate including group decorations. - auto decorations = decoManager->GetDecorationsFor(5u, false); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - - decoManager->CloneDecorations(1u, 5u); - decorations = decoManager->GetDecorationsFor(5u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - std::string expected_decorations = - R"(OpDecorateString %5 UserSemantic "blah" -OpDecorateId %5 CounterBuffer %2 -OpDecorate %5 Aliased -)"; - EXPECT_THAT(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateString %1 UserSemantic "blah" -OpDecorateId %1 CounterBuffer %2 -OpDecorate %1 Aliased -OpDecorateString %5 UserSemantic "blah" -OpDecorateId %5 CounterBuffer %2 -OpDecorate %5 Aliased -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Uniform %3 -%1 = OpVariable %4 Uniform -%2 = OpVariable %4 Uniform -%5 = OpVariable %4 Uniform -)"; - EXPECT_THAT(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, CloneSomeDecorations) { - const std::string spirv = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorate %1 RelaxedPrecision -OpDecorate %1 Restrict -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Function %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -%1 = OpVariable %3 Function -%8 = OpUndef %2 -OpReturn -OpFunctionEnd -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_EQ(GetErrorMessage(), ""); - - // Check cloning OpDecorate including group decorations. - auto decorations = decoManager->GetDecorationsFor(8u, false); - EXPECT_EQ(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - - decoManager->CloneDecorations(1u, 8u, {SpvDecorationRelaxedPrecision}); - decorations = decoManager->GetDecorationsFor(8u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - std::string expected_decorations = - R"(OpDecorate %8 RelaxedPrecision -)"; - EXPECT_EQ(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorate %1 RelaxedPrecision -OpDecorate %1 Restrict -OpDecorate %8 RelaxedPrecision -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Function %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -%1 = OpVariable %3 Function -%8 = OpUndef %2 -OpReturn -OpFunctionEnd -)"; - EXPECT_EQ(ModuleToText(), expected_binary); -} - -// Test cloning decoration for an id that is decorated via a group decoration. -TEST_F(DecorationManagerTest, CloneSomeGroupDecorations) { - const std::string spirv = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 RelaxedPrecision -OpDecorate %1 Restrict -%1 = OpDecorationGroup -OpGroupDecorate %1 %2 -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Function %3 -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpFunction %5 None %6 -%8 = OpLabel -%2 = OpVariable %4 Function -%9 = OpUndef %3 -OpReturn -OpFunctionEnd -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_EQ(GetErrorMessage(), ""); - - // Check cloning OpDecorate including group decorations. - auto decorations = decoManager->GetDecorationsFor(9u, false); - EXPECT_EQ(GetErrorMessage(), ""); - EXPECT_TRUE(decorations.empty()); - - decoManager->CloneDecorations(2u, 9u, {SpvDecorationRelaxedPrecision}); - decorations = decoManager->GetDecorationsFor(9u, false); - EXPECT_THAT(GetErrorMessage(), ""); - - std::string expected_decorations = - R"(OpDecorate %9 RelaxedPrecision -)"; - EXPECT_EQ(ToText(decorations), expected_decorations); - - const std::string expected_binary = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 RelaxedPrecision -OpDecorate %1 Restrict -%1 = OpDecorationGroup -OpGroupDecorate %1 %2 -OpDecorate %9 RelaxedPrecision -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Function %3 -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpFunction %5 None %6 -%8 = OpLabel -%2 = OpVariable %4 Function -%9 = OpUndef %3 -OpReturn -OpFunctionEnd -)"; - EXPECT_EQ(ModuleToText(), expected_binary); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsWithoutGroupsTrue) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Restrict -OpDecorate %1 Constant -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsWithoutGroupsFalse) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Restrict -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsIdWithoutGroupsTrue) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %nine -OpDecorateId %3 MaxByteOffsetId %nine -OpDecorateId %3 AlignmentId %nine -OpDecorateId %1 MaxByteOffsetId %nine -%u32 = OpTypeInt 32 0 -%nine = OpConstant %u32 9 -%1 = OpVariable %u32 Uniform -%3 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 3u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsIdWithoutGroupsFalse) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %nine -OpDecorateId %2 MaxByteOffsetId %nine -OpDecorateId %2 AlignmentId %nine -%u32 = OpTypeInt 32 0 -%nine = OpConstant %u32 9 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsStringWithoutGroupsTrue) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "world" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "world" -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsStringWithoutGroupsFalse) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "world" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsWithGroupsTrue) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %1 Constant -OpDecorate %3 Restrict -%3 = OpDecorationGroup -OpGroupDecorate %3 %2 -OpDecorate %4 Invariant -%4 = OpDecorationGroup -OpGroupDecorate %4 %1 %2 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsWithGroupsFalse) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %1 Constant -OpDecorate %4 Invariant -%4 = OpDecorationGroup -OpGroupDecorate %4 %1 %2 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsDuplicateDecorations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Constant -OpDecorate %2 Constant -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsDifferentVariations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Location 0 -OpDecorate %2 Location 1 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, - HaveTheSameDecorationsDuplicateMemberDecorations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %1 0 Location 0 -OpMemberDecorate %2 0 Location 0 -OpMemberDecorate %2 0 Location 0 -%u32 = OpTypeInt 32 0 -%1 = OpTypeStruct %u32 %u32 -%2 = OpTypeStruct %u32 %u32 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, - HaveTheSameDecorationsDifferentMemberSameDecoration) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %1 0 Location 0 -OpMemberDecorate %2 1 Location 0 -%u32 = OpTypeInt 32 0 -%1 = OpTypeStruct %u32 %u32 -%2 = OpTypeStruct %u32 %u32 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsDifferentMemberVariations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %1 0 Location 0 -OpMemberDecorate %2 0 Location 1 -%u32 = OpTypeInt 32 0 -%1 = OpTypeStruct %u32 %u32 -%2 = OpTypeStruct %u32 %u32 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsDuplicateIdDecorations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %2 -OpDecorateId %3 AlignmentId %2 -OpDecorateId %3 AlignmentId %2 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%3 = OpVariable %u32 Uniform -%2 = OpSpecConstant %u32 0 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 3u)); -} - -TEST_F(DecorationManagerTest, - HaveTheSameDecorationsDuplicateStringDecorations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsDifferentIdVariations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %2 -OpDecorateId %3 AlignmentId %4 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%3 = OpVariable %u32 Uniform -%2 = OpSpecConstant %u32 0 -%4 = OpSpecConstant %u32 0 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsDifferentStringVariations) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "world" -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsLeftSymmetry) { - // Left being a subset of right is not enough. - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %1 Constant -OpDecorate %2 Constant -OpDecorate %2 Restrict -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationsRightSymmetry) { - // Right being a subset of left is not enough. - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Constant -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationIdsLeftSymmetry) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %nine -OpDecorateId %1 AlignmentId %nine -OpDecorateId %2 AlignmentId %nine -OpDecorateId %2 MaxByteOffsetId %nine -%u32 = OpTypeInt 32 0 -%nine = OpConstant %u32 9 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationIdsRightSymmetry) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %nine -OpDecorateId %1 MaxByteOffsetId %nine -OpDecorateId %2 AlignmentId %nine -OpDecorateId %2 AlignmentId %nine -%u32 = OpTypeInt 32 0 -%nine = OpConstant %u32 9 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationStringsLeftSymmetry) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "world" -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, HaveTheSameDecorationStringsRightSymmetry) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE "world" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "hello" -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveTheSameDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Restrict -OpDecorate %1 Constant -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Restrict -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate3) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Constant -OpDecorate %2 Restrict -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate4) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Restrict -OpDecorate %1 Constant -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate5) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Restrict -OpDecorate %2 Constant -OpDecorate %2 Restrict -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate6) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Constant -OpDecorate %2 Restrict -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorate7) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %2 Constant -OpDecorate %2 Restrict -OpDecorate %1 Invariant -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%2 = OpVariable %u32 Uniform -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(2u, 1u)); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(1u, 2u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpMemberDecorate1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %1 0 Offset 4 -OpMemberDecorate %2 0 Offset 0 -OpMemberDecorate %2 0 Offset 4 -%u32 = OpTypeInt 32 0 -%1 = OpTypeStruct %u32 %u32 %u32 -%2 = OpTypeStruct %u32 %u32 %u32 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(1u, 2u)); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpMemberDecorate2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %2 0 Offset 0 -OpMemberDecorate %2 0 Offset 4 -%u32 = OpTypeInt 32 0 -%1 = OpTypeStruct %u32 %u32 %u32 -%2 = OpTypeStruct %u32 %u32 %u32 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(1u, 2u)); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorateId1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %2 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%3 = OpVariable %u32 Uniform -%2 = OpSpecConstant %u32 0 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(1u, 3u)); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(3u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorateId2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorateId %1 AlignmentId %2 -OpDecorateId %3 AlignmentId %4 -%u32 = OpTypeInt 32 0 -%1 = OpVariable %u32 Uniform -%3 = OpVariable %u32 Uniform -%2 = OpSpecConstant %u32 0 -%4 = OpSpecConstant %u32 1 -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(1u, 3u)); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(3u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorateString1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateString %1 HlslSemanticGOOGLE "hello" -OpDecorateString %2 HlslSemanticGOOGLE "world" -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(1u, 2u)); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} - -TEST_F(DecorationManagerTest, SubSetTestOpDecorateString2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpExtension "SPV_GOOGLE_decorate_string" -OpMemoryModel Logical GLSL450 -OpDecorateString %1 HlslSemanticGOOGLE "hello" -)"; - DecorationManager* decoManager = GetDecorationManager(spirv); - EXPECT_THAT(GetErrorMessage(), ""); - EXPECT_FALSE(decoManager->HaveSubsetOfDecorations(1u, 2u)); - EXPECT_TRUE(decoManager->HaveSubsetOfDecorations(2u, 1u)); -} -} // namespace -} // namespace analysis -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/def_use_test.cpp b/3rdparty/spirv-tools/test/opt/def_use_test.cpp deleted file mode 100644 index cfdad74a1..000000000 --- a/3rdparty/spirv-tools/test/opt/def_use_test.cpp +++ /dev/null @@ -1,1719 +0,0 @@ -// 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 - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/def_use_manager.h" -#include "source/opt/ir_context.h" -#include "source/opt/module.h" -#include "spirv-tools/libspirv.hpp" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace analysis { -namespace { - -using ::testing::Contains; -using ::testing::UnorderedElementsAre; -using ::testing::UnorderedElementsAreArray; - -// Returns the number of uses of |id|. -uint32_t NumUses(const std::unique_ptr& context, uint32_t id) { - uint32_t count = 0; - context->get_def_use_mgr()->ForEachUse( - id, [&count](Instruction*, uint32_t) { ++count; }); - return count; -} - -// Returns the opcode of each use of |id|. -// -// If |id| is used multiple times in a single instruction, that instruction's -// opcode will appear a corresponding number of times. -std::vector GetUseOpcodes(const std::unique_ptr& context, - uint32_t id) { - std::vector opcodes; - context->get_def_use_mgr()->ForEachUse( - id, [&opcodes](Instruction* user, uint32_t) { - opcodes.push_back(user->opcode()); - }); - return opcodes; -} - -// Disassembles the given |inst| and returns the disassembly. -std::string DisassembleInst(Instruction* inst) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); - - std::vector binary; - // We need this to generate the necessary header in the binary. - tools.Assemble("", &binary); - inst->ToBinaryWithoutAttachedDebugInsts(&binary); - - std::string text; - // We'll need to check the underlying id numbers. - // So turn off friendly names for ids. - tools.Disassemble(binary, &text, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - while (!text.empty() && text.back() == '\n') text.pop_back(); - return text; -} - -// A struct for holding expected id defs and uses. -struct InstDefUse { - using IdInstPair = std::pair; - using IdInstsPair = std::pair>; - - // Ids and their corresponding def instructions. - std::vector defs; - // Ids and their corresponding use instructions. - std::vector uses; -}; - -// Checks that the |actual_defs| and |actual_uses| are in accord with -// |expected_defs_uses|. -void CheckDef(const InstDefUse& expected_defs_uses, - const DefUseManager::IdToDefMap& actual_defs) { - // Check defs. - ASSERT_EQ(expected_defs_uses.defs.size(), actual_defs.size()); - for (uint32_t i = 0; i < expected_defs_uses.defs.size(); ++i) { - const auto id = expected_defs_uses.defs[i].first; - const auto expected_def = expected_defs_uses.defs[i].second; - ASSERT_EQ(1u, actual_defs.count(id)) << "expected to def id [" << id << "]"; - auto def = actual_defs.at(id); - if (def->opcode() != SpvOpConstant) { - // Constants don't disassemble properly without a full context. - EXPECT_EQ(expected_def, DisassembleInst(actual_defs.at(id))); - } - } -} - -using UserMap = std::unordered_map>; - -// Creates a mapping of all definitions to their users (except OpConstant). -// -// OpConstants are skipped because they cannot be disassembled in isolation. -UserMap BuildAllUsers(const DefUseManager* mgr, uint32_t idBound) { - UserMap userMap; - for (uint32_t id = 0; id != idBound; ++id) { - if (mgr->GetDef(id)) { - mgr->ForEachUser(id, [id, &userMap](Instruction* user) { - if (user->opcode() != SpvOpConstant) { - userMap[id].push_back(user); - } - }); - } - } - return userMap; -} - -// Constants don't disassemble properly without a full context, so skip them as -// checks. -void CheckUse(const InstDefUse& expected_defs_uses, const DefUseManager* mgr, - uint32_t idBound) { - UserMap actual_uses = BuildAllUsers(mgr, idBound); - // Check uses. - ASSERT_EQ(expected_defs_uses.uses.size(), actual_uses.size()); - for (uint32_t i = 0; i < expected_defs_uses.uses.size(); ++i) { - const auto id = expected_defs_uses.uses[i].first; - const auto& expected_uses = expected_defs_uses.uses[i].second; - - ASSERT_EQ(1u, actual_uses.count(id)) << "expected to use id [" << id << "]"; - const auto& uses = actual_uses.at(id); - - ASSERT_EQ(expected_uses.size(), uses.size()) - << "id [" << id << "] # uses: expected: " << expected_uses.size() - << " actual: " << uses.size(); - - std::vector actual_uses_disassembled; - for (const auto actual_use : uses) { - actual_uses_disassembled.emplace_back(DisassembleInst(actual_use)); - } - EXPECT_THAT(actual_uses_disassembled, - UnorderedElementsAreArray(expected_uses)); - } -} - -// The following test case mimics how LLVM handles induction variables. -// But, yeah, it's not very readable. However, we only care about the id -// defs and uses. So, no need to make sure this is valid OpPhi construct. -const char kOpPhiTestFunction[] = - " %1 = OpTypeVoid " - " %6 = OpTypeInt 32 0 " - "%10 = OpTypeFloat 32 " - "%16 = OpTypeBool " - " %3 = OpTypeFunction %1 " - " %8 = OpConstant %6 0 " - "%18 = OpConstant %6 1 " - "%12 = OpConstant %10 1.0 " - " %2 = OpFunction %1 None %3 " - " %4 = OpLabel " - " OpBranch %5 " - - " %5 = OpLabel " - " %7 = OpPhi %6 %8 %4 %9 %5 " - "%11 = OpPhi %10 %12 %4 %13 %5 " - " %9 = OpIAdd %6 %7 %8 " - "%13 = OpFAdd %10 %11 %12 " - "%17 = OpSLessThan %16 %7 %18 " - " OpLoopMerge %19 %5 None " - " OpBranchConditional %17 %5 %19 " - - "%19 = OpLabel " - " OpReturn " - " OpFunctionEnd"; - -struct ParseDefUseCase { - const char* text; - InstDefUse du; -}; - -using ParseDefUseTest = ::testing::TestWithParam; - -TEST_P(ParseDefUseTest, Case) { - const auto& tc = GetParam(); - - // Build module. - const std::vector text = {tc.text}; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, JoinAllInsts(text), - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - // Analyze def and use. - DefUseManager manager(context->module()); - - CheckDef(tc.du, manager.id_to_defs()); - CheckUse(tc.du, &manager, context->module()->IdBound()); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TestCase, ParseDefUseTest, - ::testing::ValuesIn(std::vector{ - {"", {{}, {}}}, // no instruction - {"OpMemoryModel Logical GLSL450", {{}, {}}}, // no def and use - { // single def, no use - "%1 = OpString \"wow\"", - { - {{1, "%1 = OpString \"wow\""}}, // defs - {} // uses - } - }, - { // multiple def, no use - "%1 = OpString \"hello\" " - "%2 = OpString \"world\" " - "%3 = OpTypeVoid", - { - { // defs - {1, "%1 = OpString \"hello\""}, - {2, "%2 = OpString \"world\""}, - {3, "%3 = OpTypeVoid"}, - }, - {} // uses - } - }, - { // multiple def, multiple use - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 3 " - "%3 = OpTypeMatrix %2 3", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %1 3"}, - {3, "%3 = OpTypeMatrix %2 3"}, - }, - { // uses - {1, {"%2 = OpTypeVector %1 3"}}, - {2, {"%3 = OpTypeMatrix %2 3"}}, - } - } - }, - { // multiple use of the same id - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 2 " - "%3 = OpTypeVector %1 3 " - "%4 = OpTypeVector %1 4", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %1 2"}, - {3, "%3 = OpTypeVector %1 3"}, - {4, "%4 = OpTypeVector %1 4"}, - }, - { // uses - {1, - { - "%2 = OpTypeVector %1 2", - "%3 = OpTypeVector %1 3", - "%4 = OpTypeVector %1 4", - } - }, - } - } - }, - { // labels - "%1 = OpTypeVoid " - "%2 = OpTypeBool " - "%3 = OpTypeFunction %1 " - "%4 = OpConstantTrue %2 " - "%5 = OpFunction %1 None %3 " - - "%6 = OpLabel " - "OpBranchConditional %4 %7 %8 " - - "%7 = OpLabel " - "OpBranch %7 " - - "%8 = OpLabel " - "OpReturn " - - "OpFunctionEnd", - { - { // defs - {1, "%1 = OpTypeVoid"}, - {2, "%2 = OpTypeBool"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpConstantTrue %2"}, - {5, "%5 = OpFunction %1 None %3"}, - {6, "%6 = OpLabel"}, - {7, "%7 = OpLabel"}, - {8, "%8 = OpLabel"}, - }, - { // uses - {1, { - "%3 = OpTypeFunction %1", - "%5 = OpFunction %1 None %3", - } - }, - {2, {"%4 = OpConstantTrue %2"}}, - {3, {"%5 = OpFunction %1 None %3"}}, - {4, {"OpBranchConditional %4 %7 %8"}}, - {7, - { - "OpBranchConditional %4 %7 %8", - "OpBranch %7", - } - }, - {8, {"OpBranchConditional %4 %7 %8"}}, - } - } - }, - { // cross function - "%1 = OpTypeBool " - "%3 = OpTypeFunction %1 " - "%2 = OpFunction %1 None %3 " - - "%4 = OpLabel " - "%5 = OpVariable %1 Function " - "%6 = OpFunctionCall %1 %2 %5 " - "OpReturnValue %6 " - - "OpFunctionEnd", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpFunction %1 None %3"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpLabel"}, - {5, "%5 = OpVariable %1 Function"}, - {6, "%6 = OpFunctionCall %1 %2 %5"}, - }, - { // uses - {1, - { - "%2 = OpFunction %1 None %3", - "%3 = OpTypeFunction %1", - "%5 = OpVariable %1 Function", - "%6 = OpFunctionCall %1 %2 %5", - } - }, - {2, {"%6 = OpFunctionCall %1 %2 %5"}}, - {3, {"%2 = OpFunction %1 None %3"}}, - {5, {"%6 = OpFunctionCall %1 %2 %5"}}, - {6, {"OpReturnValue %6"}}, - } - } - }, - { // selection merge and loop merge - "%1 = OpTypeVoid " - "%3 = OpTypeFunction %1 " - "%10 = OpTypeBool " - "%8 = OpConstantTrue %10 " - "%2 = OpFunction %1 None %3 " - - "%4 = OpLabel " - "OpLoopMerge %5 %4 None " - "OpBranch %6 " - - "%5 = OpLabel " - "OpReturn " - - "%6 = OpLabel " - "OpSelectionMerge %7 None " - "OpBranchConditional %8 %9 %7 " - - "%7 = OpLabel " - "OpReturn " - - "%9 = OpLabel " - "OpReturn " - - "OpFunctionEnd", - { - { // defs - {1, "%1 = OpTypeVoid"}, - {2, "%2 = OpFunction %1 None %3"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpLabel"}, - {5, "%5 = OpLabel"}, - {6, "%6 = OpLabel"}, - {7, "%7 = OpLabel"}, - {8, "%8 = OpConstantTrue %10"}, - {9, "%9 = OpLabel"}, - {10, "%10 = OpTypeBool"}, - }, - { // uses - {1, - { - "%2 = OpFunction %1 None %3", - "%3 = OpTypeFunction %1", - } - }, - {3, {"%2 = OpFunction %1 None %3"}}, - {4, {"OpLoopMerge %5 %4 None"}}, - {5, {"OpLoopMerge %5 %4 None"}}, - {6, {"OpBranch %6"}}, - {7, - { - "OpSelectionMerge %7 None", - "OpBranchConditional %8 %9 %7", - } - }, - {8, {"OpBranchConditional %8 %9 %7"}}, - {9, {"OpBranchConditional %8 %9 %7"}}, - {10, {"%8 = OpConstantTrue %10"}}, - } - } - }, - { // Forward reference - "OpDecorate %1 Block " - "OpTypeForwardPointer %2 Input " - "%3 = OpTypeInt 32 0 " - "%1 = OpTypeStruct %3 " - "%2 = OpTypePointer Input %3", - { - { // defs - {1, "%1 = OpTypeStruct %3"}, - {2, "%2 = OpTypePointer Input %3"}, - {3, "%3 = OpTypeInt 32 0"}, - }, - { // uses - {1, {"OpDecorate %1 Block"}}, - {2, {"OpTypeForwardPointer %2 Input"}}, - {3, - { - "%1 = OpTypeStruct %3", - "%2 = OpTypePointer Input %3", - } - } - }, - }, - }, - { // OpPhi - kOpPhiTestFunction, - { - { // defs - {1, "%1 = OpTypeVoid"}, - {2, "%2 = OpFunction %1 None %3"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpLabel"}, - {5, "%5 = OpLabel"}, - {6, "%6 = OpTypeInt 32 0"}, - {7, "%7 = OpPhi %6 %8 %4 %9 %5"}, - {8, "%8 = OpConstant %6 0"}, - {9, "%9 = OpIAdd %6 %7 %8"}, - {10, "%10 = OpTypeFloat 32"}, - {11, "%11 = OpPhi %10 %12 %4 %13 %5"}, - {12, "%12 = OpConstant %10 1.0"}, - {13, "%13 = OpFAdd %10 %11 %12"}, - {16, "%16 = OpTypeBool"}, - {17, "%17 = OpSLessThan %16 %7 %18"}, - {18, "%18 = OpConstant %6 1"}, - {19, "%19 = OpLabel"}, - }, - { // uses - {1, - { - "%2 = OpFunction %1 None %3", - "%3 = OpTypeFunction %1", - } - }, - {3, {"%2 = OpFunction %1 None %3"}}, - {4, - { - "%7 = OpPhi %6 %8 %4 %9 %5", - "%11 = OpPhi %10 %12 %4 %13 %5", - } - }, - {5, - { - "OpBranch %5", - "%7 = OpPhi %6 %8 %4 %9 %5", - "%11 = OpPhi %10 %12 %4 %13 %5", - "OpLoopMerge %19 %5 None", - "OpBranchConditional %17 %5 %19", - } - }, - {6, - { - // Can't check constants properly - // "%8 = OpConstant %6 0", - // "%18 = OpConstant %6 1", - "%7 = OpPhi %6 %8 %4 %9 %5", - "%9 = OpIAdd %6 %7 %8", - } - }, - {7, - { - "%9 = OpIAdd %6 %7 %8", - "%17 = OpSLessThan %16 %7 %18", - } - }, - {8, - { - "%7 = OpPhi %6 %8 %4 %9 %5", - "%9 = OpIAdd %6 %7 %8", - } - }, - {9, {"%7 = OpPhi %6 %8 %4 %9 %5"}}, - {10, - { - // "%12 = OpConstant %10 1.0", - "%11 = OpPhi %10 %12 %4 %13 %5", - "%13 = OpFAdd %10 %11 %12", - } - }, - {11, {"%13 = OpFAdd %10 %11 %12"}}, - {12, - { - "%11 = OpPhi %10 %12 %4 %13 %5", - "%13 = OpFAdd %10 %11 %12", - } - }, - {13, {"%11 = OpPhi %10 %12 %4 %13 %5"}}, - {16, {"%17 = OpSLessThan %16 %7 %18"}}, - {17, {"OpBranchConditional %17 %5 %19"}}, - {18, {"%17 = OpSLessThan %16 %7 %18"}}, - {19, - { - "OpLoopMerge %19 %5 None", - "OpBranchConditional %17 %5 %19", - } - }, - }, - }, - }, - { // OpPhi defining and referencing the same id. - "%1 = OpTypeBool " - "%3 = OpTypeFunction %1 " - "%2 = OpConstantTrue %1 " - "%4 = OpFunction %1 None %3 " - "%6 = OpLabel " - " OpBranch %7 " - "%7 = OpLabel " - "%8 = OpPhi %1 %8 %7 %2 %6 " // both defines and uses %8 - " OpBranch %7 " - " OpFunctionEnd", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpConstantTrue %1"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpFunction %1 None %3"}, - {6, "%6 = OpLabel"}, - {7, "%7 = OpLabel"}, - {8, "%8 = OpPhi %1 %8 %7 %2 %6"}, - }, - { // uses - {1, - { - "%2 = OpConstantTrue %1", - "%3 = OpTypeFunction %1", - "%4 = OpFunction %1 None %3", - "%8 = OpPhi %1 %8 %7 %2 %6", - } - }, - {2, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - {3, {"%4 = OpFunction %1 None %3"}}, - {6, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - {7, - { - "OpBranch %7", - "%8 = OpPhi %1 %8 %7 %2 %6", - "OpBranch %7", - } - }, - {8, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - }, - }, - }, - }) -); -// clang-format on - -struct ReplaceUseCase { - const char* before; - std::vector> candidates; - const char* after; - InstDefUse du; -}; - -using ReplaceUseTest = ::testing::TestWithParam; - -// Disassembles the given |module| and returns the disassembly. -std::string DisassembleModule(Module* module) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); - - std::vector binary; - module->ToBinary(&binary, /* skip_nop = */ false); - - std::string text; - // We'll need to check the underlying id numbers. - // So turn off friendly names for ids. - tools.Disassemble(binary, &text, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - while (!text.empty() && text.back() == '\n') text.pop_back(); - return text; -} - -TEST_P(ReplaceUseTest, Case) { - const auto& tc = GetParam(); - - // Build module. - const std::vector text = {tc.before}; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, JoinAllInsts(text), - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - // Force a re-build of def-use manager. - context->InvalidateAnalyses(IRContext::Analysis::kAnalysisDefUse); - (void)context->get_def_use_mgr(); - - // Do the substitution. - for (const auto& candidate : tc.candidates) { - context->ReplaceAllUsesWith(candidate.first, candidate.second); - } - - EXPECT_EQ(tc.after, DisassembleModule(context->module())); - CheckDef(tc.du, context->get_def_use_mgr()->id_to_defs()); - CheckUse(tc.du, context->get_def_use_mgr(), context->module()->IdBound()); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TestCase, ReplaceUseTest, - ::testing::ValuesIn(std::vector{ - { // no use, no replace request - "", {}, "", {}, - }, - { // replace one use - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 3 " - "%3 = OpTypeInt 32 0 ", - {{1, 3}}, - "%1 = OpTypeBool\n" - "%2 = OpTypeVector %3 3\n" - "%3 = OpTypeInt 32 0", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %3 3"}, - {3, "%3 = OpTypeInt 32 0"}, - }, - { // uses - {3, {"%2 = OpTypeVector %3 3"}}, - }, - }, - }, - { // replace and then replace back - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 3 " - "%3 = OpTypeInt 32 0", - {{1, 3}, {3, 1}}, - "%1 = OpTypeBool\n" - "%2 = OpTypeVector %1 3\n" - "%3 = OpTypeInt 32 0", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %1 3"}, - {3, "%3 = OpTypeInt 32 0"}, - }, - { // uses - {1, {"%2 = OpTypeVector %1 3"}}, - }, - }, - }, - { // replace with the same id - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 3", - {{1, 1}, {2, 2}, {3, 3}}, - "%1 = OpTypeBool\n" - "%2 = OpTypeVector %1 3", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %1 3"}, - }, - { // uses - {1, {"%2 = OpTypeVector %1 3"}}, - }, - }, - }, - { // replace in sequence - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 3 " - "%3 = OpTypeInt 32 0 " - "%4 = OpTypeInt 32 1 ", - {{1, 3}, {3, 4}}, - "%1 = OpTypeBool\n" - "%2 = OpTypeVector %4 3\n" - "%3 = OpTypeInt 32 0\n" - "%4 = OpTypeInt 32 1", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %4 3"}, - {3, "%3 = OpTypeInt 32 0"}, - {4, "%4 = OpTypeInt 32 1"}, - }, - { // uses - {4, {"%2 = OpTypeVector %4 3"}}, - }, - }, - }, - { // replace multiple uses - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 2 " - "%3 = OpTypeVector %1 3 " - "%4 = OpTypeVector %1 4 " - "%5 = OpTypeMatrix %2 2 " - "%6 = OpTypeMatrix %3 3 " - "%7 = OpTypeMatrix %4 4 " - "%8 = OpTypeInt 32 0 " - "%9 = OpTypeInt 32 1 " - "%10 = OpTypeInt 64 0", - {{1, 8}, {2, 9}, {4, 10}}, - "%1 = OpTypeBool\n" - "%2 = OpTypeVector %8 2\n" - "%3 = OpTypeVector %8 3\n" - "%4 = OpTypeVector %8 4\n" - "%5 = OpTypeMatrix %9 2\n" - "%6 = OpTypeMatrix %3 3\n" - "%7 = OpTypeMatrix %10 4\n" - "%8 = OpTypeInt 32 0\n" - "%9 = OpTypeInt 32 1\n" - "%10 = OpTypeInt 64 0", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %8 2"}, - {3, "%3 = OpTypeVector %8 3"}, - {4, "%4 = OpTypeVector %8 4"}, - {5, "%5 = OpTypeMatrix %9 2"}, - {6, "%6 = OpTypeMatrix %3 3"}, - {7, "%7 = OpTypeMatrix %10 4"}, - {8, "%8 = OpTypeInt 32 0"}, - {9, "%9 = OpTypeInt 32 1"}, - {10, "%10 = OpTypeInt 64 0"}, - }, - { // uses - {8, - { - "%2 = OpTypeVector %8 2", - "%3 = OpTypeVector %8 3", - "%4 = OpTypeVector %8 4", - } - }, - {9, {"%5 = OpTypeMatrix %9 2"}}, - {3, {"%6 = OpTypeMatrix %3 3"}}, - {10, {"%7 = OpTypeMatrix %10 4"}}, - }, - }, - }, - { // OpPhi. - kOpPhiTestFunction, - // replace one id used by OpPhi, replace one id generated by OpPhi - {{9, 13}, {11, 9}}, - "%1 = OpTypeVoid\n" - "%6 = OpTypeInt 32 0\n" - "%10 = OpTypeFloat 32\n" - "%16 = OpTypeBool\n" - "%3 = OpTypeFunction %1\n" - "%8 = OpConstant %6 0\n" - "%18 = OpConstant %6 1\n" - "%12 = OpConstant %10 1\n" - "%2 = OpFunction %1 None %3\n" - "%4 = OpLabel\n" - "OpBranch %5\n" - - "%5 = OpLabel\n" - "%7 = OpPhi %6 %8 %4 %13 %5\n" // %9 -> %13 - "%11 = OpPhi %10 %12 %4 %13 %5\n" - "%9 = OpIAdd %6 %7 %8\n" - "%13 = OpFAdd %10 %9 %12\n" // %11 -> %9 - "%17 = OpSLessThan %16 %7 %18\n" - "OpLoopMerge %19 %5 None\n" - "OpBranchConditional %17 %5 %19\n" - - "%19 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd", - { - { // defs. - {1, "%1 = OpTypeVoid"}, - {2, "%2 = OpFunction %1 None %3"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpLabel"}, - {5, "%5 = OpLabel"}, - {6, "%6 = OpTypeInt 32 0"}, - {7, "%7 = OpPhi %6 %8 %4 %13 %5"}, - {8, "%8 = OpConstant %6 0"}, - {9, "%9 = OpIAdd %6 %7 %8"}, - {10, "%10 = OpTypeFloat 32"}, - {11, "%11 = OpPhi %10 %12 %4 %13 %5"}, - {12, "%12 = OpConstant %10 1.0"}, - {13, "%13 = OpFAdd %10 %9 %12"}, - {16, "%16 = OpTypeBool"}, - {17, "%17 = OpSLessThan %16 %7 %18"}, - {18, "%18 = OpConstant %6 1"}, - {19, "%19 = OpLabel"}, - }, - { // uses - {1, - { - "%2 = OpFunction %1 None %3", - "%3 = OpTypeFunction %1", - } - }, - {3, {"%2 = OpFunction %1 None %3"}}, - {4, - { - "%7 = OpPhi %6 %8 %4 %13 %5", - "%11 = OpPhi %10 %12 %4 %13 %5", - } - }, - {5, - { - "OpBranch %5", - "%7 = OpPhi %6 %8 %4 %13 %5", - "%11 = OpPhi %10 %12 %4 %13 %5", - "OpLoopMerge %19 %5 None", - "OpBranchConditional %17 %5 %19", - } - }, - {6, - { - // Can't properly check constants - // "%8 = OpConstant %6 0", - // "%18 = OpConstant %6 1", - "%7 = OpPhi %6 %8 %4 %13 %5", - "%9 = OpIAdd %6 %7 %8" - } - }, - {7, - { - "%9 = OpIAdd %6 %7 %8", - "%17 = OpSLessThan %16 %7 %18", - } - }, - {8, - { - "%7 = OpPhi %6 %8 %4 %13 %5", - "%9 = OpIAdd %6 %7 %8", - } - }, - {9, {"%13 = OpFAdd %10 %9 %12"}}, // uses of %9 changed from %7 to %13 - {10, - { - "%11 = OpPhi %10 %12 %4 %13 %5", - // "%12 = OpConstant %10 1", - "%13 = OpFAdd %10 %9 %12" - } - }, - // no more uses of %11 - {12, - { - "%11 = OpPhi %10 %12 %4 %13 %5", - "%13 = OpFAdd %10 %9 %12" - } - }, - {13, { - "%7 = OpPhi %6 %8 %4 %13 %5", - "%11 = OpPhi %10 %12 %4 %13 %5", - } - }, - {16, {"%17 = OpSLessThan %16 %7 %18"}}, - {17, {"OpBranchConditional %17 %5 %19"}}, - {18, {"%17 = OpSLessThan %16 %7 %18"}}, - {19, - { - "OpLoopMerge %19 %5 None", - "OpBranchConditional %17 %5 %19", - } - }, - }, - }, - }, - { // OpPhi defining and referencing the same id. - "%1 = OpTypeBool " - "%3 = OpTypeFunction %1 " - "%2 = OpConstantTrue %1 " - - "%4 = OpFunction %3 None %1 " - "%6 = OpLabel " - " OpBranch %7 " - "%7 = OpLabel " - "%8 = OpPhi %1 %8 %7 %2 %6 " // both defines and uses %8 - " OpBranch %7 " - " OpFunctionEnd", - {{8, 2}}, - "%1 = OpTypeBool\n" - "%3 = OpTypeFunction %1\n" - "%2 = OpConstantTrue %1\n" - - "%4 = OpFunction %3 None %1\n" - "%6 = OpLabel\n" - "OpBranch %7\n" - "%7 = OpLabel\n" - "%8 = OpPhi %1 %2 %7 %2 %6\n" // use of %8 changed to %2 - "OpBranch %7\n" - "OpFunctionEnd", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpConstantTrue %1"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpFunction %3 None %1"}, - {6, "%6 = OpLabel"}, - {7, "%7 = OpLabel"}, - {8, "%8 = OpPhi %1 %2 %7 %2 %6"}, - }, - { // uses - {1, - { - "%2 = OpConstantTrue %1", - "%3 = OpTypeFunction %1", - "%4 = OpFunction %3 None %1", - "%8 = OpPhi %1 %2 %7 %2 %6", - } - }, - {2, - { - // Only checking users - "%8 = OpPhi %1 %2 %7 %2 %6", - } - }, - {3, {"%4 = OpFunction %3 None %1"}}, - {6, {"%8 = OpPhi %1 %2 %7 %2 %6"}}, - {7, - { - "OpBranch %7", - "%8 = OpPhi %1 %2 %7 %2 %6", - "OpBranch %7", - } - }, - // {8, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - }, - }, - }, - }) -); -// clang-format on - -struct KillDefCase { - const char* before; - std::vector ids_to_kill; - const char* after; - InstDefUse du; -}; - -using KillDefTest = ::testing::TestWithParam; - -TEST_P(KillDefTest, Case) { - const auto& tc = GetParam(); - - // Build module. - const std::vector text = {tc.before}; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, JoinAllInsts(text), - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - // Analyze def and use. - DefUseManager manager(context->module()); - - // Do the substitution. - for (const auto id : tc.ids_to_kill) context->KillDef(id); - - EXPECT_EQ(tc.after, DisassembleModule(context->module())); - CheckDef(tc.du, context->get_def_use_mgr()->id_to_defs()); - CheckUse(tc.du, context->get_def_use_mgr(), context->module()->IdBound()); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TestCase, KillDefTest, - ::testing::ValuesIn(std::vector{ - { // no def, no use, no kill - "", {}, "", {} - }, - { // kill nothing - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 2 " - "%3 = OpTypeVector %1 3 ", - {}, - "%1 = OpTypeBool\n" - "%2 = OpTypeVector %1 2\n" - "%3 = OpTypeVector %1 3", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpTypeVector %1 2"}, - {3, "%3 = OpTypeVector %1 3"}, - }, - { // uses - {1, - { - "%2 = OpTypeVector %1 2", - "%3 = OpTypeVector %1 3", - } - }, - }, - }, - }, - { // kill id used, kill id not used, kill id not defined - "%1 = OpTypeBool " - "%2 = OpTypeVector %1 2 " - "%3 = OpTypeVector %1 3 " - "%4 = OpTypeVector %1 4 " - "%5 = OpTypeMatrix %3 3 " - "%6 = OpTypeMatrix %2 3", - {1, 3, 5, 10}, // ids to kill - "%2 = OpTypeVector %1 2\n" - "%4 = OpTypeVector %1 4\n" - "%6 = OpTypeMatrix %2 3", - { - { // defs - {2, "%2 = OpTypeVector %1 2"}, - {4, "%4 = OpTypeVector %1 4"}, - {6, "%6 = OpTypeMatrix %2 3"}, - }, - { // uses. %1 and %3 are both killed, so no uses - // recorded for them anymore. - {2, {"%6 = OpTypeMatrix %2 3"}}, - } - }, - }, - { // OpPhi. - kOpPhiTestFunction, - {9, 11}, // kill one id used by OpPhi, kill one id generated by OpPhi - "%1 = OpTypeVoid\n" - "%6 = OpTypeInt 32 0\n" - "%10 = OpTypeFloat 32\n" - "%16 = OpTypeBool\n" - "%3 = OpTypeFunction %1\n" - "%8 = OpConstant %6 0\n" - "%18 = OpConstant %6 1\n" - "%12 = OpConstant %10 1\n" - "%2 = OpFunction %1 None %3\n" - "%4 = OpLabel\n" - "OpBranch %5\n" - - "%5 = OpLabel\n" - "%7 = OpPhi %6 %8 %4 %9 %5\n" - "%13 = OpFAdd %10 %11 %12\n" - "%17 = OpSLessThan %16 %7 %18\n" - "OpLoopMerge %19 %5 None\n" - "OpBranchConditional %17 %5 %19\n" - - "%19 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd", - { - { // defs. %9 & %11 are killed. - {1, "%1 = OpTypeVoid"}, - {2, "%2 = OpFunction %1 None %3"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpLabel"}, - {5, "%5 = OpLabel"}, - {6, "%6 = OpTypeInt 32 0"}, - {7, "%7 = OpPhi %6 %8 %4 %9 %5"}, - {8, "%8 = OpConstant %6 0"}, - {10, "%10 = OpTypeFloat 32"}, - {12, "%12 = OpConstant %10 1.0"}, - {13, "%13 = OpFAdd %10 %11 %12"}, - {16, "%16 = OpTypeBool"}, - {17, "%17 = OpSLessThan %16 %7 %18"}, - {18, "%18 = OpConstant %6 1"}, - {19, "%19 = OpLabel"}, - }, - { // uses - {1, - { - "%2 = OpFunction %1 None %3", - "%3 = OpTypeFunction %1", - } - }, - {3, {"%2 = OpFunction %1 None %3"}}, - {4, - { - "%7 = OpPhi %6 %8 %4 %9 %5", - // "%11 = OpPhi %10 %12 %4 %13 %5", - } - }, - {5, - { - "OpBranch %5", - "%7 = OpPhi %6 %8 %4 %9 %5", - // "%11 = OpPhi %10 %12 %4 %13 %5", - "OpLoopMerge %19 %5 None", - "OpBranchConditional %17 %5 %19", - } - }, - {6, - { - // Can't properly check constants - // "%8 = OpConstant %6 0", - // "%18 = OpConstant %6 1", - "%7 = OpPhi %6 %8 %4 %9 %5", - // "%9 = OpIAdd %6 %7 %8" - } - }, - {7, {"%17 = OpSLessThan %16 %7 %18"}}, - {8, - { - "%7 = OpPhi %6 %8 %4 %9 %5", - // "%9 = OpIAdd %6 %7 %8", - } - }, - // {9, {"%7 = OpPhi %6 %8 %4 %13 %5"}}, - {10, - { - // "%11 = OpPhi %10 %12 %4 %13 %5", - // "%12 = OpConstant %10 1", - "%13 = OpFAdd %10 %11 %12" - } - }, - // {11, {"%13 = OpFAdd %10 %11 %12"}}, - {12, - { - // "%11 = OpPhi %10 %12 %4 %13 %5", - "%13 = OpFAdd %10 %11 %12" - } - }, - // {13, {"%11 = OpPhi %10 %12 %4 %13 %5"}}, - {16, {"%17 = OpSLessThan %16 %7 %18"}}, - {17, {"OpBranchConditional %17 %5 %19"}}, - {18, {"%17 = OpSLessThan %16 %7 %18"}}, - {19, - { - "OpLoopMerge %19 %5 None", - "OpBranchConditional %17 %5 %19", - } - }, - }, - }, - }, - { // OpPhi defining and referencing the same id. - "%1 = OpTypeBool " - "%3 = OpTypeFunction %1 " - "%2 = OpConstantTrue %1 " - "%4 = OpFunction %3 None %1 " - "%6 = OpLabel " - " OpBranch %7 " - "%7 = OpLabel " - "%8 = OpPhi %1 %8 %7 %2 %6 " // both defines and uses %8 - " OpBranch %7 " - " OpFunctionEnd", - {8}, - "%1 = OpTypeBool\n" - "%3 = OpTypeFunction %1\n" - "%2 = OpConstantTrue %1\n" - - "%4 = OpFunction %3 None %1\n" - "%6 = OpLabel\n" - "OpBranch %7\n" - "%7 = OpLabel\n" - "OpBranch %7\n" - "OpFunctionEnd", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpConstantTrue %1"}, - {3, "%3 = OpTypeFunction %1"}, - {4, "%4 = OpFunction %3 None %1"}, - {6, "%6 = OpLabel"}, - {7, "%7 = OpLabel"}, - // {8, "%8 = OpPhi %1 %8 %7 %2 %6"}, - }, - { // uses - {1, - { - "%2 = OpConstantTrue %1", - "%3 = OpTypeFunction %1", - "%4 = OpFunction %3 None %1", - // "%8 = OpPhi %1 %8 %7 %2 %6", - } - }, - // {2, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - {3, {"%4 = OpFunction %3 None %1"}}, - // {6, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - {7, - { - "OpBranch %7", - // "%8 = OpPhi %1 %8 %7 %2 %6", - "OpBranch %7", - } - }, - // {8, {"%8 = OpPhi %1 %8 %7 %2 %6"}}, - }, - }, - }, - }) -); -// clang-format on - -TEST(DefUseTest, OpSwitch) { - // Because disassembler has basic type check for OpSwitch's selector, we - // cannot use the DisassembleInst() in the above. Thus, this special spotcheck - // test case. - - const char original_text[] = - // int64 f(int64 v) { - // switch (v) { - // case 1: break; - // case -4294967296: break; - // case 9223372036854775807: break; - // default: break; - // } - // return v; - // } - " %1 = OpTypeInt 64 1 " - " %3 = OpTypePointer Input %1 " - " %2 = OpFunction %1 None %3 " // %3 is int64(int64)* - " %4 = OpFunctionParameter %1 " - " %5 = OpLabel " - " %6 = OpLoad %1 %4 " // selector value - " OpSelectionMerge %7 None " - " OpSwitch %6 %8 " - " 1 %9 " // 1 - " -4294967296 %10 " // -2^32 - " 9223372036854775807 %11 " // 2^63-1 - " %8 = OpLabel " // default - " OpBranch %7 " - " %9 = OpLabel " - " OpBranch %7 " - "%10 = OpLabel " - " OpBranch %7 " - "%11 = OpLabel " - " OpBranch %7 " - " %7 = OpLabel " - " OpReturnValue %6 " - " OpFunctionEnd"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, original_text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - // Force a re-build of def-use manager. - context->InvalidateAnalyses(IRContext::Analysis::kAnalysisDefUse); - (void)context->get_def_use_mgr(); - - // Do a bunch replacements. - context->ReplaceAllUsesWith(11, 7); // to existing id - context->ReplaceAllUsesWith(10, 11); // to existing id - context->ReplaceAllUsesWith(9, 10); // to existing id - - // clang-format off - const char modified_text[] = - "%1 = OpTypeInt 64 1\n" - "%3 = OpTypePointer Input %1\n" - "%2 = OpFunction %1 None %3\n" // %3 is int64(int64)* - "%4 = OpFunctionParameter %1\n" - "%5 = OpLabel\n" - "%6 = OpLoad %1 %4\n" // selector value - "OpSelectionMerge %7 None\n" - "OpSwitch %6 %8 1 %10 -4294967296 %11 9223372036854775807 %7\n" // changed! - "%8 = OpLabel\n" // default - "OpBranch %7\n" - "%9 = OpLabel\n" - "OpBranch %7\n" - "%10 = OpLabel\n" - "OpBranch %7\n" - "%11 = OpLabel\n" - "OpBranch %7\n" - "%7 = OpLabel\n" - "OpReturnValue %6\n" - "OpFunctionEnd"; - // clang-format on - - EXPECT_EQ(modified_text, DisassembleModule(context->module())); - - InstDefUse def_uses = {}; - def_uses.defs = { - {1, "%1 = OpTypeInt 64 1"}, - {2, "%2 = OpFunction %1 None %3"}, - {3, "%3 = OpTypePointer Input %1"}, - {4, "%4 = OpFunctionParameter %1"}, - {5, "%5 = OpLabel"}, - {6, "%6 = OpLoad %1 %4"}, - {7, "%7 = OpLabel"}, - {8, "%8 = OpLabel"}, - {9, "%9 = OpLabel"}, - {10, "%10 = OpLabel"}, - {11, "%11 = OpLabel"}, - }; - CheckDef(def_uses, context->get_def_use_mgr()->id_to_defs()); - - { - EXPECT_EQ(2u, NumUses(context, 6)); - std::vector opcodes = GetUseOpcodes(context, 6u); - EXPECT_THAT(opcodes, UnorderedElementsAre(SpvOpSwitch, SpvOpReturnValue)); - } - { - EXPECT_EQ(6u, NumUses(context, 7)); - std::vector opcodes = GetUseOpcodes(context, 7u); - // OpSwitch is now a user of %7. - EXPECT_THAT(opcodes, UnorderedElementsAre(SpvOpSelectionMerge, SpvOpBranch, - SpvOpBranch, SpvOpBranch, - SpvOpBranch, SpvOpSwitch)); - } - // Check all ids only used by OpSwitch after replacement. - for (const auto id : {8u, 10u, 11u}) { - EXPECT_EQ(1u, NumUses(context, id)); - EXPECT_EQ(SpvOpSwitch, GetUseOpcodes(context, id).back()); - } -} - -// Test case for analyzing individual instructions. -struct AnalyzeInstDefUseTestCase { - const char* module_text; - InstDefUse expected_define_use; -}; - -using AnalyzeInstDefUseTest = - ::testing::TestWithParam; - -// Test the analyzing result for individual instructions. -TEST_P(AnalyzeInstDefUseTest, Case) { - auto tc = GetParam(); - - // Build module. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.module_text); - ASSERT_NE(nullptr, context); - - // Analyze the instructions. - DefUseManager manager(context->module()); - - CheckDef(tc.expected_define_use, manager.id_to_defs()); - CheckUse(tc.expected_define_use, &manager, context->module()->IdBound()); - // CheckUse(tc.expected_define_use, manager.id_to_uses()); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TestCase, AnalyzeInstDefUseTest, - ::testing::ValuesIn(std::vector{ - { // A type declaring instruction. - "%1 = OpTypeInt 32 1", - { - // defs - {{1, "%1 = OpTypeInt 32 1"}}, - {}, // no uses - }, - }, - { // A type declaring instruction and a constant value. - "%1 = OpTypeBool " - "%2 = OpConstantTrue %1", - { - { // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpConstantTrue %1"}, - }, - { // uses - {1, {"%2 = OpConstantTrue %1"}}, - }, - }, - }, - })); -// clang-format on - -using AnalyzeInstDefUse = ::testing::Test; - -TEST(AnalyzeInstDefUse, UseWithNoResultId) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - - // Analyze the instructions. - DefUseManager manager(context.module()); - - Instruction label(&context, SpvOpLabel, 0, 2, {}); - manager.AnalyzeInstDefUse(&label); - - Instruction branch(&context, SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {2}}}); - manager.AnalyzeInstDefUse(&branch); - context.module()->SetIdBound(3); - - InstDefUse expected = { - // defs - { - {2, "%2 = OpLabel"}, - }, - // uses - {{2, {"OpBranch %2"}}}, - }; - - CheckDef(expected, manager.id_to_defs()); - CheckUse(expected, &manager, context.module()->IdBound()); -} - -TEST(AnalyzeInstDefUse, AddNewInstruction) { - const std::string input = "%1 = OpTypeBool"; - - // Build module. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input); - ASSERT_NE(nullptr, context); - - // Analyze the instructions. - DefUseManager manager(context->module()); - - Instruction newInst(context.get(), SpvOpConstantTrue, 1, 2, {}); - manager.AnalyzeInstDefUse(&newInst); - - InstDefUse expected = { - { - // defs - {1, "%1 = OpTypeBool"}, - {2, "%2 = OpConstantTrue %1"}, - }, - { - // uses - {1, {"%2 = OpConstantTrue %1"}}, - }, - }; - - CheckDef(expected, manager.id_to_defs()); - CheckUse(expected, &manager, context->module()->IdBound()); -} - -struct KillInstTestCase { - const char* before; - std::unordered_set indices_for_inst_to_kill; - const char* after; - InstDefUse expected_define_use; -}; - -using KillInstTest = ::testing::TestWithParam; - -TEST_P(KillInstTest, Case) { - auto tc = GetParam(); - - // Build module. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.before, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - // Force a re-build of the def-use manager. - context->InvalidateAnalyses(IRContext::Analysis::kAnalysisDefUse); - (void)context->get_def_use_mgr(); - - // KillInst - context->module()->ForEachInst([&tc, &context](Instruction* inst) { - if (tc.indices_for_inst_to_kill.count(inst->result_id())) { - context->KillInst(inst); - } - }); - - EXPECT_EQ(tc.after, DisassembleModule(context->module())); - CheckDef(tc.expected_define_use, context->get_def_use_mgr()->id_to_defs()); - CheckUse(tc.expected_define_use, context->get_def_use_mgr(), - context->module()->IdBound()); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TestCase, KillInstTest, - ::testing::ValuesIn(std::vector{ - // Kill id defining instructions. - { - "%3 = OpTypeVoid " - "%1 = OpTypeFunction %3 " - "%2 = OpFunction %1 None %3 " - "%4 = OpLabel " - " OpBranch %5 " - "%5 = OpLabel " - " OpBranch %6 " - "%6 = OpLabel " - " OpBranch %4 " - "%7 = OpLabel " - " OpReturn " - " OpFunctionEnd", - {3, 5, 7}, - "%1 = OpTypeFunction %3\n" - "%2 = OpFunction %1 None %3\n" - "%4 = OpLabel\n" - "OpBranch %5\n" - "OpNop\n" - "OpBranch %6\n" - "%6 = OpLabel\n" - "OpBranch %4\n" - "OpNop\n" - "OpReturn\n" - "OpFunctionEnd", - { - // defs - { - {1, "%1 = OpTypeFunction %3"}, - {2, "%2 = OpFunction %1 None %3"}, - {4, "%4 = OpLabel"}, - {6, "%6 = OpLabel"}, - }, - // uses - { - {1, {"%2 = OpFunction %1 None %3"}}, - {4, {"OpBranch %4"}}, - {6, {"OpBranch %6"}}, - } - } - }, - // Kill instructions that do not have result ids. - { - "%3 = OpTypeVoid " - "%1 = OpTypeFunction %3 " - "%2 = OpFunction %1 None %3 " - "%4 = OpLabel " - " OpBranch %5 " - "%5 = OpLabel " - " OpBranch %6 " - "%6 = OpLabel " - " OpBranch %4 " - "%7 = OpLabel " - " OpReturn " - " OpFunctionEnd", - {2, 4}, - "%3 = OpTypeVoid\n" - "%1 = OpTypeFunction %3\n" - "OpNop\n" - "OpNop\n" - "OpBranch %5\n" - "%5 = OpLabel\n" - "OpBranch %6\n" - "%6 = OpLabel\n" - "OpBranch %4\n" - "%7 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd", - { - // defs - { - {1, "%1 = OpTypeFunction %3"}, - {3, "%3 = OpTypeVoid"}, - {5, "%5 = OpLabel"}, - {6, "%6 = OpLabel"}, - {7, "%7 = OpLabel"}, - }, - // uses - { - {3, {"%1 = OpTypeFunction %3"}}, - {5, {"OpBranch %5"}}, - {6, {"OpBranch %6"}}, - } - } - }, - })); -// clang-format on - -struct GetAnnotationsTestCase { - const char* code; - uint32_t id; - std::vector annotations; -}; - -using GetAnnotationsTest = ::testing::TestWithParam; - -TEST_P(GetAnnotationsTest, Case) { - const GetAnnotationsTestCase& tc = GetParam(); - - // Build module. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.code); - ASSERT_NE(nullptr, context); - - // Get annotations - DefUseManager manager(context->module()); - auto insts = manager.GetAnnotations(tc.id); - - // Check - ASSERT_EQ(tc.annotations.size(), insts.size()) - << "wrong number of annotation instructions"; - auto inst_iter = insts.begin(); - for (const std::string& expected_anno_inst : tc.annotations) { - EXPECT_EQ(expected_anno_inst, DisassembleInst(*inst_iter)) - << "annotation instruction mismatch"; - inst_iter++; - } -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TestCase, GetAnnotationsTest, - ::testing::ValuesIn(std::vector{ - // empty - {"", 0, {}}, - // basic - { - // code - "OpDecorate %1 Block " - "OpDecorate %1 RelaxedPrecision " - "%3 = OpTypeInt 32 0 " - "%1 = OpTypeStruct %3", - // id - 1, - // annotations - { - "OpDecorate %1 Block", - "OpDecorate %1 RelaxedPrecision", - }, - }, - // with debug instructions - { - // code - "OpName %1 \"struct_type\" " - "OpName %3 \"int_type\" " - "OpDecorate %1 Block " - "OpDecorate %1 RelaxedPrecision " - "%3 = OpTypeInt 32 0 " - "%1 = OpTypeStruct %3", - // id - 1, - // annotations - { - "OpDecorate %1 Block", - "OpDecorate %1 RelaxedPrecision", - }, - }, - // no annotations - { - // code - "OpName %1 \"struct_type\" " - "OpName %3 \"int_type\" " - "OpDecorate %1 Block " - "OpDecorate %1 RelaxedPrecision " - "%3 = OpTypeInt 32 0 " - "%1 = OpTypeStruct %3", - // id - 3, - // annotations - {}, - }, - // decoration group - { - // code - "OpDecorate %1 Block " - "OpDecorate %1 RelaxedPrecision " - "%1 = OpDecorationGroup " - "OpGroupDecorate %1 %2 %3 " - "%4 = OpTypeInt 32 0 " - "%2 = OpTypeStruct %4 " - "%3 = OpTypeStruct %4 %4", - // id - 3, - // annotations - { - "OpGroupDecorate %1 %2 %3", - }, - }, - // memeber decorate - { - // code - "OpMemberDecorate %1 0 RelaxedPrecision " - "%2 = OpTypeInt 32 0 " - "%1 = OpTypeStruct %2 %2", - // id - 1, - // annotations - { - "OpMemberDecorate %1 0 RelaxedPrecision", - }, - }, - })); - -using UpdateUsesTest = PassTest<::testing::Test>; - -TEST_F(UpdateUsesTest, KeepOldUses) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "%void = OpTypeVoid", - "%4 = OpTypeFunction %void", - "%uint = OpTypeInt 32 0", - "%uint_5 = OpConstant %uint 5", - "%25 = OpConstant %uint 25", - "%main = OpFunction %void None %4", - "%8 = OpLabel", - "%9 = OpIMul %uint %uint_5 %uint_5", - "%10 = OpIMul %uint %9 %uint_5", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, JoinAllInsts(text), - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - - DefUseManager* def_use_mgr = context->get_def_use_mgr(); - Instruction* def = def_use_mgr->GetDef(9); - Instruction* use = def_use_mgr->GetDef(10); - def->SetOpcode(SpvOpCopyObject); - def->SetInOperands({{SPV_OPERAND_TYPE_ID, {25}}}); - context->UpdateDefUse(def); - - auto users = def_use_mgr->id_to_users(); - UserEntry entry = {def, use}; - EXPECT_THAT(users, Contains(entry)); -} -// clang-format on - -} // namespace -} // namespace analysis -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/desc_sroa_test.cpp b/3rdparty/spirv-tools/test/opt/desc_sroa_test.cpp deleted file mode 100644 index 11074c347..000000000 --- a/3rdparty/spirv-tools/test/opt/desc_sroa_test.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DescriptorScalarReplacementTest = PassTest<::testing::Test>; - -TEST_F(DescriptorScalarReplacementTest, ExpandTexture) { - const std::string text = R"( -; CHECK: OpDecorate [[var1:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var1]] Binding 0 -; CHECK: OpDecorate [[var2:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var2]] Binding 1 -; CHECK: OpDecorate [[var3:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var3]] Binding 2 -; CHECK: OpDecorate [[var4:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var4]] Binding 3 -; CHECK: OpDecorate [[var5:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var5]] Binding 4 -; CHECK: [[image_type:%\w+]] = OpTypeImage -; CHECK: [[ptr_type:%\w+]] = OpTypePointer UniformConstant [[image_type]] -; CHECK: [[var1]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: [[var2]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: [[var3]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: [[var4]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: [[var5]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: OpLoad [[image_type]] [[var1]] -; CHECK: OpLoad [[image_type]] [[var2]] -; CHECK: OpLoad [[image_type]] [[var3]] -; CHECK: OpLoad [[image_type]] [[var4]] -; CHECK: OpLoad [[image_type]] [[var5]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpDecorate %MyTextures DescriptorSet 0 - OpDecorate %MyTextures Binding 0 - %int = OpTypeInt 32 1 - %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 - %uint = OpTypeInt 32 0 - %uint_5 = OpConstant %uint 5 - %float = OpTypeFloat 32 -%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown -%_arr_type_2d_image_uint_5 = OpTypeArray %type_2d_image %uint_5 -%_ptr_UniformConstant__arr_type_2d_image_uint_5 = OpTypePointer UniformConstant %_arr_type_2d_image_uint_5 - %v2float = OpTypeVector %float 2 - %void = OpTypeVoid - %26 = OpTypeFunction %void -%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image - %MyTextures = OpVariable %_ptr_UniformConstant__arr_type_2d_image_uint_5 UniformConstant - %main = OpFunction %void None %26 - %28 = OpLabel - %29 = OpUndef %v2float - %30 = OpAccessChain %_ptr_UniformConstant_type_2d_image %MyTextures %int_0 - %31 = OpLoad %type_2d_image %30 - %35 = OpAccessChain %_ptr_UniformConstant_type_2d_image %MyTextures %int_1 - %36 = OpLoad %type_2d_image %35 - %40 = OpAccessChain %_ptr_UniformConstant_type_2d_image %MyTextures %int_2 - %41 = OpLoad %type_2d_image %40 - %45 = OpAccessChain %_ptr_UniformConstant_type_2d_image %MyTextures %int_3 - %46 = OpLoad %type_2d_image %45 - %50 = OpAccessChain %_ptr_UniformConstant_type_2d_image %MyTextures %int_4 - %51 = OpLoad %type_2d_image %50 - OpReturn - OpFunctionEnd - - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DescriptorScalarReplacementTest, ExpandSampler) { - const std::string text = R"( -; CHECK: OpDecorate [[var1:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var1]] Binding 1 -; CHECK: OpDecorate [[var2:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var2]] Binding 2 -; CHECK: OpDecorate [[var3:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var3]] Binding 3 -; CHECK: [[sampler_type:%\w+]] = OpTypeSampler -; CHECK: [[ptr_type:%\w+]] = OpTypePointer UniformConstant [[sampler_type]] -; CHECK: [[var1]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: [[var2]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: [[var3]] = OpVariable [[ptr_type]] UniformConstant -; CHECK: OpLoad [[sampler_type]] [[var1]] -; CHECK: OpLoad [[sampler_type]] [[var2]] -; CHECK: OpLoad [[sampler_type]] [[var3]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpDecorate %MySampler DescriptorSet 0 - OpDecorate %MySampler Binding 1 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 -%type_sampler = OpTypeSampler -%_arr_type_sampler_uint_3 = OpTypeArray %type_sampler %uint_3 -%_ptr_UniformConstant__arr_type_sampler_uint_3 = OpTypePointer UniformConstant %_arr_type_sampler_uint_3 - %void = OpTypeVoid - %26 = OpTypeFunction %void -%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler - %MySampler = OpVariable %_ptr_UniformConstant__arr_type_sampler_uint_3 UniformConstant - %main = OpFunction %void None %26 - %28 = OpLabel - %31 = OpAccessChain %_ptr_UniformConstant_type_sampler %MySampler %int_0 - %32 = OpLoad %type_sampler %31 - %35 = OpAccessChain %_ptr_UniformConstant_type_sampler %MySampler %int_1 - %36 = OpLoad %type_sampler %35 - %40 = OpAccessChain %_ptr_UniformConstant_type_sampler %MySampler %int_2 - %41 = OpLoad %type_sampler %40 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DescriptorScalarReplacementTest, ExpandSSBO) { - // Tests the expansion of an SSBO. Also check that an access chain with more - // than 1 index is correctly handled. - const std::string text = R"( -; CHECK: OpDecorate [[var1:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var1]] Binding 0 -; CHECK: OpDecorate [[var2:%\w+]] DescriptorSet 0 -; CHECK: OpDecorate [[var2]] Binding 1 -; CHECK: OpTypeStruct -; CHECK: [[struct_type:%\w+]] = OpTypeStruct -; CHECK: [[ptr_type:%\w+]] = OpTypePointer Uniform [[struct_type]] -; CHECK: [[var1]] = OpVariable [[ptr_type]] Uniform -; CHECK: [[var2]] = OpVariable [[ptr_type]] Uniform -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[var1]] %uint_0 %uint_0 %uint_0 -; CHECK: OpLoad %v4float [[ac1]] -; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[var2]] %uint_0 %uint_0 %uint_0 -; CHECK: OpLoad %v4float [[ac2]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpDecorate %buffers DescriptorSet 0 - OpDecorate %buffers Binding 0 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %_runtimearr_S ArrayStride 16 - OpMemberDecorate %type_StructuredBuffer_S 0 Offset 0 - OpMemberDecorate %type_StructuredBuffer_S 0 NonWritable - OpDecorate %type_StructuredBuffer_S BufferBlock - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %S = OpTypeStruct %v4float -%_runtimearr_S = OpTypeRuntimeArray %S -%type_StructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_arr_type_StructuredBuffer_S_uint_2 = OpTypeArray %type_StructuredBuffer_S %uint_2 -%_ptr_Uniform__arr_type_StructuredBuffer_S_uint_2 = OpTypePointer Uniform %_arr_type_StructuredBuffer_S_uint_2 -%_ptr_Uniform_type_StructuredBuffer_S = OpTypePointer Uniform %type_StructuredBuffer_S - %void = OpTypeVoid - %19 = OpTypeFunction %void -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float - %buffers = OpVariable %_ptr_Uniform__arr_type_StructuredBuffer_S_uint_2 Uniform - %main = OpFunction %void None %19 - %21 = OpLabel - %22 = OpAccessChain %_ptr_Uniform_v4float %buffers %uint_0 %uint_0 %uint_0 %uint_0 - %23 = OpLoad %v4float %22 - %24 = OpAccessChain %_ptr_Uniform_type_StructuredBuffer_S %buffers %uint_1 - %25 = OpAccessChain %_ptr_Uniform_v4float %24 %uint_0 %uint_0 %uint_0 - %26 = OpLoad %v4float %25 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(DescriptorScalarReplacementTest, NameNewVariables) { - // Checks that if the original variable has a name, then the new variables - // will have a name derived from that name. - const std::string text = R"( -; CHECK: OpName [[var1:%\w+]] "SSBO[0]" -; CHECK: OpName [[var2:%\w+]] "SSBO[1]" -; CHECK: OpDecorate [[var1]] DescriptorSet 0 -; CHECK: OpDecorate [[var1]] Binding 0 -; CHECK: OpDecorate [[var2]] DescriptorSet 0 -; CHECK: OpDecorate [[var2]] Binding 1 -; CHECK: OpTypeStruct -; CHECK: [[struct_type:%\w+]] = OpTypeStruct -; CHECK: [[ptr_type:%\w+]] = OpTypePointer Uniform [[struct_type]] -; CHECK: [[var1]] = OpVariable [[ptr_type]] Uniform -; CHECK: [[var2]] = OpVariable [[ptr_type]] Uniform -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[var1]] %uint_0 %uint_0 %uint_0 -; CHECK: OpLoad %v4float [[ac1]] -; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_v4float [[var2]] %uint_0 %uint_0 %uint_0 -; CHECK: OpLoad %v4float [[ac2]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - OpName %buffers "SSBO" - OpDecorate %buffers DescriptorSet 0 - OpDecorate %buffers Binding 0 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %_runtimearr_S ArrayStride 16 - OpMemberDecorate %type_StructuredBuffer_S 0 Offset 0 - OpMemberDecorate %type_StructuredBuffer_S 0 NonWritable - OpDecorate %type_StructuredBuffer_S BufferBlock - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %S = OpTypeStruct %v4float -%_runtimearr_S = OpTypeRuntimeArray %S -%type_StructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_arr_type_StructuredBuffer_S_uint_2 = OpTypeArray %type_StructuredBuffer_S %uint_2 -%_ptr_Uniform__arr_type_StructuredBuffer_S_uint_2 = OpTypePointer Uniform %_arr_type_StructuredBuffer_S_uint_2 -%_ptr_Uniform_type_StructuredBuffer_S = OpTypePointer Uniform %type_StructuredBuffer_S - %void = OpTypeVoid - %19 = OpTypeFunction %void -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float - %buffers = OpVariable %_ptr_Uniform__arr_type_StructuredBuffer_S_uint_2 Uniform - %main = OpFunction %void None %19 - %21 = OpLabel - %22 = OpAccessChain %_ptr_Uniform_v4float %buffers %uint_0 %uint_0 %uint_0 %uint_0 - %23 = OpLoad %v4float %22 - %24 = OpAccessChain %_ptr_Uniform_type_StructuredBuffer_S %buffers %uint_1 - %25 = OpAccessChain %_ptr_Uniform_v4float %24 %uint_0 %uint_0 %uint_0 - %26 = OpLoad %v4float %25 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/CMakeLists.txt b/3rdparty/spirv-tools/test/opt/dominator_tree/CMakeLists.txt deleted file mode 100644 index 813d628a0..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2017 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. - - -add_spvtools_unittest(TARGET dominator_analysis - SRCS ../function_utils.h - common_dominators.cpp - generated.cpp - nested_ifs.cpp - nested_ifs_post.cpp - nested_loops.cpp - nested_loops_with_unreachables.cpp - post.cpp - simple.cpp - switch_case_fallthrough.cpp - unreachable_for.cpp - unreachable_for_post.cpp - LIBS SPIRV-Tools-opt - PCH_FILE pch_test_opt_dom -) diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/common_dominators.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/common_dominators.cpp deleted file mode 100644 index dfa03e986..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/common_dominators.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { -namespace { - -using CommonDominatorsTest = ::testing::Test; - -const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %3 %4 None -OpBranch %5 -%5 = OpLabel -OpBranchConditional %true %3 %4 -%4 = OpLabel -OpBranch %2 -%3 = OpLabel -OpSelectionMerge %6 None -OpBranchConditional %true %7 %8 -%7 = OpLabel -OpBranch %6 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpBranch %6 -%6 = OpLabel -OpBranch %10 -%11 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - -BasicBlock* GetBlock(uint32_t id, std::unique_ptr& context) { - return context->get_instr_block(context->get_def_use_mgr()->GetDef(id)); -} - -TEST(CommonDominatorsTest, SameBlock) { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, context); - - DominatorAnalysis* analysis = - context->GetDominatorAnalysis(&*context->module()->begin()); - - for (auto& block : *context->module()->begin()) { - EXPECT_EQ(&block, analysis->CommonDominator(&block, &block)); - } -} - -TEST(CommonDominatorsTest, ParentAndChild) { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, context); - - DominatorAnalysis* analysis = - context->GetDominatorAnalysis(&*context->module()->begin()); - - EXPECT_EQ( - GetBlock(1u, context), - analysis->CommonDominator(GetBlock(1u, context), GetBlock(2u, context))); - EXPECT_EQ( - GetBlock(2u, context), - analysis->CommonDominator(GetBlock(2u, context), GetBlock(5u, context))); - EXPECT_EQ( - GetBlock(1u, context), - analysis->CommonDominator(GetBlock(1u, context), GetBlock(5u, context))); -} - -TEST(CommonDominatorsTest, BranchSplit) { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, context); - - DominatorAnalysis* analysis = - context->GetDominatorAnalysis(&*context->module()->begin()); - - EXPECT_EQ( - GetBlock(3u, context), - analysis->CommonDominator(GetBlock(7u, context), GetBlock(8u, context))); - EXPECT_EQ( - GetBlock(3u, context), - analysis->CommonDominator(GetBlock(7u, context), GetBlock(9u, context))); -} - -TEST(CommonDominatorsTest, LoopContinueAndMerge) { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, context); - - DominatorAnalysis* analysis = - context->GetDominatorAnalysis(&*context->module()->begin()); - - EXPECT_EQ( - GetBlock(5u, context), - analysis->CommonDominator(GetBlock(3u, context), GetBlock(4u, context))); -} - -TEST(CommonDominatorsTest, NoCommonDominator) { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, context); - - DominatorAnalysis* analysis = - context->GetDominatorAnalysis(&*context->module()->begin()); - - EXPECT_EQ(nullptr, analysis->CommonDominator(GetBlock(10u, context), - GetBlock(11u, context))); - EXPECT_EQ(nullptr, analysis->CommonDominator(GetBlock(11u, context), - GetBlock(6u, context))); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/generated.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/generated.cpp deleted file mode 100644 index 43b723e93..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/generated.cpp +++ /dev/null @@ -1,900 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/iterator.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -// Check that x dominates y, and -// if x != y then -// x strictly dominates y and -// y does not dominate x and -// y does not strictly dominate x -// if x == x then -// x does not strictly dominate itself -void check_dominance(const DominatorAnalysisBase& dom_tree, const Function* fn, - uint32_t x, uint32_t y) { - SCOPED_TRACE("Check dominance properties for Basic Block " + - std::to_string(x) + " and " + std::to_string(y)); - EXPECT_TRUE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, x), - spvtest::GetBasicBlock(fn, y))); - EXPECT_TRUE(dom_tree.Dominates(x, y)); - if (x == y) { - EXPECT_FALSE(dom_tree.StrictlyDominates(x, x)); - } else { - EXPECT_TRUE(dom_tree.StrictlyDominates(x, y)); - EXPECT_FALSE(dom_tree.Dominates(y, x)); - EXPECT_FALSE(dom_tree.StrictlyDominates(y, x)); - } -} - -// Check that x does not dominates y and vise versa -void check_no_dominance(const DominatorAnalysisBase& dom_tree, - const Function* fn, uint32_t x, uint32_t y) { - SCOPED_TRACE("Check no domination for Basic Block " + std::to_string(x) + - " and " + std::to_string(y)); - EXPECT_FALSE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, x), - spvtest::GetBasicBlock(fn, y))); - EXPECT_FALSE(dom_tree.Dominates(x, y)); - EXPECT_FALSE(dom_tree.StrictlyDominates(spvtest::GetBasicBlock(fn, x), - spvtest::GetBasicBlock(fn, y))); - EXPECT_FALSE(dom_tree.StrictlyDominates(x, y)); - - EXPECT_FALSE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, y), - spvtest::GetBasicBlock(fn, x))); - EXPECT_FALSE(dom_tree.Dominates(y, x)); - EXPECT_FALSE(dom_tree.StrictlyDominates(spvtest::GetBasicBlock(fn, y), - spvtest::GetBasicBlock(fn, x))); - EXPECT_FALSE(dom_tree.StrictlyDominates(y, x)); -} - -TEST_F(PassClassTest, DominatorSimpleCFG) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpTypeBool - %5 = OpTypeInt 32 0 - %6 = OpConstant %5 0 - %7 = OpConstantFalse %4 - %8 = OpConstantTrue %4 - %9 = OpConstant %5 1 - %1 = OpFunction %2 None %3 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - OpSwitch %6 %12 1 %13 - %12 = OpLabel - OpBranch %14 - %13 = OpLabel - OpBranch %14 - %14 = OpLabel - OpBranchConditional %8 %11 %15 - %15 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* fn = spvtest::GetFunction(module, 1); - const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); - EXPECT_EQ(entry, fn->entry().get()) - << "The entry node is not the expected one"; - - // Test normal dominator tree - { - DominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE( - dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12, 13, 14, 15}) - check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 10, 11); - check_dominance(dom_tree, fn, 10, 12); - check_dominance(dom_tree, fn, 10, 13); - check_dominance(dom_tree, fn, 10, 14); - check_dominance(dom_tree, fn, 10, 15); - - check_dominance(dom_tree, fn, 11, 12); - check_dominance(dom_tree, fn, 11, 13); - check_dominance(dom_tree, fn, 11, 14); - check_dominance(dom_tree, fn, 11, 15); - - check_dominance(dom_tree, fn, 14, 15); - - check_no_dominance(dom_tree, fn, 12, 13); - check_no_dominance(dom_tree, fn, 12, 14); - check_no_dominance(dom_tree, fn, 13, 14); - - // check with some invalid inputs - EXPECT_FALSE(dom_tree.Dominates(nullptr, entry)); - EXPECT_FALSE(dom_tree.Dominates(entry, nullptr)); - EXPECT_FALSE(dom_tree.Dominates(static_cast(nullptr), - static_cast(nullptr))); - EXPECT_FALSE(dom_tree.Dominates(10, 1)); - EXPECT_FALSE(dom_tree.Dominates(1, 10)); - EXPECT_FALSE(dom_tree.Dominates(1, 1)); - - EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, entry)); - EXPECT_FALSE(dom_tree.StrictlyDominates(entry, nullptr)); - EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, nullptr)); - EXPECT_FALSE(dom_tree.StrictlyDominates(10, 1)); - EXPECT_FALSE(dom_tree.StrictlyDominates(1, 10)); - EXPECT_FALSE(dom_tree.StrictlyDominates(1, 1)); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); - EXPECT_EQ(dom_tree.ImmediateDominator(nullptr), nullptr); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 10)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), - spvtest::GetBasicBlock(fn, 14)); - } - - // Test post dominator tree - { - PostDominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); - EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 15)); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12, 13, 14, 15}) - check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 14, 10); - check_dominance(dom_tree, fn, 14, 11); - check_dominance(dom_tree, fn, 14, 12); - check_dominance(dom_tree, fn, 14, 13); - - check_dominance(dom_tree, fn, 15, 10); - check_dominance(dom_tree, fn, 15, 11); - check_dominance(dom_tree, fn, 15, 12); - check_dominance(dom_tree, fn, 15, 13); - check_dominance(dom_tree, fn, 15, 14); - - check_no_dominance(dom_tree, fn, 13, 12); - check_no_dominance(dom_tree, fn, 12, 11); - check_no_dominance(dom_tree, fn, 13, 11); - - // check with some invalid inputs - EXPECT_FALSE(dom_tree.Dominates(nullptr, entry)); - EXPECT_FALSE(dom_tree.Dominates(entry, nullptr)); - EXPECT_FALSE(dom_tree.Dominates(static_cast(nullptr), - static_cast(nullptr))); - EXPECT_FALSE(dom_tree.Dominates(10, 1)); - EXPECT_FALSE(dom_tree.Dominates(1, 10)); - EXPECT_FALSE(dom_tree.Dominates(1, 1)); - - EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, entry)); - EXPECT_FALSE(dom_tree.StrictlyDominates(entry, nullptr)); - EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, nullptr)); - EXPECT_FALSE(dom_tree.StrictlyDominates(10, 1)); - EXPECT_FALSE(dom_tree.StrictlyDominates(1, 10)); - EXPECT_FALSE(dom_tree.StrictlyDominates(1, 1)); - - EXPECT_EQ(dom_tree.ImmediateDominator(nullptr), nullptr); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 14)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 14)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), - spvtest::GetBasicBlock(fn, 14)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), - spvtest::GetBasicBlock(fn, 15)); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), - cfg.pseudo_exit_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); - } -} - -TEST_F(PassClassTest, DominatorIrreducibleCFG) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpTypeBool - %5 = OpTypeInt 32 0 - %6 = OpConstantFalse %4 - %7 = OpConstantTrue %4 - %1 = OpFunction %2 None %3 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpBranchConditional %7 %10 %11 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - OpBranchConditional %7 %10 %12 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* fn = spvtest::GetFunction(module, 1); - - const BasicBlock* entry = spvtest::GetBasicBlock(fn, 8); - EXPECT_EQ(entry, fn->entry().get()) - << "The entry node is not the expected one"; - - // Check normal dominator tree - { - DominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE( - dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); - - // (strict) dominance checks - for (uint32_t id : {8, 9, 10, 11, 12}) - check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 8, 9); - check_dominance(dom_tree, fn, 8, 10); - check_dominance(dom_tree, fn, 8, 11); - check_dominance(dom_tree, fn, 8, 12); - - check_dominance(dom_tree, fn, 9, 10); - check_dominance(dom_tree, fn, 9, 11); - check_dominance(dom_tree, fn, 9, 12); - - check_dominance(dom_tree, fn, 11, 12); - - check_no_dominance(dom_tree, fn, 10, 11); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), - spvtest::GetBasicBlock(fn, 8)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), - spvtest::GetBasicBlock(fn, 9)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 9)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 11)); - } - - // Check post dominator tree - { - PostDominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); - EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12)); - - // (strict) dominance checks - for (uint32_t id : {8, 9, 10, 11, 12}) - check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 12, 8); - check_dominance(dom_tree, fn, 12, 10); - check_dominance(dom_tree, fn, 12, 11); - check_dominance(dom_tree, fn, 12, 12); - - check_dominance(dom_tree, fn, 11, 8); - check_dominance(dom_tree, fn, 11, 9); - check_dominance(dom_tree, fn, 11, 10); - - check_dominance(dom_tree, fn, 9, 8); - - EXPECT_EQ(dom_tree.ImmediateDominator(entry), - spvtest::GetBasicBlock(fn, 9)); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 12)); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - cfg.pseudo_exit_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); - } -} - -TEST_F(PassClassTest, DominatorLoopToSelf) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpTypeBool - %5 = OpTypeInt 32 0 - %6 = OpConstant %5 0 - %7 = OpConstantFalse %4 - %8 = OpConstantTrue %4 - %9 = OpConstant %5 1 - %1 = OpFunction %2 None %3 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - OpSwitch %6 %12 1 %11 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* fn = spvtest::GetFunction(module, 1); - - const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); - EXPECT_EQ(entry, fn->entry().get()) - << "The entry node is not the expected one"; - - // Check normal dominator tree - { - DominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE( - dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 10, 11); - check_dominance(dom_tree, fn, 10, 12); - check_dominance(dom_tree, fn, 11, 12); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 10)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 11)); - - std::array node_order = {{10, 11, 12}}; - { - // Test dominator tree iteration order. - DominatorTree::iterator node_it = dom_tree.GetDomTree().begin(); - DominatorTree::iterator node_end = dom_tree.GetDomTree().end(); - for (uint32_t id : node_order) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - { - // Same as above, but with const iterators. - DominatorTree::const_iterator node_it = dom_tree.GetDomTree().cbegin(); - DominatorTree::const_iterator node_end = dom_tree.GetDomTree().cend(); - for (uint32_t id : node_order) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - { - // Test dominator tree iteration order. - DominatorTree::post_iterator node_it = dom_tree.GetDomTree().post_begin(); - DominatorTree::post_iterator node_end = dom_tree.GetDomTree().post_end(); - for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - { - // Same as above, but with const iterators. - DominatorTree::const_post_iterator node_it = - dom_tree.GetDomTree().post_cbegin(); - DominatorTree::const_post_iterator node_end = - dom_tree.GetDomTree().post_cend(); - for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - } - - // Check post dominator tree - { - PostDominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); - EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12)); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 12, 10); - check_dominance(dom_tree, fn, 12, 11); - check_dominance(dom_tree, fn, 12, 12); - - EXPECT_EQ(dom_tree.ImmediateDominator(entry), - spvtest::GetBasicBlock(fn, 11)); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 12)); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - cfg.pseudo_exit_block()); - - std::array node_order = {{12, 11, 10}}; - { - // Test dominator tree iteration order. - DominatorTree::iterator node_it = tree.begin(); - DominatorTree::iterator node_end = tree.end(); - for (uint32_t id : node_order) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - { - // Same as above, but with const iterators. - DominatorTree::const_iterator node_it = tree.cbegin(); - DominatorTree::const_iterator node_end = tree.cend(); - for (uint32_t id : node_order) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - { - // Test dominator tree iteration order. - DominatorTree::post_iterator node_it = dom_tree.GetDomTree().post_begin(); - DominatorTree::post_iterator node_end = dom_tree.GetDomTree().post_end(); - for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - { - // Same as above, but with const iterators. - DominatorTree::const_post_iterator node_it = - dom_tree.GetDomTree().post_cbegin(); - DominatorTree::const_post_iterator node_end = - dom_tree.GetDomTree().post_cend(); - for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { - EXPECT_NE(node_it, node_end); - EXPECT_EQ(node_it->id(), id); - node_it++; - } - EXPECT_EQ(node_it, node_end); - } - } -} - -TEST_F(PassClassTest, DominatorUnreachableInLoop) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpTypeBool - %5 = OpTypeInt 32 0 - %6 = OpConstant %5 0 - %7 = OpConstantFalse %4 - %8 = OpConstantTrue %4 - %9 = OpConstant %5 1 - %1 = OpFunction %2 None %3 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - OpSwitch %6 %12 1 %13 - %12 = OpLabel - OpBranch %14 - %13 = OpLabel - OpUnreachable - %14 = OpLabel - OpBranchConditional %8 %11 %15 - %15 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* fn = spvtest::GetFunction(module, 1); - - const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); - EXPECT_EQ(entry, fn->entry().get()) - << "The entry node is not the expected one"; - - // Check normal dominator tree - { - DominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE( - dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12, 13, 14, 15}) - check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 10, 11); - check_dominance(dom_tree, fn, 10, 13); - check_dominance(dom_tree, fn, 10, 12); - check_dominance(dom_tree, fn, 10, 14); - check_dominance(dom_tree, fn, 10, 15); - - check_dominance(dom_tree, fn, 11, 12); - check_dominance(dom_tree, fn, 11, 13); - check_dominance(dom_tree, fn, 11, 14); - check_dominance(dom_tree, fn, 11, 15); - - check_dominance(dom_tree, fn, 12, 14); - check_dominance(dom_tree, fn, 12, 15); - - check_dominance(dom_tree, fn, 14, 15); - - check_no_dominance(dom_tree, fn, 13, 12); - check_no_dominance(dom_tree, fn, 13, 14); - check_no_dominance(dom_tree, fn, 13, 15); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 10)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), - spvtest::GetBasicBlock(fn, 12)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), - spvtest::GetBasicBlock(fn, 14)); - } - - // Check post dominator tree. - { - PostDominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // (strict) dominance checks. - for (uint32_t id : {10, 11, 12, 13, 14, 15}) - check_dominance(dom_tree, fn, id, id); - - check_no_dominance(dom_tree, fn, 15, 10); - check_no_dominance(dom_tree, fn, 15, 11); - check_no_dominance(dom_tree, fn, 15, 12); - check_no_dominance(dom_tree, fn, 15, 13); - check_no_dominance(dom_tree, fn, 15, 14); - - check_dominance(dom_tree, fn, 14, 12); - - check_no_dominance(dom_tree, fn, 13, 10); - check_no_dominance(dom_tree, fn, 13, 11); - check_no_dominance(dom_tree, fn, 13, 12); - check_no_dominance(dom_tree, fn, 13, 14); - check_no_dominance(dom_tree, fn, 13, 15); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 14)); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), - cfg.pseudo_exit_block()); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), - cfg.pseudo_exit_block()); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), - cfg.pseudo_exit_block()); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - cfg.pseudo_exit_block()); - } -} - -TEST_F(PassClassTest, DominatorInfinitLoop) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpTypeBool - %5 = OpTypeInt 32 0 - %6 = OpConstant %5 0 - %7 = OpConstantFalse %4 - %8 = OpConstantTrue %4 - %9 = OpConstant %5 1 - %1 = OpFunction %2 None %3 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - OpSwitch %6 %12 1 %13 - %12 = OpLabel - OpReturn - %13 = OpLabel - OpBranch %13 - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* fn = spvtest::GetFunction(module, 1); - - const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); - EXPECT_EQ(entry, fn->entry().get()) - << "The entry node is not the expected one"; - // Check normal dominator tree - { - DominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE( - dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12, 13}) check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 10, 11); - check_dominance(dom_tree, fn, 10, 12); - check_dominance(dom_tree, fn, 10, 13); - - check_dominance(dom_tree, fn, 11, 12); - check_dominance(dom_tree, fn, 11, 13); - - check_no_dominance(dom_tree, fn, 13, 12); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 10)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - spvtest::GetBasicBlock(fn, 11)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), - spvtest::GetBasicBlock(fn, 11)); - } - - // Check post dominator tree - { - PostDominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); - EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12)); - - // (strict) dominance checks - for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 12, 11); - check_dominance(dom_tree, fn, 12, 10); - - // 13 should be completely out of tree as it's unreachable from exit nodes - check_no_dominance(dom_tree, fn, 12, 13); - check_no_dominance(dom_tree, fn, 11, 13); - check_no_dominance(dom_tree, fn, 10, 13); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), - cfg.pseudo_exit_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), - spvtest::GetBasicBlock(fn, 11)); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), - spvtest::GetBasicBlock(fn, 12)); - } -} - -TEST_F(PassClassTest, DominatorUnreachableFromEntry) { - const std::string text = R"( - OpCapability Addresses - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpTypeBool - %5 = OpTypeInt 32 0 - %6 = OpConstantFalse %4 - %7 = OpConstantTrue %4 - %1 = OpFunction %2 None %3 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpReturn - %10 = OpLabel - OpBranch %9 - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* fn = spvtest::GetFunction(module, 1); - - const BasicBlock* entry = spvtest::GetBasicBlock(fn, 8); - EXPECT_EQ(entry, fn->entry().get()) - << "The entry node is not the expected one"; - - // Check dominator tree - { - DominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE( - dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); - - // (strict) dominance checks - for (uint32_t id : {8, 9}) check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 8, 9); - - check_no_dominance(dom_tree, fn, 10, 8); - check_no_dominance(dom_tree, fn, 10, 9); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); - - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), - spvtest::GetBasicBlock(fn, 8)); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), - nullptr); - } - - // Check post dominator tree - { - PostDominatorAnalysis dom_tree; - const CFG& cfg = *context->cfg(); - dom_tree.InitializeTree(cfg, fn); - - // Inspect the actual tree - DominatorTree& tree = dom_tree.GetDomTree(); - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); - EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 9)); - - // (strict) dominance checks - for (uint32_t id : {8, 9, 10}) check_dominance(dom_tree, fn, id, id); - - check_dominance(dom_tree, fn, 9, 8); - check_dominance(dom_tree, fn, 9, 10); - - EXPECT_EQ(dom_tree.ImmediateDominator(entry), - spvtest::GetBasicBlock(fn, 9)); - - EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), - cfg.pseudo_exit_block()); - EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), - spvtest::GetBasicBlock(fn, 9)); - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_ifs.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/nested_ifs.cpp deleted file mode 100644 index 0552b7580..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_ifs.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 v; -void main(){ - if (true) { - if (true) { - v = vec4(1,1,1,1); - } else { - v = vec4(2,2,2,2); - } - } else { - if (true) { - v = vec4(3,3,3,3); - } else { - v = vec4(4,4,4,4); - } - } -} -*/ -TEST_F(PassClassTest, UnreachableNestedIfs) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %15 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 330 - OpName %4 "main" - OpName %15 "v" - OpDecorate %15 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpConstantTrue %6 - %12 = OpTypeFloat 32 - %13 = OpTypeVector %12 4 - %14 = OpTypePointer Output %13 - %15 = OpVariable %14 Output - %16 = OpConstant %12 1 - %17 = OpConstantComposite %13 %16 %16 %16 %16 - %19 = OpConstant %12 2 - %20 = OpConstantComposite %13 %19 %19 %19 %19 - %24 = OpConstant %12 3 - %25 = OpConstantComposite %13 %24 %24 %24 %24 - %27 = OpConstant %12 4 - %28 = OpConstantComposite %13 %27 %27 %27 %27 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %7 %8 %21 - %8 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %7 %10 %18 - %10 = OpLabel - OpStore %15 %17 - OpBranch %11 - %18 = OpLabel - OpStore %15 %20 - OpBranch %11 - %11 = OpLabel - OpBranch %9 - %21 = OpLabel - OpSelectionMerge %23 None - OpBranchConditional %7 %22 %26 - %22 = OpLabel - OpStore %15 %25 - OpBranch %23 - %26 = OpLabel - OpStore %15 %28 - OpBranch %23 - %23 = OpLabel - OpBranch %9 - %9 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - - DominatorAnalysis* analysis = context->GetDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(5, 8)); - EXPECT_TRUE(analysis->Dominates(5, 9)); - EXPECT_TRUE(analysis->Dominates(5, 21)); - EXPECT_TRUE(analysis->Dominates(5, 18)); - EXPECT_TRUE(analysis->Dominates(5, 10)); - EXPECT_TRUE(analysis->Dominates(5, 11)); - EXPECT_TRUE(analysis->Dominates(5, 23)); - EXPECT_TRUE(analysis->Dominates(5, 22)); - EXPECT_TRUE(analysis->Dominates(5, 26)); - EXPECT_TRUE(analysis->Dominates(8, 18)); - EXPECT_TRUE(analysis->Dominates(8, 10)); - EXPECT_TRUE(analysis->Dominates(8, 11)); - EXPECT_TRUE(analysis->Dominates(21, 23)); - EXPECT_TRUE(analysis->Dominates(21, 22)); - EXPECT_TRUE(analysis->Dominates(21, 26)); - - EXPECT_TRUE(analysis->StrictlyDominates(5, 8)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 9)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 21)); - EXPECT_TRUE(analysis->StrictlyDominates(8, 18)); - EXPECT_TRUE(analysis->StrictlyDominates(8, 10)); - EXPECT_TRUE(analysis->StrictlyDominates(8, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(21, 23)); - EXPECT_TRUE(analysis->StrictlyDominates(21, 22)); - EXPECT_TRUE(analysis->StrictlyDominates(21, 26)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_ifs_post.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/nested_ifs_post.cpp deleted file mode 100644 index ad759df86..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_ifs_post.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 v; -void main(){ - if (true) { - if (true) { - v = vec4(1,1,1,1); - } else { - v = vec4(2,2,2,2); - } - } else { - if (true) { - v = vec4(3,3,3,3); - } else { - v = vec4(4,4,4,4); - } - } -} -*/ -TEST_F(PassClassTest, UnreachableNestedIfs) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %15 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 330 - OpName %4 "main" - OpName %15 "v" - OpDecorate %15 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpConstantTrue %6 - %12 = OpTypeFloat 32 - %13 = OpTypeVector %12 4 - %14 = OpTypePointer Output %13 - %15 = OpVariable %14 Output - %16 = OpConstant %12 1 - %17 = OpConstantComposite %13 %16 %16 %16 %16 - %19 = OpConstant %12 2 - %20 = OpConstantComposite %13 %19 %19 %19 %19 - %24 = OpConstant %12 3 - %25 = OpConstantComposite %13 %24 %24 %24 %24 - %27 = OpConstant %12 4 - %28 = OpConstantComposite %13 %27 %27 %27 %27 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %7 %8 %21 - %8 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %7 %10 %18 - %10 = OpLabel - OpStore %15 %17 - OpBranch %11 - %18 = OpLabel - OpStore %15 %20 - OpBranch %11 - %11 = OpLabel - OpBranch %9 - %21 = OpLabel - OpSelectionMerge %23 None - OpBranchConditional %7 %22 %26 - %22 = OpLabel - OpStore %15 %25 - OpBranch %23 - %26 = OpLabel - OpStore %15 %28 - OpBranch %23 - %23 = OpLabel - OpBranch %9 - %9 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - - PostDominatorAnalysis* analysis = context->GetPostDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(5, 5)); - EXPECT_TRUE(analysis->Dominates(8, 8)); - EXPECT_TRUE(analysis->Dominates(9, 9)); - EXPECT_TRUE(analysis->Dominates(10, 10)); - EXPECT_TRUE(analysis->Dominates(11, 11)); - EXPECT_TRUE(analysis->Dominates(18, 18)); - EXPECT_TRUE(analysis->Dominates(21, 21)); - EXPECT_TRUE(analysis->Dominates(22, 22)); - EXPECT_TRUE(analysis->Dominates(23, 23)); - EXPECT_TRUE(analysis->Dominates(26, 26)); - EXPECT_TRUE(analysis->Dominates(9, 5)); - EXPECT_TRUE(analysis->Dominates(9, 11)); - EXPECT_TRUE(analysis->Dominates(9, 23)); - EXPECT_TRUE(analysis->Dominates(11, 10)); - EXPECT_TRUE(analysis->Dominates(11, 18)); - EXPECT_TRUE(analysis->Dominates(11, 8)); - EXPECT_TRUE(analysis->Dominates(23, 22)); - EXPECT_TRUE(analysis->Dominates(23, 26)); - EXPECT_TRUE(analysis->Dominates(23, 21)); - - EXPECT_TRUE(analysis->StrictlyDominates(9, 5)); - EXPECT_TRUE(analysis->StrictlyDominates(9, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(9, 23)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 10)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 18)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 8)); - EXPECT_TRUE(analysis->StrictlyDominates(23, 22)); - EXPECT_TRUE(analysis->StrictlyDominates(23, 26)); - EXPECT_TRUE(analysis->StrictlyDominates(23, 21)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_loops.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/nested_loops.cpp deleted file mode 100644 index 7d03937b1..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_loops.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 440 core -layout(location = 0) out vec4 v; -layout(location = 1) in vec4 in_val; -void main() { - for (int i = 0; i < in_val.x; ++i) { - for (int j = 0; j < in_val.y; j++) { - } - } - for (int i = 0; i < in_val.x; ++i) { - for (int j = 0; j < in_val.y; j++) { - } - if (in_val.z == in_val.w) { - break; - } - } - int i = 0; - while (i < in_val.x) { - ++i; - for (int j = 0; j < 1; j++) { - for (int k = 0; k < 1; k++) { - } - } - } - i = 0; - while (i < in_val.x) { - ++i; - if (in_val.z == in_val.w) { - continue; - } - for (int j = 0; j < 1; j++) { - for (int k = 0; k < 1; k++) { - } - if (in_val.z == in_val.w) { - break; - } - } - } - v = vec4(1,1,1,1); -} -*/ -TEST_F(PassClassTest, BasicVisitFromEntryPoint) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %20 %163 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %20 "in_val" - OpName %28 "j" - OpName %45 "i" - OpName %56 "j" - OpName %81 "i" - OpName %94 "j" - OpName %102 "k" - OpName %134 "j" - OpName %142 "k" - OpName %163 "v" - OpDecorate %20 Location 1 - OpDecorate %163 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpTypeFloat 32 - %18 = OpTypeVector %16 4 - %19 = OpTypePointer Input %18 - %20 = OpVariable %19 Input - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 0 - %23 = OpTypePointer Input %16 - %26 = OpTypeBool - %36 = OpConstant %21 1 - %41 = OpConstant %6 1 - %69 = OpConstant %21 2 - %72 = OpConstant %21 3 - %162 = OpTypePointer Output %18 - %163 = OpVariable %162 Output - %164 = OpConstant %16 1 - %165 = OpConstantComposite %18 %164 %164 %164 %164 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %28 = OpVariable %7 Function - %45 = OpVariable %7 Function - %56 = OpVariable %7 Function - %81 = OpVariable %7 Function - %94 = OpVariable %7 Function - %102 = OpVariable %7 Function - %134 = OpVariable %7 Function - %142 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %17 = OpConvertSToF %16 %15 - %24 = OpAccessChain %23 %20 %22 - %25 = OpLoad %16 %24 - %27 = OpFOrdLessThan %26 %17 %25 - OpBranchConditional %27 %11 %12 - %11 = OpLabel - OpStore %28 %9 - OpBranch %29 - %29 = OpLabel - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %34 = OpLoad %6 %28 - %35 = OpConvertSToF %16 %34 - %37 = OpAccessChain %23 %20 %36 - %38 = OpLoad %16 %37 - %39 = OpFOrdLessThan %26 %35 %38 - OpBranchConditional %39 %30 %31 - %30 = OpLabel - OpBranch %32 - %32 = OpLabel - %40 = OpLoad %6 %28 - %42 = OpIAdd %6 %40 %41 - OpStore %28 %42 - OpBranch %29 - %31 = OpLabel - OpBranch %13 - %13 = OpLabel - %43 = OpLoad %6 %8 - %44 = OpIAdd %6 %43 %41 - OpStore %8 %44 - OpBranch %10 - %12 = OpLabel - OpStore %45 %9 - OpBranch %46 - %46 = OpLabel - OpLoopMerge %48 %49 None - OpBranch %50 - %50 = OpLabel - %51 = OpLoad %6 %45 - %52 = OpConvertSToF %16 %51 - %53 = OpAccessChain %23 %20 %22 - %54 = OpLoad %16 %53 - %55 = OpFOrdLessThan %26 %52 %54 - OpBranchConditional %55 %47 %48 - %47 = OpLabel - OpStore %56 %9 - OpBranch %57 - %57 = OpLabel - OpLoopMerge %59 %60 None - OpBranch %61 - %61 = OpLabel - %62 = OpLoad %6 %56 - %63 = OpConvertSToF %16 %62 - %64 = OpAccessChain %23 %20 %36 - %65 = OpLoad %16 %64 - %66 = OpFOrdLessThan %26 %63 %65 - OpBranchConditional %66 %58 %59 - %58 = OpLabel - OpBranch %60 - %60 = OpLabel - %67 = OpLoad %6 %56 - %68 = OpIAdd %6 %67 %41 - OpStore %56 %68 - OpBranch %57 - %59 = OpLabel - %70 = OpAccessChain %23 %20 %69 - %71 = OpLoad %16 %70 - %73 = OpAccessChain %23 %20 %72 - %74 = OpLoad %16 %73 - %75 = OpFOrdEqual %26 %71 %74 - OpSelectionMerge %77 None - OpBranchConditional %75 %76 %77 - %76 = OpLabel - OpBranch %48 - %77 = OpLabel - OpBranch %49 - %49 = OpLabel - %79 = OpLoad %6 %45 - %80 = OpIAdd %6 %79 %41 - OpStore %45 %80 - OpBranch %46 - %48 = OpLabel - OpStore %81 %9 - OpBranch %82 - %82 = OpLabel - OpLoopMerge %84 %85 None - OpBranch %86 - %86 = OpLabel - %87 = OpLoad %6 %81 - %88 = OpConvertSToF %16 %87 - %89 = OpAccessChain %23 %20 %22 - %90 = OpLoad %16 %89 - %91 = OpFOrdLessThan %26 %88 %90 - OpBranchConditional %91 %83 %84 - %83 = OpLabel - %92 = OpLoad %6 %81 - %93 = OpIAdd %6 %92 %41 - OpStore %81 %93 - OpStore %94 %9 - OpBranch %95 - %95 = OpLabel - OpLoopMerge %97 %98 None - OpBranch %99 - %99 = OpLabel - %100 = OpLoad %6 %94 - %101 = OpSLessThan %26 %100 %41 - OpBranchConditional %101 %96 %97 - %96 = OpLabel - OpStore %102 %9 - OpBranch %103 - %103 = OpLabel - OpLoopMerge %105 %106 None - OpBranch %107 - %107 = OpLabel - %108 = OpLoad %6 %102 - %109 = OpSLessThan %26 %108 %41 - OpBranchConditional %109 %104 %105 - %104 = OpLabel - OpBranch %106 - %106 = OpLabel - %110 = OpLoad %6 %102 - %111 = OpIAdd %6 %110 %41 - OpStore %102 %111 - OpBranch %103 - %105 = OpLabel - OpBranch %98 - %98 = OpLabel - %112 = OpLoad %6 %94 - %113 = OpIAdd %6 %112 %41 - OpStore %94 %113 - OpBranch %95 - %97 = OpLabel - OpBranch %85 - %85 = OpLabel - OpBranch %82 - %84 = OpLabel - OpStore %81 %9 - OpBranch %114 - %114 = OpLabel - OpLoopMerge %116 %117 None - OpBranch %118 - %118 = OpLabel - %119 = OpLoad %6 %81 - %120 = OpConvertSToF %16 %119 - %121 = OpAccessChain %23 %20 %22 - %122 = OpLoad %16 %121 - %123 = OpFOrdLessThan %26 %120 %122 - OpBranchConditional %123 %115 %116 - %115 = OpLabel - %124 = OpLoad %6 %81 - %125 = OpIAdd %6 %124 %41 - OpStore %81 %125 - %126 = OpAccessChain %23 %20 %69 - %127 = OpLoad %16 %126 - %128 = OpAccessChain %23 %20 %72 - %129 = OpLoad %16 %128 - %130 = OpFOrdEqual %26 %127 %129 - OpSelectionMerge %132 None - OpBranchConditional %130 %131 %132 - %131 = OpLabel - OpBranch %117 - %132 = OpLabel - OpStore %134 %9 - OpBranch %135 - %135 = OpLabel - OpLoopMerge %137 %138 None - OpBranch %139 - %139 = OpLabel - %140 = OpLoad %6 %134 - %141 = OpSLessThan %26 %140 %41 - OpBranchConditional %141 %136 %137 - %136 = OpLabel - OpStore %142 %9 - OpBranch %143 - %143 = OpLabel - OpLoopMerge %145 %146 None - OpBranch %147 - %147 = OpLabel - %148 = OpLoad %6 %142 - %149 = OpSLessThan %26 %148 %41 - OpBranchConditional %149 %144 %145 - %144 = OpLabel - OpBranch %146 - %146 = OpLabel - %150 = OpLoad %6 %142 - %151 = OpIAdd %6 %150 %41 - OpStore %142 %151 - OpBranch %143 - %145 = OpLabel - %152 = OpAccessChain %23 %20 %69 - %153 = OpLoad %16 %152 - %154 = OpAccessChain %23 %20 %72 - %155 = OpLoad %16 %154 - %156 = OpFOrdEqual %26 %153 %155 - OpSelectionMerge %158 None - OpBranchConditional %156 %157 %158 - %157 = OpLabel - OpBranch %137 - %158 = OpLabel - OpBranch %138 - %138 = OpLabel - %160 = OpLoad %6 %134 - %161 = OpIAdd %6 %160 %41 - OpStore %134 %161 - OpBranch %135 - %137 = OpLabel - OpBranch %117 - %117 = OpLabel - OpBranch %114 - %116 = OpLabel - OpStore %163 %165 - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - DominatorAnalysis* analysis = context->GetDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(5, 10)); - EXPECT_TRUE(analysis->Dominates(5, 46)); - EXPECT_TRUE(analysis->Dominates(5, 82)); - EXPECT_TRUE(analysis->Dominates(5, 114)); - EXPECT_TRUE(analysis->Dominates(5, 116)); - - EXPECT_TRUE(analysis->Dominates(10, 14)); - EXPECT_TRUE(analysis->Dominates(10, 11)); - EXPECT_TRUE(analysis->Dominates(10, 29)); - EXPECT_TRUE(analysis->Dominates(10, 33)); - EXPECT_TRUE(analysis->Dominates(10, 30)); - EXPECT_TRUE(analysis->Dominates(10, 32)); - EXPECT_TRUE(analysis->Dominates(10, 31)); - EXPECT_TRUE(analysis->Dominates(10, 13)); - EXPECT_TRUE(analysis->Dominates(10, 12)); - - EXPECT_TRUE(analysis->Dominates(12, 46)); - - EXPECT_TRUE(analysis->Dominates(46, 50)); - EXPECT_TRUE(analysis->Dominates(46, 47)); - EXPECT_TRUE(analysis->Dominates(46, 57)); - EXPECT_TRUE(analysis->Dominates(46, 61)); - EXPECT_TRUE(analysis->Dominates(46, 58)); - EXPECT_TRUE(analysis->Dominates(46, 60)); - EXPECT_TRUE(analysis->Dominates(46, 59)); - EXPECT_TRUE(analysis->Dominates(46, 77)); - EXPECT_TRUE(analysis->Dominates(46, 49)); - EXPECT_TRUE(analysis->Dominates(46, 76)); - EXPECT_TRUE(analysis->Dominates(46, 48)); - - EXPECT_TRUE(analysis->Dominates(48, 82)); - - EXPECT_TRUE(analysis->Dominates(82, 86)); - EXPECT_TRUE(analysis->Dominates(82, 83)); - EXPECT_TRUE(analysis->Dominates(82, 95)); - EXPECT_TRUE(analysis->Dominates(82, 99)); - EXPECT_TRUE(analysis->Dominates(82, 96)); - EXPECT_TRUE(analysis->Dominates(82, 103)); - EXPECT_TRUE(analysis->Dominates(82, 107)); - EXPECT_TRUE(analysis->Dominates(82, 104)); - EXPECT_TRUE(analysis->Dominates(82, 106)); - EXPECT_TRUE(analysis->Dominates(82, 105)); - EXPECT_TRUE(analysis->Dominates(82, 98)); - EXPECT_TRUE(analysis->Dominates(82, 97)); - EXPECT_TRUE(analysis->Dominates(82, 85)); - EXPECT_TRUE(analysis->Dominates(82, 84)); - - EXPECT_TRUE(analysis->Dominates(84, 114)); - - EXPECT_TRUE(analysis->Dominates(114, 118)); - EXPECT_TRUE(analysis->Dominates(114, 116)); - EXPECT_TRUE(analysis->Dominates(114, 115)); - EXPECT_TRUE(analysis->Dominates(114, 132)); - EXPECT_TRUE(analysis->Dominates(114, 135)); - EXPECT_TRUE(analysis->Dominates(114, 139)); - EXPECT_TRUE(analysis->Dominates(114, 136)); - EXPECT_TRUE(analysis->Dominates(114, 143)); - EXPECT_TRUE(analysis->Dominates(114, 147)); - EXPECT_TRUE(analysis->Dominates(114, 144)); - EXPECT_TRUE(analysis->Dominates(114, 146)); - EXPECT_TRUE(analysis->Dominates(114, 145)); - EXPECT_TRUE(analysis->Dominates(114, 158)); - EXPECT_TRUE(analysis->Dominates(114, 138)); - EXPECT_TRUE(analysis->Dominates(114, 137)); - EXPECT_TRUE(analysis->Dominates(114, 131)); - EXPECT_TRUE(analysis->Dominates(114, 117)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_loops_with_unreachables.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/nested_loops_with_unreachables.cpp deleted file mode 100644 index e87e8ddab..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/nested_loops_with_unreachables.cpp +++ /dev/null @@ -1,848 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; - -using PassClassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL -#version 440 core -layout(location = 0) out vec4 v; -layout(location = 1) in vec4 in_val; -void main() { - for (int i = 0; i < in_val.x; ++i) { - for (int j = 0; j < in_val.y; j++) { - } - } - for (int i = 0; i < in_val.x; ++i) { - for (int j = 0; j < in_val.y; j++) { - } - break; - } - int i = 0; - while (i < in_val.x) { - ++i; - for (int j = 0; j < 1; j++) { - for (int k = 0; k < 1; k++) { - } - break; - } - } - i = 0; - while (i < in_val.x) { - ++i; - continue; - for (int j = 0; j < 1; j++) { - for (int k = 0; k < 1; k++) { - } - break; - } - } - v = vec4(1,1,1,1); -} -*/ -TEST_F(PassClassTest, BasicVisitFromEntryPoint) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %20 %141 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %20 "in_val" - OpName %28 "j" - OpName %45 "i" - OpName %56 "j" - OpName %72 "i" - OpName %85 "j" - OpName %93 "k" - OpName %119 "j" - OpName %127 "k" - OpName %141 "v" - OpDecorate %20 Location 1 - OpDecorate %141 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpTypeFloat 32 - %18 = OpTypeVector %16 4 - %19 = OpTypePointer Input %18 - %20 = OpVariable %19 Input - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 0 - %23 = OpTypePointer Input %16 - %26 = OpTypeBool - %36 = OpConstant %21 1 - %41 = OpConstant %6 1 - %140 = OpTypePointer Output %18 - %141 = OpVariable %140 Output - %142 = OpConstant %16 1 - %143 = OpConstantComposite %18 %142 %142 %142 %142 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %28 = OpVariable %7 Function - %45 = OpVariable %7 Function - %56 = OpVariable %7 Function - %72 = OpVariable %7 Function - %85 = OpVariable %7 Function - %93 = OpVariable %7 Function - %119 = OpVariable %7 Function - %127 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %17 = OpConvertSToF %16 %15 - %24 = OpAccessChain %23 %20 %22 - %25 = OpLoad %16 %24 - %27 = OpFOrdLessThan %26 %17 %25 - OpBranchConditional %27 %11 %12 - %11 = OpLabel - OpStore %28 %9 - OpBranch %29 - %29 = OpLabel - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %34 = OpLoad %6 %28 - %35 = OpConvertSToF %16 %34 - %37 = OpAccessChain %23 %20 %36 - %38 = OpLoad %16 %37 - %39 = OpFOrdLessThan %26 %35 %38 - OpBranchConditional %39 %30 %31 - %30 = OpLabel - OpBranch %32 - %32 = OpLabel - %40 = OpLoad %6 %28 - %42 = OpIAdd %6 %40 %41 - OpStore %28 %42 - OpBranch %29 - %31 = OpLabel - OpBranch %13 - %13 = OpLabel - %43 = OpLoad %6 %8 - %44 = OpIAdd %6 %43 %41 - OpStore %8 %44 - OpBranch %10 - %12 = OpLabel - OpStore %45 %9 - OpBranch %46 - %46 = OpLabel - OpLoopMerge %48 %49 None - OpBranch %50 - %50 = OpLabel - %51 = OpLoad %6 %45 - %52 = OpConvertSToF %16 %51 - %53 = OpAccessChain %23 %20 %22 - %54 = OpLoad %16 %53 - %55 = OpFOrdLessThan %26 %52 %54 - OpBranchConditional %55 %47 %48 - %47 = OpLabel - OpStore %56 %9 - OpBranch %57 - %57 = OpLabel - OpLoopMerge %59 %60 None - OpBranch %61 - %61 = OpLabel - %62 = OpLoad %6 %56 - %63 = OpConvertSToF %16 %62 - %64 = OpAccessChain %23 %20 %36 - %65 = OpLoad %16 %64 - %66 = OpFOrdLessThan %26 %63 %65 - OpBranchConditional %66 %58 %59 - %58 = OpLabel - OpBranch %60 - %60 = OpLabel - %67 = OpLoad %6 %56 - %68 = OpIAdd %6 %67 %41 - OpStore %56 %68 - OpBranch %57 - %59 = OpLabel - OpBranch %48 - %49 = OpLabel - %70 = OpLoad %6 %45 - %71 = OpIAdd %6 %70 %41 - OpStore %45 %71 - OpBranch %46 - %48 = OpLabel - OpStore %72 %9 - OpBranch %73 - %73 = OpLabel - OpLoopMerge %75 %76 None - OpBranch %77 - %77 = OpLabel - %78 = OpLoad %6 %72 - %79 = OpConvertSToF %16 %78 - %80 = OpAccessChain %23 %20 %22 - %81 = OpLoad %16 %80 - %82 = OpFOrdLessThan %26 %79 %81 - OpBranchConditional %82 %74 %75 - %74 = OpLabel - %83 = OpLoad %6 %72 - %84 = OpIAdd %6 %83 %41 - OpStore %72 %84 - OpStore %85 %9 - OpBranch %86 - %86 = OpLabel - OpLoopMerge %88 %89 None - OpBranch %90 - %90 = OpLabel - %91 = OpLoad %6 %85 - %92 = OpSLessThan %26 %91 %41 - OpBranchConditional %92 %87 %88 - %87 = OpLabel - OpStore %93 %9 - OpBranch %94 - %94 = OpLabel - OpLoopMerge %96 %97 None - OpBranch %98 - %98 = OpLabel - %99 = OpLoad %6 %93 - %100 = OpSLessThan %26 %99 %41 - OpBranchConditional %100 %95 %96 - %95 = OpLabel - OpBranch %97 - %97 = OpLabel - %101 = OpLoad %6 %93 - %102 = OpIAdd %6 %101 %41 - OpStore %93 %102 - OpBranch %94 - %96 = OpLabel - OpBranch %88 - %89 = OpLabel - %104 = OpLoad %6 %85 - %105 = OpIAdd %6 %104 %41 - OpStore %85 %105 - OpBranch %86 - %88 = OpLabel - OpBranch %76 - %76 = OpLabel - OpBranch %73 - %75 = OpLabel - OpStore %72 %9 - OpBranch %106 - %106 = OpLabel - OpLoopMerge %108 %109 None - OpBranch %110 - %110 = OpLabel - %111 = OpLoad %6 %72 - %112 = OpConvertSToF %16 %111 - %113 = OpAccessChain %23 %20 %22 - %114 = OpLoad %16 %113 - %115 = OpFOrdLessThan %26 %112 %114 - OpBranchConditional %115 %107 %108 - %107 = OpLabel - %116 = OpLoad %6 %72 - %117 = OpIAdd %6 %116 %41 - OpStore %72 %117 - OpBranch %109 - %109 = OpLabel - OpBranch %106 - %108 = OpLabel - OpStore %141 %143 - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - DominatorAnalysis* analysis = context->GetDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(5, 10)); - EXPECT_TRUE(analysis->Dominates(5, 14)); - EXPECT_TRUE(analysis->Dominates(5, 11)); - EXPECT_TRUE(analysis->Dominates(5, 29)); - EXPECT_TRUE(analysis->Dominates(5, 33)); - EXPECT_TRUE(analysis->Dominates(5, 30)); - EXPECT_TRUE(analysis->Dominates(5, 32)); - EXPECT_TRUE(analysis->Dominates(5, 31)); - EXPECT_TRUE(analysis->Dominates(5, 13)); - EXPECT_TRUE(analysis->Dominates(5, 12)); - EXPECT_TRUE(analysis->Dominates(5, 46)); - EXPECT_TRUE(analysis->Dominates(5, 50)); - EXPECT_TRUE(analysis->Dominates(5, 47)); - EXPECT_TRUE(analysis->Dominates(5, 57)); - EXPECT_TRUE(analysis->Dominates(5, 61)); - EXPECT_TRUE(analysis->Dominates(5, 59)); - EXPECT_TRUE(analysis->Dominates(5, 58)); - EXPECT_TRUE(analysis->Dominates(5, 60)); - EXPECT_TRUE(analysis->Dominates(5, 48)); - EXPECT_TRUE(analysis->Dominates(5, 73)); - EXPECT_TRUE(analysis->Dominates(5, 77)); - EXPECT_TRUE(analysis->Dominates(5, 75)); - EXPECT_TRUE(analysis->Dominates(5, 106)); - EXPECT_TRUE(analysis->Dominates(5, 110)); - EXPECT_TRUE(analysis->Dominates(5, 107)); - EXPECT_TRUE(analysis->Dominates(5, 108)); - EXPECT_TRUE(analysis->Dominates(5, 109)); - EXPECT_TRUE(analysis->Dominates(5, 74)); - EXPECT_TRUE(analysis->Dominates(5, 86)); - EXPECT_TRUE(analysis->Dominates(5, 90)); - EXPECT_TRUE(analysis->Dominates(5, 87)); - EXPECT_TRUE(analysis->Dominates(5, 94)); - EXPECT_TRUE(analysis->Dominates(5, 98)); - EXPECT_TRUE(analysis->Dominates(5, 95)); - EXPECT_TRUE(analysis->Dominates(5, 97)); - EXPECT_TRUE(analysis->Dominates(5, 96)); - EXPECT_TRUE(analysis->Dominates(5, 88)); - EXPECT_TRUE(analysis->Dominates(5, 76)); - - EXPECT_TRUE(analysis->Dominates(10, 14)); - EXPECT_TRUE(analysis->Dominates(10, 11)); - EXPECT_TRUE(analysis->Dominates(10, 29)); - EXPECT_TRUE(analysis->Dominates(10, 33)); - EXPECT_TRUE(analysis->Dominates(10, 30)); - EXPECT_TRUE(analysis->Dominates(10, 32)); - EXPECT_TRUE(analysis->Dominates(10, 31)); - EXPECT_TRUE(analysis->Dominates(10, 13)); - EXPECT_TRUE(analysis->Dominates(10, 12)); - EXPECT_TRUE(analysis->Dominates(10, 46)); - EXPECT_TRUE(analysis->Dominates(10, 50)); - EXPECT_TRUE(analysis->Dominates(10, 47)); - EXPECT_TRUE(analysis->Dominates(10, 57)); - EXPECT_TRUE(analysis->Dominates(10, 61)); - EXPECT_TRUE(analysis->Dominates(10, 59)); - EXPECT_TRUE(analysis->Dominates(10, 58)); - EXPECT_TRUE(analysis->Dominates(10, 60)); - EXPECT_TRUE(analysis->Dominates(10, 48)); - EXPECT_TRUE(analysis->Dominates(10, 73)); - EXPECT_TRUE(analysis->Dominates(10, 77)); - EXPECT_TRUE(analysis->Dominates(10, 75)); - EXPECT_TRUE(analysis->Dominates(10, 106)); - EXPECT_TRUE(analysis->Dominates(10, 110)); - EXPECT_TRUE(analysis->Dominates(10, 107)); - EXPECT_TRUE(analysis->Dominates(10, 108)); - EXPECT_TRUE(analysis->Dominates(10, 109)); - EXPECT_TRUE(analysis->Dominates(10, 74)); - EXPECT_TRUE(analysis->Dominates(10, 86)); - EXPECT_TRUE(analysis->Dominates(10, 90)); - EXPECT_TRUE(analysis->Dominates(10, 87)); - EXPECT_TRUE(analysis->Dominates(10, 94)); - EXPECT_TRUE(analysis->Dominates(10, 98)); - EXPECT_TRUE(analysis->Dominates(10, 95)); - EXPECT_TRUE(analysis->Dominates(10, 97)); - EXPECT_TRUE(analysis->Dominates(10, 96)); - EXPECT_TRUE(analysis->Dominates(10, 88)); - EXPECT_TRUE(analysis->Dominates(10, 76)); - - EXPECT_TRUE(analysis->Dominates(14, 11)); - EXPECT_TRUE(analysis->Dominates(14, 29)); - EXPECT_TRUE(analysis->Dominates(14, 33)); - EXPECT_TRUE(analysis->Dominates(14, 30)); - EXPECT_TRUE(analysis->Dominates(14, 32)); - EXPECT_TRUE(analysis->Dominates(14, 31)); - - EXPECT_TRUE(analysis->Dominates(11, 29)); - EXPECT_TRUE(analysis->Dominates(11, 33)); - EXPECT_TRUE(analysis->Dominates(11, 30)); - EXPECT_TRUE(analysis->Dominates(11, 32)); - EXPECT_TRUE(analysis->Dominates(11, 31)); - - EXPECT_TRUE(analysis->Dominates(29, 33)); - EXPECT_TRUE(analysis->Dominates(29, 30)); - EXPECT_TRUE(analysis->Dominates(29, 32)); - EXPECT_TRUE(analysis->Dominates(29, 31)); - - EXPECT_TRUE(analysis->Dominates(33, 30)); - - EXPECT_TRUE(analysis->Dominates(12, 46)); - EXPECT_TRUE(analysis->Dominates(12, 50)); - EXPECT_TRUE(analysis->Dominates(12, 47)); - EXPECT_TRUE(analysis->Dominates(12, 57)); - EXPECT_TRUE(analysis->Dominates(12, 61)); - EXPECT_TRUE(analysis->Dominates(12, 59)); - EXPECT_TRUE(analysis->Dominates(12, 58)); - EXPECT_TRUE(analysis->Dominates(12, 60)); - EXPECT_TRUE(analysis->Dominates(12, 48)); - EXPECT_TRUE(analysis->Dominates(12, 73)); - EXPECT_TRUE(analysis->Dominates(12, 77)); - EXPECT_TRUE(analysis->Dominates(12, 75)); - EXPECT_TRUE(analysis->Dominates(12, 106)); - EXPECT_TRUE(analysis->Dominates(12, 110)); - EXPECT_TRUE(analysis->Dominates(12, 107)); - EXPECT_TRUE(analysis->Dominates(12, 108)); - EXPECT_TRUE(analysis->Dominates(12, 109)); - EXPECT_TRUE(analysis->Dominates(12, 74)); - EXPECT_TRUE(analysis->Dominates(12, 86)); - EXPECT_TRUE(analysis->Dominates(12, 90)); - EXPECT_TRUE(analysis->Dominates(12, 87)); - EXPECT_TRUE(analysis->Dominates(12, 94)); - EXPECT_TRUE(analysis->Dominates(12, 98)); - EXPECT_TRUE(analysis->Dominates(12, 95)); - EXPECT_TRUE(analysis->Dominates(12, 97)); - EXPECT_TRUE(analysis->Dominates(12, 96)); - EXPECT_TRUE(analysis->Dominates(12, 88)); - EXPECT_TRUE(analysis->Dominates(12, 76)); - - EXPECT_TRUE(analysis->Dominates(46, 50)); - EXPECT_TRUE(analysis->Dominates(46, 47)); - EXPECT_TRUE(analysis->Dominates(46, 57)); - EXPECT_TRUE(analysis->Dominates(46, 61)); - EXPECT_TRUE(analysis->Dominates(46, 59)); - EXPECT_TRUE(analysis->Dominates(46, 58)); - EXPECT_TRUE(analysis->Dominates(46, 60)); - EXPECT_TRUE(analysis->Dominates(46, 48)); - EXPECT_TRUE(analysis->Dominates(46, 73)); - EXPECT_TRUE(analysis->Dominates(46, 77)); - EXPECT_TRUE(analysis->Dominates(46, 75)); - EXPECT_TRUE(analysis->Dominates(46, 106)); - EXPECT_TRUE(analysis->Dominates(46, 110)); - EXPECT_TRUE(analysis->Dominates(46, 107)); - EXPECT_TRUE(analysis->Dominates(46, 108)); - EXPECT_TRUE(analysis->Dominates(46, 109)); - EXPECT_TRUE(analysis->Dominates(46, 74)); - EXPECT_TRUE(analysis->Dominates(46, 86)); - EXPECT_TRUE(analysis->Dominates(46, 90)); - EXPECT_TRUE(analysis->Dominates(46, 87)); - EXPECT_TRUE(analysis->Dominates(46, 94)); - EXPECT_TRUE(analysis->Dominates(46, 98)); - EXPECT_TRUE(analysis->Dominates(46, 95)); - EXPECT_TRUE(analysis->Dominates(46, 97)); - EXPECT_TRUE(analysis->Dominates(46, 96)); - EXPECT_TRUE(analysis->Dominates(46, 88)); - EXPECT_TRUE(analysis->Dominates(46, 76)); - - EXPECT_TRUE(analysis->Dominates(50, 47)); - EXPECT_TRUE(analysis->Dominates(50, 57)); - EXPECT_TRUE(analysis->Dominates(50, 61)); - EXPECT_TRUE(analysis->Dominates(50, 59)); - EXPECT_TRUE(analysis->Dominates(50, 58)); - EXPECT_TRUE(analysis->Dominates(50, 60)); - - EXPECT_TRUE(analysis->Dominates(47, 57)); - EXPECT_TRUE(analysis->Dominates(47, 61)); - EXPECT_TRUE(analysis->Dominates(47, 59)); - EXPECT_TRUE(analysis->Dominates(47, 58)); - EXPECT_TRUE(analysis->Dominates(47, 60)); - - EXPECT_TRUE(analysis->Dominates(57, 61)); - EXPECT_TRUE(analysis->Dominates(57, 59)); - EXPECT_TRUE(analysis->Dominates(57, 58)); - EXPECT_TRUE(analysis->Dominates(57, 60)); - - EXPECT_TRUE(analysis->Dominates(61, 59)); - - EXPECT_TRUE(analysis->Dominates(48, 73)); - EXPECT_TRUE(analysis->Dominates(48, 77)); - EXPECT_TRUE(analysis->Dominates(48, 75)); - EXPECT_TRUE(analysis->Dominates(48, 106)); - EXPECT_TRUE(analysis->Dominates(48, 110)); - EXPECT_TRUE(analysis->Dominates(48, 107)); - EXPECT_TRUE(analysis->Dominates(48, 108)); - EXPECT_TRUE(analysis->Dominates(48, 109)); - EXPECT_TRUE(analysis->Dominates(48, 74)); - EXPECT_TRUE(analysis->Dominates(48, 86)); - EXPECT_TRUE(analysis->Dominates(48, 90)); - EXPECT_TRUE(analysis->Dominates(48, 87)); - EXPECT_TRUE(analysis->Dominates(48, 94)); - EXPECT_TRUE(analysis->Dominates(48, 98)); - EXPECT_TRUE(analysis->Dominates(48, 95)); - EXPECT_TRUE(analysis->Dominates(48, 97)); - EXPECT_TRUE(analysis->Dominates(48, 96)); - EXPECT_TRUE(analysis->Dominates(48, 88)); - EXPECT_TRUE(analysis->Dominates(48, 76)); - - EXPECT_TRUE(analysis->Dominates(73, 77)); - EXPECT_TRUE(analysis->Dominates(73, 75)); - EXPECT_TRUE(analysis->Dominates(73, 106)); - EXPECT_TRUE(analysis->Dominates(73, 110)); - EXPECT_TRUE(analysis->Dominates(73, 107)); - EXPECT_TRUE(analysis->Dominates(73, 108)); - EXPECT_TRUE(analysis->Dominates(73, 109)); - EXPECT_TRUE(analysis->Dominates(73, 74)); - EXPECT_TRUE(analysis->Dominates(73, 86)); - EXPECT_TRUE(analysis->Dominates(73, 90)); - EXPECT_TRUE(analysis->Dominates(73, 87)); - EXPECT_TRUE(analysis->Dominates(73, 94)); - EXPECT_TRUE(analysis->Dominates(73, 98)); - EXPECT_TRUE(analysis->Dominates(73, 95)); - EXPECT_TRUE(analysis->Dominates(73, 97)); - EXPECT_TRUE(analysis->Dominates(73, 96)); - EXPECT_TRUE(analysis->Dominates(73, 88)); - EXPECT_TRUE(analysis->Dominates(73, 76)); - - EXPECT_TRUE(analysis->Dominates(75, 106)); - EXPECT_TRUE(analysis->Dominates(75, 110)); - EXPECT_TRUE(analysis->Dominates(75, 107)); - EXPECT_TRUE(analysis->Dominates(75, 108)); - EXPECT_TRUE(analysis->Dominates(75, 109)); - - EXPECT_TRUE(analysis->Dominates(106, 110)); - EXPECT_TRUE(analysis->Dominates(106, 107)); - EXPECT_TRUE(analysis->Dominates(106, 108)); - EXPECT_TRUE(analysis->Dominates(106, 109)); - - EXPECT_TRUE(analysis->Dominates(110, 107)); - - EXPECT_TRUE(analysis->Dominates(77, 74)); - EXPECT_TRUE(analysis->Dominates(77, 86)); - EXPECT_TRUE(analysis->Dominates(77, 90)); - EXPECT_TRUE(analysis->Dominates(77, 87)); - EXPECT_TRUE(analysis->Dominates(77, 94)); - EXPECT_TRUE(analysis->Dominates(77, 98)); - EXPECT_TRUE(analysis->Dominates(77, 95)); - EXPECT_TRUE(analysis->Dominates(77, 97)); - EXPECT_TRUE(analysis->Dominates(77, 96)); - EXPECT_TRUE(analysis->Dominates(77, 88)); - - EXPECT_TRUE(analysis->Dominates(74, 86)); - EXPECT_TRUE(analysis->Dominates(74, 90)); - EXPECT_TRUE(analysis->Dominates(74, 87)); - EXPECT_TRUE(analysis->Dominates(74, 94)); - EXPECT_TRUE(analysis->Dominates(74, 98)); - EXPECT_TRUE(analysis->Dominates(74, 95)); - EXPECT_TRUE(analysis->Dominates(74, 97)); - EXPECT_TRUE(analysis->Dominates(74, 96)); - EXPECT_TRUE(analysis->Dominates(74, 88)); - - EXPECT_TRUE(analysis->Dominates(86, 90)); - EXPECT_TRUE(analysis->Dominates(86, 87)); - EXPECT_TRUE(analysis->Dominates(86, 94)); - EXPECT_TRUE(analysis->Dominates(86, 98)); - EXPECT_TRUE(analysis->Dominates(86, 95)); - EXPECT_TRUE(analysis->Dominates(86, 97)); - EXPECT_TRUE(analysis->Dominates(86, 96)); - EXPECT_TRUE(analysis->Dominates(86, 88)); - - EXPECT_TRUE(analysis->Dominates(90, 87)); - EXPECT_TRUE(analysis->Dominates(90, 94)); - EXPECT_TRUE(analysis->Dominates(90, 98)); - EXPECT_TRUE(analysis->Dominates(90, 95)); - EXPECT_TRUE(analysis->Dominates(90, 97)); - EXPECT_TRUE(analysis->Dominates(90, 96)); - - EXPECT_TRUE(analysis->Dominates(87, 94)); - EXPECT_TRUE(analysis->Dominates(87, 98)); - EXPECT_TRUE(analysis->Dominates(87, 95)); - EXPECT_TRUE(analysis->Dominates(87, 97)); - EXPECT_TRUE(analysis->Dominates(87, 96)); - - EXPECT_TRUE(analysis->Dominates(94, 98)); - EXPECT_TRUE(analysis->Dominates(94, 95)); - EXPECT_TRUE(analysis->Dominates(94, 97)); - EXPECT_TRUE(analysis->Dominates(94, 96)); - - EXPECT_TRUE(analysis->Dominates(98, 95)); - - EXPECT_TRUE(analysis->StrictlyDominates(5, 10)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 14)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 29)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 33)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 30)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 32)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 31)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 13)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 12)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 46)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 50)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 47)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 57)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 60)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 48)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 73)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 77)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 75)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 109)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 88)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 76)); - - EXPECT_TRUE(analysis->StrictlyDominates(10, 14)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 29)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 33)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 30)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 32)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 31)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 13)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 12)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 46)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 50)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 47)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 57)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 60)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 48)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 73)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 77)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 75)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 109)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 88)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 76)); - - EXPECT_TRUE(analysis->StrictlyDominates(14, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 29)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 33)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 30)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 32)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 31)); - - EXPECT_TRUE(analysis->StrictlyDominates(11, 29)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 33)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 30)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 32)); - EXPECT_TRUE(analysis->StrictlyDominates(11, 31)); - - EXPECT_TRUE(analysis->StrictlyDominates(29, 33)); - EXPECT_TRUE(analysis->StrictlyDominates(29, 30)); - EXPECT_TRUE(analysis->StrictlyDominates(29, 32)); - EXPECT_TRUE(analysis->StrictlyDominates(29, 31)); - - EXPECT_TRUE(analysis->StrictlyDominates(33, 30)); - - EXPECT_TRUE(analysis->StrictlyDominates(12, 46)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 50)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 47)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 57)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 60)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 48)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 73)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 77)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 75)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 109)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 88)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 76)); - - EXPECT_TRUE(analysis->StrictlyDominates(46, 50)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 47)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 57)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 60)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 48)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 73)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 77)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 75)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 109)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 88)); - EXPECT_TRUE(analysis->StrictlyDominates(46, 76)); - - EXPECT_TRUE(analysis->StrictlyDominates(50, 47)); - EXPECT_TRUE(analysis->StrictlyDominates(50, 57)); - EXPECT_TRUE(analysis->StrictlyDominates(50, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(50, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(50, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(50, 60)); - - EXPECT_TRUE(analysis->StrictlyDominates(47, 57)); - EXPECT_TRUE(analysis->StrictlyDominates(47, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(47, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(47, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(47, 60)); - - EXPECT_TRUE(analysis->StrictlyDominates(57, 61)); - EXPECT_TRUE(analysis->StrictlyDominates(57, 59)); - EXPECT_TRUE(analysis->StrictlyDominates(57, 58)); - EXPECT_TRUE(analysis->StrictlyDominates(57, 60)); - - EXPECT_TRUE(analysis->StrictlyDominates(61, 59)); - - EXPECT_TRUE(analysis->StrictlyDominates(48, 73)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 77)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 75)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 109)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 88)); - EXPECT_TRUE(analysis->StrictlyDominates(48, 76)); - - EXPECT_TRUE(analysis->StrictlyDominates(73, 77)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 75)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 109)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 88)); - EXPECT_TRUE(analysis->StrictlyDominates(73, 76)); - - EXPECT_TRUE(analysis->StrictlyDominates(75, 106)); - EXPECT_TRUE(analysis->StrictlyDominates(75, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(75, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(75, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(75, 109)); - - EXPECT_TRUE(analysis->StrictlyDominates(106, 110)); - EXPECT_TRUE(analysis->StrictlyDominates(106, 107)); - EXPECT_TRUE(analysis->StrictlyDominates(106, 108)); - EXPECT_TRUE(analysis->StrictlyDominates(106, 109)); - - EXPECT_TRUE(analysis->StrictlyDominates(110, 107)); - - EXPECT_TRUE(analysis->StrictlyDominates(77, 74)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(77, 88)); - - EXPECT_TRUE(analysis->StrictlyDominates(74, 86)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(74, 88)); - - EXPECT_TRUE(analysis->StrictlyDominates(86, 90)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 96)); - EXPECT_TRUE(analysis->StrictlyDominates(86, 88)); - - EXPECT_TRUE(analysis->StrictlyDominates(90, 87)); - EXPECT_TRUE(analysis->StrictlyDominates(90, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(90, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(90, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(90, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(90, 96)); - - EXPECT_TRUE(analysis->StrictlyDominates(87, 94)); - EXPECT_TRUE(analysis->StrictlyDominates(87, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(87, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(87, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(87, 96)); - - EXPECT_TRUE(analysis->StrictlyDominates(94, 98)); - EXPECT_TRUE(analysis->StrictlyDominates(94, 95)); - EXPECT_TRUE(analysis->StrictlyDominates(94, 97)); - EXPECT_TRUE(analysis->StrictlyDominates(94, 96)); - - EXPECT_TRUE(analysis->StrictlyDominates(98, 95)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/pch_test_opt_dom.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/pch_test_opt_dom.cpp deleted file mode 100644 index a28310e57..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/pch_test_opt_dom.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "pch_test_opt_dom.h" diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/pch_test_opt_dom.h b/3rdparty/spirv-tools/test/opt/dominator_tree/pch_test_opt_dom.h deleted file mode 100644 index 4e8106fbf..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/pch_test_opt_dom.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_dependence.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/scalar_analysis.h" -#include "source/opt/tree_iterator.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/post.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/post.cpp deleted file mode 100644 index bb10fdef1..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/post.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 440 core -layout(location = 0) out vec4 c; -layout(location = 1)in vec4 in_val; -void main(){ - if ( in_val.x < 10) { - int z = 0; - int i = 0; - for (i = 0; i < in_val.y; ++i) { - z += i; - } - c = vec4(i,i,i,i); - } else { - c = vec4(1,1,1,1); - } -} -*/ -TEST_F(PassClassTest, BasicVisitFromEntryPoint) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 %43 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %9 "in_val" - OpName %22 "z" - OpName %24 "i" - OpName %43 "c" - OpDecorate %9 Location 1 - OpDecorate %43 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Input %7 - %9 = OpVariable %8 Input - %10 = OpTypeInt 32 0 - %11 = OpConstant %10 0 - %12 = OpTypePointer Input %6 - %15 = OpConstant %6 10 - %16 = OpTypeBool - %20 = OpTypeInt 32 1 - %21 = OpTypePointer Function %20 - %23 = OpConstant %20 0 - %32 = OpConstant %10 1 - %40 = OpConstant %20 1 - %42 = OpTypePointer Output %7 - %43 = OpVariable %42 Output - %54 = OpConstant %6 1 - %55 = OpConstantComposite %7 %54 %54 %54 %54 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %22 = OpVariable %21 Function - %24 = OpVariable %21 Function - %13 = OpAccessChain %12 %9 %11 - %14 = OpLoad %6 %13 - %17 = OpFOrdLessThan %16 %14 %15 - OpSelectionMerge %19 None - OpBranchConditional %17 %18 %53 - %18 = OpLabel - OpStore %22 %23 - OpStore %24 %23 - OpStore %24 %23 - OpBranch %25 - %25 = OpLabel - OpLoopMerge %27 %28 None - OpBranch %29 - %29 = OpLabel - %30 = OpLoad %20 %24 - %31 = OpConvertSToF %6 %30 - %33 = OpAccessChain %12 %9 %32 - %34 = OpLoad %6 %33 - %35 = OpFOrdLessThan %16 %31 %34 - OpBranchConditional %35 %26 %27 - %26 = OpLabel - %36 = OpLoad %20 %24 - %37 = OpLoad %20 %22 - %38 = OpIAdd %20 %37 %36 - OpStore %22 %38 - OpBranch %28 - %28 = OpLabel - %39 = OpLoad %20 %24 - %41 = OpIAdd %20 %39 %40 - OpStore %24 %41 - OpBranch %25 - %27 = OpLabel - %44 = OpLoad %20 %24 - %45 = OpConvertSToF %6 %44 - %46 = OpLoad %20 %24 - %47 = OpConvertSToF %6 %46 - %48 = OpLoad %20 %24 - %49 = OpConvertSToF %6 %48 - %50 = OpLoad %20 %24 - %51 = OpConvertSToF %6 %50 - %52 = OpCompositeConstruct %7 %45 %47 %49 %51 - OpStore %43 %52 - OpBranch %19 - %53 = OpLabel - OpStore %43 %55 - OpBranch %19 - %19 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - CFG cfg(module); - PostDominatorAnalysis* analysis = context->GetPostDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(19, 18)); - EXPECT_TRUE(analysis->Dominates(19, 5)); - EXPECT_TRUE(analysis->Dominates(19, 53)); - EXPECT_TRUE(analysis->Dominates(19, 19)); - EXPECT_TRUE(analysis->Dominates(19, 25)); - EXPECT_TRUE(analysis->Dominates(19, 29)); - EXPECT_TRUE(analysis->Dominates(19, 27)); - EXPECT_TRUE(analysis->Dominates(19, 26)); - EXPECT_TRUE(analysis->Dominates(19, 28)); - - EXPECT_TRUE(analysis->Dominates(27, 18)); - EXPECT_TRUE(analysis->Dominates(27, 25)); - EXPECT_TRUE(analysis->Dominates(27, 29)); - EXPECT_TRUE(analysis->Dominates(27, 27)); - EXPECT_TRUE(analysis->Dominates(27, 26)); - EXPECT_TRUE(analysis->Dominates(27, 28)); - - EXPECT_FALSE(analysis->Dominates(27, 19)); - EXPECT_FALSE(analysis->Dominates(27, 5)); - EXPECT_FALSE(analysis->Dominates(27, 53)); - - EXPECT_FALSE(analysis->StrictlyDominates(19, 19)); - - EXPECT_TRUE(analysis->StrictlyDominates(19, 18)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 5)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 53)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 25)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 29)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 27)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 26)); - EXPECT_TRUE(analysis->StrictlyDominates(19, 28)); - - // These would be expected true for a normal, non post, dominator tree - EXPECT_FALSE(analysis->Dominates(5, 18)); - EXPECT_FALSE(analysis->Dominates(5, 53)); - EXPECT_FALSE(analysis->Dominates(5, 19)); - EXPECT_FALSE(analysis->Dominates(5, 25)); - EXPECT_FALSE(analysis->Dominates(5, 29)); - EXPECT_FALSE(analysis->Dominates(5, 27)); - EXPECT_FALSE(analysis->Dominates(5, 26)); - EXPECT_FALSE(analysis->Dominates(5, 28)); - - EXPECT_FALSE(analysis->StrictlyDominates(5, 18)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 53)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 19)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 25)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 29)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 27)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 26)); - EXPECT_FALSE(analysis->StrictlyDominates(5, 28)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/simple.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/simple.cpp deleted file mode 100644 index d11854d55..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/simple.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL -#version 440 core -layout(location = 0) out vec4 c; -layout(location = 1)in vec4 in_val; -void main(){ - if ( in_val.x < 10) { - int z = 0; - int i = 0; - for (i = 0; i < in_val.y; ++i) { - z += i; - } - c = vec4(i,i,i,i); - } else { - c = vec4(1,1,1,1); - } -} -*/ -TEST_F(PassClassTest, BasicVisitFromEntryPoint) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 %43 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %9 "in_val" - OpName %22 "z" - OpName %24 "i" - OpName %43 "c" - OpDecorate %9 Location 1 - OpDecorate %43 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Input %7 - %9 = OpVariable %8 Input - %10 = OpTypeInt 32 0 - %11 = OpConstant %10 0 - %12 = OpTypePointer Input %6 - %15 = OpConstant %6 10 - %16 = OpTypeBool - %20 = OpTypeInt 32 1 - %21 = OpTypePointer Function %20 - %23 = OpConstant %20 0 - %32 = OpConstant %10 1 - %40 = OpConstant %20 1 - %42 = OpTypePointer Output %7 - %43 = OpVariable %42 Output - %54 = OpConstant %6 1 - %55 = OpConstantComposite %7 %54 %54 %54 %54 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %22 = OpVariable %21 Function - %24 = OpVariable %21 Function - %13 = OpAccessChain %12 %9 %11 - %14 = OpLoad %6 %13 - %17 = OpFOrdLessThan %16 %14 %15 - OpSelectionMerge %19 None - OpBranchConditional %17 %18 %53 - %18 = OpLabel - OpStore %22 %23 - OpStore %24 %23 - OpStore %24 %23 - OpBranch %25 - %25 = OpLabel - OpLoopMerge %27 %28 None - OpBranch %29 - %29 = OpLabel - %30 = OpLoad %20 %24 - %31 = OpConvertSToF %6 %30 - %33 = OpAccessChain %12 %9 %32 - %34 = OpLoad %6 %33 - %35 = OpFOrdLessThan %16 %31 %34 - OpBranchConditional %35 %26 %27 - %26 = OpLabel - %36 = OpLoad %20 %24 - %37 = OpLoad %20 %22 - %38 = OpIAdd %20 %37 %36 - OpStore %22 %38 - OpBranch %28 - %28 = OpLabel - %39 = OpLoad %20 %24 - %41 = OpIAdd %20 %39 %40 - OpStore %24 %41 - OpBranch %25 - %27 = OpLabel - %44 = OpLoad %20 %24 - %45 = OpConvertSToF %6 %44 - %46 = OpLoad %20 %24 - %47 = OpConvertSToF %6 %46 - %48 = OpLoad %20 %24 - %49 = OpConvertSToF %6 %48 - %50 = OpLoad %20 %24 - %51 = OpConvertSToF %6 %50 - %52 = OpCompositeConstruct %7 %45 %47 %49 %51 - OpStore %43 %52 - OpBranch %19 - %53 = OpLabel - OpStore %43 %55 - OpBranch %19 - %19 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - - DominatorAnalysis* analysis = context->GetDominatorAnalysis(f); - const CFG& cfg = *context->cfg(); - - DominatorTree& tree = analysis->GetDomTree(); - - EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); - EXPECT_TRUE(analysis->Dominates(5, 18)); - EXPECT_TRUE(analysis->Dominates(5, 53)); - EXPECT_TRUE(analysis->Dominates(5, 19)); - EXPECT_TRUE(analysis->Dominates(5, 25)); - EXPECT_TRUE(analysis->Dominates(5, 29)); - EXPECT_TRUE(analysis->Dominates(5, 27)); - EXPECT_TRUE(analysis->Dominates(5, 26)); - EXPECT_TRUE(analysis->Dominates(5, 28)); - - EXPECT_TRUE(analysis->StrictlyDominates(5, 18)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 53)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 19)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 25)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 29)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 27)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 26)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 28)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/switch_case_fallthrough.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/switch_case_fallthrough.cpp deleted file mode 100644 index d9dd7d161..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/switch_case_fallthrough.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 440 core -layout(location = 0) out vec4 v; -layout(location = 1) in vec4 in_val; -void main() { - int i; - switch (int(in_val.x)) { - case 0: - i = 0; - case 1: - i = 1; - break; - case 2: - i = 2; - case 3: - i = 3; - case 4: - i = 4; - break; - default: - i = 0; - } - v = vec4(i, i, i, i); -} -*/ -TEST_F(PassClassTest, UnreachableNestedIfs) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 %35 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %9 "in_val" - OpName %25 "i" - OpName %35 "v" - OpDecorate %9 Location 1 - OpDecorate %35 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Input %7 - %9 = OpVariable %8 Input - %10 = OpTypeInt 32 0 - %11 = OpConstant %10 0 - %12 = OpTypePointer Input %6 - %15 = OpTypeInt 32 1 - %24 = OpTypePointer Function %15 - %26 = OpConstant %15 0 - %27 = OpConstant %15 1 - %29 = OpConstant %15 2 - %30 = OpConstant %15 3 - %31 = OpConstant %15 4 - %34 = OpTypePointer Output %7 - %35 = OpVariable %34 Output - %4 = OpFunction %2 None %3 - %5 = OpLabel - %25 = OpVariable %24 Function - %13 = OpAccessChain %12 %9 %11 - %14 = OpLoad %6 %13 - %16 = OpConvertFToS %15 %14 - OpSelectionMerge %23 None - OpSwitch %16 %22 0 %17 1 %18 2 %19 3 %20 4 %21 - %22 = OpLabel - OpStore %25 %26 - OpBranch %23 - %17 = OpLabel - OpStore %25 %26 - OpBranch %18 - %18 = OpLabel - OpStore %25 %27 - OpBranch %23 - %19 = OpLabel - OpStore %25 %29 - OpBranch %20 - %20 = OpLabel - OpStore %25 %30 - OpBranch %21 - %21 = OpLabel - OpStore %25 %31 - OpBranch %23 - %23 = OpLabel - %36 = OpLoad %15 %25 - %37 = OpConvertSToF %6 %36 - %38 = OpLoad %15 %25 - %39 = OpConvertSToF %6 %38 - %40 = OpLoad %15 %25 - %41 = OpConvertSToF %6 %40 - %42 = OpLoad %15 %25 - %43 = OpConvertSToF %6 %42 - %44 = OpCompositeConstruct %7 %37 %39 %41 %43 - OpStore %35 %44 - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - DominatorAnalysis* analysis = context->GetDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(5, 5)); - EXPECT_TRUE(analysis->Dominates(5, 17)); - EXPECT_TRUE(analysis->Dominates(5, 18)); - EXPECT_TRUE(analysis->Dominates(5, 19)); - EXPECT_TRUE(analysis->Dominates(5, 20)); - EXPECT_TRUE(analysis->Dominates(5, 21)); - EXPECT_TRUE(analysis->Dominates(5, 22)); - EXPECT_TRUE(analysis->Dominates(5, 23)); - - EXPECT_TRUE(analysis->StrictlyDominates(5, 17)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 18)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 19)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 20)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 21)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 22)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 23)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/unreachable_for.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/unreachable_for.cpp deleted file mode 100644 index 469e5c142..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/unreachable_for.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 440 core -void main() { - for (int i = 0; i < 1; i++) { - break; - } -} -*/ -TEST_F(PassClassTest, UnreachableNestedIfs) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 1 - %17 = OpTypeBool - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %12 - %13 = OpLabel - %20 = OpLoad %6 %8 - %21 = OpIAdd %6 %20 %16 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - DominatorAnalysis* analysis = context->GetDominatorAnalysis(f); - EXPECT_TRUE(analysis->Dominates(5, 5)); - EXPECT_TRUE(analysis->Dominates(5, 10)); - EXPECT_TRUE(analysis->Dominates(5, 14)); - EXPECT_TRUE(analysis->Dominates(5, 11)); - EXPECT_TRUE(analysis->Dominates(5, 12)); - EXPECT_TRUE(analysis->Dominates(10, 10)); - EXPECT_TRUE(analysis->Dominates(10, 14)); - EXPECT_TRUE(analysis->Dominates(10, 11)); - EXPECT_TRUE(analysis->Dominates(10, 12)); - EXPECT_TRUE(analysis->Dominates(14, 14)); - EXPECT_TRUE(analysis->Dominates(14, 11)); - EXPECT_TRUE(analysis->Dominates(14, 12)); - EXPECT_TRUE(analysis->Dominates(11, 11)); - EXPECT_TRUE(analysis->Dominates(12, 12)); - - EXPECT_TRUE(analysis->StrictlyDominates(5, 10)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 14)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(5, 12)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 14)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 12)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 12)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/dominator_tree/unreachable_for_post.cpp b/3rdparty/spirv-tools/test/opt/dominator_tree/unreachable_for_post.cpp deleted file mode 100644 index 8d3e37b4a..000000000 --- a/3rdparty/spirv-tools/test/opt/dominator_tree/unreachable_for_post.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/dominator_analysis.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Generated from the following GLSL -#version 440 core -void main() { - for (int i = 0; i < 1; i++) { - break; - } -} -*/ -TEST_F(PassClassTest, UnreachableNestedIfs) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 1 - %17 = OpTypeBool - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %12 - %13 = OpLabel - %20 = OpLoad %6 %8 - %21 = OpIAdd %6 %20 %16 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - const Function* f = spvtest::GetFunction(module, 4); - - PostDominatorAnalysis* analysis = context->GetPostDominatorAnalysis(f); - - EXPECT_TRUE(analysis->Dominates(12, 12)); - EXPECT_TRUE(analysis->Dominates(12, 14)); - EXPECT_TRUE(analysis->Dominates(12, 11)); - EXPECT_TRUE(analysis->Dominates(12, 10)); - EXPECT_TRUE(analysis->Dominates(12, 5)); - EXPECT_TRUE(analysis->Dominates(14, 14)); - EXPECT_TRUE(analysis->Dominates(14, 10)); - EXPECT_TRUE(analysis->Dominates(14, 5)); - EXPECT_TRUE(analysis->Dominates(10, 10)); - EXPECT_TRUE(analysis->Dominates(10, 5)); - EXPECT_TRUE(analysis->Dominates(5, 5)); - - EXPECT_TRUE(analysis->StrictlyDominates(12, 14)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 11)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 10)); - EXPECT_TRUE(analysis->StrictlyDominates(12, 5)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 10)); - EXPECT_TRUE(analysis->StrictlyDominates(14, 5)); - EXPECT_TRUE(analysis->StrictlyDominates(10, 5)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/eliminate_dead_const_test.cpp b/3rdparty/spirv-tools/test/opt/eliminate_dead_const_test.cpp deleted file mode 100644 index 59f06f9f2..000000000 --- a/3rdparty/spirv-tools/test/opt/eliminate_dead_const_test.cpp +++ /dev/null @@ -1,847 +0,0 @@ -// 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 -#include - -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using EliminateDeadConstantBasicTest = PassTest<::testing::Test>; - -TEST_F(EliminateDeadConstantBasicTest, BasicAllDeadConstants) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "%void = OpTypeVoid", - "%4 = OpTypeFunction %void", - "%bool = OpTypeBool", - "%true = OpConstantTrue %bool", - "%false = OpConstantFalse %bool", - "%int = OpTypeInt 32 1", - "%9 = OpConstant %int 1", - "%uint = OpTypeInt 32 0", - "%11 = OpConstant %uint 2", - "%float = OpTypeFloat 32", - "%13 = OpConstant %float 3.1415", - "%double = OpTypeFloat 64", - "%15 = OpConstant %double 3.14159265358979", - "%main = OpFunction %void None %4", - "%16 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - // None of the above constants is ever used, so all of them should be - // eliminated. - const char* const_decl_opcodes[] = { - " OpConstantTrue ", - " OpConstantFalse ", - " OpConstant ", - }; - // Skip lines that have any one of const_decl_opcodes. - const std::string expected_disassembly = - SelectiveJoin(text, [&const_decl_opcodes](const char* line) { - return std::any_of( - std::begin(const_decl_opcodes), std::end(const_decl_opcodes), - [&line](const char* const_decl_op) { - return std::string(line).find(const_decl_op) != std::string::npos; - }); - }); - - SinglePassRunAndCheck( - JoinAllInsts(text), expected_disassembly, /* skip_nop = */ true); -} - -TEST_F(EliminateDeadConstantBasicTest, BasicNoneDeadConstants) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "OpName %btv \"btv\"", - "OpName %bfv \"bfv\"", - "OpName %iv \"iv\"", - "OpName %uv \"uv\"", - "OpName %fv \"fv\"", - "OpName %dv \"dv\"", - "%void = OpTypeVoid", - "%10 = OpTypeFunction %void", - "%bool = OpTypeBool", - "%_ptr_Function_bool = OpTypePointer Function %bool", - "%true = OpConstantTrue %bool", - "%false = OpConstantFalse %bool", - "%int = OpTypeInt 32 1", - "%_ptr_Function_int = OpTypePointer Function %int", - "%int_1 = OpConstant %int 1", - "%uint = OpTypeInt 32 0", - "%_ptr_Function_uint = OpTypePointer Function %uint", - "%uint_2 = OpConstant %uint 2", - "%float = OpTypeFloat 32", - "%_ptr_Function_float = OpTypePointer Function %float", - "%float_3_1415 = OpConstant %float 3.1415", - "%double = OpTypeFloat 64", - "%_ptr_Function_double = OpTypePointer Function %double", - "%double_3_14159265358979 = OpConstant %double 3.14159265358979", - "%main = OpFunction %void None %10", - "%27 = OpLabel", - "%btv = OpVariable %_ptr_Function_bool Function", - "%bfv = OpVariable %_ptr_Function_bool Function", - "%iv = OpVariable %_ptr_Function_int Function", - "%uv = OpVariable %_ptr_Function_uint Function", - "%fv = OpVariable %_ptr_Function_float Function", - "%dv = OpVariable %_ptr_Function_double Function", - "OpStore %btv %true", - "OpStore %bfv %false", - "OpStore %iv %int_1", - "OpStore %uv %uint_2", - "OpStore %fv %float_3_1415", - "OpStore %dv %double_3_14159265358979", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - // All constants are used, so none of them should be eliminated. - SinglePassRunAndCheck( - JoinAllInsts(text), JoinAllInsts(text), /* skip_nop = */ true); -} - -struct EliminateDeadConstantTestCase { - // Type declarations and constants that should be kept. - std::vector used_consts; - // Instructions that refer to constants, this is added to create uses for - // some constants so they won't be treated as dead constants. - std::vector main_insts; - // Dead constants that should be removed. - std::vector dead_consts; -}; - -// All types that are potentially required in EliminateDeadConstantTest. -const std::vector CommonTypes = { - // clang-format off - // scalar types - "%bool = OpTypeBool", - "%uint = OpTypeInt 32 0", - "%int = OpTypeInt 32 1", - "%float = OpTypeFloat 32", - "%double = OpTypeFloat 64", - // vector types - "%v2bool = OpTypeVector %bool 2", - "%v2uint = OpTypeVector %uint 2", - "%v2int = OpTypeVector %int 2", - "%v3int = OpTypeVector %int 3", - "%v4int = OpTypeVector %int 4", - "%v2float = OpTypeVector %float 2", - "%v3float = OpTypeVector %float 3", - "%v2double = OpTypeVector %double 2", - // variable pointer types - "%_pf_bool = OpTypePointer Function %bool", - "%_pf_uint = OpTypePointer Function %uint", - "%_pf_int = OpTypePointer Function %int", - "%_pf_float = OpTypePointer Function %float", - "%_pf_double = OpTypePointer Function %double", - "%_pf_v2int = OpTypePointer Function %v2int", - "%_pf_v3int = OpTypePointer Function %v3int", - "%_pf_v2float = OpTypePointer Function %v2float", - "%_pf_v3float = OpTypePointer Function %v3float", - "%_pf_v2double = OpTypePointer Function %v2double", - // struct types - "%inner_struct = OpTypeStruct %bool %int %float %double", - "%outer_struct = OpTypeStruct %inner_struct %int %double", - "%flat_struct = OpTypeStruct %bool %int %float %double", - // clang-format on -}; - -using EliminateDeadConstantTest = - PassTest<::testing::TestWithParam>; - -TEST_P(EliminateDeadConstantTest, Custom) { - auto& tc = GetParam(); - AssemblyBuilder builder; - builder.AppendTypesConstantsGlobals(CommonTypes) - .AppendTypesConstantsGlobals(tc.used_consts) - .AppendInMain(tc.main_insts); - const std::string expected = builder.GetCode(); - builder.AppendTypesConstantsGlobals(tc.dead_consts); - const std::string assembly_with_dead_const = builder.GetCode(); - SinglePassRunAndCheck( - assembly_with_dead_const, expected, /* skip_nop = */ true); -} - -INSTANTIATE_TEST_SUITE_P( - ScalarTypeConstants, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Scalar type constants, one dead constant and one used constant. - { - /* .used_consts = */ - { - "%used_const_int = OpConstant %int 1", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %used_const_int", - }, - /* .dead_consts = */ - { - "%dead_const_int = OpConstant %int 1", - }, - }, - { - /* .used_consts = */ - { - "%used_const_uint = OpConstant %uint 1", - }, - /* .main_insts = */ - { - "%uint_var = OpVariable %_pf_uint Function", - "OpStore %uint_var %used_const_uint", - }, - /* .dead_consts = */ - { - "%dead_const_uint = OpConstant %uint 1", - }, - }, - { - /* .used_consts = */ - { - "%used_const_float = OpConstant %float 3.1415", - }, - /* .main_insts = */ - { - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %used_const_float", - }, - /* .dead_consts = */ - { - "%dead_const_float = OpConstant %float 3.1415", - }, - }, - { - /* .used_consts = */ - { - "%used_const_double = OpConstant %double 3.141592653", - }, - /* .main_insts = */ - { - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %used_const_double", - }, - /* .dead_consts = */ - { - "%dead_const_double = OpConstant %double 3.141592653", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - VectorTypeConstants, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Tests eliminating dead constant type ivec2. One dead constant vector - // and one used constant vector, each built from its own group of - // scalar constants. - { - /* .used_consts = */ - { - "%used_int_x = OpConstant %int 1", - "%used_int_y = OpConstant %int 2", - "%used_v2int = OpConstantComposite %v2int %used_int_x %used_int_y", - }, - /* .main_insts = */ - { - "%v2int_var = OpVariable %_pf_v2int Function", - "OpStore %v2int_var %used_v2int", - }, - /* .dead_consts = */ - { - "%dead_int_x = OpConstant %int 1", - "%dead_int_y = OpConstant %int 2", - "%dead_v2int = OpConstantComposite %v2int %dead_int_x %dead_int_y", - }, - }, - // Tests eliminating dead constant ivec2. One dead constant vector and - // one used constant vector. But both built from a same group of - // scalar constants. - { - /* .used_consts = */ - { - "%used_int_x = OpConstant %int 1", - "%used_int_y = OpConstant %int 2", - "%used_int_z = OpConstant %int 3", - "%used_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z", - }, - /* .main_insts = */ - { - "%v3int_var = OpVariable %_pf_v3int Function", - "OpStore %v3int_var %used_v3int", - }, - /* .dead_consts = */ - { - "%dead_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z", - }, - }, - // Tests eliminating dead cosntant vec2. One dead constant vector and - // one used constant vector. Each built from its own group of scalar - // constants. - { - /* .used_consts = */ - { - "%used_float_x = OpConstant %float 3.1415", - "%used_float_y = OpConstant %float 4.25", - "%used_v2float = OpConstantComposite %v2float %used_float_x %used_float_y", - }, - /* .main_insts = */ - { - "%v2float_var = OpVariable %_pf_v2float Function", - "OpStore %v2float_var %used_v2float", - }, - /* .dead_consts = */ - { - "%dead_float_x = OpConstant %float 3.1415", - "%dead_float_y = OpConstant %float 4.25", - "%dead_v2float = OpConstantComposite %v2float %dead_float_x %dead_float_y", - }, - }, - // Tests eliminating dead cosntant vec2. One dead constant vector and - // one used constant vector. Both built from a same group of scalar - // constants. - { - /* .used_consts = */ - { - "%used_float_x = OpConstant %float 3.1415", - "%used_float_y = OpConstant %float 4.25", - "%used_float_z = OpConstant %float 4.75", - "%used_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z", - }, - /* .main_insts = */ - { - "%v3float_var = OpVariable %_pf_v3float Function", - "OpStore %v3float_var %used_v3float", - }, - /* .dead_consts = */ - { - "%dead_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - StructTypeConstants, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // A plain struct type dead constants. All of its components are dead - // constants too. - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_int = OpConstant %int 1", - "%dead_float = OpConstant %float 2.5", - "%dead_double = OpConstant %double 3.14159265358979", - "%dead_struct = OpConstantComposite %flat_struct %dead_bool %dead_int %dead_float %dead_double", - }, - }, - // A plain struct type dead constants. Some of its components are dead - // constants while others are not. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 1", - "%used_double = OpConstant %double 3.14159265358979", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %used_int", - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %used_double", - }, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_float = OpConstant %float 2.5", - "%dead_struct = OpConstantComposite %flat_struct %dead_bool %used_int %dead_float %used_double", - }, - }, - // A nesting struct type dead constants. All components of both outer - // and inner structs are dead and should be removed after dead constant - // elimination. - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_int = OpConstant %int 1", - "%dead_float = OpConstant %float 2.5", - "%dead_double = OpConstant %double 3.1415926535", - "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %dead_int %dead_float %dead_double", - "%dead_int2 = OpConstant %int 2", - "%dead_double2 = OpConstant %double 1.428571428514", - "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int2 %dead_double2", - }, - }, - // A nesting struct type dead constants. Some of its components are - // dead constants while others are not. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 1", - "%used_double = OpConstant %double 3.14159265358979", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %used_int", - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %used_double", - }, - /* .dead_consts = */ - { - "%dead_bool = OpConstantTrue %bool", - "%dead_float = OpConstant %float 2.5", - "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %used_int %dead_float %used_double", - "%dead_int = OpConstant %int 2", - "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int %used_double", - }, - }, - // A nesting struct case. The inner struct is used while the outer struct is not - { - /* .used_const = */ - { - "%used_bool = OpConstantTrue %bool", - "%used_int = OpConstant %int 1", - "%used_float = OpConstant %float 1.25", - "%used_double = OpConstant %double 1.23456789012345", - "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", - }, - /* .main_insts = */ - { - "%bool_var = OpVariable %_pf_bool Function", - "%bool_from_inner_struct = OpCompositeExtract %bool %used_inner_struct 0", - "OpStore %bool_var %bool_from_inner_struct", - }, - /* .dead_consts = */ - { - "%dead_int = OpConstant %int 2", - "%dead_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %dead_int %used_double" - }, - }, - // A nesting struct case. The outer struct is used, so the inner struct should not - // be removed even though it is not used anywhere. - { - /* .used_const = */ - { - "%used_bool = OpConstantTrue %bool", - "%used_int = OpConstant %int 1", - "%used_float = OpConstant %float 1.25", - "%used_double = OpConstant %double 1.23456789012345", - "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", - "%used_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double" - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "%int_from_outer_struct = OpCompositeExtract %int %used_outer_struct 1", - "OpStore %int_var %int_from_outer_struct", - }, - /* .dead_consts = */ {}, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - ScalarTypeSpecConstants, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // All scalar type spec constants. - { - /* .used_consts = */ - { - "%used_bool = OpSpecConstantTrue %bool", - "%used_uint = OpSpecConstant %uint 2", - "%used_int = OpSpecConstant %int 2", - "%used_float = OpSpecConstant %float 2.5", - "%used_double = OpSpecConstant %double 1.42857142851", - }, - /* .main_insts = */ - { - "%bool_var = OpVariable %_pf_bool Function", - "%uint_var = OpVariable %_pf_uint Function", - "%int_var = OpVariable %_pf_int Function", - "%float_var = OpVariable %_pf_float Function", - "%double_var = OpVariable %_pf_double Function", - "OpStore %bool_var %used_bool", "OpStore %uint_var %used_uint", - "OpStore %int_var %used_int", "OpStore %float_var %used_float", - "OpStore %double_var %used_double", - }, - /* .dead_consts = */ - { - "%dead_bool = OpSpecConstantTrue %bool", - "%dead_uint = OpSpecConstant %uint 2", - "%dead_int = OpSpecConstant %int 2", - "%dead_float = OpSpecConstant %float 2.5", - "%dead_double = OpSpecConstant %double 1.42857142851", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - VectorTypeSpecConstants, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Bool vector type spec constants. One vector has all component dead, - // another vector has one dead boolean and one used boolean. - { - /* .used_consts = */ - { - "%used_bool = OpSpecConstantTrue %bool", - }, - /* .main_insts = */ - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %used_bool", - }, - /* .dead_consts = */ - { - "%dead_bool = OpSpecConstantFalse %bool", - "%dead_bool_vec1 = OpSpecConstantComposite %v2bool %dead_bool %dead_bool", - "%dead_bool_vec2 = OpSpecConstantComposite %v2bool %dead_bool %used_bool", - }, - }, - - // Uint vector type spec constants. One vector has all component dead, - // another vector has one dead unsigend integer and one used unsigned - // integer. - { - /* .used_consts = */ - { - "%used_uint = OpSpecConstant %uint 3", - }, - /* .main_insts = */ - { - "%uint_var = OpVariable %_pf_uint Function", - "OpStore %uint_var %used_uint", - }, - /* .dead_consts = */ - { - "%dead_uint = OpSpecConstant %uint 1", - "%dead_uint_vec1 = OpSpecConstantComposite %v2uint %dead_uint %dead_uint", - "%dead_uint_vec2 = OpSpecConstantComposite %v2uint %dead_uint %used_uint", - }, - }, - - // Int vector type spec constants. One vector has all component dead, - // another vector has one dead integer and one used integer. - { - /* .used_consts = */ - { - "%used_int = OpSpecConstant %int 3", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %used_int", - }, - /* .dead_consts = */ - { - "%dead_int = OpSpecConstant %int 1", - "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_int %dead_int", - "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_int %used_int", - }, - }, - - // Int vector type spec constants built with both spec constants and - // front-end constants. - { - /* .used_consts = */ - { - "%used_spec_int = OpSpecConstant %int 3", - "%used_front_end_int = OpConstant %int 3", - }, - /* .main_insts = */ - { - "%int_var1 = OpVariable %_pf_int Function", - "OpStore %int_var1 %used_spec_int", - "%int_var2 = OpVariable %_pf_int Function", - "OpStore %int_var2 %used_front_end_int", - }, - /* .dead_consts = */ - { - "%dead_spec_int = OpSpecConstant %int 1", - "%dead_front_end_int = OpConstant %int 1", - // Dead front-end and dead spec constants - "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_spec_int %dead_front_end_int", - // Used front-end and dead spec constants - "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_spec_int %used_front_end_int", - // Dead front-end and used spec constants - "%dead_int_vec3 = OpSpecConstantComposite %v2int %dead_front_end_int %used_spec_int", - }, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - SpecConstantOp, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Cast operations: uint <-> int <-> bool - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - // Assistant constants, only used in dead spec constant - // operations. - "%signed_zero = OpConstant %int 0", - "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", - "%unsigned_zero = OpConstant %uint 0", - "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - "%signed_one = OpConstant %int 1", - "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one", - "%unsigned_one = OpConstant %uint 1", - "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - - // Spec constants that support casting to each other. - "%dead_bool = OpSpecConstantTrue %bool", - "%dead_uint = OpSpecConstant %uint 1", - "%dead_int = OpSpecConstant %int 2", - "%dead_bool_vec = OpSpecConstantComposite %v2bool %dead_bool %dead_bool", - "%dead_uint_vec = OpSpecConstantComposite %v2uint %dead_uint %dead_uint", - "%dead_int_vec = OpSpecConstantComposite %v2int %dead_int %dead_int", - - // Scalar cast to boolean spec constant. - "%int_to_bool = OpSpecConstantOp %bool INotEqual %dead_int %signed_zero", - "%uint_to_bool = OpSpecConstantOp %bool INotEqual %dead_uint %unsigned_zero", - - // Vector cast to boolean spec constant. - "%int_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_int_vec %signed_zero_vec", - "%uint_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_uint_vec %unsigned_zero_vec", - - // Scalar cast to int spec constant. - "%bool_to_int = OpSpecConstantOp %int Select %dead_bool %signed_one %signed_zero", - "%uint_to_int = OpSpecConstantOp %uint IAdd %dead_uint %unsigned_zero", - - // Vector cast to int spec constant. - "%bool_to_int_vec = OpSpecConstantOp %v2int Select %dead_bool_vec %signed_one_vec %signed_zero_vec", - "%uint_to_int_vec = OpSpecConstantOp %v2uint IAdd %dead_uint_vec %unsigned_zero_vec", - - // Scalar cast to uint spec constant. - "%bool_to_uint = OpSpecConstantOp %uint Select %dead_bool %unsigned_one %unsigned_zero", - "%int_to_uint_vec = OpSpecConstantOp %uint IAdd %dead_int %signed_zero", - - // Vector cast to uint spec constant. - "%bool_to_uint_vec = OpSpecConstantOp %v2uint Select %dead_bool_vec %unsigned_one_vec %unsigned_zero_vec", - "%int_to_uint = OpSpecConstantOp %v2uint IAdd %dead_int_vec %signed_zero_vec", - }, - }, - - // Add, sub, mul, div, rem. - { - /* .used_consts = */ {}, - /* .main_insts = */ {}, - /* .dead_consts = */ - { - "%dead_spec_int_a = OpSpecConstant %int 1", - "%dead_spec_int_a_vec = OpSpecConstantComposite %v2int %dead_spec_int_a %dead_spec_int_a", - - "%dead_spec_int_b = OpSpecConstant %int 2", - "%dead_spec_int_b_vec = OpSpecConstantComposite %v2int %dead_spec_int_b %dead_spec_int_b", - - "%dead_const_int_c = OpConstant %int 3", - "%dead_const_int_c_vec = OpConstantComposite %v2int %dead_const_int_c %dead_const_int_c", - - // Add - "%add_a_b = OpSpecConstantOp %int IAdd %dead_spec_int_a %dead_spec_int_b", - "%add_a_b_vec = OpSpecConstantOp %v2int IAdd %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Sub - "%sub_a_b = OpSpecConstantOp %int ISub %dead_spec_int_a %dead_spec_int_b", - "%sub_a_b_vec = OpSpecConstantOp %v2int ISub %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Mul - "%mul_a_b = OpSpecConstantOp %int IMul %dead_spec_int_a %dead_spec_int_b", - "%mul_a_b_vec = OpSpecConstantOp %v2int IMul %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Div - "%div_a_b = OpSpecConstantOp %int SDiv %dead_spec_int_a %dead_spec_int_b", - "%div_a_b_vec = OpSpecConstantOp %v2int SDiv %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Bitwise Xor - "%xor_a_b = OpSpecConstantOp %int BitwiseXor %dead_spec_int_a %dead_spec_int_b", - "%xor_a_b_vec = OpSpecConstantOp %v2int BitwiseXor %dead_spec_int_a_vec %dead_spec_int_b_vec", - - // Scalar Comparison - "%less_a_b = OpSpecConstantOp %bool SLessThan %dead_spec_int_a %dead_spec_int_b", - }, - }, - - // Vectors without used swizzles should be removed. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 3", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %used_int", - }, - /* .dead_consts = */ - { - "%dead_int = OpConstant %int 3", - - "%dead_spec_int_a = OpSpecConstant %int 1", - "%vec_a = OpSpecConstantComposite %v4int %dead_spec_int_a %dead_spec_int_a %dead_int %dead_int", - - "%dead_spec_int_b = OpSpecConstant %int 2", - "%vec_b = OpSpecConstantComposite %v4int %dead_spec_int_b %dead_spec_int_b %used_int %used_int", - - // Extract scalar - "%a_x = OpSpecConstantOp %int CompositeExtract %vec_a 0", - "%b_x = OpSpecConstantOp %int CompositeExtract %vec_b 0", - - // Extract vector - "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1", - "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1", - }, - }, - // Vectors with used swizzles should not be removed. - { - /* .used_consts = */ - { - "%used_int = OpConstant %int 3", - "%used_spec_int_a = OpSpecConstant %int 1", - "%used_spec_int_b = OpSpecConstant %int 2", - // Create vectors - "%vec_a = OpSpecConstantComposite %v4int %used_spec_int_a %used_spec_int_a %used_int %used_int", - "%vec_b = OpSpecConstantComposite %v4int %used_spec_int_b %used_spec_int_b %used_int %used_int", - // Extract vector - "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1", - "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1", - }, - /* .main_insts = */ - { - "%v2int_var_a = OpVariable %_pf_v2int Function", - "%v2int_var_b = OpVariable %_pf_v2int Function", - "OpStore %v2int_var_a %a_xy", - "OpStore %v2int_var_b %b_xy", - }, - /* .dead_consts = */ {}, - }, - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - LongDefUseChain, EliminateDeadConstantTest, - ::testing::ValuesIn(std::vector({ - // clang-format off - // Long Def-Use chain with binary operations. - { - /* .used_consts = */ - { - "%array_size = OpConstant %int 4", - "%type_arr_int_4 = OpTypeArray %int %array_size", - "%used_int_0 = OpConstant %int 100", - "%used_int_1 = OpConstant %int 1", - "%used_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_1", - "%used_int_3 = OpSpecConstantOp %int ISub %used_int_0 %used_int_2", - "%used_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_3", - "%used_int_5 = OpSpecConstantOp %int ISub %used_int_0 %used_int_4", - "%used_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_5", - "%used_int_7 = OpSpecConstantOp %int ISub %used_int_0 %used_int_6", - "%used_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_7", - "%used_int_9 = OpSpecConstantOp %int ISub %used_int_0 %used_int_8", - "%used_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_9", - "%used_int_11 = OpSpecConstantOp %int ISub %used_int_0 %used_int_10", - "%used_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_11", - "%used_int_13 = OpSpecConstantOp %int ISub %used_int_0 %used_int_12", - "%used_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_13", - "%used_int_15 = OpSpecConstantOp %int ISub %used_int_0 %used_int_14", - "%used_int_16 = OpSpecConstantOp %int ISub %used_int_0 %used_int_15", - "%used_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_16", - "%used_int_18 = OpSpecConstantOp %int ISub %used_int_0 %used_int_17", - "%used_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_18", - "%used_int_20 = OpSpecConstantOp %int ISub %used_int_0 %used_int_19", - "%used_vec_a = OpSpecConstantComposite %v2int %used_int_18 %used_int_19", - "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a", - "%used_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0", - "%used_array = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21", - }, - /* .main_insts = */ - { - "%int_var = OpVariable %_pf_int Function", - "%used_array_2 = OpCompositeExtract %int %used_array 2", - "OpStore %int_var %used_array_2", - }, - /* .dead_consts = */ - { - "%dead_int_1 = OpConstant %int 2", - "%dead_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_1", - "%dead_int_3 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_2", - "%dead_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_3", - "%dead_int_5 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_4", - "%dead_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_5", - "%dead_int_7 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_6", - "%dead_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_7", - "%dead_int_9 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_8", - "%dead_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_9", - "%dead_int_11 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_10", - "%dead_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_11", - "%dead_int_13 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_12", - "%dead_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_13", - "%dead_int_15 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_14", - "%dead_int_16 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_15", - "%dead_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_16", - "%dead_int_18 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_17", - "%dead_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_18", - "%dead_int_20 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_19", - "%dead_vec_a = OpSpecConstantComposite %v2int %dead_int_18 %dead_int_19", - "%dead_vec_b = OpSpecConstantOp %v2int IMul %dead_vec_a %dead_vec_a", - "%dead_int_21 = OpSpecConstantOp %int CompositeExtract %dead_vec_b 0", - "%dead_array = OpConstantComposite %type_arr_int_4 %dead_int_20 %used_int_20 %dead_int_19 %used_int_19", - }, - }, - // Long Def-Use chain with swizzle - // clang-format on - }))); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/eliminate_dead_functions_test.cpp b/3rdparty/spirv-tools/test/opt/eliminate_dead_functions_test.cpp deleted file mode 100644 index 0a3d490a8..000000000 --- a/3rdparty/spirv-tools/test/opt/eliminate_dead_functions_test.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::HasSubstr; -using EliminateDeadFunctionsBasicTest = PassTest<::testing::Test>; - -TEST_F(EliminateDeadFunctionsBasicTest, BasicDeleteDeadFunction) { - // The function Dead should be removed because it is never called. - const std::vector common_code = { - // clang-format off - "OpCapability Shader", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\"", - "OpName %main \"main\"", - "OpName %Live \"Live\"", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%main = OpFunction %void None %7", - "%15 = OpLabel", - "%16 = OpFunctionCall %void %Live", - "%17 = OpFunctionCall %void %Live", - "OpReturn", - "OpFunctionEnd", - "%Live = OpFunction %void None %7", - "%20 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - const std::vector dead_function = { - // clang-format off - "%Dead = OpFunction %void None %7", - "%19 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - JoinAllInsts(Concat(common_code, dead_function)), - JoinAllInsts(common_code), /* skip_nop = */ true); -} - -TEST_F(EliminateDeadFunctionsBasicTest, BasicKeepLiveFunction) { - // Everything is reachable from an entry point, so no functions should be - // deleted. - const std::vector text = { - // clang-format off - "OpCapability Shader", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\"", - "OpName %main \"main\"", - "OpName %Live1 \"Live1\"", - "OpName %Live2 \"Live2\"", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%main = OpFunction %void None %7", - "%15 = OpLabel", - "%16 = OpFunctionCall %void %Live2", - "%17 = OpFunctionCall %void %Live1", - "OpReturn", - "OpFunctionEnd", - "%Live1 = OpFunction %void None %7", - "%19 = OpLabel", - "OpReturn", - "OpFunctionEnd", - "%Live2 = OpFunction %void None %7", - "%20 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - std::string assembly = JoinAllInsts(text); - auto result = SinglePassRunAndDisassemble( - assembly, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); - EXPECT_EQ(assembly, std::get<0>(result)); -} - -TEST_F(EliminateDeadFunctionsBasicTest, BasicKeepExportFunctions) { - // All functions are reachable. In particular, ExportedFunc and Constant are - // reachable because ExportedFunc is exported. Nothing should be removed. - const std::vector text = { - // clang-format off - "OpCapability Shader", - "OpCapability Linkage", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\"", - "OpName %main \"main\"", - "OpName %ExportedFunc \"ExportedFunc\"", - "OpName %Live \"Live\"", - "OpDecorate %ExportedFunc LinkageAttributes \"ExportedFunc\" Export", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%main = OpFunction %void None %7", - "%15 = OpLabel", - "OpReturn", - "OpFunctionEnd", -"%ExportedFunc = OpFunction %void None %7", - "%19 = OpLabel", - "%16 = OpFunctionCall %void %Live", - "OpReturn", - "OpFunctionEnd", - "%Live = OpFunction %void None %7", - "%20 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - std::string assembly = JoinAllInsts(text); - auto result = SinglePassRunAndDisassemble( - assembly, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); - EXPECT_EQ(assembly, std::get<0>(result)); -} - -TEST_F(EliminateDeadFunctionsBasicTest, BasicRemoveDecorationsAndNames) { - // We want to remove the names and decorations associated with results that - // are removed. This test will check for that. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - OpName %Dead "Dead" - OpName %x "x" - OpName %y "y" - OpName %z "z" - OpDecorate %x RelaxedPrecision - OpDecorate %y RelaxedPrecision - OpDecorate %z RelaxedPrecision - OpDecorate %6 RelaxedPrecision - OpDecorate %7 RelaxedPrecision - OpDecorate %8 RelaxedPrecision - %void = OpTypeVoid - %10 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float - %float_1 = OpConstant %float 1 - %main = OpFunction %void None %10 - %14 = OpLabel - OpReturn - OpFunctionEnd - %Dead = OpFunction %void None %10 - %15 = OpLabel - %x = OpVariable %_ptr_Function_float Function - %y = OpVariable %_ptr_Function_float Function - %z = OpVariable %_ptr_Function_float Function - OpStore %x %float_1 - OpStore %y %float_1 - %6 = OpLoad %float %x - %7 = OpLoad %float %y - %8 = OpFAdd %float %6 %7 - OpStore %z %8 - OpReturn - OpFunctionEnd)"; - - const std::string expected_output = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_1 = OpConstant %float 1 -%main = OpFunction %void None %10 -%14 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, expected_output, - /* skip_nop = */ true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/eliminate_dead_member_test.cpp b/3rdparty/spirv-tools/test/opt/eliminate_dead_member_test.cpp deleted file mode 100644 index b6925d7d7..000000000 --- a/3rdparty/spirv-tools/test/opt/eliminate_dead_member_test.cpp +++ /dev/null @@ -1,1088 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "assembly_builder.h" -#include "gmock/gmock.h" -#include "pass_fixture.h" -#include "pass_utils.h" - -namespace { - -using namespace spvtools; - -using EliminateDeadMemberTest = opt::PassTest<::testing::Test>; - -TEST_F(EliminateDeadMemberTest, RemoveMember1) { - // Test that the member "y" is removed. - // Update OpMemberName for |y| and |z|. - // Update OpMemberDecorate for |y| and |z|. - // Update OpAccessChain for access to |z|. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "x" -; CHECK-NEXT: OpMemberName %type__Globals 1 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 0 -; CHECK: OpMemberDecorate %type__Globals 1 Offset 8 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %int_0 -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %in_var_Position "in.var.Position" - OpName %main "main" - OpDecorate %gl_Position BuiltIn Position - OpDecorate %in_var_Position Location 0 - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 8 - OpDecorate %type__Globals Block - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %int_2 = OpConstant %int 2 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %void = OpTypeVoid - %15 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform -%in_var_Position = OpVariable %_ptr_Input_v4float Input -%gl_Position = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %15 - %17 = OpLabel - %18 = OpLoad %v4float %in_var_Position - %19 = OpAccessChain %_ptr_Uniform_float %_Globals %int_0 - %20 = OpLoad %float %19 - %21 = OpCompositeExtract %float %18 0 - %22 = OpFAdd %float %21 %20 - %23 = OpCompositeInsert %v4float %22 %18 0 - %24 = OpCompositeExtract %float %18 1 - %25 = OpCompositeInsert %v4float %24 %23 1 - %26 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2 - %27 = OpLoad %float %26 - %28 = OpCompositeExtract %float %18 2 - %29 = OpFAdd %float %28 %27 - %30 = OpCompositeInsert %v4float %29 %25 2 - OpStore %gl_Position %30 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberWithGroupDecorations) { - // Test that the member "y" is removed. - // Update OpGroupMemberDecorate for %type__Globals member 1 and 2. - // Update OpAccessChain for access to %type__Globals member 2. - const std::string text = R"( -; CHECK: OpDecorate [[gr1:%\w+]] Offset 0 -; CHECK: OpDecorate [[gr2:%\w+]] Offset 4 -; CHECK: OpDecorate [[gr3:%\w+]] Offset 8 -; CHECK: [[gr1]] = OpDecorationGroup -; CHECK: [[gr2]] = OpDecorationGroup -; CHECK: [[gr3]] = OpDecorationGroup -; CHECK: OpGroupMemberDecorate [[gr1]] %type__Globals 0 -; CHECK-NOT: OpGroupMemberDecorate [[gr2]] -; CHECK: OpGroupMemberDecorate [[gr3]] %type__Globals 1 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %int_0 -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpName %_Globals "$Globals" - OpDecorate %gl_Position BuiltIn Position - OpDecorate %in_var_Position Location 0 - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpDecorate %gr1 Offset 0 - OpDecorate %gr2 Offset 4 - OpDecorate %gr3 Offset 8 - OpDecorate %type__Globals Block - %gr1 = OpDecorationGroup - %gr2 = OpDecorationGroup - %gr3 = OpDecorationGroup - OpGroupMemberDecorate %gr1 %type__Globals 0 - OpGroupMemberDecorate %gr2 %type__Globals 1 - OpGroupMemberDecorate %gr3 %type__Globals 2 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %int_2 = OpConstant %int 2 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %void = OpTypeVoid - %15 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform -%in_var_Position = OpVariable %_ptr_Input_v4float Input -%gl_Position = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %15 - %17 = OpLabel - %18 = OpLoad %v4float %in_var_Position - %19 = OpAccessChain %_ptr_Uniform_float %_Globals %int_0 - %20 = OpLoad %float %19 - %21 = OpCompositeExtract %float %18 0 - %22 = OpFAdd %float %21 %20 - %23 = OpCompositeInsert %v4float %22 %18 0 - %24 = OpCompositeExtract %float %18 1 - %25 = OpCompositeInsert %v4float %24 %23 1 - %26 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2 - %27 = OpLoad %float %26 - %28 = OpCompositeExtract %float %18 2 - %29 = OpFAdd %float %28 %27 - %30 = OpCompositeInsert %v4float %29 %25 2 - OpStore %gl_Position %30 - OpReturn - OpFunctionEnd -)"; - - // Skipping validation because of a bug in the validator. See issue #2376. - SinglePassRunAndMatch(text, false); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberUpdateConstant) { - // Test that the member "x" is removed. - // Update the OpConstantComposite instruction. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NEXT: OpMemberName %type__Globals 1 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 4 -; CHECK: OpMemberDecorate %type__Globals 1 Offset 8 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: OpConstantComposite %type__Globals %float_1 %float_2 -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_0 -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %in_var_Position "in.var.Position" - OpName %main "main" - OpDecorate %gl_Position BuiltIn Position - OpDecorate %in_var_Position Location 0 - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 8 - OpDecorate %type__Globals Block - %int = OpTypeInt 32 1 - %int_1 = OpConstant %int 1 - %float = OpTypeFloat 32 - %float_0 = OpConstant %float 0 - %float_1 = OpConstant %float 1 - %float_2 = OpConstant %float 2 - %int_2 = OpConstant %int 2 -%type__Globals = OpTypeStruct %float %float %float - %13 = OpConstantComposite %type__Globals %float_0 %float_1 %float_2 -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %void = OpTypeVoid - %19 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform -%in_var_Position = OpVariable %_ptr_Input_v4float Input -%gl_Position = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %19 - %21 = OpLabel - %22 = OpLoad %v4float %in_var_Position - %23 = OpAccessChain %_ptr_Uniform_float %_Globals %int_1 - %24 = OpLoad %float %23 - %25 = OpCompositeExtract %float %22 0 - %26 = OpFAdd %float %25 %24 - %27 = OpCompositeInsert %v4float %26 %22 0 - %28 = OpCompositeExtract %float %22 1 - %29 = OpCompositeInsert %v4float %28 %27 1 - %30 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2 - %31 = OpLoad %float %30 - %32 = OpCompositeExtract %float %22 2 - %33 = OpFAdd %float %32 %31 - %34 = OpCompositeInsert %v4float %33 %29 2 - OpStore %gl_Position %34 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberUpdateCompositeConstruct) { - // Test that the member "x" is removed. - // Update the OpConstantComposite instruction. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NEXT: OpMemberName %type__Globals 1 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 4 -; CHECK: OpMemberDecorate %type__Globals 1 Offset 8 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: OpCompositeConstruct %type__Globals %float_1 %float_2 -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_0 -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals %uint_1 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %in_var_Position "in.var.Position" - OpName %main "main" - OpDecorate %gl_Position BuiltIn Position - OpDecorate %in_var_Position Location 0 - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 8 - OpDecorate %type__Globals Block - %int = OpTypeInt 32 1 - %int_1 = OpConstant %int 1 - %float = OpTypeFloat 32 - %float_0 = OpConstant %float 0 - %float_1 = OpConstant %float 1 - %float_2 = OpConstant %float 2 - %int_2 = OpConstant %int 2 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %void = OpTypeVoid - %19 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform -%in_var_Position = OpVariable %_ptr_Input_v4float Input -%gl_Position = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %19 - %21 = OpLabel - %13 = OpCompositeConstruct %type__Globals %float_0 %float_1 %float_2 - %22 = OpLoad %v4float %in_var_Position - %23 = OpAccessChain %_ptr_Uniform_float %_Globals %int_1 - %24 = OpLoad %float %23 - %25 = OpCompositeExtract %float %22 0 - %26 = OpFAdd %float %25 %24 - %27 = OpCompositeInsert %v4float %26 %22 0 - %28 = OpCompositeExtract %float %22 1 - %29 = OpCompositeInsert %v4float %28 %27 1 - %30 = OpAccessChain %_ptr_Uniform_float %_Globals %int_2 - %31 = OpLoad %float %30 - %32 = OpCompositeExtract %float %22 2 - %33 = OpFAdd %float %32 %31 - %34 = OpCompositeInsert %v4float %33 %29 2 - OpStore %gl_Position %34 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract1) { - // Test that the members "x" and "z" are removed. - // Update the OpCompositeExtract instruction. - // Remove the OpCompositeInsert instruction since the member being inserted is - // dead. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 4 -; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset -; CHECK: %type__Globals = OpTypeStruct %float -; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals -; CHECK: OpCompositeExtract %float [[ld]] 0 -; CHECK-NOT: OpCompositeInsert -; CHECK: OpReturn - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 8 - OpDecorate %type__Globals Block - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %7 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %7 - %8 = OpLabel - %9 = OpLoad %type__Globals %_Globals - %10 = OpCompositeExtract %float %9 1 - %11 = OpCompositeInsert %type__Globals %10 %9 2 - OpReturn - OpFunctionEnd - -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract2) { - // Test that the members "x" and "z" are removed. - // Update the OpCompositeExtract instruction. - // Update the OpCompositeInsert instruction. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 4 -; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset -; CHECK: %type__Globals = OpTypeStruct %float -; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals -; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 -; CHECK: OpCompositeInsert %type__Globals [[ex]] [[ld]] 0 -; CHECK: OpReturn - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 8 - OpDecorate %type__Globals Block - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %7 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %7 - %8 = OpLabel - %9 = OpLoad %type__Globals %_Globals - %10 = OpCompositeExtract %float %9 1 - %11 = OpCompositeInsert %type__Globals %10 %9 1 - OpReturn - OpFunctionEnd - -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract3) { - // Test that the members "x" and "z" are removed, and one member from the - // substruct. Update the OpCompositeExtract instruction. Update the - // OpCompositeInsert instruction. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 16 -; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset -; CHECK: OpMemberDecorate [[struct:%\w+]] 0 Offset 4 -; CHECK: [[struct:%\w+]] = OpTypeStruct %float -; CHECK: %type__Globals = OpTypeStruct [[struct]] -; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals -; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 0 -; CHECK: OpCompositeInsert %type__Globals [[ex]] [[ld]] 0 0 -; CHECK: OpReturn - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 16 - OpMemberDecorate %type__Globals 2 Offset 24 - OpMemberDecorate %_struct_6 0 Offset 0 - OpMemberDecorate %_struct_6 1 Offset 4 - OpDecorate %type__Globals Block - %float = OpTypeFloat 32 - %_struct_6 = OpTypeStruct %float %float -%type__Globals = OpTypeStruct %float %_struct_6 %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %7 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %7 - %8 = OpLabel - %9 = OpLoad %type__Globals %_Globals - %10 = OpCompositeExtract %float %9 1 1 - %11 = OpCompositeInsert %type__Globals %10 %9 1 1 - OpReturn - OpFunctionEnd - -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateInserExtract4) { - // Test that the members "x" and "z" are removed, and one member from the - // substruct. Update the OpCompositeExtract instruction. Update the - // OpCompositeInsert instruction. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 16 -; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset -; CHECK: OpMemberDecorate [[struct:%\w+]] 0 Offset 4 -; CHECK: [[struct:%\w+]] = OpTypeStruct %float -; CHECK: [[array:%\w+]] = OpTypeArray [[struct]] -; CHECK: %type__Globals = OpTypeStruct [[array]] -; CHECK: [[ld:%\w+]] = OpLoad %type__Globals %_Globals -; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 1 0 -; CHECK: OpCompositeInsert %type__Globals [[ex]] [[ld]] 0 1 0 -; CHECK: OpReturn - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 16 - OpMemberDecorate %type__Globals 2 Offset 80 - OpMemberDecorate %_struct_6 0 Offset 0 - OpMemberDecorate %_struct_6 1 Offset 4 - OpDecorate %array ArrayStride 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 ; 32-bit int, sign-less - %uint_4 = OpConstant %uint 4 - %float = OpTypeFloat 32 - %_struct_6 = OpTypeStruct %float %float - %array = OpTypeArray %_struct_6 %uint_4 -%type__Globals = OpTypeStruct %float %array %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %7 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %7 - %8 = OpLabel - %9 = OpLoad %type__Globals %_Globals - %10 = OpCompositeExtract %float %9 1 1 1 - %11 = OpCompositeInsert %type__Globals %10 %9 1 1 1 - OpReturn - OpFunctionEnd - -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMembersUpdateArrayLength) { - // Test that the members "x" and "y" are removed. - // Member "z" is live because of the OpArrayLength instruction. - // Update the OpArrayLength instruction. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 16 -; CHECK-NOT: OpMemberDecorate %type__Globals 1 Offset -; CHECK: %type__Globals = OpTypeStruct %_runtimearr_float -; CHECK: OpArrayLength %uint %_Globals 0 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpDecorate %_runtimearr_float ArrayStride 16 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 -%_runtimearr_float = OpTypeRuntimeArray %float -%type__Globals = OpTypeStruct %float %float %_runtimearr_float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %9 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %9 - %10 = OpLabel - %11 = OpLoad %type__Globals %_Globals - %12 = OpArrayLength %uint %_Globals 2 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, KeepMembersOpStore) { - // Test that all members are kept because of an OpStore. - // No change expected. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %_Globals "$Globals2" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %9 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %9 - %10 = OpLabel - %11 = OpLoad %type__Globals %_Globals - OpStore %_Globals2 %11 - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(EliminateDeadMemberTest, KeepMembersOpCopyMemory) { - // Test that all members are kept because of an OpCopyMemory. - // No change expected. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %_Globals "$Globals2" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %9 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %9 - %10 = OpLabel - OpCopyMemory %_Globals2 %_Globals - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(EliminateDeadMemberTest, KeepMembersOpCopyMemorySized) { - // Test that all members are kept because of an OpCopyMemorySized. - // No change expected. - const std::string text = R"( - OpCapability Shader - OpCapability Addresses - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %_Globals "$Globals2" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %uint_20 = OpConstant %uint 20 - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %9 = OpTypeFunction %void - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %void None %9 - %10 = OpLabel - OpCopyMemorySized %_Globals2 %_Globals %uint_20 - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(EliminateDeadMemberTest, KeepMembersOpReturnValue) { - // Test that all members are kept because of an OpCopyMemorySized. - // No change expected. - const std::string text = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %_Globals "$Globals2" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %uint_20 = OpConstant %uint 20 - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %void = OpTypeVoid - %9 = OpTypeFunction %type__Globals - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform - %_Globals2 = OpVariable %_ptr_Uniform_type__Globals Uniform - %main = OpFunction %type__Globals None %9 - %10 = OpLabel - %11 = OpLoad %type__Globals %_Globals - OpReturnValue %11 - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberAccessChainWithArrays) { - // Leave only 1 member in each of the structs. - // Update OpMemberName, OpMemberDecorate, and OpAccessChain. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "y" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 16 -; CHECK: OpMemberDecorate [[struct:%\w+]] 0 Offset 4 -; CHECK: [[struct]] = OpTypeStruct %float -; CHECK: [[array:%\w+]] = OpTypeArray [[struct]] -; CHECK: %type__Globals = OpTypeStruct [[array]] -; CHECK: [[undef:%\w+]] = OpUndef %uint -; CHECK: OpAccessChain %_ptr_Uniform_float %_Globals [[undef]] %uint_0 [[undef]] %uint_0 - OpCapability Shader - OpCapability VariablePointersStorageBuffer - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 16 - OpMemberDecorate %type__Globals 2 Offset 48 - OpMemberDecorate %_struct_4 0 Offset 0 - OpMemberDecorate %_struct_4 1 Offset 4 - OpDecorate %_arr__struct_4_uint_2 ArrayStride 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %uint_3 = OpConstant %uint 3 - %float = OpTypeFloat 32 - %_struct_4 = OpTypeStruct %float %float -%_arr__struct_4_uint_2 = OpTypeArray %_struct_4 %uint_2 -%type__Globals = OpTypeStruct %float %_arr__struct_4_uint_2 %float -%_arr_type__Globals_uint_3 = OpTypeArray %type__Globals %uint_3 -%_ptr_Uniform__arr_type__Globals_uint_3 = OpTypePointer Uniform %_arr_type__Globals_uint_3 - %void = OpTypeVoid - %15 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform__arr_type__Globals_uint_3 Uniform - %main = OpFunction %void None %15 - %17 = OpLabel - %18 = OpUndef %uint - %19 = OpAccessChain %_ptr_Uniform_float %_Globals %18 %uint_1 %18 %uint_1 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberInboundsAccessChain) { - // Test that the member "y" is removed. - // Update OpMemberName for |y| and |z|. - // Update OpMemberDecorate for |y| and |z|. - // Update OpInboundsAccessChain for access to |z|. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "x" -; CHECK-NEXT: OpMemberName %type__Globals 1 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 0 -; CHECK: OpMemberDecorate %type__Globals 1 Offset 8 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %int_0 -; CHECK: OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %uint_1 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %in_var_Position %gl_Position - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %in_var_Position "in.var.Position" - OpName %main "main" - OpDecorate %gl_Position BuiltIn Position - OpDecorate %in_var_Position Location 0 - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 8 - OpDecorate %type__Globals Block - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %int_2 = OpConstant %int 2 -%type__Globals = OpTypeStruct %float %float %float -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %void = OpTypeVoid - %15 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform_type__Globals Uniform -%in_var_Position = OpVariable %_ptr_Input_v4float Input -%gl_Position = OpVariable %_ptr_Output_v4float Output - %main = OpFunction %void None %15 - %17 = OpLabel - %18 = OpLoad %v4float %in_var_Position - %19 = OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %int_0 - %20 = OpLoad %float %19 - %21 = OpCompositeExtract %float %18 0 - %22 = OpFAdd %float %21 %20 - %23 = OpCompositeInsert %v4float %22 %18 0 - %24 = OpCompositeExtract %float %18 1 - %25 = OpCompositeInsert %v4float %24 %23 1 - %26 = OpInBoundsAccessChain %_ptr_Uniform_float %_Globals %int_2 - %27 = OpLoad %float %26 - %28 = OpCompositeExtract %float %18 2 - %29 = OpFAdd %float %28 %27 - %30 = OpCompositeInsert %v4float %29 %25 2 - OpStore %gl_Position %30 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberPtrAccessChain) { - // Test that the member "y" is removed. - // Update OpMemberName for |y| and |z|. - // Update OpMemberDecorate for |y| and |z|. - // Update OpInboundsAccessChain for access to |z|. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "x" -; CHECK-NEXT: OpMemberName %type__Globals 1 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 0 -; CHECK: OpMemberDecorate %type__Globals 1 Offset 16 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0 -; CHECK: OpPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_1 %uint_0 -; CHECK: OpPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_0 %uint_1 - OpCapability Shader - OpCapability VariablePointersStorageBuffer - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %uint_3 = OpConstant %uint 3 - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_arr_type__Globals_uint_3 = OpTypeArray %type__Globals %uint_3 -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals -%_ptr_Uniform__arr_type__Globals_uint_3 = OpTypePointer Uniform %_arr_type__Globals_uint_3 - %void = OpTypeVoid - %14 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform__arr_type__Globals_uint_3 Uniform - %main = OpFunction %void None %14 - %16 = OpLabel - %17 = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0 - %18 = OpPtrAccessChain %_ptr_Uniform_float %17 %uint_1 %uint_0 - %19 = OpPtrAccessChain %_ptr_Uniform_float %17 %uint_0 %uint_2 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, RemoveMemberInBoundsPtrAccessChain) { - // Test that the member "y" is removed. - // Update OpMemberName for |y| and |z|. - // Update OpMemberDecorate for |y| and |z|. - // Update OpInboundsAccessChain for access to |z|. - const std::string text = R"( -; CHECK: OpName -; CHECK-NEXT: OpMemberName %type__Globals 0 "x" -; CHECK-NEXT: OpMemberName %type__Globals 1 "z" -; CHECK-NOT: OpMemberName -; CHECK: OpMemberDecorate %type__Globals 0 Offset 0 -; CHECK: OpMemberDecorate %type__Globals 1 Offset 16 -; CHECK: %type__Globals = OpTypeStruct %float %float -; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0 -; CHECK: OpInBoundsPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_1 %uint_0 -; CHECK: OpInBoundsPtrAccessChain %_ptr_Uniform_float [[ac]] %uint_0 %uint_1 - OpCapability Shader - OpCapability Addresses - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource HLSL 600 - OpName %type__Globals "type.$Globals" - OpMemberName %type__Globals 0 "x" - OpMemberName %type__Globals 1 "y" - OpMemberName %type__Globals 2 "z" - OpName %_Globals "$Globals" - OpName %main "main" - OpDecorate %_Globals DescriptorSet 0 - OpDecorate %_Globals Binding 0 - OpMemberDecorate %type__Globals 0 Offset 0 - OpMemberDecorate %type__Globals 1 Offset 4 - OpMemberDecorate %type__Globals 2 Offset 16 - OpDecorate %type__Globals Block - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %uint_3 = OpConstant %uint 3 - %float = OpTypeFloat 32 -%type__Globals = OpTypeStruct %float %float %float -%_arr_type__Globals_uint_3 = OpTypeArray %type__Globals %uint_3 -%_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals -%_ptr_Uniform__arr_type__Globals_uint_3 = OpTypePointer Uniform %_arr_type__Globals_uint_3 - %void = OpTypeVoid - %14 = OpTypeFunction %void -%_ptr_Uniform_float = OpTypePointer Uniform %float - %_Globals = OpVariable %_ptr_Uniform__arr_type__Globals_uint_3 Uniform - %main = OpFunction %void None %14 - %16 = OpLabel - %17 = OpAccessChain %_ptr_Uniform_type__Globals %_Globals %uint_0 - %18 = OpInBoundsPtrAccessChain %_ptr_Uniform_float %17 %uint_1 %uint_0 - %19 = OpInBoundsPtrAccessChain %_ptr_Uniform_float %17 %uint_0 %uint_2 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(EliminateDeadMemberTest, DontRemoveModfStructResultTypeMembers) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - %float = OpTypeFloat 32 - %void = OpTypeVoid - %21 = OpTypeFunction %void -%ModfStructType = OpTypeStruct %float %float -%main = OpFunction %void None %21 - %22 = OpLabel - %23 = OpUndef %float - %24 = OpExtInst %ModfStructType %1 ModfStruct %23 - %25 = OpCompositeExtract %float %24 1 - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(EliminateDeadMemberTest, DontChangeInputStructs) { - // The input for a shader has to match the type of the output from the - // previous shader in the pipeline. Because of that, we cannot change the - // types of input variables. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %input_var - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - %float = OpTypeFloat 32 - %void = OpTypeVoid - %21 = OpTypeFunction %void -%in_var_type = OpTypeStruct %float %float -%in_ptr_type = OpTypePointer Input %in_var_type -%input_var = OpVariable %in_ptr_type Input -%main = OpFunction %void None %21 - %22 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(EliminateDeadMemberTest, DontChangeOutputStructs) { - // The output for a shader has to match the type of the output from the - // previous shader in the pipeline. Because of that, we cannot change the - // types of output variables. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %output_var - OpExecutionMode %main OriginUpperLeft - OpSource HLSL 600 - %float = OpTypeFloat 32 - %void = OpTypeVoid - %21 = OpTypeFunction %void -%out_var_type = OpTypeStruct %float %float -%out_ptr_type = OpTypePointer Output %out_var_type -%output_var = OpVariable %out_ptr_type Output -%main = OpFunction %void None %21 - %22 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ true); - EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -} // namespace diff --git a/3rdparty/spirv-tools/test/opt/feature_manager_test.cpp b/3rdparty/spirv-tools/test/opt/feature_manager_test.cpp deleted file mode 100644 index 767376cf5..000000000 --- a/3rdparty/spirv-tools/test/opt/feature_manager_test.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { -namespace { - -using FeatureManagerTest = ::testing::Test; - -TEST_F(FeatureManagerTest, MissingExtension) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - EXPECT_FALSE(context->get_feature_mgr()->HasExtension( - Extension::kSPV_KHR_variable_pointers)); -} - -TEST_F(FeatureManagerTest, OneExtension) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpExtension "SPV_KHR_variable_pointers" - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - EXPECT_TRUE(context->get_feature_mgr()->HasExtension( - Extension::kSPV_KHR_variable_pointers)); -} - -TEST_F(FeatureManagerTest, NotADifferentExtension) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpExtension "SPV_KHR_variable_pointers" - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - EXPECT_FALSE(context->get_feature_mgr()->HasExtension( - Extension::kSPV_KHR_storage_buffer_storage_class)); -} - -TEST_F(FeatureManagerTest, TwoExtensions) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_storage_buffer_storage_class" - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - EXPECT_TRUE(context->get_feature_mgr()->HasExtension( - Extension::kSPV_KHR_variable_pointers)); - EXPECT_TRUE(context->get_feature_mgr()->HasExtension( - Extension::kSPV_KHR_storage_buffer_storage_class)); -} - -// Test capability checks. -TEST_F(FeatureManagerTest, ExplicitlyPresent1) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader)); - EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel)); -} - -TEST_F(FeatureManagerTest, ExplicitlyPresent2) { - const std::string text = R"( -OpCapability Kernel -OpMemoryModel Logical GLSL450 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader)); - EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel)); -} - -TEST_F(FeatureManagerTest, ImplicitlyPresent) { - const std::string text = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ASSERT_NE(context, nullptr); - - // Check multiple levels of indirection. Tessellation implies Shader, which - // implies Matrix. - EXPECT_TRUE( - context->get_feature_mgr()->HasCapability(SpvCapabilityTessellation)); - EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader)); - EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityMatrix)); - EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/fix_storage_class_test.cpp b/3rdparty/spirv-tools/test/opt/fix_storage_class_test.cpp deleted file mode 100644 index 4c8504ae1..000000000 --- a/3rdparty/spirv-tools/test/opt/fix_storage_class_test.cpp +++ /dev/null @@ -1,840 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using FixStorageClassTest = PassTest<::testing::Test>; - -TEST_F(FixStorageClassTest, FixAccessChain) { - const std::string text = R"( -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %8 DescriptorSet 0 - OpDecorate %8 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%ptr = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_5 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_5 = OpTypePointer Workgroup %_struct_5 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %30 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %6 = OpVariable %_ptr_Workgroup__struct_5 Workgroup - %8 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %30 - %38 = OpLabel - %44 = OpLoad %v3uint %gl_LocalInvocationID - %50 = OpAccessChain %_ptr_Function_float %6 %int_0 %int_0 %int_0 - %51 = OpLoad %float %50 - %52 = OpFMul %float %float_2 %51 - OpStore %50 %52 - %55 = OpLoad %float %50 - %59 = OpCompositeExtract %uint %44 0 - %60 = OpAccessChain %_ptr_Uniform_float %8 %int_0 %59 - OpStore %60 %55 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixStorageClassTest, FixLinkedAccessChain) { - const std::string text = R"( -; CHECK: OpAccessChain %_ptr_Workgroup__arr_float_uint_10 -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10 -%_ptr = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_17 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_17 = OpTypePointer Workgroup %_struct_17 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %23 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %27 = OpVariable %_ptr_Workgroup__struct_17 Workgroup - %5 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %23 - %28 = OpLabel - %29 = OpLoad %v3uint %gl_LocalInvocationID - %30 = OpAccessChain %_ptr_Function__arr_float_uint_10 %27 %int_0 %int_0 - %31 = OpAccessChain %_ptr_Function_float %30 %int_0 - %32 = OpLoad %float %31 - %33 = OpFMul %float %float_2 %32 - OpStore %31 %33 - %34 = OpLoad %float %31 - %35 = OpCompositeExtract %uint %29 0 - %36 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %35 - OpStore %36 %34 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixStorageClassTest, FixCopyObject) { - const std::string text = R"( -; CHECK: OpCopyObject %_ptr_Workgroup__struct_17 -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %8 DescriptorSet 0 - OpDecorate %8 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%ptr = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_17 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_17 = OpTypePointer Workgroup %_struct_17 -%_ptr_Function__struct_17 = OpTypePointer Function %_struct_17 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %30 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %6 = OpVariable %_ptr_Workgroup__struct_17 Workgroup - %8 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %30 - %38 = OpLabel - %44 = OpLoad %v3uint %gl_LocalInvocationID - %cp = OpCopyObject %_ptr_Function__struct_17 %6 - %50 = OpAccessChain %_ptr_Function_float %cp %int_0 %int_0 %int_0 - %51 = OpLoad %float %50 - %52 = OpFMul %float %float_2 %51 - OpStore %50 %52 - %55 = OpLoad %float %50 - %59 = OpCompositeExtract %uint %44 0 - %60 = OpAccessChain %_ptr_Uniform_float %8 %int_0 %59 - OpStore %60 %55 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixStorageClassTest, FixPhiInSelMerge) { - const std::string text = R"( -; CHECK: OpPhi %_ptr_Workgroup__struct_19 -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %bool = OpTypeBool - %true = OpConstantTrue %bool - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_19 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_19 = OpTypePointer Workgroup %_struct_19 -%_ptr_Function__struct_19 = OpTypePointer Function %_struct_19 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %25 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %28 = OpVariable %_ptr_Workgroup__struct_19 Workgroup - %29 = OpVariable %_ptr_Workgroup__struct_19 Workgroup - %5 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %25 - %30 = OpLabel - OpSelectionMerge %31 None - OpBranchConditional %true %32 %31 - %32 = OpLabel - OpBranch %31 - %31 = OpLabel - %33 = OpPhi %_ptr_Function__struct_19 %28 %30 %29 %32 - %34 = OpLoad %v3uint %gl_LocalInvocationID - %35 = OpAccessChain %_ptr_Function_float %33 %int_0 %int_0 %int_0 - %36 = OpLoad %float %35 - %37 = OpFMul %float %float_2 %36 - OpStore %35 %37 - %38 = OpLoad %float %35 - %39 = OpCompositeExtract %uint %34 0 - %40 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %39 - OpStore %40 %38 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixStorageClassTest, FixPhiInLoop) { - const std::string text = R"( -; CHECK: OpPhi %_ptr_Workgroup__struct_19 -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %bool = OpTypeBool - %true = OpConstantTrue %bool - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_19 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_19 = OpTypePointer Workgroup %_struct_19 -%_ptr_Function__struct_19 = OpTypePointer Function %_struct_19 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %25 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %28 = OpVariable %_ptr_Workgroup__struct_19 Workgroup - %29 = OpVariable %_ptr_Workgroup__struct_19 Workgroup - %5 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %25 - %30 = OpLabel - OpSelectionMerge %31 None - OpBranchConditional %true %32 %31 - %32 = OpLabel - OpBranch %31 - %31 = OpLabel - %33 = OpPhi %_ptr_Function__struct_19 %28 %30 %29 %32 - %34 = OpLoad %v3uint %gl_LocalInvocationID - %35 = OpAccessChain %_ptr_Function_float %33 %int_0 %int_0 %int_0 - %36 = OpLoad %float %35 - %37 = OpFMul %float %float_2 %36 - OpStore %35 %37 - %38 = OpLoad %float %35 - %39 = OpCompositeExtract %uint %34 0 - %40 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %39 - OpStore %40 %38 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixStorageClassTest, DontChangeFunctionCalls) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "testMain" -OpExecutionMode %1 LocalSize 8 8 1 -OpDecorate %2 DescriptorSet 0 -OpDecorate %2 Binding 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Workgroup_int = OpTypePointer Workgroup %int -%_ptr_Uniform_int = OpTypePointer Uniform %int -%void = OpTypeVoid -%8 = OpTypeFunction %void -%9 = OpTypeFunction %_ptr_Uniform_int %_ptr_Function_int -%10 = OpVariable %_ptr_Workgroup_int Workgroup -%2 = OpVariable %_ptr_Uniform_int Uniform -%1 = OpFunction %void None %8 -%11 = OpLabel -%12 = OpFunctionCall %_ptr_Uniform_int %13 %10 -OpReturn -OpFunctionEnd -%13 = OpFunction %_ptr_Uniform_int None %9 -%14 = OpFunctionParameter %_ptr_Function_int -%15 = OpLabel -OpReturnValue %2 -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, false, false); -} - -TEST_F(FixStorageClassTest, FixSelect) { - const std::string text = R"( -; CHECK: OpSelect %_ptr_Workgroup__struct_19 -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %bool = OpTypeBool - %true = OpConstantTrue %bool - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_19 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_19 = OpTypePointer Workgroup %_struct_19 -%_ptr_Function__struct_19 = OpTypePointer Function %_struct_19 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %25 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %28 = OpVariable %_ptr_Workgroup__struct_19 Workgroup - %29 = OpVariable %_ptr_Workgroup__struct_19 Workgroup - %5 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %25 - %30 = OpLabel - %33 = OpSelect %_ptr_Function__struct_19 %true %28 %29 - %34 = OpLoad %v3uint %gl_LocalInvocationID - %35 = OpAccessChain %_ptr_Function_float %33 %int_0 %int_0 %int_0 - %36 = OpLoad %float %35 - %37 = OpFMul %float %float_2 %36 - OpStore %35 %37 - %38 = OpLoad %float %35 - %39 = OpCompositeExtract %uint %34 0 - %40 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %39 - OpStore %40 %38 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixStorageClassTest, BitCast) { - const std::string text = R"(OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%_ptr_Output_void = OpTypePointer Output %void -%_ptr_Private__ptr_Output_void = OpTypePointer Private %_ptr_Output_void -%6 = OpVariable %_ptr_Private__ptr_Output_void Private -%1 = OpFunction %void Inline %3 -%7 = OpLabel -%8 = OpBitcast %_ptr_Output_void %6 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, false); -} - -TEST_F(FixStorageClassTest, FixLinkedAccessChain2) { - // This case is similar to FixLinkedAccessChain. The difference is that the - // first OpAccessChain instruction starts as workgroup storage class. Only - // the second one needs to change. - const std::string text = R"( -; CHECK: OpAccessChain %_ptr_Workgroup__arr_float_uint_10 -; CHECK: OpAccessChain %_ptr_Workgroup_float -; CHECK: OpAccessChain %_ptr_Uniform_float - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID - OpExecutionMode %1 LocalSize 8 8 1 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId - OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %_runtimearr_float ArrayStride 4 - OpMemberDecorate %_struct_7 0 Offset 0 - OpDecorate %_struct_7 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_2 = OpConstant %float 2 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_float_uint_10 = OpTypeArray %float %uint_10 -%_ptr_Workgroup__arr_float_uint_10 = OpTypePointer Workgroup %_arr_float_uint_10 -%_ptr = OpTypePointer Function %_arr_float_uint_10 -%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 - %_struct_17 = OpTypeStruct %_arr__arr_float_uint_10_uint_10 -%_ptr_Workgroup__struct_17 = OpTypePointer Workgroup %_struct_17 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint - %void = OpTypeVoid - %23 = OpTypeFunction %void -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Uniform_float = OpTypePointer Uniform %float - %27 = OpVariable %_ptr_Workgroup__struct_17 Workgroup - %5 = OpVariable %_ptr_Uniform__struct_7 Uniform -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input -%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input - %1 = OpFunction %void None %23 - %28 = OpLabel - %29 = OpLoad %v3uint %gl_LocalInvocationID - %30 = OpAccessChain %_ptr_Workgroup__arr_float_uint_10 %27 %int_0 %int_0 - %31 = OpAccessChain %_ptr_Function_float %30 %int_0 - %32 = OpLoad %float %31 - %33 = OpFMul %float %float_2 %32 - OpStore %31 %33 - %34 = OpLoad %float %31 - %35 = OpCompositeExtract %uint %29 0 - %36 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %35 - OpStore %36 %34 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -using FixTypeTest = PassTest<::testing::Test>; - -TEST_F(FixTypeTest, FixAccessChain) { - const std::string text = R"( -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0 -; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_T [[ac1]] %int_0 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource HLSL 600 - OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" - OpName %S "S" - OpMemberName %S 0 "t" - OpName %T "T" - OpMemberName %T 0 "a" - OpName %A "A" - OpName %type_ACSBuffer_counter "type.ACSBuffer.counter" - OpMemberName %type_ACSBuffer_counter 0 "counter" - OpName %counter_var_A "counter.var.A" - OpName %main "main" - OpName %S_0 "S" - OpMemberName %S_0 0 "t" - OpName %T_0 "T" - OpMemberName %T_0 0 "a" - OpDecorate %A DescriptorSet 0 - OpDecorate %A Binding 0 - OpDecorate %counter_var_A DescriptorSet 0 - OpDecorate %counter_var_A Binding 1 - OpMemberDecorate %T 0 Offset 0 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %_runtimearr_S ArrayStride 4 - OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 - OpDecorate %type_RWStructuredBuffer_S BufferBlock - OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0 - OpDecorate %type_ACSBuffer_counter BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %T = OpTypeStruct %int - %S = OpTypeStruct %T -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S -%type_ACSBuffer_counter = OpTypeStruct %int -%_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter - %void = OpTypeVoid - %18 = OpTypeFunction %void - %T_0 = OpTypeStruct %int - %S_0 = OpTypeStruct %T_0 -%_ptr_Function_S_0 = OpTypePointer Function %S_0 -%_ptr_Uniform_S = OpTypePointer Uniform %S -%_ptr_Uniform_T = OpTypePointer Uniform %T - %22 = OpTypeFunction %T_0 %_ptr_Function_S_0 -%_ptr_Function_T_0 = OpTypePointer Function %T_0 - %A = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform -%counter_var_A = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform - %main = OpFunction %void None %18 - %24 = OpLabel - %25 = OpVariable %_ptr_Function_T_0 Function - %26 = OpVariable %_ptr_Function_S_0 Function - %27 = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0 - %28 = OpAccessChain %_ptr_Function_T_0 %27 %int_0 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixTypeTest, FixLoad) { - const std::string text = R"( -; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0 -; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_T [[ac1]] %int_0 -; CHECK: [[ld:%\w+]] = OpLoad %T [[ac2]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource HLSL 600 - OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" - OpName %S "S" - OpMemberName %S 0 "t" - OpName %T "T" - OpMemberName %T 0 "a" - OpName %A "A" - OpName %type_ACSBuffer_counter "type.ACSBuffer.counter" - OpMemberName %type_ACSBuffer_counter 0 "counter" - OpName %counter_var_A "counter.var.A" - OpName %main "main" - OpName %S_0 "S" - OpMemberName %S_0 0 "t" - OpName %T_0 "T" - OpMemberName %T_0 0 "a" - OpDecorate %A DescriptorSet 0 - OpDecorate %A Binding 0 - OpDecorate %counter_var_A DescriptorSet 0 - OpDecorate %counter_var_A Binding 1 - OpMemberDecorate %T 0 Offset 0 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %_runtimearr_S ArrayStride 4 - OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 - OpDecorate %type_RWStructuredBuffer_S BufferBlock - OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0 - OpDecorate %type_ACSBuffer_counter BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %T = OpTypeStruct %int - %S = OpTypeStruct %T -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S -%type_ACSBuffer_counter = OpTypeStruct %int -%_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter - %void = OpTypeVoid - %18 = OpTypeFunction %void - %T_0 = OpTypeStruct %int - %S_0 = OpTypeStruct %T_0 -%_ptr_Function_S_0 = OpTypePointer Function %S_0 -%_ptr_Uniform_S = OpTypePointer Uniform %S -%_ptr_Uniform_T = OpTypePointer Uniform %T - %22 = OpTypeFunction %T_0 %_ptr_Function_S_0 -%_ptr_Function_T_0 = OpTypePointer Function %T_0 - %A = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform -%counter_var_A = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform - %main = OpFunction %void None %18 - %24 = OpLabel - %25 = OpVariable %_ptr_Function_T_0 Function - %26 = OpVariable %_ptr_Function_S_0 Function - %27 = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0 - %28 = OpAccessChain %_ptr_Uniform_T %27 %int_0 - %29 = OpLoad %T_0 %28 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixTypeTest, FixStore) { - const std::string text = R"( -; CHECK: [[ld:%\w+]] = OpLoad %T -; CHECK: OpStore - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource HLSL 600 - OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" - OpName %S "S" - OpMemberName %S 0 "t" - OpName %T "T" - OpMemberName %T 0 "a" - OpName %A "A" - OpName %type_ACSBuffer_counter "type.ACSBuffer.counter" - OpMemberName %type_ACSBuffer_counter 0 "counter" - OpName %counter_var_A "counter.var.A" - OpName %main "main" - OpName %S_0 "S" - OpMemberName %S_0 0 "t" - OpName %T_0 "T" - OpMemberName %T_0 0 "a" - OpDecorate %A DescriptorSet 0 - OpDecorate %A Binding 0 - OpDecorate %counter_var_A DescriptorSet 0 - OpDecorate %counter_var_A Binding 1 - OpMemberDecorate %T 0 Offset 0 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %_runtimearr_S ArrayStride 4 - OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 - OpDecorate %type_RWStructuredBuffer_S BufferBlock - OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0 - OpDecorate %type_ACSBuffer_counter BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %T = OpTypeStruct %int - %S = OpTypeStruct %T -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S -%type_ACSBuffer_counter = OpTypeStruct %int -%_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter - %void = OpTypeVoid - %18 = OpTypeFunction %void - %T_0 = OpTypeStruct %int - %S_0 = OpTypeStruct %T_0 -%_ptr_Function_S_0 = OpTypePointer Function %S_0 -%_ptr_Uniform_S = OpTypePointer Uniform %S -%_ptr_Uniform_T = OpTypePointer Uniform %T - %22 = OpTypeFunction %T_0 %_ptr_Function_S_0 -%_ptr_Function_T_0 = OpTypePointer Function %T_0 - %A = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform -%counter_var_A = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform - %main = OpFunction %void None %18 - %24 = OpLabel - %25 = OpVariable %_ptr_Function_T_0 Function - %26 = OpVariable %_ptr_Function_S_0 Function - %27 = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0 - %28 = OpAccessChain %_ptr_Uniform_T %27 %int_0 - %29 = OpLoad %T %28 - OpStore %25 %29 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixTypeTest, FixSelect) { - const std::string text = R"( -; CHECK: OpSelect %_ptr_Uniform__struct_3 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 BufferBlock - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %_struct_3 = OpTypeStruct %uint -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 - %void = OpTypeVoid - %11 = OpTypeFunction %void - %_struct_12 = OpTypeStruct %uint -%_ptr_Function__struct_12 = OpTypePointer Function %_struct_12 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint - %bool = OpTypeBool -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 - %2 = OpVariable %_ptr_Uniform__struct_5 Uniform - %1 = OpFunction %void None %11 - %17 = OpLabel - %18 = OpAccessChain %_ptr_Uniform_uint %2 %uint_0 %uint_0 %uint_0 - %19 = OpLoad %uint %18 - %20 = OpSGreaterThan %bool %19 %uint_0 - %21 = OpAccessChain %_ptr_Uniform__struct_3 %2 %uint_0 %uint_0 - %22 = OpAccessChain %_ptr_Uniform__struct_3 %2 %uint_0 %uint_1 - %23 = OpSelect %_ptr_Function__struct_12 %20 %21 %22 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(FixTypeTest, FixPhiInLoop) { - const std::string text = R"( -; CHECK: [[ac_init:%\w+]] = OpAccessChain %_ptr_Uniform__struct_3 -; CHECK: [[ac_phi:%\w+]] = OpPhi %_ptr_Uniform__struct_3 [[ac_init]] {{%\w+}} [[ac_update:%\w+]] {{%\w+}} -; CHECK: [[ac_update]] = OpPtrAccessChain %_ptr_Uniform__struct_3 [[ac_phi]] %int_1 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %_struct_3 = OpTypeStruct %int - %_struct_9 = OpTypeStruct %int -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 - %void = OpTypeVoid - %12 = OpTypeFunction %void - %bool = OpTypeBool -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 -%_ptr_Function__struct_9 = OpTypePointer Function %_struct_9 - %2 = OpVariable %_ptr_Uniform__struct_5 Uniform - %1 = OpFunction %void None %12 - %16 = OpLabel - %17 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %int_0 - OpBranch %18 - %18 = OpLabel - %20 = OpPhi %_ptr_Function__struct_9 %17 %16 %21 %22 - %23 = OpUndef %bool - OpLoopMerge %24 %22 None - OpBranchConditional %23 %22 %24 - %22 = OpLabel - %21 = OpPtrAccessChain %_ptr_Function__struct_9 %20 %int_1 - OpBranch %18 - %24 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/flatten_decoration_test.cpp b/3rdparty/spirv-tools/test/opt/flatten_decoration_test.cpp deleted file mode 100644 index d8d886771..000000000 --- a/3rdparty/spirv-tools/test/opt/flatten_decoration_test.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "gmock/gmock.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -// Returns the initial part of the assembly text for a valid -// SPIR-V module, including instructions prior to decorations. -std::string PreambleAssembly() { - return - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %hue %saturation %value -OpExecutionMode %main OriginUpperLeft -OpName %main "main" -OpName %void_fn "void_fn" -OpName %hue "hue" -OpName %saturation "saturation" -OpName %value "value" -OpName %entry "entry" -OpName %Point "Point" -OpName %Camera "Camera" -)"; -} - -// Retuns types -std::string TypesAndFunctionsAssembly() { - return - R"(%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%float = OpTypeFloat 32 -%Point = OpTypeStruct %float %float %float -%Camera = OpTypeStruct %float %float -%_ptr_Input_float = OpTypePointer Input %float -%hue = OpVariable %_ptr_Input_float Input -%saturation = OpVariable %_ptr_Input_float Input -%value = OpVariable %_ptr_Input_float Input -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; -} - -struct FlattenDecorationCase { - // Names and decorations before the pass. - std::string input; - // Names and decorations after the pass. - std::string expected; -}; - -using FlattenDecorationTest = - PassTest<::testing::TestWithParam>; - -TEST_P(FlattenDecorationTest, TransformsDecorations) { - const auto before = - PreambleAssembly() + GetParam().input + TypesAndFunctionsAssembly(); - const auto after = - PreambleAssembly() + GetParam().expected + TypesAndFunctionsAssembly(); - - SinglePassRunAndCheck(before, after, false, true); -} - -INSTANTIATE_TEST_SUITE_P(NoUses, FlattenDecorationTest, - ::testing::ValuesIn(std::vector{ - // No OpDecorationGroup - {"", ""}, - - // OpDecorationGroup without any uses, and - // no OpName. - {"%group = OpDecorationGroup\n", ""}, - - // OpDecorationGroup without any uses, and - // with OpName targeting it. Proves you must - // remove the names as well. - {"OpName %group \"group\"\n" - "%group = OpDecorationGroup\n", - ""}, - - // OpDecorationGroup with decorations that - // target it, but no uses in OpGroupDecorate - // or OpGroupMemberDecorate instructions. - {"OpDecorate %group Flat\n" - "OpDecorate %group NoPerspective\n" - "%group = OpDecorationGroup\n", - ""}, - })); - -INSTANTIATE_TEST_SUITE_P(OpGroupDecorate, FlattenDecorationTest, - ::testing::ValuesIn(std::vector{ - // One OpGroupDecorate - {"OpName %group \"group\"\n" - "OpDecorate %group Flat\n" - "OpDecorate %group NoPerspective\n" - "%group = OpDecorationGroup\n" - "OpGroupDecorate %group %hue %saturation\n", - "OpDecorate %hue Flat\n" - "OpDecorate %saturation Flat\n" - "OpDecorate %hue NoPerspective\n" - "OpDecorate %saturation NoPerspective\n"}, - // Multiple OpGroupDecorate - {"OpName %group \"group\"\n" - "OpDecorate %group Flat\n" - "OpDecorate %group NoPerspective\n" - "%group = OpDecorationGroup\n" - "OpGroupDecorate %group %hue %value\n" - "OpGroupDecorate %group %saturation\n", - "OpDecorate %hue Flat\n" - "OpDecorate %value Flat\n" - "OpDecorate %saturation Flat\n" - "OpDecorate %hue NoPerspective\n" - "OpDecorate %value NoPerspective\n" - "OpDecorate %saturation NoPerspective\n"}, - // Two group decorations, interleaved - {"OpName %group0 \"group0\"\n" - "OpName %group1 \"group1\"\n" - "OpDecorate %group0 Flat\n" - "OpDecorate %group1 NoPerspective\n" - "%group0 = OpDecorationGroup\n" - "%group1 = OpDecorationGroup\n" - "OpGroupDecorate %group0 %hue %value\n" - "OpGroupDecorate %group1 %saturation\n", - "OpDecorate %hue Flat\n" - "OpDecorate %value Flat\n" - "OpDecorate %saturation NoPerspective\n"}, - // Decoration with operands - {"OpName %group \"group\"\n" - "OpDecorate %group Location 42\n" - "%group = OpDecorationGroup\n" - "OpGroupDecorate %group %hue %saturation\n", - "OpDecorate %hue Location 42\n" - "OpDecorate %saturation Location 42\n"}, - })); - -INSTANTIATE_TEST_SUITE_P(OpGroupMemberDecorate, FlattenDecorationTest, - ::testing::ValuesIn(std::vector{ - // One OpGroupMemberDecorate - {"OpName %group \"group\"\n" - "OpDecorate %group Flat\n" - "OpDecorate %group Offset 16\n" - "%group = OpDecorationGroup\n" - "OpGroupMemberDecorate %group %Point 1\n", - "OpMemberDecorate %Point 1 Flat\n" - "OpMemberDecorate %Point 1 Offset 16\n"}, - // Multiple OpGroupMemberDecorate using the same - // decoration group. - {"OpName %group \"group\"\n" - "OpDecorate %group Flat\n" - "OpDecorate %group NoPerspective\n" - "OpDecorate %group Offset 8\n" - "%group = OpDecorationGroup\n" - "OpGroupMemberDecorate %group %Point 2\n" - "OpGroupMemberDecorate %group %Camera 1\n", - "OpMemberDecorate %Point 2 Flat\n" - "OpMemberDecorate %Camera 1 Flat\n" - "OpMemberDecorate %Point 2 NoPerspective\n" - "OpMemberDecorate %Camera 1 NoPerspective\n" - "OpMemberDecorate %Point 2 Offset 8\n" - "OpMemberDecorate %Camera 1 Offset 8\n"}, - // Two groups of member decorations, interleaved. - // Decoration is with and without operands. - {"OpName %group0 \"group0\"\n" - "OpName %group1 \"group1\"\n" - "OpDecorate %group0 Flat\n" - "OpDecorate %group0 Offset 8\n" - "OpDecorate %group1 NoPerspective\n" - "OpDecorate %group1 Offset 16\n" - "%group0 = OpDecorationGroup\n" - "%group1 = OpDecorationGroup\n" - "OpGroupMemberDecorate %group0 %Point 0\n" - "OpGroupMemberDecorate %group1 %Point 2\n", - "OpMemberDecorate %Point 0 Flat\n" - "OpMemberDecorate %Point 0 Offset 8\n" - "OpMemberDecorate %Point 2 NoPerspective\n" - "OpMemberDecorate %Point 2 Offset 16\n"}, - })); - -INSTANTIATE_TEST_SUITE_P(UnrelatedDecorations, FlattenDecorationTest, - ::testing::ValuesIn(std::vector{ - // A non-group non-member decoration is untouched. - {"OpDecorate %hue Centroid\n" - "OpDecorate %saturation Flat\n", - "OpDecorate %hue Centroid\n" - "OpDecorate %saturation Flat\n"}, - // A non-group member decoration is untouched. - {"OpMemberDecorate %Point 0 Offset 0\n" - "OpMemberDecorate %Point 1 Offset 4\n" - "OpMemberDecorate %Point 1 Flat\n", - "OpMemberDecorate %Point 0 Offset 0\n" - "OpMemberDecorate %Point 1 Offset 4\n" - "OpMemberDecorate %Point 1 Flat\n"}, - // A non-group non-member decoration survives any - // replacement of group decorations. - {"OpName %group \"group\"\n" - "OpDecorate %group Flat\n" - "OpDecorate %hue Centroid\n" - "OpDecorate %group NoPerspective\n" - "%group = OpDecorationGroup\n" - "OpGroupDecorate %group %hue %saturation\n", - "OpDecorate %hue Flat\n" - "OpDecorate %saturation Flat\n" - "OpDecorate %hue Centroid\n" - "OpDecorate %hue NoPerspective\n" - "OpDecorate %saturation NoPerspective\n"}, - // A non-group member decoration survives any - // replacement of group decorations. - {"OpDecorate %group Offset 0\n" - "OpDecorate %group Flat\n" - "OpMemberDecorate %Point 1 Offset 4\n" - "%group = OpDecorationGroup\n" - "OpGroupMemberDecorate %group %Point 0\n", - "OpMemberDecorate %Point 0 Offset 0\n" - "OpMemberDecorate %Point 0 Flat\n" - "OpMemberDecorate %Point 1 Offset 4\n"}, - })); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/fold_spec_const_op_composite_test.cpp b/3rdparty/spirv-tools/test/opt/fold_spec_const_op_composite_test.cpp deleted file mode 100644 index 7eddf7e99..000000000 --- a/3rdparty/spirv-tools/test/opt/fold_spec_const_op_composite_test.cpp +++ /dev/null @@ -1,1513 +0,0 @@ -// 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 "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using FoldSpecConstantOpAndCompositePassBasicTest = PassTest<::testing::Test>; - -TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Empty) { - SinglePassRunAndCheck( - "", "", /* skip_nop = */ true); -} - -// A test of the basic functionality of FoldSpecConstantOpAndCompositePass. -// A spec constant defined with an integer addition operation should be folded -// to a normal constant with fixed value. -TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Basic) { - AssemblyBuilder builder; - builder.AppendTypesConstantsGlobals({ - // clang-format off - "%int = OpTypeInt 32 1", - "%frozen_spec_const_int = OpConstant %int 1", - "%const_int = OpConstant %int 2", - // Folding target: - "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int", - // clang-format on - }); - - std::vector expected = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %void \"void\"", - "OpName %main_func_type \"main_func_type\"", - "OpName %main \"main\"", - "OpName %main_func_entry_block \"main_func_entry_block\"", - "OpName %int \"int\"", - "OpName %frozen_spec_const_int \"frozen_spec_const_int\"", - "OpName %const_int \"const_int\"", - "OpName %spec_add \"spec_add\"", - "%void = OpTypeVoid", - "%main_func_type = OpTypeFunction %void", - "%int = OpTypeInt 32 1", -"%frozen_spec_const_int = OpConstant %int 1", - "%const_int = OpConstant %int 2", - // The SpecConstantOp IAdd instruction should be replace by OpConstant - // instruction: - "%spec_add = OpConstant %int 3", - "%main = OpFunction %void None %main_func_type", -"%main_func_entry_block = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true); -} - -// A test of skipping folding an instruction when the instruction result type -// has decorations. -TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, - SkipWhenTypeHasDecorations) { - AssemblyBuilder builder; - builder - .AppendAnnotations({ - // clang-format off - "OpDecorate %int RelaxedPrecision", - // clang-format on - }) - .AppendTypesConstantsGlobals({ - // clang-format off - "%int = OpTypeInt 32 1", - "%frozen_spec_const_int = OpConstant %int 1", - "%const_int = OpConstant %int 2", - // The following spec constant should not be folded as the result type - // has relaxed precision decoration. - "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int", - // clang-format on - }); - - SinglePassRunAndCheck( - builder.GetCode(), builder.GetCode(), /* skip_nop = */ true); -} - -// All types and some common constants that are potentially required in -// FoldSpecConstantOpAndCompositeTest. -std::vector CommonTypesAndConstants() { - return std::vector{ - // clang-format off - // scalar types - "%bool = OpTypeBool", - "%ushort = OpTypeInt 16 0", - "%short = OpTypeInt 16 1", - "%uint = OpTypeInt 32 0", - "%int = OpTypeInt 32 1", - "%ulong = OpTypeInt 64 0", - "%long = OpTypeInt 64 1", - "%float = OpTypeFloat 32", - "%double = OpTypeFloat 64", - // vector types - "%v2bool = OpTypeVector %bool 2", - "%v2uint = OpTypeVector %uint 2", - "%v2int = OpTypeVector %int 2", - "%v3int = OpTypeVector %int 3", - "%v4int = OpTypeVector %int 4", - "%v2long = OpTypeVector %long 2", - "%v2ulong = OpTypeVector %ulong 2", - "%v2float = OpTypeVector %float 2", - "%v2double = OpTypeVector %double 2", - // variable pointer types - "%_pf_bool = OpTypePointer Function %bool", - "%_pf_uint = OpTypePointer Function %uint", - "%_pf_int = OpTypePointer Function %int", - "%_pf_float = OpTypePointer Function %float", - "%_pf_double = OpTypePointer Function %double", - "%_pf_v2int = OpTypePointer Function %v2int", - "%_pf_v2float = OpTypePointer Function %v2float", - "%_pf_v2double = OpTypePointer Function %v2double", - // struct types - "%inner_struct = OpTypeStruct %bool %int %float", - "%outer_struct = OpTypeStruct %inner_struct %int", - "%flat_struct = OpTypeStruct %bool %int %float", - - // common constants - // scalar constants: - "%bool_true = OpConstantTrue %bool", - "%bool_false = OpConstantFalse %bool", - "%bool_null = OpConstantNull %bool", - "%signed_zero = OpConstant %int 0", - "%unsigned_zero = OpConstant %uint 0", - "%long_zero = OpConstant %long 0", - "%ulong_zero = OpConstant %ulong 0", - "%signed_one = OpConstant %int 1", - "%unsigned_one = OpConstant %uint 1", - "%signed_two = OpConstant %int 2", - "%unsigned_two = OpConstant %uint 2", - "%signed_three = OpConstant %int 3", - "%unsigned_three = OpConstant %uint 3", - "%signed_null = OpConstantNull %int", - "%unsigned_null = OpConstantNull %uint", - "%signed_minus_one = OpConstant %int -1", - // vector constants: - "%bool_true_vec = OpConstantComposite %v2bool %bool_true %bool_true", - "%bool_false_vec = OpConstantComposite %v2bool %bool_false %bool_false", - "%bool_null_vec = OpConstantNull %v2bool", - "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", - "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one", - "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - "%signed_two_vec = OpConstantComposite %v2int %signed_two %signed_two", - "%unsigned_two_vec = OpConstantComposite %v2uint %unsigned_two %unsigned_two", - "%signed_three_vec = OpConstantComposite %v2int %signed_three %signed_three", - "%unsigned_three_vec = OpConstantComposite %v2uint %unsigned_three %unsigned_three", - "%signed_null_vec = OpConstantNull %v2int", - "%unsigned_null_vec = OpConstantNull %v2uint", - "%signed_minus_one_vec = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", - "%v4int_0_1_2_3 = OpConstantComposite %v4int %signed_zero %signed_one %signed_two %signed_three", - // clang-format on - }; -} - -// A helper function to strip OpName instructions from the given string of -// disassembly code. Returns the string with all OpName instruction stripped. -std::string StripOpNameInstructions(const std::string& str) { - std::stringstream ss(str); - std::ostringstream oss; - std::string inst_str; - while (std::getline(ss, inst_str, '\n')) { - if (inst_str.find("OpName %") == std::string::npos) { - oss << inst_str << '\n'; - } - } - return oss.str(); -} - -struct FoldSpecConstantOpAndCompositePassTestCase { - // Original constants with unfolded spec constants. - std::vector original; - // Expected cosntants after folding. - std::vector expected; -}; - -using FoldSpecConstantOpAndCompositePassTest = PassTest< - ::testing::TestWithParam>; - -TEST_P(FoldSpecConstantOpAndCompositePassTest, ParamTestCase) { - AssemblyBuilder test_code_builder, expected_code_builder; - const auto& tc = GetParam(); - test_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants()); - test_code_builder.AppendTypesConstantsGlobals(tc.original); - expected_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants()); - expected_code_builder.AppendTypesConstantsGlobals(tc.expected); - const std::string original = test_code_builder.GetCode(); - const std::string expected = expected_code_builder.GetCode(); - - // Run the optimization and get the result code in disassembly. - std::string optimized; - auto status = Pass::Status::SuccessWithoutChange; - std::tie(optimized, status) = - SinglePassRunAndDisassemble( - original, /* skip_nop = */ true, /* do_validation = */ false); - - // Check the optimized code, but ignore the OpName instructions. - EXPECT_NE(Pass::Status::Failure, status); - EXPECT_EQ( - StripOpNameInstructions(expected) == StripOpNameInstructions(original), - status == Pass::Status::SuccessWithoutChange); - EXPECT_EQ(StripOpNameInstructions(expected), - StripOpNameInstructions(optimized)); -} - -// Tests that OpSpecConstantComposite opcodes are replace with -// OpConstantComposite correctly. -INSTANTIATE_TEST_SUITE_P( - Composite, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // normal vector - { - // original - { - "%spec_v2bool = OpSpecConstantComposite %v2bool %bool_true %bool_false", - "%spec_v2uint = OpSpecConstantComposite %v2uint %unsigned_one %unsigned_one", - "%spec_v2int_a = OpSpecConstantComposite %v2int %signed_one %signed_two", - // Spec constants whose value can not be fully resolved should - // not be processed. - "%spec_int = OpSpecConstant %int 99", - "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int", - }, - // expected - { - "%spec_v2bool = OpConstantComposite %v2bool %bool_true %bool_false", - "%spec_v2uint = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - "%spec_v2int_a = OpConstantComposite %v2int %signed_one %signed_two", - "%spec_int = OpSpecConstant %int 99", - "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int", - }, - }, - // vector with null constants - { - // original - { - "%null_bool = OpConstantNull %bool", - "%null_int = OpConstantNull %int", - "%spec_v2bool = OpSpecConstantComposite %v2bool %null_bool %null_bool", - "%spec_v3int = OpSpecConstantComposite %v3int %null_int %null_int %null_int", - "%spec_v4int = OpSpecConstantComposite %v4int %null_int %null_int %null_int %null_int", - }, - // expected - { - "%null_bool = OpConstantNull %bool", - "%null_int = OpConstantNull %int", - "%spec_v2bool = OpConstantComposite %v2bool %null_bool %null_bool", - "%spec_v3int = OpConstantComposite %v3int %null_int %null_int %null_int", - "%spec_v4int = OpConstantComposite %v4int %null_int %null_int %null_int %null_int", - }, - }, - // flat struct - { - // original - { - "%float_1 = OpConstant %float 1", - "%flat_1 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1", - // following struct should not be folded as the value of - // %spec_float is not determined. - "%spec_float = OpSpecConstant %float 1", - "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float", - }, - // expected - { - "%float_1 = OpConstant %float 1", - "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", - "%spec_float = OpSpecConstant %float 1", - "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float", - } - }, - // nested struct - { - // original - { - "%float_1 = OpConstant %float 1", - "%inner_1 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %float_1", - "%outer_1 = OpSpecConstantComposite %outer_struct %inner_1 %signed_one", - // following structs should not be folded as the value of - // %spec_float is not determined. - "%spec_float = OpSpecConstant %float 1", - "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", - "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one", - }, - // expected - { - "%float_1 = OpConstant %float 1", - "%inner_1 = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", - "%outer_1 = OpConstantComposite %outer_struct %inner_1 %signed_one", - "%spec_float = OpSpecConstant %float 1", - "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", - "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one", - } - }, - // composite constants touched by OpUndef should be skipped - { - // original - { - "%undef = OpUndef %float", - "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", - "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one", - }, - // expected - { - "%undef = OpUndef %float", - "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", - "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one", - }, - }, - // Fold an QuantizetoF16 instruction - { - // original - { - "%float_1 = OpConstant %float 1", - "%quant_float = OpSpecConstantOp %float QuantizeToF16 %float_1", - }, - // expected - { - "%float_1 = OpConstant %float 1", - "%quant_float = OpConstant %float 1", - }, - } - // clang-format on - }))); - -// Tests for operations that resulting in different types. -INSTANTIATE_TEST_SUITE_P( - Cast, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // int -> bool scalar - { - // original - { - "%spec_bool_t = OpSpecConstantOp %bool INotEqual %signed_three %signed_zero", - "%spec_bool_f = OpSpecConstantOp %bool INotEqual %signed_zero %signed_zero", - "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %signed_null %signed_zero", - }, - // expected - { - "%spec_bool_t = OpConstantTrue %bool", - "%spec_bool_f = OpConstantFalse %bool", - "%spec_bool_from_null = OpConstantFalse %bool", - }, - }, - - // uint -> bool scalar - { - // original - { - "%spec_bool_t = OpSpecConstantOp %bool INotEqual %unsigned_three %unsigned_zero", - "%spec_bool_f = OpSpecConstantOp %bool INotEqual %unsigned_zero %unsigned_zero", - "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %unsigned_null %unsigned_zero", - }, - // expected - { - "%spec_bool_t = OpConstantTrue %bool", - "%spec_bool_f = OpConstantFalse %bool", - "%spec_bool_from_null = OpConstantFalse %bool", - }, - }, - - // bool -> int scalar - { - // original - { - "%spec_int_one = OpSpecConstantOp %int Select %bool_true %signed_one %signed_zero", - "%spec_int_zero = OpSpecConstantOp %int Select %bool_false %signed_one %signed_zero", - "%spec_int_from_null = OpSpecConstantOp %int Select %bool_null %signed_one %signed_zero", - }, - // expected - { - "%spec_int_one = OpConstant %int 1", - "%spec_int_zero = OpConstant %int 0", - "%spec_int_from_null = OpConstant %int 0", - }, - }, - - // uint -> int scalar - { - // original - { - "%spec_int_one = OpSpecConstantOp %int IAdd %unsigned_one %signed_zero", - "%spec_int_zero = OpSpecConstantOp %int IAdd %unsigned_zero %signed_zero", - "%spec_int_from_null = OpSpecConstantOp %int IAdd %unsigned_null %unsigned_zero", - }, - // expected - { - "%spec_int_one = OpConstant %int 1", - "%spec_int_zero = OpConstant %int 0", - "%spec_int_from_null = OpConstant %int 0", - }, - }, - - // bool -> uint scalar - { - // original - { - "%spec_uint_one = OpSpecConstantOp %uint Select %bool_true %unsigned_one %unsigned_zero", - "%spec_uint_zero = OpSpecConstantOp %uint Select %bool_false %unsigned_one %unsigned_zero", - "%spec_uint_from_null = OpSpecConstantOp %uint Select %bool_null %unsigned_one %unsigned_zero", - }, - // expected - { - "%spec_uint_one = OpConstant %uint 1", - "%spec_uint_zero = OpConstant %uint 0", - "%spec_uint_from_null = OpConstant %uint 0", - }, - }, - - // int -> uint scalar - { - // original - { - "%spec_uint_one = OpSpecConstantOp %uint IAdd %signed_one %unsigned_zero", - "%spec_uint_zero = OpSpecConstantOp %uint IAdd %signed_zero %unsigned_zero", - "%spec_uint_from_null = OpSpecConstantOp %uint IAdd %signed_null %unsigned_zero", - }, - // expected - { - "%spec_uint_one = OpConstant %uint 1", - "%spec_uint_zero = OpConstant %uint 0", - "%spec_uint_from_null = OpConstant %uint 0", - }, - }, - - // int -> bool vector - { - // original - { - "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %signed_three_vec %signed_zero_vec", - "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %signed_zero_vec %signed_zero_vec", - "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %signed_null_vec %signed_zero_vec", - }, - // expected - { - "%true = OpConstantTrue %bool", - "%true_0 = OpConstantTrue %bool", - "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true", - "%false = OpConstantFalse %bool", - "%false_0 = OpConstantFalse %bool", - "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false", - "%false_1 = OpConstantFalse %bool", - "%false_2 = OpConstantFalse %bool", - "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false", - }, - }, - - // uint -> bool vector - { - // original - { - "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_three_vec %unsigned_zero_vec", - "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_zero_vec %unsigned_zero_vec", - "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %unsigned_null_vec %unsigned_zero_vec", - }, - // expected - { - "%true = OpConstantTrue %bool", - "%true_0 = OpConstantTrue %bool", - "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true", - "%false = OpConstantFalse %bool", - "%false_0 = OpConstantFalse %bool", - "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false", - "%false_1 = OpConstantFalse %bool", - "%false_2 = OpConstantFalse %bool", - "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false", - }, - }, - - // bool -> int vector - { - // original - { - "%spec_int_one_vec = OpSpecConstantOp %v2int Select %bool_true_vec %signed_one_vec %signed_zero_vec", - "%spec_int_zero_vec = OpSpecConstantOp %v2int Select %bool_false_vec %signed_one_vec %signed_zero_vec", - "%spec_int_from_null = OpSpecConstantOp %v2int Select %bool_null_vec %signed_one_vec %signed_zero_vec", - }, - // expected - { - "%int_1 = OpConstant %int 1", - "%int_1_0 = OpConstant %int 1", - "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one", - "%int_0 = OpConstant %int 0", - "%int_0_0 = OpConstant %int 0", - "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", - "%int_0_1 = OpConstant %int 0", - "%int_0_2 = OpConstant %int 0", - "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero", - }, - }, - - // uint -> int vector - { - // original - { - "%spec_int_one_vec = OpSpecConstantOp %v2int IAdd %unsigned_one_vec %signed_zero_vec", - "%spec_int_zero_vec = OpSpecConstantOp %v2int IAdd %unsigned_zero_vec %signed_zero_vec", - "%spec_int_from_null = OpSpecConstantOp %v2int IAdd %unsigned_null_vec %signed_zero_vec", - }, - // expected - { - "%int_1 = OpConstant %int 1", - "%int_1_0 = OpConstant %int 1", - "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one", - "%int_0 = OpConstant %int 0", - "%int_0_0 = OpConstant %int 0", - "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", - "%int_0_1 = OpConstant %int 0", - "%int_0_2 = OpConstant %int 0", - "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero", - }, - }, - - // bool -> uint vector - { - // original - { - "%spec_uint_one_vec = OpSpecConstantOp %v2uint Select %bool_true_vec %unsigned_one_vec %unsigned_zero_vec", - "%spec_uint_zero_vec = OpSpecConstantOp %v2uint Select %bool_false_vec %unsigned_one_vec %unsigned_zero_vec", - "%spec_uint_from_null = OpSpecConstantOp %v2uint Select %bool_null_vec %unsigned_one_vec %unsigned_zero_vec", - }, - // expected - { - "%uint_1 = OpConstant %uint 1", - "%uint_1_0 = OpConstant %uint 1", - "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - "%uint_0 = OpConstant %uint 0", - "%uint_0_0 = OpConstant %uint 0", - "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - "%uint_0_1 = OpConstant %uint 0", - "%uint_0_2 = OpConstant %uint 0", - "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - }, - }, - - // int -> uint vector - { - // original - { - "%spec_uint_one_vec = OpSpecConstantOp %v2uint IAdd %signed_one_vec %unsigned_zero_vec", - "%spec_uint_zero_vec = OpSpecConstantOp %v2uint IAdd %signed_zero_vec %unsigned_zero_vec", - "%spec_uint_from_null = OpSpecConstantOp %v2uint IAdd %signed_null_vec %unsigned_zero_vec", - }, - // expected - { - "%uint_1 = OpConstant %uint 1", - "%uint_1_0 = OpConstant %uint 1", - "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - "%uint_0 = OpConstant %uint 0", - "%uint_0_0 = OpConstant %uint 0", - "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - "%uint_0_1 = OpConstant %uint 0", - "%uint_0_2 = OpConstant %uint 0", - "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - }, - }, - - // UConvert scalar - { - // original - { - "%spec_uint_zero = OpSpecConstantOp %uint UConvert %bool_false", - "%spec_uint_one = OpSpecConstantOp %uint UConvert %bool_true", - "%spec_ulong_zero = OpSpecConstantOp %ulong UConvert %unsigned_zero", - "%spec_ulong_one = OpSpecConstantOp %ulong UConvert %unsigned_one", - "%spec_short_zero = OpSpecConstantOp %ushort UConvert %unsigned_zero", - "%spec_short_one = OpSpecConstantOp %ushort UConvert %unsigned_one", - "%uint_max = OpConstant %uint 4294967295", - "%spec_ushort_max = OpSpecConstantOp %ushort UConvert %uint_max", - "%uint_0xDDDDDDDD = OpConstant %uint 3722304989", - "%spec_ushort_0xDDDD = OpSpecConstantOp %ushort UConvert %uint_0xDDDDDDDD", - }, - // expected - { - "%spec_uint_zero = OpConstant %uint 0", - "%spec_uint_one = OpConstant %uint 1", - "%spec_ulong_zero = OpConstant %ulong 0", - "%spec_ulong_one = OpConstant %ulong 1", - "%spec_short_zero = OpConstant %ushort 0", - "%spec_short_one = OpConstant %ushort 1", - "%uint_max = OpConstant %uint 4294967295", - "%spec_ushort_max = OpConstant %ushort 65535", - "%uint_0xDDDDDDDD = OpConstant %uint 3722304989", - "%spec_ushort_0xDDDD = OpConstant %ushort 56797", - }, - }, - - // SConvert scalar - { - // original - { - "%spec_long_zero = OpSpecConstantOp %long SConvert %signed_zero", - "%spec_long_one = OpSpecConstantOp %long SConvert %signed_one", - "%spec_long_minus_one = OpSpecConstantOp %long SConvert %signed_minus_one", - "%spec_short_minus_one_trunc = OpSpecConstantOp %short SConvert %signed_minus_one", - "%int_2_to_17_minus_one = OpConstant %int 131071", - "%spec_short_minus_one_trunc2 = OpSpecConstantOp %short SConvert %int_2_to_17_minus_one", - }, - // expected - { - "%spec_long_zero = OpConstant %long 0", - "%spec_long_one = OpConstant %long 1", - "%spec_long_minus_one = OpConstant %long -1", - "%spec_short_minus_one_trunc = OpConstant %short -1", - "%int_2_to_17_minus_one = OpConstant %int 131071", - "%spec_short_minus_one_trunc2 = OpConstant %short -1", - }, - }, - - // UConvert vector - { - // original - { - "%spec_v2uint_zero = OpSpecConstantOp %v2uint UConvert %bool_false_vec", - "%spec_v2uint_one = OpSpecConstantOp %v2uint UConvert %bool_true_vec", - "%spec_v2ulong_zero = OpSpecConstantOp %v2ulong UConvert %unsigned_zero_vec", - "%spec_v2ulong_one = OpSpecConstantOp %v2ulong UConvert %unsigned_one_vec", - }, - // expected - { - "%uint_0 = OpConstant %uint 0", - "%uint_0_0 = OpConstant %uint 0", - "%spec_v2uint_zero = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", - "%uint_1 = OpConstant %uint 1", - "%uint_1_0 = OpConstant %uint 1", - "%spec_v2uint_one = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - "%ulong_0 = OpConstant %ulong 0", - "%ulong_0_0 = OpConstant %ulong 0", - "%spec_v2ulong_zero = OpConstantComposite %v2ulong %ulong_zero %ulong_zero", - "%ulong_1 = OpConstant %ulong 1", - "%ulong_1_0 = OpConstant %ulong 1", - "%spec_v2ulong_one = OpConstantComposite %v2ulong %ulong_1 %ulong_1", - }, - }, - - // SConvert vector - { - // original - { - "%spec_v2long_zero = OpSpecConstantOp %v2long SConvert %signed_zero_vec", - "%spec_v2long_one = OpSpecConstantOp %v2long SConvert %signed_one_vec", - "%spec_v2long_minus_one = OpSpecConstantOp %v2long SConvert %signed_minus_one_vec", - }, - // expected - { - "%long_0 = OpConstant %long 0", - "%long_0_0 = OpConstant %long 0", - "%spec_v2long_zero = OpConstantComposite %v2long %long_zero %long_zero", - "%long_1 = OpConstant %long 1", - "%long_1_0 = OpConstant %long 1", - "%spec_v2long_one = OpConstantComposite %v2long %long_1 %long_1", - "%long_n1 = OpConstant %long -1", - "%long_n1_0 = OpConstant %long -1", - "%spec_v2long_minus_one = OpConstantComposite %v2long %long_n1 %long_n1", - }, - }, - // clang-format on - }))); - -// Tests about boolean scalar logical operations and comparison operations with -// scalar int/uint type. -INSTANTIATE_TEST_SUITE_P( - Logical, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // scalar integer comparison - { - // original - { - "%int_minus_1 = OpConstant %int -1", - - "%slt_0_1 = OpSpecConstantOp %bool SLessThan %signed_zero %signed_one", - "%sgt_0_1 = OpSpecConstantOp %bool SGreaterThan %signed_zero %signed_one", - "%sle_2_2 = OpSpecConstantOp %bool SLessThanEqual %signed_two %signed_two", - "%sge_2_1 = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_one", - "%sge_2_null = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_null", - "%sge_minus_1_null = OpSpecConstantOp %bool SGreaterThanEqual %int_minus_1 %signed_null", - - "%ult_0_1 = OpSpecConstantOp %bool ULessThan %unsigned_zero %unsigned_one", - "%ugt_0_1 = OpSpecConstantOp %bool UGreaterThan %unsigned_zero %unsigned_one", - "%ule_2_3 = OpSpecConstantOp %bool ULessThanEqual %unsigned_two %unsigned_three", - "%uge_1_1 = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_one %unsigned_one", - "%uge_2_null = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_two %unsigned_null", - "%uge_minus_1_null = OpSpecConstantOp %bool UGreaterThanEqual %int_minus_1 %unsigned_null", - }, - // expected - { - "%int_minus_1 = OpConstant %int -1", - - "%slt_0_1 = OpConstantTrue %bool", - "%sgt_0_1 = OpConstantFalse %bool", - "%sle_2_2 = OpConstantTrue %bool", - "%sge_2_1 = OpConstantTrue %bool", - "%sge_2_null = OpConstantTrue %bool", - "%sge_minus_1_null = OpConstantFalse %bool", - - "%ult_0_1 = OpConstantTrue %bool", - "%ugt_0_1 = OpConstantFalse %bool", - "%ule_2_3 = OpConstantTrue %bool", - "%uge_1_1 = OpConstantTrue %bool", - "%uge_2_null = OpConstantTrue %bool", - "%uge_minus_1_null = OpConstantTrue %bool", - }, - }, - // Logical and, or, xor. - { - // original - { - "%logical_or = OpSpecConstantOp %bool LogicalOr %bool_true %bool_false", - "%logical_and = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_false", - "%logical_not = OpSpecConstantOp %bool LogicalNot %bool_true", - "%logical_eq = OpSpecConstantOp %bool LogicalEqual %bool_true %bool_true", - "%logical_neq = OpSpecConstantOp %bool LogicalNotEqual %bool_true %bool_true", - "%logical_and_null = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_null", - }, - // expected - { - "%logical_or = OpConstantTrue %bool", - "%logical_and = OpConstantFalse %bool", - "%logical_not = OpConstantFalse %bool", - "%logical_eq = OpConstantTrue %bool", - "%logical_neq = OpConstantFalse %bool", - "%logical_and_null = OpConstantFalse %bool", - }, - }, - // clang-format on - }))); - -// Tests about arithmetic operations for scalar int and uint types. -INSTANTIATE_TEST_SUITE_P( - ScalarArithmetic, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // scalar integer negate - { - // original - { - "%int_minus_1 = OpSpecConstantOp %int SNegate %signed_one", - "%int_minus_2 = OpSpecConstantOp %int SNegate %signed_two", - "%int_neg_null = OpSpecConstantOp %int SNegate %signed_null", - "%int_max = OpConstant %int 2147483647", - "%int_neg_max = OpSpecConstantOp %int SNegate %int_max", - }, - // expected - { - "%int_minus_1 = OpConstant %int -1", - "%int_minus_2 = OpConstant %int -2", - "%int_neg_null = OpConstant %int 0", - "%int_max = OpConstant %int 2147483647", - "%int_neg_max = OpConstant %int -2147483647", - }, - }, - // scalar integer not - { - // original - { - "%uint_4294967294 = OpSpecConstantOp %uint Not %unsigned_one", - "%uint_4294967293 = OpSpecConstantOp %uint Not %unsigned_two", - "%uint_neg_null = OpSpecConstantOp %uint Not %unsigned_null", - }, - // expected - { - "%uint_4294967294 = OpConstant %uint 4294967294", - "%uint_4294967293 = OpConstant %uint 4294967293", - "%uint_neg_null = OpConstant %uint 4294967295", - }, - }, - // scalar integer add, sub, mul, div - { - // original - { - "%signed_max = OpConstant %int 2147483647", - "%signed_min = OpConstant %int -2147483648", - - "%spec_int_iadd = OpSpecConstantOp %int IAdd %signed_three %signed_two", - "%spec_int_isub = OpSpecConstantOp %int ISub %signed_one %spec_int_iadd", - "%spec_int_sdiv = OpSpecConstantOp %int SDiv %spec_int_isub %signed_two", - "%spec_int_imul = OpSpecConstantOp %int IMul %spec_int_sdiv %signed_three", - "%spec_int_iadd_null = OpSpecConstantOp %int IAdd %spec_int_imul %signed_null", - "%spec_int_imul_null = OpSpecConstantOp %int IMul %spec_int_iadd_null %signed_null", - "%spec_int_iadd_overflow = OpSpecConstantOp %int IAdd %signed_max %signed_three", - "%spec_int_isub_overflow = OpSpecConstantOp %int ISub %signed_min %signed_three", - - "%spec_uint_iadd = OpSpecConstantOp %uint IAdd %unsigned_three %unsigned_two", - "%spec_uint_isub = OpSpecConstantOp %uint ISub %unsigned_one %spec_uint_iadd", - "%spec_uint_udiv = OpSpecConstantOp %uint UDiv %spec_uint_isub %unsigned_three", - "%spec_uint_imul = OpSpecConstantOp %uint IMul %spec_uint_udiv %unsigned_two", - "%spec_uint_isub_null = OpSpecConstantOp %uint ISub %spec_uint_imul %signed_null", - }, - // expected - { - "%signed_max = OpConstant %int 2147483647", - "%signed_min = OpConstant %int -2147483648", - - "%spec_int_iadd = OpConstant %int 5", - "%spec_int_isub = OpConstant %int -4", - "%spec_int_sdiv = OpConstant %int -2", - "%spec_int_imul = OpConstant %int -6", - "%spec_int_iadd_null = OpConstant %int -6", - "%spec_int_imul_null = OpConstant %int 0", - "%spec_int_iadd_overflow = OpConstant %int -2147483646", - "%spec_int_isub_overflow = OpConstant %int 2147483645", - - "%spec_uint_iadd = OpConstant %uint 5", - "%spec_uint_isub = OpConstant %uint 4294967292", - "%spec_uint_udiv = OpConstant %uint 1431655764", - "%spec_uint_imul = OpConstant %uint 2863311528", - "%spec_uint_isub_null = OpConstant %uint 2863311528", - }, - }, - // scalar integer rem, mod - { - // original - { - // common constants - "%int_7 = OpConstant %int 7", - "%uint_7 = OpConstant %uint 7", - "%int_minus_7 = OpConstant %int -7", - "%int_minus_3 = OpConstant %int -3", - - // srem - "%7_srem_3 = OpSpecConstantOp %int SRem %int_7 %signed_three", - "%minus_7_srem_3 = OpSpecConstantOp %int SRem %int_minus_7 %signed_three", - "%7_srem_minus_3 = OpSpecConstantOp %int SRem %int_7 %int_minus_3", - "%minus_7_srem_minus_3 = OpSpecConstantOp %int SRem %int_minus_7 %int_minus_3", - // smod - "%7_smod_3 = OpSpecConstantOp %int SMod %int_7 %signed_three", - "%minus_7_smod_3 = OpSpecConstantOp %int SMod %int_minus_7 %signed_three", - "%7_smod_minus_3 = OpSpecConstantOp %int SMod %int_7 %int_minus_3", - "%minus_7_smod_minus_3 = OpSpecConstantOp %int SMod %int_minus_7 %int_minus_3", - // umod - "%7_umod_3 = OpSpecConstantOp %uint UMod %uint_7 %unsigned_three", - // null constant - "%null_srem_3 = OpSpecConstantOp %int SRem %signed_null %signed_three", - "%null_smod_3 = OpSpecConstantOp %int SMod %signed_null %signed_three", - "%null_umod_3 = OpSpecConstantOp %uint UMod %unsigned_null %unsigned_three", - }, - // expected - { - // common constants - "%int_7 = OpConstant %int 7", - "%uint_7 = OpConstant %uint 7", - "%int_minus_7 = OpConstant %int -7", - "%int_minus_3 = OpConstant %int -3", - - // srem - "%7_srem_3 = OpConstant %int 1", - "%minus_7_srem_3 = OpConstant %int -1", - "%7_srem_minus_3 = OpConstant %int 1", - "%minus_7_srem_minus_3 = OpConstant %int -1", - // smod - "%7_smod_3 = OpConstant %int 1", - "%minus_7_smod_3 = OpConstant %int 2", - "%7_smod_minus_3 = OpConstant %int -2", - "%minus_7_smod_minus_3 = OpConstant %int -1", - // umod - "%7_umod_3 = OpConstant %uint 1", - // null constant - "%null_srem_3 = OpConstant %int 0", - "%null_smod_3 = OpConstant %int 0", - "%null_umod_3 = OpConstant %uint 0", - }, - }, - // scalar integer bitwise and shift - { - // original - { - // bitwise - "%xor_1_3 = OpSpecConstantOp %int BitwiseXor %signed_one %signed_three", - "%and_1_2 = OpSpecConstantOp %int BitwiseAnd %signed_one %xor_1_3", - "%or_1_2 = OpSpecConstantOp %int BitwiseOr %signed_one %xor_1_3", - "%xor_3_null = OpSpecConstantOp %int BitwiseXor %or_1_2 %signed_null", - - // shift - "%unsigned_31 = OpConstant %uint 31", - "%unsigned_left_shift_max = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_one %unsigned_31", - "%unsigned_right_shift_logical = OpSpecConstantOp %uint ShiftRightLogical %unsigned_left_shift_max %unsigned_31", - "%signed_right_shift_arithmetic = OpSpecConstantOp %int ShiftRightArithmetic %unsigned_left_shift_max %unsigned_31", - "%left_shift_null_31 = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_null %unsigned_31", - "%right_shift_31_null = OpSpecConstantOp %uint ShiftRightLogical %unsigned_31 %unsigned_null", - }, - // expected - { - "%xor_1_3 = OpConstant %int 2", - "%and_1_2 = OpConstant %int 0", - "%or_1_2 = OpConstant %int 3", - "%xor_3_null = OpConstant %int 3", - - "%unsigned_31 = OpConstant %uint 31", - "%unsigned_left_shift_max = OpConstant %uint 2147483648", - "%unsigned_right_shift_logical = OpConstant %uint 1", - "%signed_right_shift_arithmetic = OpConstant %int -1", - "%left_shift_null_31 = OpConstant %uint 0", - "%right_shift_31_null = OpConstant %uint 31", - }, - }, - // Skip folding if any operands have undetermined value. - { - // original - { - "%spec_int = OpSpecConstant %int 1", - "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int", - }, - // expected - { - "%spec_int = OpSpecConstant %int 1", - "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int", - }, - }, - // clang-format on - }))); - -// Tests about arithmetic operations for vector int and uint types. -INSTANTIATE_TEST_SUITE_P( - VectorArithmetic, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // vector integer negate - { - // original - { - "%v2int_minus_1 = OpSpecConstantOp %v2int SNegate %signed_one_vec", - "%v2int_minus_2 = OpSpecConstantOp %v2int SNegate %signed_two_vec", - "%v2int_neg_null = OpSpecConstantOp %v2int SNegate %signed_null_vec", - }, - // expected - { - "%int_n1 = OpConstant %int -1", - "%int_n1_0 = OpConstant %int -1", - "%v2int_minus_1 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", - "%int_n2 = OpConstant %int -2", - "%int_n2_0 = OpConstant %int -2", - "%v2int_minus_2 = OpConstantComposite %v2int %int_n2 %int_n2", - "%int_0 = OpConstant %int 0", - "%int_0_0 = OpConstant %int 0", - "%v2int_neg_null = OpConstantComposite %v2int %signed_zero %signed_zero", - }, - }, - // vector integer (including null vetors) add, sub, div, mul - { - // original - { - "%spec_v2int_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %signed_two_vec", - "%spec_v2int_isub = OpSpecConstantOp %v2int ISub %signed_one_vec %spec_v2int_iadd", - "%spec_v2int_sdiv = OpSpecConstantOp %v2int SDiv %spec_v2int_isub %signed_two_vec", - "%spec_v2int_imul = OpSpecConstantOp %v2int IMul %spec_v2int_sdiv %signed_three_vec", - "%spec_v2int_iadd_null = OpSpecConstantOp %v2int IAdd %spec_v2int_imul %signed_null_vec", - - "%spec_v2uint_iadd = OpSpecConstantOp %v2uint IAdd %unsigned_three_vec %unsigned_two_vec", - "%spec_v2uint_isub = OpSpecConstantOp %v2uint ISub %unsigned_one_vec %spec_v2uint_iadd", - "%spec_v2uint_udiv = OpSpecConstantOp %v2uint UDiv %spec_v2uint_isub %unsigned_three_vec", - "%spec_v2uint_imul = OpSpecConstantOp %v2uint IMul %spec_v2uint_udiv %unsigned_two_vec", - "%spec_v2uint_isub_null = OpSpecConstantOp %v2uint ISub %spec_v2uint_imul %signed_null_vec", - }, - // expected - { - "%int_5 = OpConstant %int 5", - "%int_5_0 = OpConstant %int 5", - "%spec_v2int_iadd = OpConstantComposite %v2int %int_5 %int_5", - "%int_n4 = OpConstant %int -4", - "%int_n4_0 = OpConstant %int -4", - "%spec_v2int_isub = OpConstantComposite %v2int %int_n4 %int_n4", - "%int_n2 = OpConstant %int -2", - "%int_n2_0 = OpConstant %int -2", - "%spec_v2int_sdiv = OpConstantComposite %v2int %int_n2 %int_n2", - "%int_n6 = OpConstant %int -6", - "%int_n6_0 = OpConstant %int -6", - "%spec_v2int_imul = OpConstantComposite %v2int %int_n6 %int_n6", - "%int_n6_1 = OpConstant %int -6", - "%int_n6_2 = OpConstant %int -6", - "%spec_v2int_iadd_null = OpConstantComposite %v2int %int_n6 %int_n6", - - "%uint_5 = OpConstant %uint 5", - "%uint_5_0 = OpConstant %uint 5", - "%spec_v2uint_iadd = OpConstantComposite %v2uint %uint_5 %uint_5", - "%uint_4294967292 = OpConstant %uint 4294967292", - "%uint_4294967292_0 = OpConstant %uint 4294967292", - "%spec_v2uint_isub = OpConstantComposite %v2uint %uint_4294967292 %uint_4294967292", - "%uint_1431655764 = OpConstant %uint 1431655764", - "%uint_1431655764_0 = OpConstant %uint 1431655764", - "%spec_v2uint_udiv = OpConstantComposite %v2uint %uint_1431655764 %uint_1431655764", - "%uint_2863311528 = OpConstant %uint 2863311528", - "%uint_2863311528_0 = OpConstant %uint 2863311528", - "%spec_v2uint_imul = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528", - "%uint_2863311528_1 = OpConstant %uint 2863311528", - "%uint_2863311528_2 = OpConstant %uint 2863311528", - "%spec_v2uint_isub_null = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528", - }, - }, - // vector integer rem, mod - { - // original - { - // common constants - "%int_7 = OpConstant %int 7", - "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7", - "%uint_7 = OpConstant %uint 7", - "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7", - "%int_minus_7 = OpConstant %int -7", - "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7", - "%int_minus_3 = OpConstant %int -3", - "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3", - - // srem - "%7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_7 %signed_three_vec", - "%minus_7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %signed_three_vec", - "%7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_7 %v2int_minus_3", - "%minus_7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %v2int_minus_3", - // smod - "%7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_7 %signed_three_vec", - "%minus_7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %signed_three_vec", - "%7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_7 %v2int_minus_3", - "%minus_7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %v2int_minus_3", - // umod - "%7_umod_3 = OpSpecConstantOp %v2uint UMod %v2uint_7 %unsigned_three_vec", - }, - // expected - { - // common constants - "%int_7 = OpConstant %int 7", - "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7", - "%uint_7 = OpConstant %uint 7", - "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7", - "%int_minus_7 = OpConstant %int -7", - "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7", - "%int_minus_3 = OpConstant %int -3", - "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3", - - // srem - "%int_1 = OpConstant %int 1", - "%int_1_0 = OpConstant %int 1", - "%7_srem_3 = OpConstantComposite %v2int %signed_one %signed_one", - "%int_n1 = OpConstant %int -1", - "%int_n1_0 = OpConstant %int -1", - "%minus_7_srem_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", - "%int_1_1 = OpConstant %int 1", - "%int_1_2 = OpConstant %int 1", - "%7_srem_minus_3 = OpConstantComposite %v2int %signed_one %signed_one", - "%int_n1_1 = OpConstant %int -1", - "%int_n1_2 = OpConstant %int -1", - "%minus_7_srem_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", - // smod - "%int_1_3 = OpConstant %int 1", - "%int_1_4 = OpConstant %int 1", - "%7_smod_3 = OpConstantComposite %v2int %signed_one %signed_one", - "%int_2 = OpConstant %int 2", - "%int_2_0 = OpConstant %int 2", - "%minus_7_smod_3 = OpConstantComposite %v2int %signed_two %signed_two", - "%int_n2 = OpConstant %int -2", - "%int_n2_0 = OpConstant %int -2", - "%7_smod_minus_3 = OpConstantComposite %v2int %int_n2 %int_n2", - "%int_n1_3 = OpConstant %int -1", - "%int_n1_4 = OpConstant %int -1", - "%minus_7_smod_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", - // umod - "%uint_1 = OpConstant %uint 1", - "%uint_1_0 = OpConstant %uint 1", - "%7_umod_3 = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - }, - }, - // vector integer bitwise, shift - { - // original - { - "%xor_1_3 = OpSpecConstantOp %v2int BitwiseXor %signed_one_vec %signed_three_vec", - "%and_1_2 = OpSpecConstantOp %v2int BitwiseAnd %signed_one_vec %xor_1_3", - "%or_1_2 = OpSpecConstantOp %v2int BitwiseOr %signed_one_vec %xor_1_3", - - "%unsigned_31 = OpConstant %uint 31", - "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31", - "%unsigned_left_shift_max = OpSpecConstantOp %v2uint ShiftLeftLogical %unsigned_one_vec %v2unsigned_31", - "%unsigned_right_shift_logical = OpSpecConstantOp %v2uint ShiftRightLogical %unsigned_left_shift_max %v2unsigned_31", - "%signed_right_shift_arithmetic = OpSpecConstantOp %v2int ShiftRightArithmetic %unsigned_left_shift_max %v2unsigned_31", - }, - // expected - { - "%int_2 = OpConstant %int 2", - "%int_2_0 = OpConstant %int 2", - "%xor_1_3 = OpConstantComposite %v2int %signed_two %signed_two", - "%int_0 = OpConstant %int 0", - "%int_0_0 = OpConstant %int 0", - "%and_1_2 = OpConstantComposite %v2int %signed_zero %signed_zero", - "%int_3 = OpConstant %int 3", - "%int_3_0 = OpConstant %int 3", - "%or_1_2 = OpConstantComposite %v2int %signed_three %signed_three", - - "%unsigned_31 = OpConstant %uint 31", - "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31", - "%uint_2147483648 = OpConstant %uint 2147483648", - "%uint_2147483648_0 = OpConstant %uint 2147483648", - "%unsigned_left_shift_max = OpConstantComposite %v2uint %uint_2147483648 %uint_2147483648", - "%uint_1 = OpConstant %uint 1", - "%uint_1_0 = OpConstant %uint 1", - "%unsigned_right_shift_logical = OpConstantComposite %v2uint %unsigned_one %unsigned_one", - "%int_n1 = OpConstant %int -1", - "%int_n1_0 = OpConstant %int -1", - "%signed_right_shift_arithmetic = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", - }, - }, - // Skip folding if any vector operands or components of the operands - // have undetermined value. - { - // original - { - "%spec_int = OpSpecConstant %int 1", - "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int", - "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec", - }, - // expected - { - "%spec_int = OpSpecConstant %int 1", - "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int", - "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec", - }, - }, - // Skip folding if any vector operands are defined by OpUndef - { - // original - { - "%undef = OpUndef %int", - "%vec = OpConstantComposite %v2int %undef %signed_one", - "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec", - }, - // expected - { - "%undef = OpUndef %int", - "%vec = OpConstantComposite %v2int %undef %signed_one", - "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec", - }, - }, - // clang-format on - }))); - -// Tests for SpecConstantOp CompositeExtract instruction -INSTANTIATE_TEST_SUITE_P( - CompositeExtract, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // normal vector - { - // original - { - "%r = OpSpecConstantOp %int CompositeExtract %signed_three_vec 0", - "%x = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 0", - "%y = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 1", - "%z = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 2", - "%w = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 3", - }, - // expected - { - "%r = OpConstant %int 3", - "%x = OpConstant %int 0", - "%y = OpConstant %int 1", - "%z = OpConstant %int 2", - "%w = OpConstant %int 3", - }, - }, - // null vector - { - // original - { - "%x = OpSpecConstantOp %int CompositeExtract %signed_null_vec 0", - "%y = OpSpecConstantOp %int CompositeExtract %signed_null_vec 1", - "%null_v4int = OpConstantNull %v4int", - "%z = OpSpecConstantOp %int CompositeExtract %signed_null_vec 2", - }, - // expected - { - "%x = OpConstantNull %int", - "%y = OpConstantNull %int", - "%null_v4int = OpConstantNull %v4int", - "%z = OpConstantNull %int", - } - }, - // normal flat struct - { - // original - { - "%float_1 = OpConstant %float 1", - "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", - "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat_1 0", - "%extract_int = OpSpecConstantOp %int CompositeExtract %flat_1 1", - "%extract_float_1 = OpSpecConstantOp %float CompositeExtract %flat_1 2", - // foldable composite constants built with OpSpecConstantComposite - // should also be processed. - "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1", - "%extract_float_2 = OpSpecConstantOp %float CompositeExtract %flat_2 2", - }, - // expected - { - "%float_1 = OpConstant %float 1", - "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", - "%extract_bool = OpConstantTrue %bool", - "%extract_int = OpConstantNull %int", - "%extract_float_1 = OpConstant %float 1", - "%flat_2 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", - "%extract_float_2 = OpConstant %float 1", - }, - }, - // null flat struct - { - // original - { - "%flat = OpConstantNull %flat_struct", - "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat 0", - "%extract_int = OpSpecConstantOp %int CompositeExtract %flat 1", - "%extract_float = OpSpecConstantOp %float CompositeExtract %flat 2", - }, - // expected - { - "%flat = OpConstantNull %flat_struct", - "%extract_bool = OpConstantNull %bool", - "%extract_int = OpConstantNull %int", - "%extract_float = OpConstantNull %float", - }, - }, - // normal nested struct - { - // original - { - "%float_1 = OpConstant %float 1", - "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", - "%outer = OpConstantComposite %outer_struct %inner %signed_one", - "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0", - "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1", - "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2", - }, - // expected - { - "%float_1 = OpConstant %float 1", - "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", - "%outer = OpConstantComposite %outer_struct %inner %signed_one", - "%extract_inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", - "%extract_int = OpConstant %int 1", - "%extract_inner_float = OpConstant %float 1", - }, - }, - // null nested struct - { - // original - { - "%outer = OpConstantNull %outer_struct", - "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0", - "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1", - "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2", - }, - // expected - { - "%outer = OpConstantNull %outer_struct", - "%extract_inner = OpConstantNull %inner_struct", - "%extract_int = OpConstantNull %int", - "%extract_inner_float = OpConstantNull %float", - }, - }, - // skip folding if the any composite constant's value are not fully - // determined, even though the extracting target might have - // determined value. - { - // original - { - "%float_1 = OpConstant %float 1", - "%spec_float = OpSpecConstant %float 1", - "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", - "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one", - "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1", - "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1", - "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1", - "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1", - }, - // expected - { - "%float_1 = OpConstant %float 1", - "%spec_float = OpSpecConstant %float 1", - "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", - "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one", - "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1", - "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1", - "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1", - "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1", - }, - }, - // skip if the composite constant depends on the result of OpUndef, - // even though the composite extract target element does not depends - // on the OpUndef. - { - // original - { - "%undef = OpUndef %float", - "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", - "%outer = OpConstantComposite %outer_struct %inner %signed_one", - "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1", - "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1", - }, - // expected - { - "%undef = OpUndef %float", - "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", - "%outer = OpConstantComposite %outer_struct %inner %signed_one", - "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1", - "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1", - }, - }, - // TODO(qining): Add tests for Array and other composite type constants. - // clang-format on - }))); - -// Tests the swizzle operations for spec const vectors. -INSTANTIATE_TEST_SUITE_P( - VectorShuffle, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // normal vector - { - // original - { - "%xy = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 1", - "%yz = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 2", - "%zw = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 3", - "%wx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 3 0", - "%xx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 0", - "%yyy = OpSpecConstantOp %v3int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 1 1", - "%wwww = OpSpecConstantOp %v4int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 2 2 2", - }, - // expected - { - "%xy = OpConstantComposite %v2int %signed_zero %signed_one", - "%yz = OpConstantComposite %v2int %signed_one %signed_two", - "%zw = OpConstantComposite %v2int %signed_two %signed_three", - "%wx = OpConstantComposite %v2int %signed_three %signed_zero", - "%xx = OpConstantComposite %v2int %signed_zero %signed_zero", - "%yyy = OpConstantComposite %v3int %signed_one %signed_one %signed_one", - "%wwww = OpConstantComposite %v4int %signed_two %signed_two %signed_two %signed_two", - }, - }, - // null vector - { - // original - { - "%a = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 0 1", - "%b = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 2 3", - "%c = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %signed_null_vec 3 4", - "%d = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %signed_null_vec 1 2", - }, - // expected - { - "%a = OpConstantComposite %v2int %signed_null %signed_null", - "%b = OpConstantComposite %v2int %signed_zero %signed_one", - "%c = OpConstantComposite %v2int %signed_three %signed_null", - "%d = OpConstantComposite %v2int %signed_null %signed_null", - } - }, - // skip if any of the components of the vector operands do not have - // determined value, even though the result vector might not be - // built with those undermined values. - { - // original - { - "%spec_int = OpSpecConstant %int 1", - "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int", - "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1", - "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4", - }, - // expected - { - "%spec_int = OpSpecConstant %int 1", - "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int", - "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1", - "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4", - }, - }, - // Skip if any components of the two vector operands depend on - // the result of OpUndef. Even though the selected components do - // not depend on the OpUndef result. - { - // original - { - "%undef = OpUndef %int", - "%vec_1 = OpConstantComposite %v2int %undef %signed_one", - "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3", - "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3", - "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3", - }, - // expected - { - "%undef = OpUndef %int", - "%vec_1 = OpConstantComposite %v2int %undef %signed_one", - "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3", - "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3", - "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3", - }, - }, - // clang-format on - }))); - -// Test with long use-def chain. -INSTANTIATE_TEST_SUITE_P( - LongDefUseChain, FoldSpecConstantOpAndCompositePassTest, - ::testing::ValuesIn(std::vector< - FoldSpecConstantOpAndCompositePassTestCase>({ - // clang-format off - // Long Def-Use chain with binary operations. - { - // original - { - "%array_size = OpConstant %int 4", - "%type_arr_int_4 = OpTypeArray %int %array_size", - "%spec_int_0 = OpConstant %int 100", - "%spec_int_1 = OpConstant %int 1", - "%spec_int_2 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_1", - "%spec_int_3 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_2", - "%spec_int_4 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_3", - "%spec_int_5 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_4", - "%spec_int_6 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_5", - "%spec_int_7 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_6", - "%spec_int_8 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_7", - "%spec_int_9 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_8", - "%spec_int_10 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_9", - "%spec_int_11 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_10", - "%spec_int_12 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_11", - "%spec_int_13 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_12", - "%spec_int_14 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_13", - "%spec_int_15 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_14", - "%spec_int_16 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_15", - "%spec_int_17 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_16", - "%spec_int_18 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_17", - "%spec_int_19 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_18", - "%spec_int_20 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_19", - "%used_vec_a = OpSpecConstantComposite %v2int %spec_int_18 %spec_int_19", - "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a", - "%spec_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0", - "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21", - // Spec constants whose values can not be fully resolved should - // not be processed. - "%spec_int_22 = OpSpecConstant %int 123", - "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one", - }, - // expected - { - "%array_size = OpConstant %int 4", - "%type_arr_int_4 = OpTypeArray %int %array_size", - "%spec_int_0 = OpConstant %int 100", - "%spec_int_1 = OpConstant %int 1", - "%spec_int_2 = OpConstant %int 101", - "%spec_int_3 = OpConstant %int -1", - "%spec_int_4 = OpConstant %int 99", - "%spec_int_5 = OpConstant %int 1", - "%spec_int_6 = OpConstant %int 101", - "%spec_int_7 = OpConstant %int -1", - "%spec_int_8 = OpConstant %int 99", - "%spec_int_9 = OpConstant %int 1", - "%spec_int_10 = OpConstant %int 101", - "%spec_int_11 = OpConstant %int -1", - "%spec_int_12 = OpConstant %int 99", - "%spec_int_13 = OpConstant %int 1", - "%spec_int_14 = OpConstant %int 101", - "%spec_int_15 = OpConstant %int -1", - "%spec_int_16 = OpConstant %int 101", - "%spec_int_17 = OpConstant %int 201", - "%spec_int_18 = OpConstant %int -101", - "%spec_int_19 = OpConstant %int -1", - "%spec_int_20 = OpConstant %int 101", - "%used_vec_a = OpConstantComposite %v2int %spec_int_18 %spec_int_19", - "%int_10201 = OpConstant %int 10201", - "%int_1 = OpConstant %int 1", - "%used_vec_b = OpConstantComposite %v2int %int_10201 %signed_one", - "%spec_int_21 = OpConstant %int 10201", - "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21", - "%spec_int_22 = OpSpecConstant %int 123", - "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one", - }, - }, - // Long Def-Use chain with swizzle - }))); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/fold_test.cpp b/3rdparty/spirv-tools/test/opt/fold_test.cpp deleted file mode 100644 index cc67cd86f..000000000 --- a/3rdparty/spirv-tools/test/opt/fold_test.cpp +++ /dev/null @@ -1,7170 +0,0 @@ -// 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 "source/opt/fold.h" - -#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/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 -%v2half = OpTypeVector %half 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_2049 = OpConstant %float 2049 -%float_n2049 = OpConstant %float -2049 -%float_0p5 = OpConstant %float 0.5 -%float_0p2 = OpConstant %float 0.2 -%float_pi = OpConstant %float 1.5555 -%float_1e16 = OpConstant %float 1e16 -%float_n1e16 = OpConstant %float -1e16 -%float_1en16 = OpConstant %float 1e-16 -%float_n1en16 = OpConstant %float -1e-16 -%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_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %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_5 = OpConstant %double 5 -%double_0p5 = OpConstant %double 0.5 -%double_0p2 = OpConstant %double 0.2 -%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 -%half_0_1 = OpConstantComposite %v2half %108 %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_SUITE_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()), - // Test case 30: fold UMin 3 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 31: fold UMin 4 2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2), - // Test case 32: fold SMin 3 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 33: fold SMin 4 2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2), - // Test case 34: fold UMax 3 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4), - // Test case 35: fold UMax 3 2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 36: fold SMax 3 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4), - // Test case 37: fold SMax 3 2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 38: fold UClamp 2 3 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 39: fold UClamp 2 0 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2), - // Test case 40: fold UClamp 2 0 1 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1), - // Test case 41: fold SClamp 2 3 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 42: fold SClamp 2 0 4 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2), - // Test case 43: fold SClamp 2 0 1 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1), - // Test case 44: SClamp 1 2 x - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %int\n" + - "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2), - // Test case 45: SClamp 2 x 1 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %int\n" + - "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1), - // Test case 44: UClamp 1 2 x - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %uint\n" + - "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2), - // Test case 45: UClamp 2 x 1 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %uint\n" + - "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1) -)); -// 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_SUITE_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 FloatVectorInstructionFoldingTest = - ::testing::TestWithParam>>; - -TEST_P(FloatVectorInstructionFoldingTest, 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]->GetFloat()); - } - } - } -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest, -::testing::Values( - // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5} - InstructionFoldingCase>( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, {1.6f,1.5f}) -)); -// 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_SUITE_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_SUITE_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_SUITE_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) { - if (!std::isnan(tc.expected_result)) { - EXPECT_EQ(result->GetFloatValue(), tc.expected_result); - } else { - EXPECT_TRUE(std::isnan(result->GetFloatValue())); - } - } - } -} - -// 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_SUITE_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), - // Test case 12: QuantizeToF16 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0), - // Test case 13: QuantizeToF16 positive non exact - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_2049\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2048), - // Test case 14: QuantizeToF16 negative non exact - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_n2049\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, -2048), - // Test case 15: QuantizeToF16 large positive - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_1e16\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, std::numeric_limits::infinity()), - // Test case 16: QuantizeToF16 large negative - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_n1e16\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, -std::numeric_limits::infinity()), - // Test case 17: QuantizeToF16 small positive - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_1en16\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0.0), - // Test case 18: QuantizeToF16 small negative - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_n1en16\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0.0), - // Test case 19: QuantizeToF16 nan - InstructionFoldingCase( - HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpQuantizeToF16 %float %float_nan\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, std::numeric_limits::quiet_NaN()), - // Test case 20: FMix 1.0 4.0 0.2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.6f), - // Test case 21: FMin 1.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0f), - // Test case 22: FMin 4.0 0.2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0.2f), - // Test case 21: FMax 1.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4.0f), - // Test case 22: FMax 1.0 0.2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0f), - // Test case 23: FClamp 1.0 0.2 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0f), - // Test case 24: FClamp 0.2 2.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2.0f), - // Test case 25: FClamp 2049.0 2.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4.0f), - // Test case 26: FClamp 1.0 2.0 x - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %float\n" + - "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2.0), - // Test case 27: FClamp 1.0 x 0.5 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %float\n" + - "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0.5) -)); -// 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_SUITE_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), - // Test case 12: FMin 1.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0), - // Test case 13: FMin 4.0 0.2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0.2), - // Test case 14: FMax 1.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4.0), - // Test case 15: FMax 1.0 0.2 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0), - // Test case 16: FClamp 1.0 0.2 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 1.0), - // Test case 17: FClamp 0.2 2.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2.0), - // Test case 18: FClamp 5.0 2.0 4.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4.0), - // Test case 19: FClamp 1.0 2.0 x - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %double\n" + - "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 2.0), - // Test case 20: FClamp 1.0 x 0.5 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%undef = OpUndef %double\n" + - "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0.5) -)); -// clang-format on - -// clang-format off -INSTANTIATE_TEST_SUITE_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_SUITE_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_SUITE_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_SUITE_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_SUITE_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_SUITE_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_SUITE_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_SUITE_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_SUITE_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( - 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 = OpULessThanEqual %bool %load_n %uint_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 33: 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 = OpUGreaterThanEqual %bool %load_n %uint_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 34: 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 = OpULessThan %bool %load_n %int_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 35: 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 = OpUGreaterThan %bool %load_n %int_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 36: 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 = OpULessThanEqual %bool %load_n %int_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 37: 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 = OpUGreaterThanEqual %bool %load_n %int_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 38: Don't fold 2 + 3 (long), bad length - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpIAdd %long %long_2 %long_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 39: Don't fold 2 + 3 (short), bad length - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpIAdd %short %short_2 %short_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 40: fold 1*n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%3 = OpLoad %int %n\n" + - "%2 = OpIMul %int %int_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 41: fold n*1 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%3 = OpLoad %int %n\n" + - "%2 = OpIMul %int %3 %int_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest, -::testing::Values( - // Test case 0: fold Insert feeding extract - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" + - "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" + - "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" + - "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" + - "%7 = OpCompositeExtract %int %6 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 7, 2), - // Test case 1: fold Composite construct feeding extract (position 0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" + - "%4 = OpCompositeExtract %int %3 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, 2), - // Test case 2: fold Composite construct feeding extract (position 3) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" + - "%4 = OpCompositeExtract %int %3 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, INT_0_ID), - // Test case 3: fold Composite construct with vectors feeding extract (scalar element) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeConstruct %v2int %2 %int_0\n" + - "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" + - "%5 = OpCompositeExtract %int %4 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, INT_0_ID), - // Test case 4: fold Composite construct with vectors feeding extract (start of vector element) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeConstruct %v2int %2 %int_0\n" + - "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" + - "%5 = OpCompositeExtract %int %4 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, 2), - // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeConstruct %v2int %int_0 %2\n" + - "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" + - "%5 = OpCompositeExtract %int %4 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, 2), - // Test case 6: fold Composite construct with multiple indices. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %n\n" + - "%3 = OpCompositeConstruct %v2int %int_0 %2\n" + - "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" + - "%5 = OpCompositeExtract %int %4 0 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, 2), - // Test case 7: fold constant extract. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCompositeExtract %int %102 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, INT_7_ID), - // Test case 8: constant struct has OpUndef - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 9: Extracting a member of element inserted via Insert - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" + - "%2 = OpLoad %struct_v2int_int_int %n\n" + - "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" + - "%4 = OpCompositeExtract %int %3 0 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, 103), - // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" + - "%2 = OpLoad %struct_v2int_int_int %n\n" + - "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" + - "%4 = OpCompositeExtract %v2int %3 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, 0), - // Test case 11: Extracting from result of vector shuffle (first input) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %n\n" + - "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" + - "%4 = OpCompositeExtract %int %3 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, INT_7_ID), - // Test case 12: Extracting from result of vector shuffle (second input) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %n\n" + - "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" + - "%4 = OpCompositeExtract %int %3 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, INT_7_ID), - // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608 - // Out of bounds access. Do not fold. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" + - "%3 = OpCompositeExtract %float %2 4\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, 0) -)); - -INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest, -::testing::Values( - // Test case 0: fold Extracts feeding construct - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" + - "%3 = OpCompositeExtract %int %2 0\n" + - "%4 = OpCompositeExtract %int %2 1\n" + - "%5 = OpCompositeExtract %int %2 2\n" + - "%6 = OpCompositeExtract %int %2 3\n" + - "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" + - "OpReturn\n" + - "OpFunctionEnd", - 7, 2), - // Test case 1: Don't fold Extracts feeding construct (Different source) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" + - "%3 = OpCompositeExtract %int %2 0\n" + - "%4 = OpCompositeExtract %int %2 1\n" + - "%5 = OpCompositeExtract %int %2 2\n" + - "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" + - "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" + - "OpReturn\n" + - "OpFunctionEnd", - 7, 0), - // Test case 2: Don't fold Extracts feeding construct (bad indices) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" + - "%3 = OpCompositeExtract %int %2 0\n" + - "%4 = OpCompositeExtract %int %2 0\n" + - "%5 = OpCompositeExtract %int %2 2\n" + - "%6 = OpCompositeExtract %int %2 3\n" + - "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" + - "OpReturn\n" + - "OpFunctionEnd", - 7, 0), - // Test case 3: Don't fold Extracts feeding construct (different type) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" + - "%3 = OpCompositeExtract %v2int %2 0\n" + - "%4 = OpCompositeExtract %int %2 1\n" + - "%5 = OpCompositeExtract %int %2 2\n" + - "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 7, 0), - // Test case 4: Fold construct with constants to constant. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpCompositeConstruct %v2int %103 %103\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, VEC2_0_ID) -)); - -INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest, -::testing::Values( - // Test case 0: Fold phi with the same values for all edges. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - " OpBranchConditional %true %l1 %l2\n" + - "%l1 = OpLabel\n" + - " OpBranch %merge_lab\n" + - "%l2 = OpLabel\n" + - " OpBranch %merge_lab\n" + - "%merge_lab = OpLabel\n" + - "%2 = OpPhi %int %100 %l1 %100 %l2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, INT_0_ID), - // Test case 1: Fold phi in pass through loop. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - " OpBranch %l1\n" + - "%l1 = OpLabel\n" + - "%2 = OpPhi %int %100 %main_lab %2 %l1\n" + - " OpBranchConditional %true %l1 %merge_lab\n" + - "%merge_lab = OpLabel\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, INT_0_ID), - // Test case 2: Don't Fold phi because of different values. - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - " OpBranch %l1\n" + - "%l1 = OpLabel\n" + - "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" + - " OpBranchConditional %true %l1 %merge_lab\n" + - "%merge_lab = OpLabel\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0) -)); - -INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest, - ::testing::Values( - // Test case 0: Don't fold n + 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFAdd %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Don't fold n - 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFSub %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 2: Don't fold n * 2.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFMul %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 3: Fold n + 0.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFAdd %float %3 %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 4: Fold 0.0 + n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFAdd %float %float_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 5: Fold n - 0.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFSub %float %3 %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 6: Fold n * 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFMul %float %3 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 7: Fold 1.0 * n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFMul %float %float_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 8: Fold n / 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFDiv %float %3 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 9: Fold n * 0.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFMul %float %3 %104\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, FLOAT_0_ID), - // Test case 10: Fold 0.0 * n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFMul %float %104 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, FLOAT_0_ID), - // Test case 11: Fold 0.0 / n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFDiv %float %104 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, FLOAT_0_ID), - // Test case 12: Don't fold mix(a, b, 2.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_float Function\n" + - "%b = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %a\n" + - "%4 = OpLoad %float %b\n" + - "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 13: Fold mix(a, b, 0.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_float Function\n" + - "%b = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %a\n" + - "%4 = OpLoad %float %b\n" + - "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 14: Fold mix(a, b, 1.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_float Function\n" + - "%b = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %a\n" + - "%4 = OpLoad %float %b\n" + - "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4), - // Test case 15: Fold vector fadd with null - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %a\n" + - "%3 = OpFAdd %v2float %2 %v2float_null\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, 2), - // Test case 16: Fold vector fadd with null - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %a\n" + - "%3 = OpFAdd %v2float %v2float_null %2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, 2), - // Test case 17: Fold vector fsub with null - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %a\n" + - "%3 = OpFSub %v2float %2 %v2float_null\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, 2), - // Test case 18: Fold 0.0(half) * n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_half Function\n" + - "%3 = OpLoad %half %n\n" + - "%2 = OpFMul %half %108 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, HALF_0_ID), - // Test case 19: Don't fold 1.0(half) * n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_half Function\n" + - "%3 = OpLoad %half %n\n" + - "%2 = OpFMul %half %half_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 20: Don't fold 1.0 * 1.0 (half) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpFMul %half %half_1 %half_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 21: Don't fold (0.0, 1.0) * (0.0, 1.0) (half) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 22: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpDot %half %half_0_1 %half_0_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0) -)); - -INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest, - ::testing::Values( - // Test case 0: Don't fold n + 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFAdd %double %3 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Don't fold n - 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFSub %double %3 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 2: Don't fold n * 2.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFMul %double %3 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 3: Fold n + 0.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFAdd %double %3 %double_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 4: Fold 0.0 + n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFAdd %double %double_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 5: Fold n - 0.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFSub %double %3 %double_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 6: Fold n * 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFMul %double %3 %double_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 7: Fold 1.0 * n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFMul %double %double_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 8: Fold n / 1.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFDiv %double %3 %double_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 9: Fold n * 0.0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFMul %double %3 %105\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, DOUBLE_0_ID), - // Test case 10: Fold 0.0 * n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFMul %double %105 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, DOUBLE_0_ID), - // Test case 11: Fold 0.0 / n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFDiv %double %105 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, DOUBLE_0_ID), - // Test case 12: Don't fold mix(a, b, 2.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_double Function\n" + - "%b = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %a\n" + - "%4 = OpLoad %double %b\n" + - "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 13: Fold mix(a, b, 0.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_double Function\n" + - "%b = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %a\n" + - "%4 = OpLoad %double %b\n" + - "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 14: Fold mix(a, b, 1.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%a = OpVariable %_ptr_double Function\n" + - "%b = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %a\n" + - "%4 = OpLoad %double %b\n" + - "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 4) -)); - -INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest, - ::testing::Values( - // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%3 = OpLoad %v4float %n\n" + - "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%3 = OpLoad %v4float %n\n" + - "%2 = OpFMul %v4float %3 %106\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, VEC4_0_ID), - // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%3 = OpLoad %v4float %n\n" + - "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest, - ::testing::Values( - // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%3 = OpLoad %v4double %n\n" + - "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%3 = OpLoad %v4double %n\n" + - "%2 = OpFMul %v4double %3 %106\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, DVEC4_0_ID), - // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%3 = OpLoad %v4double %n\n" + - "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest, - ::testing::Values( - // Test case 0: Don't fold n + 1 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_uint Function\n" + - "%3 = OpLoad %uint %n\n" + - "%2 = OpIAdd %uint %3 %uint_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Don't fold 1 + n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_uint Function\n" + - "%3 = OpLoad %uint %n\n" + - "%2 = OpIAdd %uint %uint_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 2: Fold n + 0 - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_uint Function\n" + - "%3 = OpLoad %uint %n\n" + - "%2 = OpIAdd %uint %3 %uint_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 3: Fold 0 + n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_uint Function\n" + - "%3 = OpLoad %uint %n\n" + - "%2 = OpIAdd %uint %uint_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 4: Don't fold n + (1,0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%3 = OpLoad %v2int %n\n" + - "%2 = OpIAdd %v2int %3 %v2int_1_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 5: Don't fold (1,0) + n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%3 = OpLoad %v2int %n\n" + - "%2 = OpIAdd %v2int %v2int_1_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 6: Fold n + (0,0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%3 = OpLoad %v2int %n\n" + - "%2 = OpIAdd %v2int %3 %v2int_0_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 7: Fold (0,0) + n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%3 = OpLoad %v2int %n\n" + - "%2 = OpIAdd %v2int %v2int_0_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest, -::testing::Values( - // Test case 0: Don't Fold 0.0 < clamp(-1, 1) - 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_1\n" + - "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Don't Fold 0.0 < clamp(-1, 1) - 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_1\n" + - "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 2: Don't Fold 0.0 <= clamp(-1, 1) - 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_1\n" + - "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 3: Don't Fold 0.0 <= clamp(-1, 1) - 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_1\n" + - "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 4: Don't Fold 0.0 > clamp(-1, 1) - 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_1\n" + - "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 5: Don't Fold 0.0 > clamp(-1, 1) - 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_1\n" + - "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 6: Don't Fold 0.0 >= clamp(-1, 1) - 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_1\n" + - "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 7: Don't Fold 0.0 >= clamp(-1, 1) - 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_1\n" + - "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 8: Don't Fold 0.0 < clamp(0, 1) - 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 = OpFUnordLessThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 9: Don't Fold 0.0 < clamp(0, 1) - 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 = OpFOrdLessThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 10: Don't Fold 0.0 > clamp(-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 = OpFUnordGreaterThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 11: Don't Fold 0.0 > clamp(-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 = OpFOrdGreaterThan %bool %float_0 %clamp\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0) -)); - -INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest, -::testing::Values( - // Test case 0: Don't Fold clamp(-1, 1) < 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_1\n" + - "%2 = OpFUnordLessThan %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Don't Fold clamp(-1, 1) < 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_1\n" + - "%2 = OpFOrdLessThan %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 2: Don't Fold clamp(-1, 1) <= 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_1\n" + - "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 3: Don't Fold clamp(-1, 1) <= 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_1\n" + - "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 4: Don't Fold clamp(-1, 1) > 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_1\n" + - "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 5: Don't Fold clamp(-1, 1) > 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_1\n" + - "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 6: Don't Fold clamp(-1, 1) >= 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_1\n" + - "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 7: Don't Fold clamp(-1, 1) >= 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_1\n" + - "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 8: Don't Fold clamp(-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 %clamp %float_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 9: Don't Fold clamp(0, 1) < 1 - 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 = OpFOrdLessThan %bool %clamp %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 10: Don't Fold clamp(-1, 0) > -1 - 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 = OpFUnordGreaterThan %bool %clamp %float_n1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 11: Don't Fold clamp(-1, 0) > -1 - 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 = OpFOrdGreaterThan %bool %clamp %float_n1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0) -)); - -INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest, - ::testing::Values( - // Test case 0: Fold int(3.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpConvertFToS %int %float_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 1: Fold uint(3.0) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpConvertFToU %int %float_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest, - ::testing::Values( - // Test case 0: Fold float(3) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpConvertSToF %float %int_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3.0), - // Test case 1: Fold float(3u) - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpConvertUToF %float %uint_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3.0) -)); -// clang-format on - -using ToNegateFoldingTest = - ::testing::TestWithParam>; - -TEST_P(ToNegateFoldingTest, 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(), SpvOpFNegate); - 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_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest, - ::testing::Values( - // Test case 0: Don't fold 1.0 - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFSub %float %float_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Fold 0.0 - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %n\n" + - "%2 = OpFSub %float %float_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 2: Don't fold (0,0,0,1) - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%3 = OpLoad %v4float %n\n" + - "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 3: Fold (0,0,0,0) - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%3 = OpLoad %v4float %n\n" + - "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest, - ::testing::Values( - // Test case 0: Don't fold 1.0 - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFSub %double %double_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 1: Fold 0.0 - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%3 = OpLoad %double %n\n" + - "%2 = OpFSub %double %double_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3), - // Test case 2: Don't fold (0,0,0,1) - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%3 = OpLoad %v4double %n\n" + - "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 0), - // Test case 3: Fold (0,0,0,0) - n - InstructionFoldingCase( - Header() + "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%3 = OpLoad %v4double %n\n" + - "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, 3) -)); - -using MatchingInstructionFoldingTest = - ::testing::TestWithParam>; - -TEST_P(MatchingInstructionFoldingTest, 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); - EXPECT_EQ(succeeded, tc.expected_result); - if (succeeded) { - Match(tc.test_body, context.get()); - } -} - -INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: Fold 0 + n (change sign) - InstructionFoldingCase( - Header() + - "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" + - "; CHECK: %2 = OpBitcast [[uint]] %3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%3 = OpLoad %uint %n\n" + - "%2 = OpIAdd %uint %int_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 2, true), - // Test case 0: Fold 0 + n (change sign) - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: %2 = OpBitcast [[int]] %3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%3 = OpLoad %int %n\n" + - "%2 = OpIAdd %int %uint_0 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 2, true) -)); - -INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: fold consecutive fnegate - // -(-x) = x - InstructionFoldingCase( - Header() + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" + - "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFNegate %float %2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 1: fold fnegate(fmul with const). - // -(x * 2.0) = x * -2.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFMul %float %2 %float_2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 2: fold fnegate(fmul with const). - // -(2.0 * x) = x * 2.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFMul %float %float_2 %2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 3: fold fnegate(fdiv with const). - // -(x / 2.0) = x * -0.5 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %2 %float_2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 4: fold fnegate(fdiv with const). - // -(2.0 / x) = -2.0 / x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %float_2 %2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 5: fold fnegate(fadd with const). - // -(2.0 + x) = -2.0 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %float_2 %2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 6: fold fnegate(fadd with const). - // -(x + 2.0) = -2.0 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %2 %float_2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 7: fold fnegate(fsub with const). - // -(2.0 - x) = x - 2.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %float_2 %2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 8: fold fnegate(fsub with const). - // -(x - 2.0) = 2.0 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %2 %float_2\n" + - "%4 = OpFNegate %float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 9: fold consecutive snegate - // -(-x) = x - InstructionFoldingCase( - Header() + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" + - "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSNegate %int %2\n" + - "%4 = OpSNegate %int %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 10: fold consecutive vector negate - // -(-x) = x - InstructionFoldingCase( - Header() + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" + - "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %var\n" + - "%3 = OpFNegate %v2float %2\n" + - "%4 = OpFNegate %v2float %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 11: fold snegate(iadd with const). - // -(2 + x) = -2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: OpConstant [[int]] -2147483648\n" + - "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIAdd %int %int_2 %2\n" + - "%4 = OpSNegate %int %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 12: fold snegate(iadd with const). - // -(x + 2) = -2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: OpConstant [[int]] -2147483648\n" + - "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIAdd %int %2 %int_2\n" + - "%4 = OpSNegate %int %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 13: fold snegate(isub with const). - // -(2 - x) = x - 2 - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpISub %int %int_2 %2\n" + - "%4 = OpSNegate %int %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 14: fold snegate(isub with const). - // -(x - 2) = 2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpISub %int %2 %int_2\n" + - "%4 = OpSNegate %int %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 15: fold snegate(iadd with const). - // -(x + 2) = -2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpIAdd %long %2 %long_2\n" + - "%4 = OpSNegate %long %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 16: fold snegate(isub with const). - // -(2 - x) = x - 2 - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpISub %long %long_2 %2\n" + - "%4 = OpSNegate %long %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 17: fold snegate(isub with const). - // -(x - 2) = 2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpISub %long %2 %long_2\n" + - "%4 = OpSNegate %long %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0) - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" + - "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" + - "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" + - "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 19: fold vector fnegate with null - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" + - "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" + - "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpFNegate %v2double %v2double_null\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true) -)); - -INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: scalar reicprocal - // x / 0.5 = x * 2.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %2 %float_0p5\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 3, true), - // Test case 1: Unfoldable - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %2 %104\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 3, false), - // Test case 2: Vector reciprocal - // x / {2.0, 0.5} = x * {0.5, 2.0} - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" + - "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" + - "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %var\n" + - "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 3, true), - // Test case 3: double reciprocal - // x / 2.0 = x * 0.5 - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" + - "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_double Function\n" + - "%2 = OpLoad %double %var\n" + - "%3 = OpFDiv %double %2 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 3, true), - // Test case 4: don't fold x / 0. - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %var\n" + - "%3 = OpFDiv %v2float %2 %v2float_null\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 3, false) -)); - -INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: fold consecutive fmuls - // (x * 3.0) * 2.0 = x * 6.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFMul %float %2 %float_3\n" + - "%4 = OpFMul %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 1: fold consecutive fmuls - // 2.0 * (x * 3.0) = x * 6.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFMul %float %2 %float_3\n" + - "%4 = OpFMul %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 2: fold consecutive fmuls - // (3.0 * x) * 2.0 = x * 6.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFMul %float %float_3 %2\n" + - "%4 = OpFMul %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 3: fold vector fmul - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" + - "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" + - "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" + - "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %var\n" + - "%3 = OpFMul %v2float %2 %v2float_2_3\n" + - "%4 = OpFMul %v2float %3 %v2float_3_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 4: fold double fmuls - // (x * 3.0) * 2.0 = x * 6.0 - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" + - "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_double Function\n" + - "%2 = OpLoad %double %var\n" + - "%3 = OpFMul %double %2 %double_3\n" + - "%4 = OpFMul %double %3 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 5: fold 32 bit imuls - // (x * 3) * 2 = x * 6 - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIMul %int %2 %int_3\n" + - "%4 = OpIMul %int %3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 6: fold 64 bit imuls - // (x * 3) * 2 = x * 6 - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" + - "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpIMul %long %2 %long_3\n" + - "%4 = OpIMul %long %3 %long_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 7: merge vector integer mults - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" + - "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" + - "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" + - "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %var\n" + - "%3 = OpIMul %v2int %2 %v2int_2_3\n" + - "%4 = OpIMul %v2int %3 %v2int_3_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 8: merge fmul of fdiv - // 2.0 * (2.0 / x) = 4.0 / x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %float_2 %2\n" + - "%4 = OpFMul %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 9: merge fmul of fdiv - // (2.0 / x) * 2.0 = 4.0 / x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %float_2 %2\n" + - "%4 = OpFMul %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 10: Do not merge imul of sdiv - // 4 * (x / 2) - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSDiv %int %2 %int_2\n" + - "%4 = OpIMul %int %int_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 11: Do not merge imul of sdiv - // (x / 2) * 4 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSDiv %int %2 %int_2\n" + - "%4 = OpIMul %int %3 %int_4\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 12: Do not merge imul of udiv - // 4 * (x / 2) - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_uint Function\n" + - "%2 = OpLoad %uint %var\n" + - "%3 = OpUDiv %uint %2 %uint_2\n" + - "%4 = OpIMul %uint %uint_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 13: Do not merge imul of udiv - // (x / 2) * 4 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_uint Function\n" + - "%2 = OpLoad %uint %var\n" + - "%3 = OpUDiv %uint %2 %uint_2\n" + - "%4 = OpIMul %uint %3 %uint_4\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 14: Don't fold - // (x / 3) * 4 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_uint Function\n" + - "%2 = OpLoad %uint %var\n" + - "%3 = OpUDiv %uint %2 %uint_3\n" + - "%4 = OpIMul %uint %3 %uint_4\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 15: merge vector fmul of fdiv - // (x / {2,2}) * {4,4} = x * {2,2} - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" + - "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %v2float %var\n" + - "%3 = OpFDiv %v2float %2 %v2float_2_2\n" + - "%4 = OpFMul %v2float %3 %v2float_4_4\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 16: merge vector imul of snegate - // (-x) * {2,2} = x * {-2,-2} - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" + - "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" + - "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" + - "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" + - "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %var\n" + - "%3 = OpSNegate %v2int %2\n" + - "%4 = OpIMul %v2int %3 %v2int_2_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 17: merge vector imul of snegate - // {2,2} * (-x) = x * {-2,-2} - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" + - "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" + - "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" + - "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" + - "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %var\n" + - "%3 = OpSNegate %v2int %2\n" + - "%4 = OpIMul %v2int %v2int_2_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 18: Fold OpVectorTimesScalar - // {4,4} = OpVectorTimesScalar v2float {2,2} 2 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" + - "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" + - "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" + - "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 19: Fold OpVectorTimesScalar - // {0,0} = OpVectorTimesScalar v2float v2float_null -1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" + - "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" + - "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 20: Fold OpVectorTimesScalar - // {4,4} = OpVectorTimesScalar v2double {2,2} 2 - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" + - "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" + - "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 21: Fold OpVectorTimesScalar - // {0,0} = OpVectorTimesScalar v2double {0,0} n - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" + - "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" + - "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" + - "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_double Function\n" + - "%load = OpLoad %double %n\n" + - "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 22: Fold OpVectorTimesScalar - // {0,0} = OpVectorTimesScalar v2double n 0 - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" + - "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2double Function\n" + - "%load = OpLoad %v2double %n\n" + - "%2 = OpVectorTimesScalar %v2double %load %double_0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 23: merge fmul of fdiv - // x * (y / x) = y - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" + - "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%x = OpVariable %_ptr_float Function\n" + - "%y = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %x\n" + - "%3 = OpLoad %float %y\n" + - "%4 = OpFDiv %float %3 %2\n" + - "%5 = OpFMul %float %2 %4\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 5, true), - // Test case 24: merge fmul of fdiv - // (y / x) * x = y - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" + - "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%x = OpVariable %_ptr_float Function\n" + - "%y = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %x\n" + - "%3 = OpLoad %float %y\n" + - "%4 = OpFDiv %float %3 %2\n" + - "%5 = OpFMul %float %4 %2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 5, true) -)); - -INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: merge consecutive fdiv - // 4.0 / (2.0 / x) = 2.0 * x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %float_2 %2\n" + - "%4 = OpFDiv %float %float_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 1: merge consecutive fdiv - // 4.0 / (x / 2.0) = 8.0 / x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %2 %float_2\n" + - "%4 = OpFDiv %float %float_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 2: merge consecutive fdiv - // (4.0 / x) / 2.0 = 2.0 / x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %float_4 %2\n" + - "%4 = OpFDiv %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 3: Do not merge consecutive sdiv - // 4 / (2 / x) - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSDiv %int %int_2 %2\n" + - "%4 = OpSDiv %int %int_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 4: Do not merge consecutive sdiv - // 4 / (x / 2) - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSDiv %int %2 %int_2\n" + - "%4 = OpSDiv %int %int_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 5: Do not merge consecutive sdiv - // (4 / x) / 2 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSDiv %int %int_4 %2\n" + - "%4 = OpSDiv %int %3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 6: Do not merge consecutive sdiv - // (x / 4) / 2 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSDiv %int %2 %int_4\n" + - "%4 = OpSDiv %int %3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 7: Do not merge sdiv of imul - // 4 / (2 * x) - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIMul %int %int_2 %2\n" + - "%4 = OpSDiv %int %int_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 8: Do not merge sdiv of imul - // 4 / (x * 2) - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIMul %int %2 %int_2\n" + - "%4 = OpSDiv %int %int_4 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 9: Do not merge sdiv of imul - // (4 * x) / 2 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIMul %int %int_4 %2\n" + - "%4 = OpSDiv %int %3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 10: Do not merge sdiv of imul - // (x * 4) / 2 - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpIMul %int %2 %int_4\n" + - "%4 = OpSDiv %int %3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 11: merge sdiv of snegate - // (-x) / 2 = x / -2 - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: OpConstant [[int]] -2147483648\n" + - "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[int_n2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSNegate %int %2\n" + - "%4 = OpSDiv %int %3 %int_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 12: merge sdiv of snegate - // 2 / (-x) = -2 / x - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: OpConstant [[int]] -2147483648\n" + - "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpSDiv [[int]] [[int_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpSNegate %int %2\n" + - "%4 = OpSDiv %int %int_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 13: Don't merge - // (x / {null}) / {null} - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_v2float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFDiv %float %2 %v2float_null\n" + - "%4 = OpFDiv %float %3 %v2float_null\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, false), - // Test case 14: merge fmul of fdiv - // (y * x) / x = y - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" + - "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%x = OpVariable %_ptr_float Function\n" + - "%y = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %x\n" + - "%3 = OpLoad %float %y\n" + - "%4 = OpFMul %float %3 %2\n" + - "%5 = OpFDiv %float %4 %2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 5, true), - // Test case 15: merge fmul of fdiv - // (x * y) / x = y - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" + - "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%x = OpVariable %_ptr_float Function\n" + - "%y = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %x\n" + - "%3 = OpLoad %float %y\n" + - "%4 = OpFMul %float %2 %3\n" + - "%5 = OpFDiv %float %4 %2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 5, true) -)); - -INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: merge add of negate - // (-x) + 2 = 2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFNegate %float %2\n" + - "%4 = OpFAdd %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 1: merge add of negate - // 2 + (-x) = 2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpSNegate %float %2\n" + - "%4 = OpIAdd %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 2: merge add of negate - // (-x) + 2 = 2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpSNegate %long %2\n" + - "%4 = OpIAdd %long %3 %long_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 3: merge add of negate - // 2 + (-x) = 2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpSNegate %long %2\n" + - "%4 = OpIAdd %long %long_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 4: merge add of subtract - // (x - 1) + 2 = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %2 %float_1\n" + - "%4 = OpFAdd %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 5: merge add of subtract - // (1 - x) + 2 = 3 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %float_1 %2\n" + - "%4 = OpFAdd %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 6: merge add of subtract - // 2 + (x - 1) = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %2 %float_1\n" + - "%4 = OpFAdd %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 7: merge add of subtract - // 2 + (1 - x) = 3 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %float_1 %2\n" + - "%4 = OpFAdd %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 8: merge add of add - // (x + 1) + 2 = x + 3 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %2 %float_1\n" + - "%4 = OpFAdd %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 9: merge add of add - // (1 + x) + 2 = 3 + x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %float_1 %2\n" + - "%4 = OpFAdd %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 10: merge add of add - // 2 + (x + 1) = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %2 %float_1\n" + - "%4 = OpFAdd %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 11: merge add of add - // 2 + (1 + x) = 3 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %float_1 %2\n" + - "%4 = OpFAdd %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true) -)); - -INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: merge of add of sub - // (a - b) + b => a - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: %6 = OpCopyObject [[float]] %3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var0 = OpVariable %_ptr_float Function\n" + - "%var1 = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %var0\n" + - "%4 = OpLoad %float %var1\n" + - "%5 = OpFSub %float %3 %4\n" + - "%6 = OpFAdd %float %5 %4\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 6, true), - // Test case 1: merge of add of sub - // b + (a - b) => a - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: %6 = OpCopyObject [[float]] %3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var0 = OpVariable %_ptr_float Function\n" + - "%var1 = OpVariable %_ptr_float Function\n" + - "%3 = OpLoad %float %var0\n" + - "%4 = OpLoad %float %var1\n" + - "%5 = OpFSub %float %3 %4\n" + - "%6 = OpFAdd %float %4 %5\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 6, true) -)); - -INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: factor of add of muls - // (a * b) + (a * c) => a * (b + c) - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" + - "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var0 = OpVariable %_ptr_float Function\n" + - "%var1 = OpVariable %_ptr_float Function\n" + - "%var2 = OpVariable %_ptr_float Function\n" + - "%4 = OpLoad %float %var0\n" + - "%5 = OpLoad %float %var1\n" + - "%6 = OpLoad %float %var2\n" + - "%7 = OpFMul %float %6 %4\n" + - "%8 = OpFMul %float %6 %5\n" + - "%9 = OpFAdd %float %7 %8\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true), - // Test case 1: factor of add of muls - // (b * a) + (a * c) => a * (b + c) - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" + - "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var0 = OpVariable %_ptr_float Function\n" + - "%var1 = OpVariable %_ptr_float Function\n" + - "%var2 = OpVariable %_ptr_float Function\n" + - "%4 = OpLoad %float %var0\n" + - "%5 = OpLoad %float %var1\n" + - "%6 = OpLoad %float %var2\n" + - "%7 = OpFMul %float %4 %6\n" + - "%8 = OpFMul %float %6 %5\n" + - "%9 = OpFAdd %float %7 %8\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true), - // Test case 2: factor of add of muls - // (a * b) + (c * a) => a * (b + c) - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" + - "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var0 = OpVariable %_ptr_float Function\n" + - "%var1 = OpVariable %_ptr_float Function\n" + - "%var2 = OpVariable %_ptr_float Function\n" + - "%4 = OpLoad %float %var0\n" + - "%5 = OpLoad %float %var1\n" + - "%6 = OpLoad %float %var2\n" + - "%7 = OpFMul %float %6 %4\n" + - "%8 = OpFMul %float %5 %6\n" + - "%9 = OpFAdd %float %7 %8\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true), - // Test case 3: factor of add of muls - // (b * a) + (c * a) => a * (b + c) - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" + - "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var0 = OpVariable %_ptr_float Function\n" + - "%var1 = OpVariable %_ptr_float Function\n" + - "%var2 = OpVariable %_ptr_float Function\n" + - "%4 = OpLoad %float %var0\n" + - "%5 = OpLoad %float %var1\n" + - "%6 = OpLoad %float %var2\n" + - "%7 = OpFMul %float %4 %6\n" + - "%8 = OpFMul %float %5 %6\n" + - "%9 = OpFAdd %float %7 %8\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true) -)); - -INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: merge sub of negate - // (-x) - 2 = -2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFNegate %float %2\n" + - "%4 = OpFSub %float %3 %float_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 1: merge sub of negate - // 2 - (-x) = x + 2 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFNegate %float %2\n" + - "%4 = OpFSub %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 2: merge sub of negate - // (-x) - 2 = -2 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpSNegate %long %2\n" + - "%4 = OpISub %long %3 %long_2\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 3: merge sub of negate - // 2 - (-x) = x + 2 - InstructionFoldingCase( - Header() + - "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" + - "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" + - "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_long Function\n" + - "%2 = OpLoad %long %var\n" + - "%3 = OpSNegate %long %2\n" + - "%4 = OpISub %long %long_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 4: merge add of subtract - // (x + 2) - 1 = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %2 %float_2\n" + - "%4 = OpFSub %float %3 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 5: merge add of subtract - // (2 + x) - 1 = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %float_2 %2\n" + - "%4 = OpFSub %float %3 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 6: merge add of subtract - // 2 - (x + 1) = 1 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %2 %float_1\n" + - "%4 = OpFSub %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 7: merge add of subtract - // 2 - (1 + x) = 1 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFAdd %float %float_1 %2\n" + - "%4 = OpFSub %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 8: merge subtract of subtract - // (x - 2) - 1 = x - 3 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %2 %float_2\n" + - "%4 = OpFSub %float %3 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 9: merge subtract of subtract - // (2 - x) - 1 = 1 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %float_2 %2\n" + - "%4 = OpFSub %float %3 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 10: merge subtract of subtract - // 2 - (x - 1) = 3 - x - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %2 %float_1\n" + - "%4 = OpFSub %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 11: merge subtract of subtract - // 1 - (2 - x) = x + (-1) - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %float_2 %2\n" + - "%4 = OpFSub %float %float_1 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 12: merge subtract of subtract - // 2 - (1 - x) = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" + - "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_float Function\n" + - "%2 = OpLoad %float %var\n" + - "%3 = OpFSub %float %float_1 %2\n" + - "%4 = OpFSub %float %float_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true), - // Test case 13: merge subtract of subtract with mixed types. - // 2 - (1 - x) = x + 1 - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" + - "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%var = OpVariable %_ptr_int Function\n" + - "%2 = OpLoad %int %var\n" + - "%3 = OpISub %int %uint_1 %2\n" + - "%4 = OpISub %int %int_2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 4, true) -)); - -INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: Fold select with the same values for both sides - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" + - "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_bool Function\n" + - "%load = OpLoad %bool %n\n" + - "%2 = OpSelect %int %load %100 %100\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 1: Fold select true to left side - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" + - "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%load = OpLoad %bool %n\n" + - "%2 = OpSelect %int %true %100 %n\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 2: Fold select false to right side - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" + - "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%load = OpLoad %bool %n\n" + - "%2 = OpSelect %int %false %n %100\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 3: Fold select null to right side - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" + - "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_int Function\n" + - "%load = OpLoad %int %n\n" + - "%2 = OpSelect %int %bool_null %load %100\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 4: vector null - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" + - "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" + - "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" + - "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%load = OpLoad %v2int %n\n" + - "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 2, true), - // Test case 5: vector select - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" + - "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%m = OpVariable %_ptr_v2int Function\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %n\n" + - "%3 = OpLoad %v2int %n\n" + - "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 6: vector select - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" + - "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%m = OpVariable %_ptr_v2int Function\n" + - "%n = OpVariable %_ptr_v2int Function\n" + - "%2 = OpLoad %v2int %n\n" + - "%3 = OpLoad %v2int %n\n" + - "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true) -)); - -INSTANTIATE_TEST_SUITE_P(CompositeExtractMatchingTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: Extracting from result of consecutive shuffles of differing - // size. - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4int Function\n" + - "%2 = OpLoad %v4int %n\n" + - "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" + - "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" + - "%5 = OpCompositeExtract %int %4 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, true), - // Test case 1: Extracting from result of vector shuffle of differing - // input and result sizes. - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4int Function\n" + - "%2 = OpLoad %v4int %n\n" + - "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" + - "%4 = OpCompositeExtract %int %3 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 2: Extracting from result of vector shuffle of differing - // input and result sizes. - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4int Function\n" + - "%2 = OpLoad %v4int %n\n" + - "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" + - "%4 = OpCompositeExtract %int %3 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true), - // Test case 3: Using fmix feeding extract with a 1 in the a position. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" + - "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" + - "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" + - "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" + - "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%m = OpVariable %_ptr_v4double Function\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %m\n" + - "%3 = OpLoad %v4double %n\n" + - "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" + - "%5 = OpCompositeExtract %double %4 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, true), - // Test case 4: Using fmix feeding extract with a 0 in the a position. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" + - "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" + - "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" + - "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" + - "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%m = OpVariable %_ptr_v4double Function\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %m\n" + - "%3 = OpLoad %v4double %n\n" + - "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" + - "%5 = OpCompositeExtract %double %4 2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, true), - // Test case 5: Using fmix feeding extract with a null for the alpha - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" + - "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" + - "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" + - "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" + - "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" + - "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%m = OpVariable %_ptr_v4double Function\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %m\n" + - "%3 = OpLoad %v4double %n\n" + - "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" + - "%5 = OpCompositeExtract %double %4 0\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, true), - // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a - // position. - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%m = OpVariable %_ptr_v4double Function\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %m\n" + - "%3 = OpLoad %v4double %n\n" + - "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" + - "%5 = OpCompositeExtract %double %4 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 5, false), - // Test case 7: Extracting the undefined literal value from a vector - // shuffle. - InstructionFoldingCase( - Header() + - "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" + - "; CHECK: %4 = OpUndef [[int]]\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4int Function\n" + - "%2 = OpLoad %v4int %n\n" + - "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" + - "%4 = OpCompositeExtract %int %3 1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 4, true) -)); - -INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest, -::testing::Values( - // Test case 0: Using OpDot to extract last element. - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%2 = OpLoad %v4float %n\n" + - "%3 = OpDot %float %2 %v4float_0_0_0_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, true), - // Test case 1: Using OpDot to extract last element. - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%2 = OpLoad %v4float %n\n" + - "%3 = OpDot %float %v4float_0_0_0_1 %2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, true), - // Test case 2: Using OpDot to extract second element. - InstructionFoldingCase( - Header() + - "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" + - "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4float Function\n" + - "%2 = OpLoad %v4float %n\n" + - "%3 = OpDot %float %v4float_0_1_0_0 %2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, true), - // Test case 3: Using OpDot to extract last element. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %n\n" + - "%3 = OpDot %double %2 %v4double_0_0_0_1\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, true), - // Test case 4: Using OpDot to extract last element. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %n\n" + - "%3 = OpDot %double %v4double_0_0_0_1 %2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, true), - // Test case 5: Using OpDot to extract second element. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%2 = OpLoad %v4double %n\n" + - "%3 = OpDot %double %v4double_0_1_0_0 %2\n" + - "OpReturn\n" + - "OpFunctionEnd", - 3, true) -)); - -using MatchingInstructionWithNoResultFoldingTest = -::testing::TestWithParam>; - -// Test folding instructions that do not have a result. The instruction -// that will be folded is the last instruction before the return. If there -// are multiple returns, there is not guarentee which one is used. -TEST_P(MatchingInstructionWithNoResultFoldingTest, 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. - Instruction* inst = nullptr; - Function* func = &*context->module()->begin(); - for (auto& bb : *func) { - Instruction* terminator = bb.terminator(); - if (terminator->IsReturnOrAbort()) { - inst = terminator->PreviousNode(); - break; - } - } - assert(inst && "Invalid test. Could not find instruction to fold."); - std::unique_ptr original_inst(inst->Clone(context.get())); - bool succeeded = context->get_instruction_folder().FoldInstruction(inst); - EXPECT_EQ(succeeded, tc.expected_result); - if (succeeded) { - Match(tc.test_body, context.get()); - } -} - -INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest, -::testing::Values( - // Test case 0: Remove store of undef. - InstructionFoldingCase( - Header() + - "; CHECK: OpLabel\n" + - "; CHECK-NOT: OpStore\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%undef = OpUndef %v4double\n" + - "OpStore %n %undef\n" + - "OpReturn\n" + - "OpFunctionEnd", - 0 /* OpStore */, true), - // Test case 1: Keep volatile store. - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%n = OpVariable %_ptr_v4double Function\n" + - "%undef = OpUndef %v4double\n" + - "OpStore %n %undef Volatile\n" + - "OpReturn\n" + - "OpFunctionEnd", - 0 /* OpStore */, false) -)); - -INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest, -::testing::Values( - // Test case 0: Basic test 1 - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 1: Basic test 2 - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 2: Basic test 3 - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 3: Basic test 4 - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 4: Don't fold, need both operands of the feeder. - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, false), - // Test case 5: Don't fold, need both operands of the feeder. - InstructionFoldingCase( - Header() + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, false), - // Test case 6: Fold, need both operands of the feeder, but they are the same. - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 7: Fold, need both operands of the feeder, but they are the same. - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" + - "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 8: Replace first operand with a smaller vector. - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v2double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v2double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" + - "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 9: Replace first operand with a larger vector. - InstructionFoldingCase( - Header() + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" + - "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 10: Replace unused operand with null. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" + - "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 11: Replace unused operand with null. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" + - "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 12: Replace unused operand with null. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" + - "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true), - // Test case 13: Shuffle with undef literal. - InstructionFoldingCase( - Header() + - "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" + - "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" + - "; CHECK: OpVectorShuffle\n" + - "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" + - "; CHECK: OpReturn\n" + - "%main = OpFunction %void None %void_func\n" + - "%main_lab = OpLabel\n" + - "%2 = OpVariable %_ptr_v4double Function\n" + - "%3 = OpVariable %_ptr_v4double Function\n" + - "%4 = OpVariable %_ptr_v4double Function\n" + - "%5 = OpLoad %v4double %2\n" + - "%6 = OpLoad %v4double %3\n" + - "%7 = OpLoad %v4double %4\n" + - "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" + - "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" + - "OpReturn\n" + - "OpFunctionEnd", - 9, true) -)); - -using EntryPointFoldingTest = -::testing::TestWithParam>; - -TEST_P(EntryPointFoldingTest, 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. - Instruction* inst = nullptr; - inst = &*context->module()->entry_points().begin(); - assert(inst && "Invalid test. Could not find entry point instruction to fold."); - std::unique_ptr original_inst(inst->Clone(context.get())); - bool succeeded = context->get_instruction_folder().FoldInstruction(inst); - EXPECT_EQ(succeeded, tc.expected_result); - if (succeeded) { - Match(tc.test_body, context.get()); - } -} - -INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest, -::testing::Values( - // Test case 0: Basic test 1 - InstructionFoldingCase(std::string() + - "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" + - "OpCapability Shader\n" + - "%1 = OpExtInstImport \"GLSL.std.450\"\n" + - "OpMemoryModel Logical GLSL450\n" + - "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" + - "OpExecutionMode %2 OriginUpperLeft\n" + - "OpSource GLSL 430\n" + - "OpDecorate %3 Location 0\n" + - "%void = OpTypeVoid\n" + - "%5 = OpTypeFunction %void\n" + - "%float = OpTypeFloat 32\n" + - "%v4float = OpTypeVector %float 4\n" + - "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" + - "%3 = OpVariable %_ptr_Output_v4float Output\n" + - "%int = OpTypeInt 32 1\n" + - "%int_0 = OpConstant %int 0\n" + -"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" + - "%2 = OpFunction %void None %5\n" + - "%12 = OpLabel\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true), - InstructionFoldingCase(std::string() + - "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" + - "OpCapability Shader\n" + - "%1 = OpExtInstImport \"GLSL.std.450\"\n" + - "OpMemoryModel Logical GLSL450\n" + - "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" + - "OpExecutionMode %2 OriginUpperLeft\n" + - "OpSource GLSL 430\n" + - "OpDecorate %3 Location 0\n" + - "%void = OpTypeVoid\n" + - "%5 = OpTypeFunction %void\n" + - "%float = OpTypeFloat 32\n" + - "%v4float = OpTypeVector %float 4\n" + - "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" + - "%3 = OpVariable %_ptr_Output_v4float Output\n" + - "%4 = OpVariable %_ptr_Output_v4float Output\n" + - "%int = OpTypeInt 32 1\n" + - "%int_0 = OpConstant %int 0\n" + -"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" + - "%2 = OpFunction %void None %5\n" + - "%12 = OpLabel\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true), - InstructionFoldingCase(std::string() + - "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" + - "OpCapability Shader\n" + - "%1 = OpExtInstImport \"GLSL.std.450\"\n" + - "OpMemoryModel Logical GLSL450\n" + - "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" + - "OpExecutionMode %2 OriginUpperLeft\n" + - "OpSource GLSL 430\n" + - "OpDecorate %3 Location 0\n" + - "%void = OpTypeVoid\n" + - "%5 = OpTypeFunction %void\n" + - "%float = OpTypeFloat 32\n" + - "%v4float = OpTypeVector %float 4\n" + - "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" + - "%3 = OpVariable %_ptr_Output_v4float Output\n" + - "%4 = OpVariable %_ptr_Output_v4float Output\n" + - "%int = OpTypeInt 32 1\n" + - "%int_0 = OpConstant %int 0\n" + -"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" + - "%2 = OpFunction %void None %5\n" + - "%12 = OpLabel\n" + - "OpReturn\n" + - "OpFunctionEnd\n", - 9, true) -)); - -using SPV14FoldingTest = -::testing::TestWithParam>; - -TEST_P(SPV14FoldingTest, Case) { - const auto& tc = GetParam(); - - // Build module. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_4, 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); - EXPECT_EQ(succeeded, tc.expected_result); - if (succeeded) { - Match(tc.test_body, context.get()); - } -} - -INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest, -::testing::Values( - // Test case 0: select vectors with scalar condition. - InstructionFoldingCase(std::string() + -"; CHECK-NOT: OpSelect\n" + -"; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" + -"OpCapability Shader\n" + -"OpCapability Linkage\n" + -"%void = OpTypeVoid\n" + -"%bool = OpTypeBool\n" + -"%true = OpConstantTrue %bool\n" + -"%int = OpTypeInt 32 0\n" + -"%int4 = OpTypeVector %int 4\n" + -"%int_0 = OpConstant %int 0\n" + -"%int_1 = OpConstant %int 1\n" + -"%1 = OpUndef %int4\n" + -"%2 = OpUndef %int4\n" + -"%void_fn = OpTypeFunction %void\n" + -"%func = OpFunction %void None %void_fn\n" + -"%entry = OpLabel\n" + -"%3 = OpSelect %int4 %true %1 %2\n" + -"OpReturn\n" + -"OpFunctionEnd\n" -, - 3, true), - // Test case 1: select struct with scalar condition. - InstructionFoldingCase(std::string() + -"; CHECK-NOT: OpSelect\n" + -"; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" + -"OpCapability Shader\n" + -"OpCapability Linkage\n" + -"%void = OpTypeVoid\n" + -"%bool = OpTypeBool\n" + -"%true = OpConstantFalse %bool\n" + -"%int = OpTypeInt 32 0\n" + -"%struct = OpTypeStruct %int %int %int %int\n" + -"%int_0 = OpConstant %int 0\n" + -"%int_1 = OpConstant %int 1\n" + -"%1 = OpUndef %struct\n" + -"%2 = OpUndef %struct\n" + -"%void_fn = OpTypeFunction %void\n" + -"%func = OpFunction %void None %void_fn\n" + -"%entry = OpLabel\n" + -"%3 = OpSelect %struct %true %1 %2\n" + -"OpReturn\n" + -"OpFunctionEnd\n" -, - 3, true), - // Test case 1: select array with scalar condition. - InstructionFoldingCase(std::string() + -"; CHECK-NOT: OpSelect\n" + -"; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" + -"OpCapability Shader\n" + -"OpCapability Linkage\n" + -"%void = OpTypeVoid\n" + -"%bool = OpTypeBool\n" + -"%true = OpConstantFalse %bool\n" + -"%int = OpTypeInt 32 0\n" + -"%int_0 = OpConstant %int 0\n" + -"%int_1 = OpConstant %int 1\n" + -"%int_4 = OpConstant %int 4\n" + -"%array = OpTypeStruct %int %int %int %int\n" + -"%1 = OpUndef %array\n" + -"%2 = OpUndef %array\n" + -"%void_fn = OpTypeFunction %void\n" + -"%func = OpFunction %void None %void_fn\n" + -"%entry = OpLabel\n" + -"%3 = OpSelect %array %true %1 %2\n" + -"OpReturn\n" + -"OpFunctionEnd\n" -, - 3, true) -)); - -std::string FloatControlsHeader(const std::string& capabilities) { - std::string header = R"( -OpCapability Shader -)" + capabilities + R"( -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -)"; - - return header; -} - -using FloatControlsFoldingTest = -::testing::TestWithParam>; - -TEST_P(FloatControlsFoldingTest, Case) { - const auto& tc = GetParam(); - - // Build module. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_4, 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); - EXPECT_EQ(succeeded, tc.expected_result); - if (succeeded) { - Match(tc.test_body, context.get()); - } -} - -INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest, -::testing::Values( - // Test case 0: no folding with DenormPreserve - InstructionFoldingCase(FloatControlsHeader("OpCapability DenormPreserve") + - "%1 = OpFAdd %float %float_0 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n" -, - 1, false), - // Test case 1: no folding with DenormFlushToZero - InstructionFoldingCase(FloatControlsHeader("OpCapability DenormFlushToZero") + - "%1 = OpFAdd %float %float_0 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n" -, - 1, false), - // Test case 2: no folding with SignedZeroInfNanPreserve - InstructionFoldingCase(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") + - "%1 = OpFAdd %float %float_0 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n" -, - 1, false), - // Test case 3: no folding with RoundingModeRTE - InstructionFoldingCase(FloatControlsHeader("OpCapability RoundingModeRTE") + - "%1 = OpFAdd %float %float_0 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n" -, - 1, false), - // Test case 4: no folding with RoundingModeRTZ - InstructionFoldingCase(FloatControlsHeader("OpCapability RoundingModeRTZ") + - "%1 = OpFAdd %float %float_0 %float_1\n" + - "OpReturn\n" + - "OpFunctionEnd\n" -, - 1, false) -)); - -std::string ImageOperandsTestBody(const std::string& image_instruction) { - std::string body = R"( - OpCapability Shader - OpCapability ImageGatherExtended - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpDecorate %Texture DescriptorSet 0 - OpDecorate %Texture Binding 0 - %int = OpTypeInt 32 1 - %int_n1 = OpConstant %int -1 - %5 = OpConstant %int 0 - %float = OpTypeFloat 32 - %float_0 = OpConstant %float 0 -%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown -%type_sampled_image = OpTypeSampledImage %type_2d_image -%type_sampler = OpTypeSampler -%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler -%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image - %_ptr_int = OpTypePointer Function %int - %v2int = OpTypeVector %int 2 - %10 = OpTypeVector %float 4 - %void = OpTypeVoid - %22 = OpTypeFunction %void - %v2float = OpTypeVector %float 2 - %v3int = OpTypeVector %int 3 - %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant - %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant - %101 = OpConstantComposite %v2int %int_n1 %int_n1 - %20 = OpConstantComposite %v2float %float_0 %float_0 - %main = OpFunction %void None %22 - %23 = OpLabel - %var = OpVariable %_ptr_int Function - %88 = OpLoad %type_2d_image %Texture - %val = OpLoad %int %var - %sampler = OpLoad %type_sampler %gSampler - %26 = OpSampledImage %type_sampled_image %88 %sampler -)" + image_instruction + R"( - OpReturn - OpFunctionEnd -)"; - - return body; -} - -INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest, -::testing::Values( - // Test case 0: OpImageFetch without Offset - InstructionFoldingCase(ImageOperandsTestBody( - "%89 = OpImageFetch %10 %88 %101 Lod %5 \n") - , 89, false), - // Test case 1: OpImageFetch with non-const offset - InstructionFoldingCase(ImageOperandsTestBody( - "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n") - , 89, false), - // Test case 2: OpImageFetch with Lod and Offset - InstructionFoldingCase(ImageOperandsTestBody( - " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101 \n" - "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n") - , 89, true), - // Test case 3: OpImageFetch with Bias and Offset - InstructionFoldingCase(ImageOperandsTestBody( - " %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101 \n" - "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n") - , 89, true), - // Test case 4: OpImageFetch with Grad and Offset. - // Grad adds 2 operands to the instruction. - InstructionFoldingCase(ImageOperandsTestBody( - " %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101 \n" - "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n") - , 89, true), - // Test case 5: OpImageFetch with Offset and MinLod. - // This is an example of a case where the bitmask bit-offset is larger than - // that of the Offset. - InstructionFoldingCase(ImageOperandsTestBody( - " %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5 \n" - "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n") - , 89, true), - // Test case 6: OpImageGather with constant Offset - InstructionFoldingCase(ImageOperandsTestBody( - " %89 = OpImageGather %10 %26 %20 %5 Offset %101 \n" - "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n") - , 89, true), - // Test case 7: OpImageWrite with constant Offset - InstructionFoldingCase(ImageOperandsTestBody( - " OpImageWrite %88 %5 %101 Offset %101 \n" - "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n") - , 0 /* No result-id */, true) -)); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/freeze_spec_const_test.cpp b/3rdparty/spirv-tools/test/opt/freeze_spec_const_test.cpp deleted file mode 100644 index e5999cec6..000000000 --- a/3rdparty/spirv-tools/test/opt/freeze_spec_const_test.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -struct FreezeSpecConstantValueTypeTestCase { - const char* type_decl; - const char* spec_const; - const char* expected_frozen_const; -}; - -using FreezeSpecConstantValueTypeTest = - PassTest<::testing::TestWithParam>; - -TEST_P(FreezeSpecConstantValueTypeTest, PrimaryType) { - auto& test_case = GetParam(); - std::vector text = {"OpCapability Shader", - "OpMemoryModel Logical GLSL450", - test_case.type_decl, test_case.spec_const}; - std::vector expected = { - "OpCapability Shader", "OpMemoryModel Logical GLSL450", - test_case.type_decl, test_case.expected_frozen_const}; - SinglePassRunAndCheck( - JoinAllInsts(text), JoinAllInsts(expected), /* skip_nop = */ false); -} - -// Test each primary type. -INSTANTIATE_TEST_SUITE_P( - PrimaryTypeSpecConst, FreezeSpecConstantValueTypeTest, - ::testing::ValuesIn(std::vector({ - // Type declaration, original spec constant definition, expected frozen - // spec constants. - {"%int = OpTypeInt 32 1", "%2 = OpSpecConstant %int 1", - "%int_1 = OpConstant %int 1"}, - {"%uint = OpTypeInt 32 0", "%2 = OpSpecConstant %uint 1", - "%uint_1 = OpConstant %uint 1"}, - {"%float = OpTypeFloat 32", "%2 = OpSpecConstant %float 3.1415", - "%float_3_1415 = OpConstant %float 3.1415"}, - {"%double = OpTypeFloat 64", "%2 = OpSpecConstant %double 3.141592653", - "%double_3_141592653 = OpConstant %double 3.141592653"}, - {"%bool = OpTypeBool", "%2 = OpSpecConstantTrue %bool", - "%true = OpConstantTrue %bool"}, - {"%bool = OpTypeBool", "%2 = OpSpecConstantFalse %bool", - "%false = OpConstantFalse %bool"}, - }))); - -using FreezeSpecConstantValueRemoveDecorationTest = PassTest<::testing::Test>; - -TEST_F(FreezeSpecConstantValueRemoveDecorationTest, - RemoveDecorationInstWithSpecId) { - std::vector text = { - // clang-format off - "OpCapability Shader", - "OpCapability Float64", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpSource GLSL 450", - "OpSourceExtension \"GL_GOOGLE_cpp_style_line_directive\"", - "OpSourceExtension \"GL_GOOGLE_include_directive\"", - "OpName %main \"main\"", - "OpDecorate %3 SpecId 200", - "OpDecorate %4 SpecId 201", - "OpDecorate %5 SpecId 202", - "OpDecorate %6 SpecId 203", - "%void = OpTypeVoid", - "%8 = OpTypeFunction %void", - "%int = OpTypeInt 32 1", - "%3 = OpSpecConstant %int 3", - "%float = OpTypeFloat 32", - "%4 = OpSpecConstant %float 3.1415", - "%double = OpTypeFloat 64", - "%5 = OpSpecConstant %double 3.14159265358979", - "%bool = OpTypeBool", - "%6 = OpSpecConstantTrue %bool", - "%13 = OpSpecConstantFalse %bool", - "%main = OpFunction %void None %8", - "%14 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - std::string expected_disassembly = SelectiveJoin(text, [](const char* line) { - return std::string(line).find("SpecId") != std::string::npos; - }); - std::vector> replacement_pairs = { - {"%3 = OpSpecConstant %int 3", "%int_3 = OpConstant %int 3"}, - {"%4 = OpSpecConstant %float 3.1415", - "%float_3_1415 = OpConstant %float 3.1415"}, - {"%5 = OpSpecConstant %double 3.14159265358979", - "%double_3_14159265358979 = OpConstant %double 3.14159265358979"}, - {"%6 = OpSpecConstantTrue ", "%true = OpConstantTrue "}, - {"%13 = OpSpecConstantFalse ", "%false = OpConstantFalse "}, - }; - for (auto& p : replacement_pairs) { - EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second)) - << "text:\n" - << expected_disassembly << "\n" - << "find_str:\n" - << p.first << "\n" - << "replace_str:\n" - << p.second << "\n"; - } - SinglePassRunAndCheck(JoinAllInsts(text), - expected_disassembly, - /* skip_nop = */ true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/function_test.cpp b/3rdparty/spirv-tools/test/opt/function_test.cpp deleted file mode 100644 index 38ab29876..000000000 --- a/3rdparty/spirv-tools/test/opt/function_test.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "function_utils.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::Eq; - -TEST(FunctionTest, IsNotRecursive) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 DescriptorSet 439418829 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%7 = OpTypeFunction %_struct_6 -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %12 -OpUnreachable -OpFunctionEnd -%12 = OpFunction %_struct_6 None %7 -%13 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - std::unique_ptr ctx = - spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto* func = spvtest::GetFunction(ctx->module(), 9); - EXPECT_FALSE(func->IsRecursive()); - - func = spvtest::GetFunction(ctx->module(), 12); - EXPECT_FALSE(func->IsRecursive()); -} - -TEST(FunctionTest, IsDirectlyRecursive) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 DescriptorSet 439418829 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%7 = OpTypeFunction %_struct_6 -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %9 -OpUnreachable -OpFunctionEnd -)"; - - std::unique_ptr ctx = - spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto* func = spvtest::GetFunction(ctx->module(), 9); - EXPECT_TRUE(func->IsRecursive()); -} - -TEST(FunctionTest, IsIndirectlyRecursive) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 DescriptorSet 439418829 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%7 = OpTypeFunction %_struct_6 -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %12 -OpUnreachable -OpFunctionEnd -%12 = OpFunction %_struct_6 None %7 -%13 = OpLabel -%14 = OpFunctionCall %_struct_6 %9 -OpUnreachable -OpFunctionEnd -)"; - - std::unique_ptr ctx = - spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto* func = spvtest::GetFunction(ctx->module(), 9); - EXPECT_TRUE(func->IsRecursive()); - - func = spvtest::GetFunction(ctx->module(), 12); - EXPECT_TRUE(func->IsRecursive()); -} - -TEST(FunctionTest, IsNotRecuriseCallingRecursive) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 DescriptorSet 439418829 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%7 = OpTypeFunction %_struct_6 -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %9 -OpUnreachable -OpFunctionEnd -)"; - - std::unique_ptr ctx = - spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto* func = spvtest::GetFunction(ctx->module(), 1); - EXPECT_FALSE(func->IsRecursive()); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/function_utils.h b/3rdparty/spirv-tools/test/opt/function_utils.h deleted file mode 100644 index 803cacdd5..000000000 --- a/3rdparty/spirv-tools/test/opt/function_utils.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2017 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. - -#ifndef TEST_OPT_FUNCTION_UTILS_H_ -#define TEST_OPT_FUNCTION_UTILS_H_ - -#include "source/opt/function.h" -#include "source/opt/module.h" - -namespace spvtest { - -inline spvtools::opt::Function* GetFunction(spvtools::opt::Module* module, - uint32_t id) { - for (spvtools::opt::Function& f : *module) { - if (f.result_id() == id) { - return &f; - } - } - return nullptr; -} - -inline const spvtools::opt::Function* GetFunction( - const spvtools::opt::Module* module, uint32_t id) { - for (const spvtools::opt::Function& f : *module) { - if (f.result_id() == id) { - return &f; - } - } - return nullptr; -} - -inline const spvtools::opt::BasicBlock* GetBasicBlock( - const spvtools::opt::Function* fn, uint32_t id) { - for (const spvtools::opt::BasicBlock& bb : *fn) { - if (bb.id() == id) { - return &bb; - } - } - return nullptr; -} - -} // namespace spvtest - -#endif // TEST_OPT_FUNCTION_UTILS_H_ diff --git a/3rdparty/spirv-tools/test/opt/generate_webgpu_initializers_test.cpp b/3rdparty/spirv-tools/test/opt/generate_webgpu_initializers_test.cpp deleted file mode 100644 index 4aab2ce21..000000000 --- a/3rdparty/spirv-tools/test/opt/generate_webgpu_initializers_test.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -typedef std::tuple GenerateWebGPUInitializersParam; - -using GlobalVariableTest = - PassTest<::testing::TestWithParam>; -using LocalVariableTest = - PassTest<::testing::TestWithParam>; - -using GenerateWebGPUInitializersTest = PassTest<::testing::Test>; - -void operator+=(std::vector& lhs, const char* rhs) { - lhs.push_back(rhs); -} - -void operator+=(std::vector& lhs, - const std::vector& rhs) { - lhs.reserve(lhs.size() + rhs.size()); - for (auto* c : rhs) lhs.push_back(c); -} - -std::string GetGlobalVariableTestString(std::string ptr_str, - std::string var_str, - std::string const_str = "") { - std::vector result = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - ptr_str.c_str()}; - // clang-format on - - if (!const_str.empty()) result += const_str.c_str(); - - result += { - // clang-format off - var_str.c_str(), - "%uint_0 = OpConstant %uint 0", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%1 = OpFunction %void None %7", - "%8 = OpLabel", - "OpStore %4 %uint_0", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - return JoinAllInsts(result); -} - -std::string GetPointerString(std::string storage_type) { - std::string result = "%_ptr_"; - result += storage_type + "_uint = OpTypePointer "; - result += storage_type + " %uint"; - return result; -} - -std::string GetGlobalVariableString(std::string storage_type, - bool initialized) { - std::string result = "%4 = OpVariable %_ptr_"; - result += storage_type + "_uint "; - result += storage_type; - if (initialized) result += " %9"; - return result; -} - -std::string GetUninitializedGlobalVariableTestString(std::string storage_type) { - return GetGlobalVariableTestString( - GetPointerString(storage_type), - GetGlobalVariableString(storage_type, false)); -} - -std::string GetNullConstantString() { return "%9 = OpConstantNull %uint"; } - -std::string GetInitializedGlobalVariableTestString(std::string storage_type) { - return GetGlobalVariableTestString( - GetPointerString(storage_type), - GetGlobalVariableString(storage_type, true), GetNullConstantString()); -} - -TEST_P(GlobalVariableTest, Check) { - std::string storage_class = std::get<0>(GetParam()); - bool changed = std::get<1>(GetParam()); - std::string input = GetUninitializedGlobalVariableTestString(storage_class); - std::string expected = - changed ? GetInitializedGlobalVariableTestString(storage_class) : input; - - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - GenerateWebGPUInitializers, GlobalVariableTest, - ::testing::ValuesIn(std::vector({ - std::make_tuple("Private", true), - std::make_tuple("Output", true), - std::make_tuple("Function", true), - std::make_tuple("UniformConstant", false), - std::make_tuple("Input", false), - std::make_tuple("Uniform", false), - std::make_tuple("Workgroup", false) - }))); -// clang-format on - -std::string GetLocalVariableTestString(std::string ptr_str, std::string var_str, - std::string const_str = "") { - std::vector result = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - ptr_str.c_str(), - "%uint_0 = OpConstant %uint 0", - "%void = OpTypeVoid", - "%6 = OpTypeFunction %void"}; - // clang-format on - - if (!const_str.empty()) result += const_str.c_str(); - - result += { - // clang-format off - "%1 = OpFunction %void None %6", - "%7 = OpLabel", - var_str.c_str(), - "OpStore %8 %uint_0" - // clang-format on - }; - return JoinAllInsts(result); -} - -std::string GetLocalVariableString(std::string storage_type, bool initialized) { - std::string result = "%8 = OpVariable %_ptr_"; - result += storage_type + "_uint "; - result += storage_type; - if (initialized) result += " %9"; - return result; -} - -std::string GetUninitializedLocalVariableTestString(std::string storage_type) { - return GetLocalVariableTestString( - GetPointerString(storage_type), - GetLocalVariableString(storage_type, false)); -} - -std::string GetInitializedLocalVariableTestString(std::string storage_type) { - return GetLocalVariableTestString(GetPointerString(storage_type), - GetLocalVariableString(storage_type, true), - GetNullConstantString()); -} - -TEST_P(LocalVariableTest, Check) { - std::string storage_class = std::get<0>(GetParam()); - bool changed = std::get<1>(GetParam()); - - std::string input = GetUninitializedLocalVariableTestString(storage_class); - std::string expected = - changed ? GetInitializedLocalVariableTestString(storage_class) : input; - - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - GenerateWebGPUInitializers, LocalVariableTest, - ::testing::ValuesIn(std::vector({ - std::make_tuple("Private", true), - std::make_tuple("Output", true), - std::make_tuple("Function", true), - std::make_tuple("UniformConstant", false), - std::make_tuple("Input", false), - std::make_tuple("Uniform", false), - std::make_tuple("Workgroup", false) - }))); -// clang-format on - -TEST_F(GenerateWebGPUInitializersTest, AlreadyInitializedUnchanged) { - std::vector spirv = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - "%_ptr_Private_uint = OpTypePointer Private %uint", - "%uint_0 = OpConstant %uint 0", - "%5 = OpVariable %_ptr_Private_uint Private %uint_0", - "%void = OpTypeVoid", - "%7 = OpTypeFunction %void", - "%1 = OpFunction %void None %7", - "%8 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - std::string str = JoinAllInsts(spirv); - - SinglePassRunAndCheck(str, str, - /* skip_nop = */ false); -} - -TEST_F(GenerateWebGPUInitializersTest, AmbigiousArrays) { - std::vector input_spirv = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - "%uint_2 = OpConstant %uint 2", - "%_arr_uint_uint_2 = OpTypeArray %uint %uint_2", - "%_arr_uint_uint_2_0 = OpTypeArray %uint %uint_2", - "%_ptr_Private__arr_uint_uint_2 = OpTypePointer Private %_arr_uint_uint_2", -"%_ptr_Private__arr_uint_uint_2_0 = OpTypePointer Private %_arr_uint_uint_2_0", - "%8 = OpConstantNull %_arr_uint_uint_2_0", - "%9 = OpVariable %_ptr_Private__arr_uint_uint_2 Private", - "%10 = OpVariable %_ptr_Private__arr_uint_uint_2_0 Private %8", - "%void = OpTypeVoid", - "%12 = OpTypeFunction %void", - "%1 = OpFunction %void None %12", - "%13 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - std::string input_str = JoinAllInsts(input_spirv); - - std::vector expected_spirv = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - "%uint_2 = OpConstant %uint 2", - "%_arr_uint_uint_2 = OpTypeArray %uint %uint_2", - "%_arr_uint_uint_2_0 = OpTypeArray %uint %uint_2", - "%_ptr_Private__arr_uint_uint_2 = OpTypePointer Private %_arr_uint_uint_2", -"%_ptr_Private__arr_uint_uint_2_0 = OpTypePointer Private %_arr_uint_uint_2_0", - "%8 = OpConstantNull %_arr_uint_uint_2_0", - "%14 = OpConstantNull %_arr_uint_uint_2", - "%9 = OpVariable %_ptr_Private__arr_uint_uint_2 Private %14", - "%10 = OpVariable %_ptr_Private__arr_uint_uint_2_0 Private %8", - "%void = OpTypeVoid", - "%12 = OpTypeFunction %void", - "%1 = OpFunction %void None %12", - "%13 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - std::string expected_str = JoinAllInsts(expected_spirv); - - SinglePassRunAndCheck(input_str, expected_str, - /* skip_nop = */ false); -} - -TEST_F(GenerateWebGPUInitializersTest, AmbigiousStructs) { - std::vector input_spirv = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - "%_struct_3 = OpTypeStruct %uint", - "%_struct_4 = OpTypeStruct %uint", -"%_ptr_Private__struct_3 = OpTypePointer Private %_struct_3", -"%_ptr_Private__struct_4 = OpTypePointer Private %_struct_4", - "%7 = OpConstantNull %_struct_3", - "%8 = OpVariable %_ptr_Private__struct_3 Private %7", - "%9 = OpVariable %_ptr_Private__struct_4 Private", - "%void = OpTypeVoid", - "%11 = OpTypeFunction %void", - "%1 = OpFunction %void None %11", - "%12 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - std::string input_str = JoinAllInsts(input_spirv); - - std::vector expected_spirv = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - "%_struct_3 = OpTypeStruct %uint", - "%_struct_4 = OpTypeStruct %uint", -"%_ptr_Private__struct_3 = OpTypePointer Private %_struct_3", -"%_ptr_Private__struct_4 = OpTypePointer Private %_struct_4", - "%7 = OpConstantNull %_struct_3", - "%8 = OpVariable %_ptr_Private__struct_3 Private %7", - "%13 = OpConstantNull %_struct_4", - "%9 = OpVariable %_ptr_Private__struct_4 Private %13", - "%void = OpTypeVoid", - "%11 = OpTypeFunction %void", - "%1 = OpFunction %void None %11", - "%12 = OpLabel", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - std::string expected_str = JoinAllInsts(expected_spirv); - - SinglePassRunAndCheck(input_str, expected_str, - /* skip_nop = */ false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/graphics_robust_access_test.cpp b/3rdparty/spirv-tools/test/opt/graphics_robust_access_test.cpp deleted file mode 100644 index d38571e79..000000000 --- a/3rdparty/spirv-tools/test/opt/graphics_robust_access_test.cpp +++ /dev/null @@ -1,1401 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "pass_fixture.h" -#include "pass_utils.h" -#include "source/opt/graphics_robust_access_pass.h" - -namespace { - -using namespace spvtools; - -using opt::GraphicsRobustAccessPass; -using GraphicsRobustAccessTest = opt::PassTest<::testing::Test>; - -// Test incompatible module, determined at module-level. - -TEST_F(GraphicsRobustAccessTest, FailNotShader) { - const std::string text = R"( -; CHECK: Can only process Shader modules -OpCapability Kernel -)"; - - SinglePassRunAndFail(text); -} - -TEST_F(GraphicsRobustAccessTest, FailCantProcessVariablePointers) { - const std::string text = R"( -; CHECK: Can't process modules with VariablePointers capability -OpCapability VariablePointers -)"; - - SinglePassRunAndFail(text); -} - -TEST_F(GraphicsRobustAccessTest, FailCantProcessVariablePointersStorageBuffer) { - const std::string text = R"( -; CHECK: Can't process modules with VariablePointersStorageBuffer capability -OpCapability VariablePointersStorageBuffer -)"; - - SinglePassRunAndFail(text); -} - -TEST_F(GraphicsRobustAccessTest, FailCantProcessRuntimeDescriptorArrayEXT) { - const std::string text = R"( -; CHECK: Can't process modules with RuntimeDescriptorArrayEXT capability -OpCapability RuntimeDescriptorArrayEXT -)"; - - SinglePassRunAndFail(text); -} - -TEST_F(GraphicsRobustAccessTest, FailCantProcessPhysical32AddressingModel) { - const std::string text = R"( -; CHECK: Addressing model must be Logical. Found OpMemoryModel Physical32 OpenCL -OpCapability Shader -OpMemoryModel Physical32 OpenCL -)"; - - SinglePassRunAndFail(text); -} - -TEST_F(GraphicsRobustAccessTest, FailCantProcessPhysical64AddressingModel) { - const std::string text = R"( -; CHECK: Addressing model must be Logical. Found OpMemoryModel Physical64 OpenCL -OpCapability Shader -OpMemoryModel Physical64 OpenCL -)"; - - SinglePassRunAndFail(text); -} - -TEST_F(GraphicsRobustAccessTest, - FailCantProcessPhysicalStorageBuffer64EXTAddressingModel) { - const std::string text = R"( -; CHECK: Addressing model must be Logical. Found OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpCapability Shader -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -)"; - - SinglePassRunAndFail(text); -} - -// Test access chains - -// Returns the names of access chain instructions handled by the pass. -// For the purposes of this pass, regular and in-bounds access chains are the -// same.) -std::vector AccessChains() { - return {"OpAccessChain", "OpInBoundsAccessChain"}; -} - -std::string ShaderPreamble() { - return R"( - OpCapability Shader - OpMemoryModel Logical Simple - OpEntryPoint GLCompute %main "main" -)"; -} - -std::string ShaderPreamble(const std::vector& names) { - std::ostringstream os; - os << ShaderPreamble(); - for (auto& name : names) { - os << " OpName %" << name << " \"" << name << "\"\n"; - } - return os.str(); -} - -std::string ShaderPreambleAC() { - return ShaderPreamble({"ac", "ptr_ty", "var"}); -} - -std::string ShaderPreambleAC(const std::vector& names) { - auto names2 = names; - names2.push_back("ac"); - names2.push_back("ptr_ty"); - names2.push_back("var"); - return ShaderPreamble(names2); -} - -std::string DecoSSBO() { - return R"( - OpDecorate %ssbo_s BufferBlock - OpMemberDecorate %ssbo_s 0 Offset 0 - OpMemberDecorate %ssbo_s 1 Offset 4 - OpMemberDecorate %ssbo_s 2 Offset 16 - OpDecorate %var DescriptorSet 0 - OpDecorate %var Binding 0 -)"; -} - -std::string TypesVoid() { - return R"( - %void = OpTypeVoid - %void_fn = OpTypeFunction %void -)"; -} - -std::string TypesInt() { - return R"( - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 -)"; -} - -std::string TypesFloat() { - return R"( - %float = OpTypeFloat 32 -)"; -} - -std::string TypesShort() { - return R"( - %ushort = OpTypeInt 16 0 - %short = OpTypeInt 16 1 -)"; -} - -std::string TypesLong() { - return R"( - %ulong = OpTypeInt 64 0 - %long = OpTypeInt 64 1 -)"; -} - -std::string MainPrefix() { - return R"( - %main = OpFunction %void None %void_fn - %entry = OpLabel -)"; -} - -std::string MainSuffix() { - return R"( - OpReturn - OpFunctionEnd -)"; -} - -std::string ACCheck(const std::string& access_chain_inst, - const std::string& original, - const std::string& transformed) { - return "\n ; CHECK: %ac = " + access_chain_inst + " %ptr_ty %var" + - (transformed.empty() ? "" : " ") + transformed + - "\n ; CHECK-NOT: " + access_chain_inst + - "\n ; CHECK-NEXT: OpReturn" - "\n %ac = " + - access_chain_inst + " %ptr_ty %var " + (original.empty() ? "" : " ") + - original + "\n"; -} - -std::string ACCheckFail(const std::string& access_chain_inst, - const std::string& original, - const std::string& transformed) { - return "\n ; CHECK: %ac = " + access_chain_inst + " %ptr_ty %var" + - (transformed.empty() ? "" : " ") + transformed + - "\n ; CHECK-NOT: " + access_chain_inst + - "\n ; CHECK-NOT: OpReturn" - "\n %ac = " + - access_chain_inst + " %ptr_ty %var " + (original.empty() ? "" : " ") + - original + "\n"; -} - -// Access chain into: -// Vector -// Vector sizes 2, 3, 4 -// Matrix -// Matrix columns 2, 4 -// Component is vector 2, 4 -// Array -// Struct -// TODO(dneto): RuntimeArray - -TEST_F(GraphicsRobustAccessTest, ACVectorLeastInboundConstantUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"( - %uvec2 = OpTypeVector %uint 2 - %var_ty = OpTypePointer Function %uvec2 - %ptr_ty = OpTypePointer Function %uint - %uint_0 = OpConstant %uint 0 - )" - << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%uint_0", "%uint_0") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorMostInboundConstantUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"( - %v4uint = OpTypeVector %uint 4 - %var_ty = OpTypePointer Function %v4uint - %ptr_ty = OpTypePointer Function %uint - %uint_3 = OpConstant %uint 3 - )" - << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%uint_3", "%uint_3") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorExcessConstantClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"( - %v4uint = OpTypeVector %uint 4 - %var_ty = OpTypePointer Function %v4uint - %ptr_ty = OpTypePointer Function %uint - %uint_4 = OpConstant %uint 4 - )" - << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%uint_4", "%int_3") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorNegativeConstantClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"( - %v4uint = OpTypeVector %uint 4 - %var_ty = OpTypePointer Function %v4uint - %ptr_ty = OpTypePointer Function %uint - %int_n1 = OpConstant %int -1 - )" - << MainPrefix() << R"( - ; CHECK: %int_0 = OpConstant %int 0 - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%int_n1", "%int_0") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -// Like the previous test, but ensures the pass knows how to modify an index -// which does not come first in the access chain. -TEST_F(GraphicsRobustAccessTest, ACVectorInArrayNegativeConstantClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"( - %v4uint = OpTypeVector %uint 4 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %arr = OpTypeArray %v4uint %uint_2 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %uint - %int_n1 = OpConstant %int -1 - )" - << MainPrefix() << R"( - ; CHECK: %int_0 = OpConstant %int 0 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%uint_1 %int_n1", "%uint_1 %int_0") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorGeneralClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() << R"( - %v4uint = OpTypeVector %uint 4 - %var_ty = OpTypePointer Function %v4uint - %ptr_ty = OpTypePointer Function %uint - %i = OpUndef %int)" - << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_3 = OpConstant %int 3 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_3 - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorGeneralShortClamped) { - // Show that signed 16 bit integers are clamped as well. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesShort() << - R"( - %v4short = OpTypeVector %short 4 - %var_ty = OpTypePointer Function %v4short - %ptr_ty = OpTypePointer Function %short - %i = OpUndef %short)" - << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK-DAG: %short_0 = OpConstant %short 0 - ; CHECK-DAG: %short_3 = OpConstant %short 3 - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %short %[[GLSLSTD450]] SClamp %i %short_0 %short_3 - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorGeneralUShortClamped) { - // Show that unsigned 16 bit integers are clamped as well. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesShort() << - R"( - %v4ushort = OpTypeVector %ushort 4 - %var_ty = OpTypePointer Function %v4ushort - %ptr_ty = OpTypePointer Function %ushort - %i = OpUndef %ushort)" - << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK-DAG: %short_0 = OpConstant %short 0 - ; CHECK-DAG: %short_3 = OpConstant %short 3 - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %ushort %[[GLSLSTD450]] SClamp %i %short_0 %short_3 - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorGeneralLongClamped) { - // Show that signed 64 bit integers are clamped as well. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesLong() << - R"( - %v4long = OpTypeVector %long 4 - %var_ty = OpTypePointer Function %v4long - %ptr_ty = OpTypePointer Function %long - %i = OpUndef %long)" - << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK-DAG: %long_0 = OpConstant %long 0 - ; CHECK-DAG: %long_3 = OpConstant %long 3 - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %long %[[GLSLSTD450]] SClamp %i %long_0 %long_3 - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACVectorGeneralULongClamped) { - // Show that unsigned 64 bit integers are clamped as well. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesLong() << - R"( - %v4ulong = OpTypeVector %ulong 4 - %var_ty = OpTypePointer Function %v4ulong - %ptr_ty = OpTypePointer Function %ulong - %i = OpUndef %ulong)" - << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK-DAG: %long_0 = OpConstant %long 0 - ; CHECK-DAG: %long_3 = OpConstant %long 3 - ; CHECK-NOT: = OpTypeInt 32 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %long_0 %long_3 - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACMatrixLeastInboundConstantUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %v2float = OpTypeVector %float 2 - %mat4v2float = OpTypeMatrix %v2float 4 - %var_ty = OpTypePointer Function %mat4v2float - %ptr_ty = OpTypePointer Function %float - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%uint_0 %uint_1", "%uint_0 %uint_1") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACMatrixMostInboundConstantUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %v2float = OpTypeVector %float 2 - %mat4v2float = OpTypeMatrix %v2float 4 - %var_ty = OpTypePointer Function %mat4v2float - %ptr_ty = OpTypePointer Function %float - %uint_1 = OpConstant %uint 1 - %uint_3 = OpConstant %uint 3 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%uint_3 %uint_1", "%uint_3 %uint_1") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACMatrixExcessConstantClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %v2float = OpTypeVector %float 2 - %mat4v2float = OpTypeMatrix %v2float 4 - %var_ty = OpTypePointer Function %mat4v2float - %ptr_ty = OpTypePointer Function %float - %uint_1 = OpConstant %uint 1 - %uint_4 = OpConstant %uint 4 - )" << MainPrefix() << R"( - ; CHECK: %int_3 = OpConstant %int 3 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%uint_4 %uint_1", "%int_3 %uint_1") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACMatrixNegativeConstantClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %v2float = OpTypeVector %float 2 - %mat4v2float = OpTypeMatrix %v2float 4 - %var_ty = OpTypePointer Function %mat4v2float - %ptr_ty = OpTypePointer Function %float - %uint_1 = OpConstant %uint 1 - %int_n1 = OpConstant %int -1 - )" << MainPrefix() << R"( - ; CHECK: %int_0 = OpConstant %int 0 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%int_n1 %uint_1", "%int_0 %uint_1") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACMatrixGeneralClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %v2float = OpTypeVector %float 2 - %mat4v2float = OpTypeMatrix %v2float 4 - %var_ty = OpTypePointer Function %mat4v2float - %ptr_ty = OpTypePointer Function %float - %uint_1 = OpConstant %uint 1 - %i = OpUndef %int - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_3 = OpConstant %int 3 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_3 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i %uint_1", "%[[clamp]] %uint_1") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayLeastInboundConstantUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %uint_200 = OpConstant %uint 200 - %arr = OpTypeArray %float %uint_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %int_0 = OpConstant %int 0 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%int_0", "%int_0") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayMostInboundConstantUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %uint_200 = OpConstant %uint 200 - %arr = OpTypeArray %float %uint_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %int_199 = OpConstant %int 199 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%int_199", "%int_199") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %uint_200 = OpConstant %uint 200 - %arr = OpTypeArray %float %uint_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %int - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_199 = OpConstant %int 199 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_199 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralShortIndexUIntBoundsClamped) { - // Index is signed short, array bounds overflows the index type. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesShort() << TypesFloat() << R"( - %uint_70000 = OpConstant %uint 70000 ; overflows 16bits - %arr = OpTypeArray %float %uint_70000 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %short - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_69999 = OpConstant %int 69999 - ; CHECK: OpLabel - ; CHECK: %[[i_ext:\w+]] = OpSConvert %uint %i - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %int_0 %int_69999 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralUShortIndexIntBoundsClamped) { - // Index is unsigned short, array bounds overflows the index type. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesShort() << TypesFloat() << R"( - %int_70000 = OpConstant %int 70000 ; overflows 16bits - %arr = OpTypeArray %float %int_70000 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %ushort - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_69999 = OpConstant %int 69999 - ; CHECK: OpLabel - ; CHECK: %[[i_ext:\w+]] = OpUConvert %uint %i - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %int_0 %int_69999 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralUIntIndexShortBoundsClamped) { - // Signed int index i is wider than the array bounds type. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesShort() << TypesFloat() << R"( - %short_200 = OpConstant %short 200 - %arr = OpTypeArray %float %short_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %uint - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_199 = OpConstant %int 199 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %i %int_0 %int_199 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralIntIndexUShortBoundsClamped) { - // Unsigned int index i is wider than the array bounds type. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesShort() << TypesFloat() << R"( - %ushort_200 = OpConstant %ushort 200 - %arr = OpTypeArray %float %ushort_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %int - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_199 = OpConstant %int 199 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_199 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralLongIndexUIntBoundsClamped) { - // Signed long index i is wider than the array bounds type. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesLong() << TypesFloat() << R"( - %uint_200 = OpConstant %uint 200 - %arr = OpTypeArray %float %uint_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %long - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %long_0 = OpConstant %long 0 - ; CHECK-DAG: %long_199 = OpConstant %long 199 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %long %[[GLSLSTD450]] SClamp %i %long_0 %long_199 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayGeneralULongIndexIntBoundsClamped) { - // Unsigned long index i is wider than the array bounds type. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesLong() << TypesFloat() << R"( - %int_200 = OpConstant %int 200 - %arr = OpTypeArray %float %int_200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %ulong - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %long_0 = OpConstant %long 0 - ; CHECK-DAG: %long_199 = OpConstant %long 199 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %long_0 %long_199 - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, - ACArrayGeneralShortIndeArrayBiggerThanShortMaxClipsToShortIntMax) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesShort() - << TypesInt() << TypesFloat() << R"( - %uint_50000 = OpConstant %uint 50000 - %arr = OpTypeArray %float %uint_50000 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %ushort - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %short_0 = OpConstant %short 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %short 32767 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %ushort %[[GLSLSTD450]] SClamp %i %short_0 %[[intmax]] - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, - ACArrayGeneralIntIndexArrayBiggerThanIntMaxClipsToSignedIntMax) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %uint_3000000000 = OpConstant %uint 3000000000 - %arr = OpTypeArray %float %uint_3000000000 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %uint - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %i %int_0 %[[intmax]] - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, - ACArrayGeneralLongIndexArrayBiggerThanLongMaxClipsToSignedLongMax) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64\n" - << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() - << TypesLong() - << TypesFloat() - // 2^63 == 9,223,372,036,854,775,807 - << R"( - %ulong_9223372036854775999 = OpConstant %ulong 9223372036854775999 - %arr = OpTypeArray %float %ulong_9223372036854775999 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %ulong - )" - << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %long_0 = OpConstant %long 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %long 9223372036854775807 - ; CHECK: OpLabel - ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %long_0 %[[intmax]] - %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArraySpecIdSizedAlwaysClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"spec200"}) << R"( - OpDecorate %spec200 SpecId 0 )" << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %spec200 = OpSpecConstant %int 200 - %arr = OpTypeArray %float %spec200 - %var_ty = OpTypePointer Function %arr - %ptr_ty = OpTypePointer Function %float - %uint_5 = OpConstant %uint 5 - )" << MainPrefix() << R"( - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %uint_0 = OpConstant %uint 0 - ; CHECK-DAG: %uint_1 = OpConstant %uint 1 - ; CHECK-DAG: %[[uint_intmax:\w+]] = OpConstant %uint 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[max:\w+]] = OpISub %uint %spec200 %uint_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[uint_intmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %uint_5 %uint_0 %[[smin]] - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%uint_5", "%[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructLeastUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - %int_0 = OpConstant %int 0 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%int_0", "%int_0") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructMostUntouched) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - %int_2 = OpConstant %int 2 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function)" - << ACCheck(ac, "%int_2", "%int_2") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructSpecConstantFail) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"struct", "spec200"}) - << "OpDecorate %spec200 SpecId 0\n" - << - - TypesVoid() << TypesInt() << TypesFloat() << R"( - %spec200 = OpSpecConstant %int 200 - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function - ; CHECK: Member index into struct is not a constant integer - ; CHECK-SAME: %spec200 = OpSpecConstant %int 200 - )" - << ACCheckFail(ac, "%spec200", "%spec200") << MainSuffix(); - SinglePassRunAndFail(shaders.str()); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructFloatConstantFail) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"struct"}) << - - TypesVoid() << TypesInt() << TypesFloat() << R"( - %float_2 = OpConstant %float 2 - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function - ; CHECK: Member index into struct is not a constant integer - ; CHECK-SAME: %float_2 = OpConstant %float 2 - )" - << ACCheckFail(ac, "%float_2", "%float_2") << MainSuffix(); - SinglePassRunAndFail(shaders.str()); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructNonConstantFail) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"struct", "i"}) << - - TypesVoid() << TypesInt() << TypesFloat() << R"( - %float_2 = OpConstant %float 2 - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - %i = OpUndef %int - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function - ; CHECK: Member index into struct is not a constant integer - ; CHECK-SAME: %i = OpUndef %int - )" - << ACCheckFail(ac, "%i", "%i") << MainSuffix(); - SinglePassRunAndFail(shaders.str()); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructExcessFail) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"struct", "i"}) << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - %i = OpConstant %int 4 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function - ; CHECK: Member index 4 is out of bounds for struct type: - ; CHECK-SAME: %struct = OpTypeStruct %float %float %float - )" - << ACCheckFail(ac, "%i", "%i") << MainSuffix(); - SinglePassRunAndFail(shaders.str()); - } -} - -TEST_F(GraphicsRobustAccessTest, ACStructNegativeFail) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"struct", "i"}) << TypesVoid() << TypesInt() - << TypesFloat() << R"( - %struct = OpTypeStruct %float %float %float - %var_ty = OpTypePointer Function %struct - %ptr_ty = OpTypePointer Function %float - %i = OpConstant %int -1 - )" << MainPrefix() << R"( - %var = OpVariable %var_ty Function - ; CHECK: Member index -1 is out of bounds for struct type: - ; CHECK-SAME: %struct = OpTypeStruct %float %float %float - )" - << ACCheckFail(ac, "%i", "%i") << MainSuffix(); - SinglePassRunAndFail(shaders.str()); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayLeastInboundClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC() << "OpDecorate %rtarr ArrayStride 4 " - << DecoSSBO() << TypesVoid() << TypesInt() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %uint %uint %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_0 = OpConstant %int 0 - %int_2 = OpConstant %int 2 - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_1 = OpConstant %int 1 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %int_0 %int_0 %[[smin]] - )" - << MainPrefix() << ACCheck(ac, "%int_2 %int_0", "%int_2 %[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralShortIndexClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 " - << DecoSSBO() << TypesVoid() << TypesShort() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %short %short %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %short_2 = OpConstant %short 2 - %i = OpUndef %short - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK: %uint = OpTypeInt 32 0 - ; CHECK-DAG: %uint_1 = OpConstant %uint 1 - ; CHECK-DAG: %uint_0 = OpConstant %uint 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %uint 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK-DAG: %[[max:\w+]] = OpISub %uint %[[arrlen]] %uint_1 - ; CHECK-DAG: %[[i_ext:\w+]] = OpSConvert %uint %i - ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %uint_0 %[[smin]] - )" - << MainPrefix() << ACCheck(ac, "%short_2 %i", "%short_2 %[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralUShortIndexClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int16\n" - << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 " - << DecoSSBO() << TypesVoid() << TypesShort() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %short %short %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %short_2 = OpConstant %short 2 - %i = OpUndef %ushort - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK: %uint = OpTypeInt 32 0 - ; CHECK-DAG: %uint_1 = OpConstant %uint 1 - ; CHECK-DAG: %uint_0 = OpConstant %uint 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %uint 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK-DAG: %[[max:\w+]] = OpISub %uint %[[arrlen]] %uint_1 - ; CHECK-DAG: %[[i_ext:\w+]] = OpSConvert %uint %i - ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %uint_0 %[[smin]] - )" - << MainPrefix() << ACCheck(ac, "%short_2 %i", "%short_2 %[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralIntIndexClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 " - << DecoSSBO() << TypesVoid() << TypesInt() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %int %int %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_2 = OpConstant %int 2 - %i = OpUndef %int - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_1 = OpConstant %int 1 - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %[[smin]] - )" - << MainPrefix() << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralUIntIndexClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 " - << DecoSSBO() << TypesVoid() << TypesInt() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %int %int %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_2 = OpConstant %int 2 - %i = OpUndef %uint - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %uint_1 = OpConstant %uint 1 - ; CHECK-DAG: %uint_0 = OpConstant %uint 0 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %uint 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK: %[[max:\w+]] = OpISub %uint %[[arrlen]] %uint_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %i %uint_0 %[[smin]] - )" - << MainPrefix() << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralLongIndexClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64" << ShaderPreambleAC({"i"}) - << "OpDecorate %rtarr ArrayStride 4 " << DecoSSBO() << TypesVoid() - << TypesInt() << TypesLong() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %int %int %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_2 = OpConstant %int 2 - %i = OpUndef %long - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %long_0 = OpConstant %long 0 - ; CHECK-DAG: %long_1 = OpConstant %long 1 - ; CHECK-DAG: %[[longmax:\w+]] = OpConstant %long 9223372036854775807 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK: %[[arrlen_ext:\w+]] = OpUConvert %ulong %[[arrlen]] - ; CHECK: %[[max:\w+]] = OpISub %long %[[arrlen_ext]] %long_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %long %[[GLSLSTD450]] UMin %[[max]] %[[longmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %long %[[GLSLSTD450]] SClamp %i %long_0 %[[smin]] - )" << MainPrefix() - << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralULongIndexClamped) { - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << "OpCapability Int64" << ShaderPreambleAC({"i"}) - << "OpDecorate %rtarr ArrayStride 4 " << DecoSSBO() << TypesVoid() - << TypesInt() << TypesLong() << TypesFloat() << R"( - %rtarr = OpTypeRuntimeArray %float - %ssbo_s = OpTypeStruct %int %int %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_2 = OpConstant %int 2 - %i = OpUndef %ulong - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %ulong_0 = OpConstant %ulong 0 - ; CHECK-DAG: %ulong_1 = OpConstant %ulong 1 - ; CHECK-DAG: %[[longmax:\w+]] = OpConstant %ulong 9223372036854775807 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK: %[[arrlen_ext:\w+]] = OpUConvert %ulong %[[arrlen]] - ; CHECK: %[[max:\w+]] = OpISub %ulong %[[arrlen_ext]] %ulong_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] UMin %[[max]] %[[longmax]] - ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %ulong_0 %[[smin]] - )" << MainPrefix() - << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]") << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACRTArrayStructVectorElem) { - // The point of this test is that the access chain can have indices past the - // index into the runtime array. For good measure, the index into the final - // struct is out of bounds. We have to clamp that index too. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i", "j"}) - << "OpDecorate %rtarr ArrayStride 32\n" - << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n" - << "OpMemberDecorate %rtelem 1 Offset 16\n" - << TypesVoid() << TypesInt() << TypesFloat() << R"( - %v4float = OpTypeVector %float 4 - %rtelem = OpTypeStruct %v4float %v4float - %rtarr = OpTypeRuntimeArray %rtelem - %ssbo_s = OpTypeStruct %int %int %rtarr - %var_ty = OpTypePointer Uniform %ssbo_s - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %i = OpUndef %int - %j = OpUndef %int - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_3 = OpConstant %int 3 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2 - ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %[[smin]] - ; CHECK: %[[clamp_j:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %j %int_0 %int_3 - )" << MainPrefix() - << ACCheck(ac, "%int_2 %i %int_1 %j", - "%int_2 %[[clamp_i]] %int_1 %[[clamp_j]]") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACArrayRTArrayStructVectorElem) { - // Now add an additional level of arrays around the Block-decorated struct. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i", "ssbo_s"}) - << "OpDecorate %rtarr ArrayStride 32\n" - << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n" - << "OpMemberDecorate %rtelem 1 Offset 16\n" - << TypesVoid() << TypesInt() << TypesFloat() << R"( - %v4float = OpTypeVector %float 4 - %rtelem = OpTypeStruct %v4float %v4float - %rtarr = OpTypeRuntimeArray %rtelem - %ssbo_s = OpTypeStruct %int %int %rtarr - %arr_size = OpConstant %int 10 - %arr_ssbo = OpTypeArray %ssbo_s %arr_size - %var_ty = OpTypePointer Uniform %arr_ssbo - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %int_17 = OpConstant %int 17 - %i = OpUndef %int - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %[[ssbo_p:\w+]] = OpTypePointer Uniform %ssbo_s - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_9 = OpConstant %int 9 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; This access chain is manufatured only so we can compute the array length. - ; Note that the %int_9 is already clamped - ; CHECK: %[[ssbo_base:\w+]] = )" << ac - << R"( %[[ssbo_p]] %var %int_9 - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %[[ssbo_base]] 2 - ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %[[smin]] - )" << MainPrefix() - << ACCheck(ac, "%int_17 %int_2 %i %int_1 %int_2", - "%int_9 %int_2 %[[clamp_i]] %int_1 %int_2") - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, ACSplitACArrayRTArrayStructVectorElem) { - // Split the address calculation across two access chains. Force - // the transform to walk up the access chains to find the base variable. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i", "j", "k", "ssbo_s", "ssbo_pty", - "rtarr_pty", "ac_ssbo", "ac_rtarr"}) - << "OpDecorate %rtarr ArrayStride 32\n" - << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n" - << "OpMemberDecorate %rtelem 1 Offset 16\n" - << TypesVoid() << TypesInt() << TypesFloat() << R"( - %v4float = OpTypeVector %float 4 - %rtelem = OpTypeStruct %v4float %v4float - %rtarr = OpTypeRuntimeArray %rtelem - %ssbo_s = OpTypeStruct %int %int %rtarr - %arr_size = OpConstant %int 10 - %arr_ssbo = OpTypeArray %ssbo_s %arr_size - %var_ty = OpTypePointer Uniform %arr_ssbo - %ssbo_pty = OpTypePointer Uniform %ssbo_s - %rtarr_pty = OpTypePointer Uniform %rtarr - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %i = OpUndef %int - %j = OpUndef %int - %k = OpUndef %int - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_9 = OpConstant %int 9 - ; CHECK-DAG: %int_3 = OpConstant %int 3 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_9 - ; CHECK: %ac_ssbo = )" << ac - << R"( %ssbo_pty %var %[[clamp_i]] - ; CHECK: %ac_rtarr = )" - << ac << R"( %rtarr_pty %ac_ssbo %int_2 - - ; This is the interesting bit. This array length is needed for an OpAccessChain - ; computing %ac, but the algorithm had to track back through %ac_rtarr's - ; definition to find the base pointer %ac_ssbo. - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %ac_ssbo 2 - ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp_j:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %j %int_0 %[[smin]] - ; CHECK: %[[clamp_k:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %k %int_0 %int_3 - ; CHECK: %ac = )" << ac - << R"( %ptr_ty %ac_rtarr %[[clamp_j]] %int_1 %[[clamp_k]] - ; CHECK-NOT: AccessChain - )" << MainPrefix() - << "%ac_ssbo = " << ac << " %ssbo_pty %var %i\n" - << "%ac_rtarr = " << ac << " %rtarr_pty %ac_ssbo %int_2\n" - << "%ac = " << ac << " %ptr_ty %ac_rtarr %j %int_1 %k\n" - - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -TEST_F(GraphicsRobustAccessTest, - ACSplitACArrayRTArrayStructVectorElemAcrossBasicBlocks) { - // Split the address calculation across two access chains. Force - // the transform to walk up the access chains to find the base variable. - // This time, put the different access chains in different basic blocks. - // This sanity checks that we keep the instruction-to-block mapping - // consistent. - for (auto* ac : AccessChains()) { - std::ostringstream shaders; - shaders << ShaderPreambleAC({"i", "j", "k", "bb1", "bb2", "ssbo_s", - "ssbo_pty", "rtarr_pty", "ac_ssbo", - "ac_rtarr"}) - << "OpDecorate %rtarr ArrayStride 32\n" - << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n" - << "OpMemberDecorate %rtelem 1 Offset 16\n" - << TypesVoid() << TypesInt() << TypesFloat() << R"( - %v4float = OpTypeVector %float 4 - %rtelem = OpTypeStruct %v4float %v4float - %rtarr = OpTypeRuntimeArray %rtelem - %ssbo_s = OpTypeStruct %int %int %rtarr - %arr_size = OpConstant %int 10 - %arr_ssbo = OpTypeArray %ssbo_s %arr_size - %var_ty = OpTypePointer Uniform %arr_ssbo - %ssbo_pty = OpTypePointer Uniform %ssbo_s - %rtarr_pty = OpTypePointer Uniform %rtarr - %ptr_ty = OpTypePointer Uniform %float - %var = OpVariable %var_ty Uniform - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %i = OpUndef %int - %j = OpUndef %int - %k = OpUndef %int - ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450" - ; CHECK-DAG: %int_0 = OpConstant %int 0 - ; CHECK-DAG: %int_9 = OpConstant %int 9 - ; CHECK-DAG: %int_3 = OpConstant %int 3 - ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647 - ; CHECK: OpLabel - ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_9 - ; CHECK: %ac_ssbo = )" << ac - << R"( %ssbo_pty %var %[[clamp_i]] - ; CHECK: %bb1 = OpLabel - ; CHECK: %ac_rtarr = )" - << ac << R"( %rtarr_pty %ac_ssbo %int_2 - ; CHECK: %bb2 = OpLabel - - ; This is the interesting bit. This array length is needed for an OpAccessChain - ; computing %ac, but the algorithm had to track back through %ac_rtarr's - ; definition to find the base pointer %ac_ssbo. - ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %ac_ssbo 2 - ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1 - ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]] - ; CHECK: %[[clamp_j:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %j %int_0 %[[smin]] - ; CHECK: %[[clamp_k:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %k %int_0 %int_3 - ; CHECK: %ac = )" << ac - << R"( %ptr_ty %ac_rtarr %[[clamp_j]] %int_1 %[[clamp_k]] - ; CHECK-NOT: AccessChain - )" << MainPrefix() - << "%ac_ssbo = " << ac << " %ssbo_pty %var %i\n" - << "OpBranch %bb1\n%bb1 = OpLabel\n" - << "%ac_rtarr = " << ac << " %rtarr_pty %ac_ssbo %int_2\n" - << "OpBranch %bb2\n%bb2 = OpLabel\n" - << "%ac = " << ac << " %ptr_ty %ac_rtarr %j %int_1 %k\n" - - << MainSuffix(); - SinglePassRunAndMatch(shaders.str(), true); - } -} - -// TODO(dneto): Test access chain index wider than 64 bits? -// TODO(dneto): Test struct access chain index wider than 64 bits? -// TODO(dneto): OpImageTexelPointer -// - all Dim types: 1D 2D Cube 3D Rect Buffer -// - all Dim types that can be arrayed: 1D 2D 3D -// - sample index: set to 0 if not multisampled -// - Dim (2D, Cube Rect} with multisampling -// -1 0 max excess -// TODO(dneto): Test OpImageTexelPointer with coordinate component index other -// than 32 bits. - -} // namespace diff --git a/3rdparty/spirv-tools/test/opt/if_conversion_test.cpp b/3rdparty/spirv-tools/test/opt/if_conversion_test.cpp deleted file mode 100644 index aa5adea6e..000000000 --- a/3rdparty/spirv-tools/test/opt/if_conversion_test.cpp +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using IfConversionTest = PassTest<::testing::Test>; - -TEST_F(IfConversionTest, TestSimpleIfThenElse) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHECK-NOT: OpPhi -; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1 -; CHECK OpStore {{%\w+}} [[sel]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%11 = OpTypeFunction %void -%1 = OpFunction %void None %11 -%12 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %true %15 %16 -%15 = OpLabel -OpBranch %14 -%16 = OpLabel -OpBranch %14 -%14 = OpLabel -%18 = OpPhi %uint %uint_0 %15 %uint_1 %16 -OpStore %2 %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, TestSimpleHalfIfTrue) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHECK-NOT: OpPhi -; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1 -; CHECK OpStore {{%\w+}} [[sel]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%11 = OpTypeFunction %void -%1 = OpFunction %void None %11 -%12 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %true %15 %14 -%15 = OpLabel -OpBranch %14 -%14 = OpLabel -%18 = OpPhi %uint %uint_0 %15 %uint_1 %12 -OpStore %2 %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, TestSimpleHalfIfExtraBlock) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHECK-NOT: OpPhi -; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1 -; CHECK OpStore {{%\w+}} [[sel]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%11 = OpTypeFunction %void -%1 = OpFunction %void None %11 -%12 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %true %15 %14 -%15 = OpLabel -OpBranch %16 -%16 = OpLabel -OpBranch %14 -%14 = OpLabel -%18 = OpPhi %uint %uint_0 %15 %uint_1 %12 -OpStore %2 %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, TestSimpleHalfIfFalse) { - const std::string text = R"( -; CHECK: OpSelectionMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHECK-NOT: OpPhi -; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1 -; CHECK OpStore {{%\w+}} [[sel]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%11 = OpTypeFunction %void -%1 = OpFunction %void None %11 -%12 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %true %14 %15 -%15 = OpLabel -OpBranch %14 -%14 = OpLabel -%18 = OpPhi %uint %uint_0 %12 %uint_1 %15 -OpStore %2 %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, TestVectorSplat) { - const std::string text = R"( -; CHECK: [[bool_vec:%\w+]] = OpTypeVector %bool 2 -; CHECK: OpSelectionMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHECK-NOT: OpPhi -; CHECK: [[comp:%\w+]] = OpCompositeConstruct [[bool_vec]] %true %true -; CHECK: [[sel:%\w+]] = OpSelect {{%\w+}} [[comp]] -; CHECK OpStore {{%\w+}} [[sel]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_vec2 = OpTypeVector %uint 2 -%vec2_01 = OpConstantComposite %uint_vec2 %uint_0 %uint_1 -%vec2_10 = OpConstantComposite %uint_vec2 %uint_1 %uint_0 -%_ptr_Output_uint = OpTypePointer Output %uint_vec2 -%2 = OpVariable %_ptr_Output_uint Output -%11 = OpTypeFunction %void -%1 = OpFunction %void None %11 -%12 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %true %15 %16 -%15 = OpLabel -OpBranch %14 -%16 = OpLabel -OpBranch %14 -%14 = OpLabel -%18 = OpPhi %uint_vec2 %vec2_01 %15 %vec2_10 %16 -OpStore %2 %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, CodeMotionSameValue) { - const std::string text = R"( -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK-NOT: OpLabel -; CHECK: [[add:%\w+]] = OpIAdd %uint %uint_0 %uint_1 -; CHECK: OpSelectionMerge [[merge_lab:%\w+]] None -; CHECK-NEXT: OpBranchConditional -; CHECK: [[merge_lab]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpStore [[var]] [[add]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "func" %2 - %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint - %2 = OpVariable %_ptr_Output_uint Output - %8 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %1 = OpFunction %void None %8 - %11 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %true %13 %15 - %13 = OpLabel - %14 = OpIAdd %uint %uint_0 %uint_1 - OpBranch %12 - %15 = OpLabel - %16 = OpIAdd %uint %uint_0 %uint_1 - OpBranch %12 - %12 = OpLabel - %17 = OpPhi %uint %16 %15 %14 %13 - OpStore %2 %17 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, CodeMotionMultipleInstructions) { - const std::string text = R"( -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK-NOT: OpLabel -; CHECK: [[a1:%\w+]] = OpIAdd %uint %uint_0 %uint_1 -; CHECK: [[a2:%\w+]] = OpIAdd %uint [[a1]] %uint_1 -; CHECK: OpSelectionMerge [[merge_lab:%\w+]] None -; CHECK-NEXT: OpBranchConditional -; CHECK: [[merge_lab]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpStore [[var]] [[a2]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "func" %2 - %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint - %2 = OpVariable %_ptr_Output_uint Output - %8 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %1 = OpFunction %void None %8 - %11 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %true %13 %15 - %13 = OpLabel - %a1 = OpIAdd %uint %uint_0 %uint_1 - %a2 = OpIAdd %uint %a1 %uint_1 - OpBranch %12 - %15 = OpLabel - %b1 = OpIAdd %uint %uint_0 %uint_1 - %b2 = OpIAdd %uint %b1 %uint_1 - OpBranch %12 - %12 = OpLabel - %17 = OpPhi %uint %b2 %15 %a2 %13 - OpStore %2 %17 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(IfConversionTest, NoCommonDominator) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%8 = OpTypeFunction %void -%1 = OpFunction %void None %8 -%9 = OpLabel -OpBranch %10 -%11 = OpLabel -OpBranch %10 -%10 = OpLabel -%12 = OpPhi %uint %uint_0 %9 %uint_1 %11 -OpStore %2 %12 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(IfConversionTest, LoopUntouched) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%8 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%1 = OpFunction %void None %8 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -%13 = OpPhi %uint %uint_0 %11 %uint_1 %12 -OpLoopMerge %14 %12 None -OpBranchConditional %true %14 %12 -%14 = OpLabel -OpStore %2 %13 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(IfConversionTest, TooManyPredecessors) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%8 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%1 = OpFunction %void None %8 -%11 = OpLabel -OpSelectionMerge %12 None -OpBranchConditional %true %13 %12 -%13 = OpLabel -OpBranchConditional %true %14 %12 -%14 = OpLabel -OpBranch %12 -%12 = OpLabel -%15 = OpPhi %uint %uint_0 %11 %uint_0 %13 %uint_1 %14 -OpStore %2 %15 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(IfConversionTest, NoCodeMotion) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%8 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%1 = OpFunction %void None %8 -%11 = OpLabel -OpSelectionMerge %12 None -OpBranchConditional %true %13 %12 -%13 = OpLabel -%14 = OpIAdd %uint %uint_0 %uint_1 -OpBranch %12 -%12 = OpLabel -%15 = OpPhi %uint %uint_0 %11 %14 %13 -OpStore %2 %15 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(IfConversionTest, NoCodeMotionImmovableInst) { - const std::string text = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %1 "func" %2 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Output_uint = OpTypePointer Output %uint -%2 = OpVariable %_ptr_Output_uint Output -%8 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%1 = OpFunction %void None %8 -%11 = OpLabel -OpSelectionMerge %12 None -OpBranchConditional %true %13 %14 -%13 = OpLabel -OpSelectionMerge %15 None -OpBranchConditional %true %16 %15 -%16 = OpLabel -%17 = OpIAdd %uint %uint_0 %uint_1 -OpBranch %15 -%15 = OpLabel -%18 = OpPhi %uint %uint_0 %13 %17 %16 -%19 = OpIAdd %uint %18 %uint_1 -OpBranch %12 -%14 = OpLabel -OpSelectionMerge %20 None -OpBranchConditional %true %21 %20 -%21 = OpLabel -%22 = OpIAdd %uint %uint_0 %uint_1 -OpBranch %20 -%20 = OpLabel -%23 = OpPhi %uint %uint_0 %14 %22 %21 -%24 = OpIAdd %uint %23 %uint_1 -OpBranch %12 -%12 = OpLabel -%25 = OpPhi %uint %24 %20 %19 %15 -OpStore %2 %25 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -TEST_F(IfConversionTest, InvalidCommonDominator) { - const std::string text = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%1 = OpTypeFunction %void -%2 = OpFunction %void None %1 -%3 = OpLabel -OpBranch %4 -%4 = OpLabel -OpLoopMerge %5 %6 None -OpBranch %7 -%7 = OpLabel -OpSelectionMerge %8 None -OpBranchConditional %true %8 %9 -%9 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %true %10 %5 -%10 = OpLabel -OpBranch %8 -%8 = OpLabel -OpBranch %6 -%6 = OpLabel -OpBranchConditional %true %4 %5 -%5 = OpLabel -%11 = OpPhi %float %float_0 %6 %float_1 %9 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(text, text, true, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/inline_opaque_test.cpp b/3rdparty/spirv-tools/test/opt/inline_opaque_test.cpp deleted file mode 100644 index d10913aec..000000000 --- a/3rdparty/spirv-tools/test/opt/inline_opaque_test.cpp +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using InlineOpaqueTest = PassTest<::testing::Test>; - -TEST_F(InlineOpaqueTest, InlineCallWithStructArgContainingSampledImage) { - // Function with opaque argument is inlined. - // TODO(greg-lunarg): Add HLSL code - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpMemberName %S_t 2 "smp" -OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" -OpName %s "s" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %s0 "s0" -OpName %texCoords "texCoords" -OpName %param "param" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%18 = OpTypeSampledImage %17 -%S_t = OpTypeStruct %v2float %v2float %18 -%_ptr_Function_S_t = OpTypePointer Function %S_t -%20 = OpTypeFunction %void %_ptr_Function_S_t -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Function_18 = OpTypePointer Function %18 -%sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %12 -%28 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%29 = OpLoad %v2float %texCoords -%30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 -OpStore %30 %29 -%31 = OpLoad %18 %sampler15 -%32 = OpAccessChain %_ptr_Function_18 %s0 %int_2 -OpStore %32 %31 -%33 = OpLoad %S_t %s0 -OpStore %param %33 -%34 = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %12 -%28 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%29 = OpLoad %v2float %texCoords -%30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 -OpStore %30 %29 -%31 = OpLoad %18 %sampler15 -%32 = OpAccessChain %_ptr_Function_18 %s0 %int_2 -OpStore %32 %31 -%33 = OpLoad %S_t %s0 -OpStore %param %33 -%41 = OpAccessChain %_ptr_Function_18 %param %int_2 -%42 = OpLoad %18 %41 -%43 = OpAccessChain %_ptr_Function_v2float %param %int_0 -%44 = OpLoad %v2float %43 -%45 = OpImageSampleImplicitLod %v4float %42 %44 -OpStore %outColor %45 -OpReturn -OpFunctionEnd -)"; - - const std::string post_defs = - R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20 -%s = OpFunctionParameter %_ptr_Function_S_t -%35 = OpLabel -%36 = OpAccessChain %_ptr_Function_18 %s %int_2 -%37 = OpLoad %18 %36 -%38 = OpAccessChain %_ptr_Function_v2float %s %int_0 -%39 = OpLoad %v2float %38 -%40 = OpImageSampleImplicitLod %v4float %37 %39 -OpStore %outColor %40 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before + post_defs, predefs + after + post_defs, true, true); -} - -TEST_F(InlineOpaqueTest, InlineOpaqueReturn) { - // Function with opaque return value is inlined. - // TODO(greg-lunarg): Add HLSL code - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %texCoords %outColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_ "foo(" -OpName %texCoords "texCoords" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %sampler16 "sampler16" -OpDecorate %sampler15 DescriptorSet 0 -OpDecorate %sampler16 DescriptorSet 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%bool = OpTypeBool -%false = OpConstantFalse %bool -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -%float_0 = OpConstant %float 0 -%16 = OpConstantComposite %v2float %float_0 %float_0 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%19 = OpTypeImage %float 2D 0 0 0 1 Unknown -%20 = OpTypeSampledImage %19 -%21 = OpTypeFunction %20 -%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 -%_ptr_Function_20 = OpTypePointer Function %20 -%sampler15 = OpVariable %_ptr_UniformConstant_20 UniformConstant -%sampler16 = OpVariable %_ptr_UniformConstant_20 UniformConstant -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%24 = OpLabel -%25 = OpVariable %_ptr_Function_20 Function -%26 = OpFunctionCall %20 %foo_ -OpStore %25 %26 -%27 = OpLoad %20 %25 -%28 = OpLoad %v2float %texCoords -%29 = OpImageSampleImplicitLod %v4float %27 %28 -OpStore %outColor %29 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%24 = OpLabel -%34 = OpVariable %_ptr_Function_20 Function -%35 = OpVariable %_ptr_Function_20 Function -%25 = OpVariable %_ptr_Function_20 Function -%36 = OpLoad %20 %sampler16 -OpStore %34 %36 -%37 = OpLoad %20 %34 -OpStore %35 %37 -%26 = OpLoad %20 %35 -OpStore %25 %26 -%27 = OpLoad %20 %25 -%28 = OpLoad %v2float %texCoords -%29 = OpImageSampleImplicitLod %v4float %27 %28 -OpStore %outColor %29 -OpReturn -OpFunctionEnd -)"; - - const std::string post_defs = - R"(%foo_ = OpFunction %20 None %21 -%30 = OpLabel -%31 = OpVariable %_ptr_Function_20 Function -%32 = OpLoad %20 %sampler16 -OpStore %31 %32 -%33 = OpLoad %20 %31 -OpReturnValue %33 -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before + post_defs, predefs + after + post_defs, true, true); -} - -TEST_F(InlineOpaqueTest, InlineInNonEntryPointFunction) { - // This demonstrates opaque inlining in a function that is not - // an entry point function (main2) but is in the call tree of an - // entry point function (main). - // TODO(greg-lunarg): Add HLSL code - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %main2 "main2" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpMemberName %S_t 2 "smp" -OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" -OpName %s "s" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %s0 "s0" -OpName %texCoords "texCoords" -OpName %param "param" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%13 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%18 = OpTypeImage %float 2D 0 0 0 1 Unknown -%19 = OpTypeSampledImage %18 -%S_t = OpTypeStruct %v2float %v2float %19 -%_ptr_Function_S_t = OpTypePointer Function %S_t -%21 = OpTypeFunction %void %_ptr_Function_S_t -%_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 -%_ptr_Function_19 = OpTypePointer Function %19 -%sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string before = - R"(%main2 = OpFunction %void None %13 -%29 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%30 = OpLoad %v2float %texCoords -%31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 -OpStore %31 %30 -%32 = OpLoad %19 %sampler15 -%33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 -OpStore %33 %32 -%34 = OpLoad %S_t %s0 -OpStore %param %34 -%35 = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main2 = OpFunction %void None %13 -%29 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%30 = OpLoad %v2float %texCoords -%31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 -OpStore %31 %30 -%32 = OpLoad %19 %sampler15 -%33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 -OpStore %33 %32 -%34 = OpLoad %S_t %s0 -OpStore %param %34 -%44 = OpAccessChain %_ptr_Function_19 %param %int_2 -%45 = OpLoad %19 %44 -%46 = OpAccessChain %_ptr_Function_v2float %param %int_0 -%47 = OpLoad %v2float %46 -%48 = OpImageSampleImplicitLod %v4float %45 %47 -OpStore %outColor %48 -OpReturn -OpFunctionEnd -)"; - - const std::string post_defs = - R"(%main = OpFunction %void None %13 -%36 = OpLabel -%37 = OpFunctionCall %void %main2 -OpReturn -OpFunctionEnd -%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21 -%s = OpFunctionParameter %_ptr_Function_S_t -%38 = OpLabel -%39 = OpAccessChain %_ptr_Function_19 %s %int_2 -%40 = OpLoad %19 %39 -%41 = OpAccessChain %_ptr_Function_v2float %s %int_0 -%42 = OpLoad %v2float %41 -%43 = OpImageSampleImplicitLod %v4float %40 %42 -OpStore %outColor %43 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before + post_defs, predefs + after + post_defs, true, true); -} - -TEST_F(InlineOpaqueTest, NoInlineNoOpaque) { - // Function without opaque interface is not inlined. - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // return bar.x + bar.y; - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_ "foo(vf4;" -OpName %bar "bar" -OpName %color "color" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%14 = OpTypeFunction %float %_ptr_Function_v4float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %10 -%21 = OpLabel -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %BaseColor -OpStore %param %22 -%23 = OpFunctionCall %float %foo_vf4_ %param -%24 = OpCompositeConstruct %v4float %23 %23 %23 %23 -OpStore %color %24 -%25 = OpLoad %v4float %color -OpStore %gl_FragColor %25 -OpReturn -OpFunctionEnd -%foo_vf4_ = OpFunction %float None %14 -%bar = OpFunctionParameter %_ptr_Function_v4float -%26 = OpLabel -%27 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%28 = OpLoad %float %27 -%29 = OpAccessChain %_ptr_Function_float %bar %uint_1 -%30 = OpLoad %float %29 -%31 = OpFAdd %float %28 %30 -OpReturnValue %31 -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/inline_test.cpp b/3rdparty/spirv-tools/test/opt/inline_test.cpp deleted file mode 100644 index f44c04a05..000000000 --- a/3rdparty/spirv-tools/test/opt/inline_test.cpp +++ /dev/null @@ -1,3056 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using InlineTest = PassTest<::testing::Test>; - -TEST_F(InlineTest, Simple) { - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // return bar.x + bar.y; - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 140", - "OpName %main \"main\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %color \"color\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param \"param\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "%void = OpTypeVoid", - "%10 = OpTypeFunction %void", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%14 = OpTypeFunction %float %_ptr_Function_v4float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", -"%_ptr_Function_float = OpTypePointer Function %float", - "%uint_1 = OpConstant %uint 1", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_vf4_ = OpFunction %float None %14", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%26 = OpLabel", - "%27 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%28 = OpLoad %float %27", - "%29 = OpAccessChain %_ptr_Function_float %bar %uint_1", - "%30 = OpLoad %float %29", - "%31 = OpFAdd %float %28 %30", - "OpReturnValue %31", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %10", - "%21 = OpLabel", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%22 = OpLoad %v4float %BaseColor", - "OpStore %param %22", - "%23 = OpFunctionCall %float %foo_vf4_ %param", - "%24 = OpCompositeConstruct %v4float %23 %23 %23 %23", - "OpStore %color %24", - "%25 = OpLoad %v4float %color", - "OpStore %gl_FragColor %25", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %10", - "%21 = OpLabel", - "%32 = OpVariable %_ptr_Function_float Function", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%22 = OpLoad %v4float %BaseColor", - "OpStore %param %22", - "%33 = OpAccessChain %_ptr_Function_float %param %uint_0", - "%34 = OpLoad %float %33", - "%35 = OpAccessChain %_ptr_Function_float %param %uint_1", - "%36 = OpLoad %float %35", - "%37 = OpFAdd %float %34 %36", - "OpStore %32 %37", - "%23 = OpLoad %float %32", - "%24 = OpCompositeConstruct %v4float %23 %23 %23 %23", - "OpStore %color %24", - "%25 = OpLoad %v4float %color", - "OpStore %gl_FragColor %25", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, Nested) { - // #version 140 - // - // in vec4 BaseColor; - // - // float foo2(float f, float f2) - // { - // return f * f2; - // } - // - // float foo(vec4 bar) - // { - // return foo2(bar.x + bar.y, bar.z); - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 140", - "OpName %main \"main\"", - "OpName %foo2_f1_f1_ \"foo2(f1;f1;\"", - "OpName %f \"f\"", - "OpName %f2 \"f2\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %param \"param\"", - "OpName %param_0 \"param\"", - "OpName %color \"color\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param_1 \"param\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "%void = OpTypeVoid", - "%15 = OpTypeFunction %void", - "%float = OpTypeFloat 32", -"%_ptr_Function_float = OpTypePointer Function %float", - "%18 = OpTypeFunction %float %_ptr_Function_float %_ptr_Function_float", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%21 = OpTypeFunction %float %_ptr_Function_v4float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", - "%uint_1 = OpConstant %uint 1", - "%uint_2 = OpConstant %uint 2", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off -"%foo2_f1_f1_ = OpFunction %float None %18", - "%f = OpFunctionParameter %_ptr_Function_float", - "%f2 = OpFunctionParameter %_ptr_Function_float", - "%33 = OpLabel", - "%34 = OpLoad %float %f", - "%35 = OpLoad %float %f2", - "%36 = OpFMul %float %34 %35", - "OpReturnValue %36", - "OpFunctionEnd", - "%foo_vf4_ = OpFunction %float None %21", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%37 = OpLabel", - "%param = OpVariable %_ptr_Function_float Function", - "%param_0 = OpVariable %_ptr_Function_float Function", - "%38 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%39 = OpLoad %float %38", - "%40 = OpAccessChain %_ptr_Function_float %bar %uint_1", - "%41 = OpLoad %float %40", - "%42 = OpFAdd %float %39 %41", - "OpStore %param %42", - "%43 = OpAccessChain %_ptr_Function_float %bar %uint_2", - "%44 = OpLoad %float %43", - "OpStore %param_0 %44", - "%45 = OpFunctionCall %float %foo2_f1_f1_ %param %param_0", - "OpReturnValue %45", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %15", - "%28 = OpLabel", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param_1 = OpVariable %_ptr_Function_v4float Function", - "%29 = OpLoad %v4float %BaseColor", - "OpStore %param_1 %29", - "%30 = OpFunctionCall %float %foo_vf4_ %param_1", - "%31 = OpCompositeConstruct %v4float %30 %30 %30 %30", - "OpStore %color %31", - "%32 = OpLoad %v4float %color", - "OpStore %gl_FragColor %32", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %15", - "%28 = OpLabel", - "%57 = OpVariable %_ptr_Function_float Function", - "%46 = OpVariable %_ptr_Function_float Function", - "%47 = OpVariable %_ptr_Function_float Function", - "%48 = OpVariable %_ptr_Function_float Function", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param_1 = OpVariable %_ptr_Function_v4float Function", - "%29 = OpLoad %v4float %BaseColor", - "OpStore %param_1 %29", - "%49 = OpAccessChain %_ptr_Function_float %param_1 %uint_0", - "%50 = OpLoad %float %49", - "%51 = OpAccessChain %_ptr_Function_float %param_1 %uint_1", - "%52 = OpLoad %float %51", - "%53 = OpFAdd %float %50 %52", - "OpStore %46 %53", - "%54 = OpAccessChain %_ptr_Function_float %param_1 %uint_2", - "%55 = OpLoad %float %54", - "OpStore %47 %55", - "%58 = OpLoad %float %46", - "%59 = OpLoad %float %47", - "%60 = OpFMul %float %58 %59", - "OpStore %57 %60", - "%56 = OpLoad %float %57", - "OpStore %48 %56", - "%30 = OpLoad %float %48", - "%31 = OpCompositeConstruct %v4float %30 %30 %30 %30", - "OpStore %color %31", - "%32 = OpLoad %v4float %color", - "OpStore %gl_FragColor %32", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, InOutParameter) { - // #version 400 - // - // in vec4 Basecolor; - // - // void foo(inout vec4 bar) - // { - // bar.z = bar.x + bar.y; - // } - // - // void main() - // { - // vec4 b = Basecolor; - // foo(b); - // vec4 color = vec4(b.z); - // gl_FragColor = color; - // } - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %Basecolor %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 400", - "OpName %main \"main\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %b \"b\"", - "OpName %Basecolor \"Basecolor\"", - "OpName %param \"param\"", - "OpName %color \"color\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "%void = OpTypeVoid", - "%11 = OpTypeFunction %void", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%15 = OpTypeFunction %void %_ptr_Function_v4float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", -"%_ptr_Function_float = OpTypePointer Function %float", - "%uint_1 = OpConstant %uint 1", - "%uint_2 = OpConstant %uint 2", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%Basecolor = OpVariable %_ptr_Input_v4float Input", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_vf4_ = OpFunction %void None %15", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%32 = OpLabel", - "%33 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%34 = OpLoad %float %33", - "%35 = OpAccessChain %_ptr_Function_float %bar %uint_1", - "%36 = OpLoad %float %35", - "%37 = OpFAdd %float %34 %36", - "%38 = OpAccessChain %_ptr_Function_float %bar %uint_2", - "OpStore %38 %37", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %11", - "%23 = OpLabel", - "%b = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color = OpVariable %_ptr_Function_v4float Function", - "%24 = OpLoad %v4float %Basecolor", - "OpStore %b %24", - "%25 = OpLoad %v4float %b", - "OpStore %param %25", - "%26 = OpFunctionCall %void %foo_vf4_ %param", - "%27 = OpLoad %v4float %param", - "OpStore %b %27", - "%28 = OpAccessChain %_ptr_Function_float %b %uint_2", - "%29 = OpLoad %float %28", - "%30 = OpCompositeConstruct %v4float %29 %29 %29 %29", - "OpStore %color %30", - "%31 = OpLoad %v4float %color", - "OpStore %gl_FragColor %31", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %11", - "%23 = OpLabel", - "%b = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color = OpVariable %_ptr_Function_v4float Function", - "%24 = OpLoad %v4float %Basecolor", - "OpStore %b %24", - "%25 = OpLoad %v4float %b", - "OpStore %param %25", - "%39 = OpAccessChain %_ptr_Function_float %param %uint_0", - "%40 = OpLoad %float %39", - "%41 = OpAccessChain %_ptr_Function_float %param %uint_1", - "%42 = OpLoad %float %41", - "%43 = OpFAdd %float %40 %42", - "%44 = OpAccessChain %_ptr_Function_float %param %uint_2", - "OpStore %44 %43", - "%27 = OpLoad %v4float %param", - "OpStore %b %27", - "%28 = OpAccessChain %_ptr_Function_float %b %uint_2", - "%29 = OpLoad %float %28", - "%30 = OpCompositeConstruct %v4float %29 %29 %29 %29", - "OpStore %color %30", - "%31 = OpLoad %v4float %color", - "OpStore %gl_FragColor %31", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, BranchInCallee) { - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // float r = bar.x; - // if (r < 0.0) - // r = -r; - // return r; - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // - // gl_FragColor = color; - // } - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 140", - "OpName %main \"main\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %r \"r\"", - "OpName %color \"color\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param \"param\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "%void = OpTypeVoid", - "%11 = OpTypeFunction %void", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%15 = OpTypeFunction %float %_ptr_Function_v4float", -"%_ptr_Function_float = OpTypePointer Function %float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", - "%float_0 = OpConstant %float 0", - "%bool = OpTypeBool", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_vf4_ = OpFunction %float None %15", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%28 = OpLabel", - "%r = OpVariable %_ptr_Function_float Function", - "%29 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%30 = OpLoad %float %29", - "OpStore %r %30", - "%31 = OpLoad %float %r", - "%32 = OpFOrdLessThan %bool %31 %float_0", - "OpSelectionMerge %33 None", - "OpBranchConditional %32 %34 %33", - "%34 = OpLabel", - "%35 = OpLoad %float %r", - "%36 = OpFNegate %float %35", - "OpStore %r %36", - "OpBranch %33", - "%33 = OpLabel", - "%37 = OpLoad %float %r", - "OpReturnValue %37", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %11", - "%23 = OpLabel", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%24 = OpLoad %v4float %BaseColor", - "OpStore %param %24", - "%25 = OpFunctionCall %float %foo_vf4_ %param", - "%26 = OpCompositeConstruct %v4float %25 %25 %25 %25", - "OpStore %color %26", - "%27 = OpLoad %v4float %color", - "OpStore %gl_FragColor %27", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %11", - "%23 = OpLabel", - "%38 = OpVariable %_ptr_Function_float Function", - "%39 = OpVariable %_ptr_Function_float Function", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%24 = OpLoad %v4float %BaseColor", - "OpStore %param %24", - "%40 = OpAccessChain %_ptr_Function_float %param %uint_0", - "%41 = OpLoad %float %40", - "OpStore %38 %41", - "%42 = OpLoad %float %38", - "%43 = OpFOrdLessThan %bool %42 %float_0", - "OpSelectionMerge %44 None", - "OpBranchConditional %43 %45 %44", - "%45 = OpLabel", - "%46 = OpLoad %float %38", - "%47 = OpFNegate %float %46", - "OpStore %38 %47", - "OpBranch %44", - "%44 = OpLabel", - "%48 = OpLoad %float %38", - "OpStore %39 %48", - "%25 = OpLoad %float %39", - "%26 = OpCompositeConstruct %v4float %25 %25 %25 %25", - "OpStore %color %26", - "%27 = OpLoad %v4float %color", - "OpStore %gl_FragColor %27", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, PhiAfterCall) { - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(float bar) - // { - // float r = bar; - // if (r < 0.0) - // r = -r; - // return r; - // } - // - // void main() - // { - // vec4 color = BaseColor; - // if (foo(color.x) > 2.0 && foo(color.y) > 2.0) - // color = vec4(0.0); - // gl_FragColor = color; - // } - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 140", - "OpName %main \"main\"", - "OpName %foo_f1_ \"foo(f1;\"", - "OpName %bar \"bar\"", - "OpName %r \"r\"", - "OpName %color \"color\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param \"param\"", - "OpName %param_0 \"param\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "%void = OpTypeVoid", - "%12 = OpTypeFunction %void", - "%float = OpTypeFloat 32", -"%_ptr_Function_float = OpTypePointer Function %float", - "%15 = OpTypeFunction %float %_ptr_Function_float", - "%float_0 = OpConstant %float 0", - "%bool = OpTypeBool", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", - "%float_2 = OpConstant %float 2", - "%uint_1 = OpConstant %uint 1", - "%25 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_f1_ = OpFunction %float None %15", - "%bar = OpFunctionParameter %_ptr_Function_float", - "%43 = OpLabel", - "%r = OpVariable %_ptr_Function_float Function", - "%44 = OpLoad %float %bar", - "OpStore %r %44", - "%45 = OpLoad %float %r", - "%46 = OpFOrdLessThan %bool %45 %float_0", - "OpSelectionMerge %47 None", - "OpBranchConditional %46 %48 %47", - "%48 = OpLabel", - "%49 = OpLoad %float %r", - "%50 = OpFNegate %float %49", - "OpStore %r %50", - "OpBranch %47", - "%47 = OpLabel", - "%51 = OpLoad %float %r", - "OpReturnValue %51", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %12", - "%27 = OpLabel", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_float Function", - "%param_0 = OpVariable %_ptr_Function_float Function", - "%28 = OpLoad %v4float %BaseColor", - "OpStore %color %28", - "%29 = OpAccessChain %_ptr_Function_float %color %uint_0", - "%30 = OpLoad %float %29", - "OpStore %param %30", - "%31 = OpFunctionCall %float %foo_f1_ %param", - "%32 = OpFOrdGreaterThan %bool %31 %float_2", - "OpSelectionMerge %33 None", - "OpBranchConditional %32 %34 %33", - "%34 = OpLabel", - "%35 = OpAccessChain %_ptr_Function_float %color %uint_1", - "%36 = OpLoad %float %35", - "OpStore %param_0 %36", - "%37 = OpFunctionCall %float %foo_f1_ %param_0", - "%38 = OpFOrdGreaterThan %bool %37 %float_2", - "OpBranch %33", - "%33 = OpLabel", - "%39 = OpPhi %bool %32 %27 %38 %34", - "OpSelectionMerge %40 None", - "OpBranchConditional %39 %41 %40", - "%41 = OpLabel", - "OpStore %color %25", - "OpBranch %40", - "%40 = OpLabel", - "%42 = OpLoad %v4float %color", - "OpStore %gl_FragColor %42", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %12", - "%27 = OpLabel", - "%62 = OpVariable %_ptr_Function_float Function", - "%63 = OpVariable %_ptr_Function_float Function", - "%52 = OpVariable %_ptr_Function_float Function", - "%53 = OpVariable %_ptr_Function_float Function", - "%color = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_float Function", - "%param_0 = OpVariable %_ptr_Function_float Function", - "%28 = OpLoad %v4float %BaseColor", - "OpStore %color %28", - "%29 = OpAccessChain %_ptr_Function_float %color %uint_0", - "%30 = OpLoad %float %29", - "OpStore %param %30", - "%54 = OpLoad %float %param", - "OpStore %52 %54", - "%55 = OpLoad %float %52", - "%56 = OpFOrdLessThan %bool %55 %float_0", - "OpSelectionMerge %57 None", - "OpBranchConditional %56 %58 %57", - "%58 = OpLabel", - "%59 = OpLoad %float %52", - "%60 = OpFNegate %float %59", - "OpStore %52 %60", - "OpBranch %57", - "%57 = OpLabel", - "%61 = OpLoad %float %52", - "OpStore %53 %61", - "%31 = OpLoad %float %53", - "%32 = OpFOrdGreaterThan %bool %31 %float_2", - "OpSelectionMerge %33 None", - "OpBranchConditional %32 %34 %33", - "%34 = OpLabel", - "%35 = OpAccessChain %_ptr_Function_float %color %uint_1", - "%36 = OpLoad %float %35", - "OpStore %param_0 %36", - "%64 = OpLoad %float %param_0", - "OpStore %62 %64", - "%65 = OpLoad %float %62", - "%66 = OpFOrdLessThan %bool %65 %float_0", - "OpSelectionMerge %67 None", - "OpBranchConditional %66 %68 %67", - "%68 = OpLabel", - "%69 = OpLoad %float %62", - "%70 = OpFNegate %float %69", - "OpStore %62 %70", - "OpBranch %67", - "%67 = OpLabel", - "%71 = OpLoad %float %62", - "OpStore %63 %71", - "%37 = OpLoad %float %63", - "%38 = OpFOrdGreaterThan %bool %37 %float_2", - "OpBranch %33", - "%33 = OpLabel", - "%39 = OpPhi %bool %32 %57 %38 %67", - "OpSelectionMerge %40 None", - "OpBranchConditional %39 %41 %40", - "%41 = OpLabel", - "OpStore %color %25", - "OpBranch %40", - "%40 = OpLabel", - "%42 = OpLoad %v4float %color", - "OpStore %gl_FragColor %42", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, OpSampledImageOutOfBlock) { - // #version 450 - // - // uniform texture2D t2D; - // uniform sampler samp; - // out vec4 FragColor; - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // float r = bar.x; - // if (r < 0.0) - // r = -r; - // return r; - // } - // - // void main() - // { - // vec4 color1 = texture(sampler2D(t2D, samp), vec2(1.0)); - // vec4 color2 = vec4(foo(BaseColor)); - // vec4 color3 = texture(sampler2D(t2D, samp), vec2(0.5)); - // FragColor = (color1 + color2 + color3)/3; - // } - // - // Note: the before SPIR-V will need to be edited to create a use of - // the OpSampledImage across the function call. - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 450", - "OpName %main \"main\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %r \"r\"", - "OpName %color1 \"color1\"", - "OpName %t2D \"t2D\"", - "OpName %samp \"samp\"", - "OpName %color2 \"color2\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param \"param\"", - "OpName %color3 \"color3\"", - "OpName %FragColor \"FragColor\"", - "OpDecorate %t2D DescriptorSet 0", - "OpDecorate %samp DescriptorSet 0", - "%void = OpTypeVoid", - "%15 = OpTypeFunction %void", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%19 = OpTypeFunction %float %_ptr_Function_v4float", -"%_ptr_Function_float = OpTypePointer Function %float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", - "%float_0 = OpConstant %float 0", - "%bool = OpTypeBool", - "%25 = OpTypeImage %float 2D 0 0 0 1 Unknown", -"%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25", - "%t2D = OpVariable %_ptr_UniformConstant_25 UniformConstant", - "%27 = OpTypeSampler", -"%_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27", - "%samp = OpVariable %_ptr_UniformConstant_27 UniformConstant", - "%29 = OpTypeSampledImage %25", - "%v2float = OpTypeVector %float 2", - "%float_1 = OpConstant %float 1", - "%32 = OpConstantComposite %v2float %float_1 %float_1", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", - "%float_0_5 = OpConstant %float 0.5", - "%35 = OpConstantComposite %v2float %float_0_5 %float_0_5", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", - "%FragColor = OpVariable %_ptr_Output_v4float Output", - "%float_3 = OpConstant %float 3", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_vf4_ = OpFunction %float None %19", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%56 = OpLabel", - "%r = OpVariable %_ptr_Function_float Function", - "%57 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%58 = OpLoad %float %57", - "OpStore %r %58", - "%59 = OpLoad %float %r", - "%60 = OpFOrdLessThan %bool %59 %float_0", - "OpSelectionMerge %61 None", - "OpBranchConditional %60 %62 %61", - "%62 = OpLabel", - "%63 = OpLoad %float %r", - "%64 = OpFNegate %float %63", - "OpStore %r %64", - "OpBranch %61", - "%61 = OpLabel", - "%65 = OpLoad %float %r", - "OpReturnValue %65", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %15", - "%38 = OpLabel", - "%color1 = OpVariable %_ptr_Function_v4float Function", - "%color2 = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color3 = OpVariable %_ptr_Function_v4float Function", - "%39 = OpLoad %25 %t2D", - "%40 = OpLoad %27 %samp", - "%41 = OpSampledImage %29 %39 %40", - "%42 = OpImageSampleImplicitLod %v4float %41 %32", - "OpStore %color1 %42", - "%43 = OpLoad %v4float %BaseColor", - "OpStore %param %43", - "%44 = OpFunctionCall %float %foo_vf4_ %param", - "%45 = OpCompositeConstruct %v4float %44 %44 %44 %44", - "OpStore %color2 %45", - "%46 = OpLoad %25 %t2D", - "%47 = OpLoad %27 %samp", - "%48 = OpImageSampleImplicitLod %v4float %41 %35", - "OpStore %color3 %48", - "%49 = OpLoad %v4float %color1", - "%50 = OpLoad %v4float %color2", - "%51 = OpFAdd %v4float %49 %50", - "%52 = OpLoad %v4float %color3", - "%53 = OpFAdd %v4float %51 %52", - "%54 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", - "%55 = OpFDiv %v4float %53 %54", - "OpStore %FragColor %55", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %15", - "%38 = OpLabel", - "%66 = OpVariable %_ptr_Function_float Function", - "%67 = OpVariable %_ptr_Function_float Function", - "%color1 = OpVariable %_ptr_Function_v4float Function", - "%color2 = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color3 = OpVariable %_ptr_Function_v4float Function", - "%39 = OpLoad %25 %t2D", - "%40 = OpLoad %27 %samp", - "%41 = OpSampledImage %29 %39 %40", - "%42 = OpImageSampleImplicitLod %v4float %41 %32", - "OpStore %color1 %42", - "%43 = OpLoad %v4float %BaseColor", - "OpStore %param %43", - "%68 = OpAccessChain %_ptr_Function_float %param %uint_0", - "%69 = OpLoad %float %68", - "OpStore %66 %69", - "%70 = OpLoad %float %66", - "%71 = OpFOrdLessThan %bool %70 %float_0", - "OpSelectionMerge %72 None", - "OpBranchConditional %71 %73 %72", - "%73 = OpLabel", - "%74 = OpLoad %float %66", - "%75 = OpFNegate %float %74", - "OpStore %66 %75", - "OpBranch %72", - "%72 = OpLabel", - "%76 = OpLoad %float %66", - "OpStore %67 %76", - "%44 = OpLoad %float %67", - "%45 = OpCompositeConstruct %v4float %44 %44 %44 %44", - "OpStore %color2 %45", - "%46 = OpLoad %25 %t2D", - "%47 = OpLoad %27 %samp", - "%77 = OpSampledImage %29 %39 %40", - "%48 = OpImageSampleImplicitLod %v4float %77 %35", - "OpStore %color3 %48", - "%49 = OpLoad %v4float %color1", - "%50 = OpLoad %v4float %color2", - "%51 = OpFAdd %v4float %49 %50", - "%52 = OpLoad %v4float %color3", - "%53 = OpFAdd %v4float %51 %52", - "%54 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", - "%55 = OpFDiv %v4float %53 %54", - "OpStore %FragColor %55", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, OpImageOutOfBlock) { - // #version 450 - // - // uniform texture2D t2D; - // uniform sampler samp; - // uniform sampler samp2; - // - // out vec4 FragColor; - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // float r = bar.x; - // if (r < 0.0) - // r = -r; - // return r; - // } - // - // void main() - // { - // vec4 color1 = texture(sampler2D(t2D, samp), vec2(1.0)); - // vec4 color2 = vec4(foo(BaseColor)); - // vec4 color3 = texture(sampler2D(t2D, samp2), vec2(0.5)); - // FragColor = (color1 + color2 + color3)/3; - // } - // Note: the before SPIR-V will need to be edited to create an OpImage - // from the first OpSampledImage, place it before the call and use it - // in the second OpSampledImage following the call. - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 450", - "OpName %main \"main\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %r \"r\"", - "OpName %color1 \"color1\"", - "OpName %t2D \"t2D\"", - "OpName %samp \"samp\"", - "OpName %color2 \"color2\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param \"param\"", - "OpName %color3 \"color3\"", - "OpName %samp2 \"samp2\"", - "OpName %FragColor \"FragColor\"", - "OpDecorate %t2D DescriptorSet 0", - "OpDecorate %samp DescriptorSet 0", - "OpDecorate %samp2 DescriptorSet 0", - "%void = OpTypeVoid", - "%16 = OpTypeFunction %void", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%20 = OpTypeFunction %float %_ptr_Function_v4float", -"%_ptr_Function_float = OpTypePointer Function %float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", - "%float_0 = OpConstant %float 0", - "%bool = OpTypeBool", - "%26 = OpTypeImage %float 2D 0 0 0 1 Unknown", -"%_ptr_UniformConstant_26 = OpTypePointer UniformConstant %26", - "%t2D = OpVariable %_ptr_UniformConstant_26 UniformConstant", - "%28 = OpTypeSampler", -"%_ptr_UniformConstant_28 = OpTypePointer UniformConstant %28", - "%samp = OpVariable %_ptr_UniformConstant_28 UniformConstant", - "%30 = OpTypeSampledImage %26", - "%v2float = OpTypeVector %float 2", - "%float_1 = OpConstant %float 1", - "%33 = OpConstantComposite %v2float %float_1 %float_1", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", - "%samp2 = OpVariable %_ptr_UniformConstant_28 UniformConstant", - "%float_0_5 = OpConstant %float 0.5", - "%36 = OpConstantComposite %v2float %float_0_5 %float_0_5", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", - "%FragColor = OpVariable %_ptr_Output_v4float Output", - "%float_3 = OpConstant %float 3", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_vf4_ = OpFunction %float None %20", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%58 = OpLabel", - "%r = OpVariable %_ptr_Function_float Function", - "%59 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%60 = OpLoad %float %59", - "OpStore %r %60", - "%61 = OpLoad %float %r", - "%62 = OpFOrdLessThan %bool %61 %float_0", - "OpSelectionMerge %63 None", - "OpBranchConditional %62 %64 %63", - "%64 = OpLabel", - "%65 = OpLoad %float %r", - "%66 = OpFNegate %float %65", - "OpStore %r %66", - "OpBranch %63", - "%63 = OpLabel", - "%67 = OpLoad %float %r", - "OpReturnValue %67", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %16", - "%39 = OpLabel", - "%color1 = OpVariable %_ptr_Function_v4float Function", - "%color2 = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color3 = OpVariable %_ptr_Function_v4float Function", - "%40 = OpLoad %26 %t2D", - "%41 = OpLoad %28 %samp", - "%42 = OpSampledImage %30 %40 %41", - "%43 = OpImageSampleImplicitLod %v4float %42 %33", - "%44 = OpImage %26 %42", - "%45 = OpLoad %28 %samp2", - "OpStore %color1 %43", - "%46 = OpLoad %v4float %BaseColor", - "OpStore %param %46", - "%47 = OpFunctionCall %float %foo_vf4_ %param", - "%48 = OpCompositeConstruct %v4float %47 %47 %47 %47", - "OpStore %color2 %48", - "%49 = OpSampledImage %30 %44 %45", - "%50 = OpImageSampleImplicitLod %v4float %49 %36", - "OpStore %color3 %50", - "%51 = OpLoad %v4float %color1", - "%52 = OpLoad %v4float %color2", - "%53 = OpFAdd %v4float %51 %52", - "%54 = OpLoad %v4float %color3", - "%55 = OpFAdd %v4float %53 %54", - "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", - "%57 = OpFDiv %v4float %55 %56", - "OpStore %FragColor %57", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %16", - "%39 = OpLabel", - "%68 = OpVariable %_ptr_Function_float Function", - "%69 = OpVariable %_ptr_Function_float Function", - "%color1 = OpVariable %_ptr_Function_v4float Function", - "%color2 = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color3 = OpVariable %_ptr_Function_v4float Function", - "%40 = OpLoad %26 %t2D", - "%41 = OpLoad %28 %samp", - "%42 = OpSampledImage %30 %40 %41", - "%43 = OpImageSampleImplicitLod %v4float %42 %33", - "%44 = OpImage %26 %42", - "%45 = OpLoad %28 %samp2", - "OpStore %color1 %43", - "%46 = OpLoad %v4float %BaseColor", - "OpStore %param %46", - "%70 = OpAccessChain %_ptr_Function_float %param %uint_0", - "%71 = OpLoad %float %70", - "OpStore %68 %71", - "%72 = OpLoad %float %68", - "%73 = OpFOrdLessThan %bool %72 %float_0", - "OpSelectionMerge %74 None", - "OpBranchConditional %73 %75 %74", - "%75 = OpLabel", - "%76 = OpLoad %float %68", - "%77 = OpFNegate %float %76", - "OpStore %68 %77", - "OpBranch %74", - "%74 = OpLabel", - "%78 = OpLoad %float %68", - "OpStore %69 %78", - "%47 = OpLoad %float %69", - "%48 = OpCompositeConstruct %v4float %47 %47 %47 %47", - "OpStore %color2 %48", - "%79 = OpSampledImage %30 %40 %41", - "%80 = OpImage %26 %79", - "%49 = OpSampledImage %30 %80 %45", - "%50 = OpImageSampleImplicitLod %v4float %49 %36", - "OpStore %color3 %50", - "%51 = OpLoad %v4float %color1", - "%52 = OpLoad %v4float %color2", - "%53 = OpFAdd %v4float %51 %52", - "%54 = OpLoad %v4float %color3", - "%55 = OpFAdd %v4float %53 %54", - "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", - "%57 = OpFDiv %v4float %55 %56", - "OpStore %FragColor %57", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, OpImageAndOpSampledImageOutOfBlock) { - // #version 450 - // - // uniform texture2D t2D; - // uniform sampler samp; - // uniform sampler samp2; - // - // out vec4 FragColor; - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // float r = bar.x; - // if (r < 0.0) - // r = -r; - // return r; - // } - // - // void main() - // { - // vec4 color1 = texture(sampler2D(t2D, samp), vec2(1.0)); - // vec4 color2 = vec4(foo(BaseColor)); - // vec4 color3 = texture(sampler2D(t2D, samp2), vec2(0.5)); - // FragColor = (color1 + color2 + color3)/3; - // } - // Note: the before SPIR-V will need to be edited to create an OpImage - // and subsequent OpSampledImage that is used across the function call. - const std::vector predefs = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %BaseColor %FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpSource GLSL 450", - "OpName %main \"main\"", - "OpName %foo_vf4_ \"foo(vf4;\"", - "OpName %bar \"bar\"", - "OpName %r \"r\"", - "OpName %color1 \"color1\"", - "OpName %t2D \"t2D\"", - "OpName %samp \"samp\"", - "OpName %color2 \"color2\"", - "OpName %BaseColor \"BaseColor\"", - "OpName %param \"param\"", - "OpName %color3 \"color3\"", - "OpName %samp2 \"samp2\"", - "OpName %FragColor \"FragColor\"", - "OpDecorate %t2D DescriptorSet 0", - "OpDecorate %samp DescriptorSet 0", - "OpDecorate %samp2 DescriptorSet 0", - "%void = OpTypeVoid", - "%16 = OpTypeFunction %void", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Function_v4float = OpTypePointer Function %v4float", - "%20 = OpTypeFunction %float %_ptr_Function_v4float", -"%_ptr_Function_float = OpTypePointer Function %float", - "%uint = OpTypeInt 32 0", - "%uint_0 = OpConstant %uint 0", - "%float_0 = OpConstant %float 0", - "%bool = OpTypeBool", - "%26 = OpTypeImage %float 2D 0 0 0 1 Unknown", -"%_ptr_UniformConstant_26 = OpTypePointer UniformConstant %26", - "%t2D = OpVariable %_ptr_UniformConstant_26 UniformConstant", - "%28 = OpTypeSampler", -"%_ptr_UniformConstant_28 = OpTypePointer UniformConstant %28", - "%samp = OpVariable %_ptr_UniformConstant_28 UniformConstant", - "%30 = OpTypeSampledImage %26", - "%v2float = OpTypeVector %float 2", - "%float_1 = OpConstant %float 1", - "%33 = OpConstantComposite %v2float %float_1 %float_1", -"%_ptr_Input_v4float = OpTypePointer Input %v4float", - "%BaseColor = OpVariable %_ptr_Input_v4float Input", - "%samp2 = OpVariable %_ptr_UniformConstant_28 UniformConstant", - "%float_0_5 = OpConstant %float 0.5", - "%36 = OpConstantComposite %v2float %float_0_5 %float_0_5", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", - "%FragColor = OpVariable %_ptr_Output_v4float Output", - "%float_3 = OpConstant %float 3", - // clang-format on - }; - - const std::vector nonEntryFuncs = { - // clang-format off - "%foo_vf4_ = OpFunction %float None %20", - "%bar = OpFunctionParameter %_ptr_Function_v4float", - "%58 = OpLabel", - "%r = OpVariable %_ptr_Function_float Function", - "%59 = OpAccessChain %_ptr_Function_float %bar %uint_0", - "%60 = OpLoad %float %59", - "OpStore %r %60", - "%61 = OpLoad %float %r", - "%62 = OpFOrdLessThan %bool %61 %float_0", - "OpSelectionMerge %63 None", - "OpBranchConditional %62 %64 %63", - "%64 = OpLabel", - "%65 = OpLoad %float %r", - "%66 = OpFNegate %float %65", - "OpStore %r %66", - "OpBranch %63", - "%63 = OpLabel", - "%67 = OpLoad %float %r", - "OpReturnValue %67", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector before = { - // clang-format off - "%main = OpFunction %void None %16", - "%39 = OpLabel", - "%color1 = OpVariable %_ptr_Function_v4float Function", - "%color2 = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color3 = OpVariable %_ptr_Function_v4float Function", - "%40 = OpLoad %26 %t2D", - "%41 = OpLoad %28 %samp", - "%42 = OpSampledImage %30 %40 %41", - "%43 = OpImageSampleImplicitLod %v4float %42 %33", - "%44 = OpImage %26 %42", - "%45 = OpLoad %28 %samp2", - "%46 = OpSampledImage %30 %44 %45", - "OpStore %color1 %43", - "%47 = OpLoad %v4float %BaseColor", - "OpStore %param %47", - "%48 = OpFunctionCall %float %foo_vf4_ %param", - "%49 = OpCompositeConstruct %v4float %48 %48 %48 %48", - "OpStore %color2 %49", - "%50 = OpImageSampleImplicitLod %v4float %46 %36", - "OpStore %color3 %50", - "%51 = OpLoad %v4float %color1", - "%52 = OpLoad %v4float %color2", - "%53 = OpFAdd %v4float %51 %52", - "%54 = OpLoad %v4float %color3", - "%55 = OpFAdd %v4float %53 %54", - "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", - "%57 = OpFDiv %v4float %55 %56", - "OpStore %FragColor %57", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - const std::vector after = { - // clang-format off - "%main = OpFunction %void None %16", - "%39 = OpLabel", - "%68 = OpVariable %_ptr_Function_float Function", - "%69 = OpVariable %_ptr_Function_float Function", - "%color1 = OpVariable %_ptr_Function_v4float Function", - "%color2 = OpVariable %_ptr_Function_v4float Function", - "%param = OpVariable %_ptr_Function_v4float Function", - "%color3 = OpVariable %_ptr_Function_v4float Function", - "%40 = OpLoad %26 %t2D", - "%41 = OpLoad %28 %samp", - "%42 = OpSampledImage %30 %40 %41", - "%43 = OpImageSampleImplicitLod %v4float %42 %33", - "%44 = OpImage %26 %42", - "%45 = OpLoad %28 %samp2", - "%46 = OpSampledImage %30 %44 %45", - "OpStore %color1 %43", - "%47 = OpLoad %v4float %BaseColor", - "OpStore %param %47", - "%70 = OpAccessChain %_ptr_Function_float %param %uint_0", - "%71 = OpLoad %float %70", - "OpStore %68 %71", - "%72 = OpLoad %float %68", - "%73 = OpFOrdLessThan %bool %72 %float_0", - "OpSelectionMerge %74 None", - "OpBranchConditional %73 %75 %74", - "%75 = OpLabel", - "%76 = OpLoad %float %68", - "%77 = OpFNegate %float %76", - "OpStore %68 %77", - "OpBranch %74", - "%74 = OpLabel", - "%78 = OpLoad %float %68", - "OpStore %69 %78", - "%48 = OpLoad %float %69", - "%49 = OpCompositeConstruct %v4float %48 %48 %48 %48", - "OpStore %color2 %49", - "%79 = OpSampledImage %30 %40 %41", - "%80 = OpImage %26 %79", - "%81 = OpSampledImage %30 %80 %45", - "%50 = OpImageSampleImplicitLod %v4float %81 %36", - "OpStore %color3 %50", - "%51 = OpLoad %v4float %color1", - "%52 = OpLoad %v4float %color2", - "%53 = OpFAdd %v4float %51 %52", - "%54 = OpLoad %v4float %color3", - "%55 = OpFAdd %v4float %53 %54", - "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", - "%57 = OpFDiv %v4float %55 %56", - "OpStore %FragColor %57", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck( - JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), - JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), - /* skip_nop = */ false, /* do_validate = */ true); -} - -TEST_F(InlineTest, EarlyReturnFunctionInlined) { - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // if (bar.x < 0.0) - // return 0.0; - // return bar.x; - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_ "foo(vf4;" -OpName %bar "bar" -OpName %color "color" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%14 = OpTypeFunction %float %_ptr_Function_v4float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string nonEntryFuncs = - R"(%foo_vf4_ = OpFunction %float None %14 -%bar = OpFunctionParameter %_ptr_Function_v4float -%27 = OpLabel -%28 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%29 = OpLoad %float %28 -%30 = OpFOrdLessThan %bool %29 %float_0 -OpSelectionMerge %31 None -OpBranchConditional %30 %32 %31 -%32 = OpLabel -OpReturnValue %float_0 -%31 = OpLabel -%33 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%34 = OpLoad %float %33 -OpReturnValue %34 -OpFunctionEnd -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%22 = OpLabel -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%23 = OpLoad %v4float %BaseColor -OpStore %param %23 -%24 = OpFunctionCall %float %foo_vf4_ %param -%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 -OpStore %color %25 -%26 = OpLoad %v4float %color -OpStore %gl_FragColor %26 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%false = OpConstantFalse %bool -%main = OpFunction %void None %10 -%22 = OpLabel -%35 = OpVariable %_ptr_Function_float Function -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%23 = OpLoad %v4float %BaseColor -OpStore %param %23 -OpBranch %36 -%36 = OpLabel -OpLoopMerge %37 %38 None -OpBranch %39 -%39 = OpLabel -%40 = OpAccessChain %_ptr_Function_float %param %uint_0 -%41 = OpLoad %float %40 -%42 = OpFOrdLessThan %bool %41 %float_0 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %43 -%44 = OpLabel -OpStore %35 %float_0 -OpBranch %37 -%43 = OpLabel -%45 = OpAccessChain %_ptr_Function_float %param %uint_0 -%46 = OpLoad %float %45 -OpStore %35 %46 -OpBranch %37 -%38 = OpLabel -OpBranchConditional %false %36 %37 -%37 = OpLabel -%24 = OpLoad %float %35 -%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 -OpStore %color %25 -%26 = OpLoad %v4float %color -OpStore %gl_FragColor %26 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before + nonEntryFuncs, - predefs + after + nonEntryFuncs, - false, true); -} - -TEST_F(InlineTest, EarlyReturnNotAppearingLastInFunctionInlined) { - // Example from https://github.com/KhronosGroup/SPIRV-Tools/issues/755 - // - // Original example is derived from: - // - // #version 450 - // - // float foo() { - // if (true) { - // } - // } - // - // void main() { foo(); } - // - // But the order of basic blocks in foo is changed so that the return - // block is listed second-last. There is only one return in the callee - // but it does not appear last. - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 450 -OpName %main "main" -OpName %foo_ "foo(" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -)"; - - const std::string nonEntryFuncs = - R"(%foo_ = OpFunction %void None %4 -%7 = OpLabel -OpSelectionMerge %8 None -OpBranchConditional %true %9 %8 -%8 = OpLabel -OpReturn -%9 = OpLabel -OpBranch %8 -OpFunctionEnd -)"; - - const std::string before = - R"(%main = OpFunction %void None %4 -%10 = OpLabel -%11 = OpFunctionCall %void %foo_ -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %4 -%10 = OpLabel -OpSelectionMerge %12 None -OpBranchConditional %true %13 %12 -%12 = OpLabel -OpBranch %14 -%13 = OpLabel -OpBranch %12 -%14 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, ForwardReferencesInPhiInlined) { - // The basic structure of the test case is like this: - // - // int foo() { - // int result = 1; - // if (true) { - // result = 1; - // } - // return result; - // } - // - // void main() { - // int x = foo(); - // } - // - // but with modifications: Using Phi instead of load/store, and the - // return block in foo appears before the "then" block. - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpSource GLSL 450 -OpName %main "main" -OpName %foo_ "foo(" -OpName %x "x" -%void = OpTypeVoid -%6 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%8 = OpTypeFunction %int -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int_0 = OpConstant %int 0 -%_ptr_Function_int = OpTypePointer Function %int -)"; - - const std::string nonEntryFuncs = - R"(%foo_ = OpFunction %int None %8 -%13 = OpLabel -%14 = OpCopyObject %int %int_0 -OpSelectionMerge %15 None -OpBranchConditional %true %16 %15 -%15 = OpLabel -%17 = OpPhi %int %14 %13 %18 %16 -OpReturnValue %17 -%16 = OpLabel -%18 = OpCopyObject %int %int_0 -OpBranch %15 -OpFunctionEnd -)"; - - const std::string before = - R"(%main = OpFunction %void None %6 -%19 = OpLabel -%x = OpVariable %_ptr_Function_int Function -%20 = OpFunctionCall %int %foo_ -OpStore %x %20 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %6 -%19 = OpLabel -%21 = OpVariable %_ptr_Function_int Function -%x = OpVariable %_ptr_Function_int Function -%22 = OpCopyObject %int %int_0 -OpSelectionMerge %23 None -OpBranchConditional %true %24 %23 -%23 = OpLabel -%26 = OpPhi %int %22 %19 %25 %24 -OpStore %21 %26 -OpBranch %27 -%24 = OpLabel -%25 = OpCopyObject %int %int_0 -OpBranch %23 -%27 = OpLabel -%20 = OpLoad %int %21 -OpStore %x %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, EarlyReturnInLoopIsNotInlined) { - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // while (true) { - // if (bar.x < 0.0) - // return 0.0; - // return bar.x; - // } - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_ "foo(vf4;" -OpName %bar "bar" -OpName %color "color" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%14 = OpTypeFunction %float %_ptr_Function_v4float -%bool = OpTypeBool -%true = OpConstantTrue %bool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %10 -%23 = OpLabel -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%24 = OpLoad %v4float %BaseColor -OpStore %param %24 -%25 = OpFunctionCall %float %foo_vf4_ %param -%26 = OpCompositeConstruct %v4float %25 %25 %25 %25 -OpStore %color %26 -%27 = OpLoad %v4float %color -OpStore %gl_FragColor %27 -OpReturn -OpFunctionEnd -%foo_vf4_ = OpFunction %float None %14 -%bar = OpFunctionParameter %_ptr_Function_v4float -%28 = OpLabel -OpBranch %29 -%29 = OpLabel -OpLoopMerge %30 %31 None -OpBranch %32 -%32 = OpLabel -OpBranchConditional %true %33 %30 -%33 = OpLabel -%34 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%35 = OpLoad %float %34 -%36 = OpFOrdLessThan %bool %35 %float_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %37 -%38 = OpLabel -OpReturnValue %float_0 -%37 = OpLabel -%39 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%40 = OpLoad %float %39 -OpReturnValue %40 -%31 = OpLabel -OpBranch %29 -%30 = OpLabel -%41 = OpUndef %float -OpReturnValue %41 -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, false, true); -} - -TEST_F(InlineTest, ExternalFunctionIsNotInlined) { - // In particular, don't crash. - // See report https://github.com/KhronosGroup/SPIRV-Tools/issues/605 - const std::string assembly = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %1 "entry_pt" -OpDecorate %2 LinkageAttributes "external" Import -%void = OpTypeVoid -%4 = OpTypeFunction %void -%2 = OpFunction %void None %4 -OpFunctionEnd -%1 = OpFunction %void None %4 -%5 = OpLabel -%6 = OpFunctionCall %void %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, false, true); -} - -TEST_F(InlineTest, SingleBlockLoopCallsMultiBlockCallee) { - // Example from https://github.com/KhronosGroup/SPIRV-Tools/issues/787 - // - // CFG structure is: - // foo: - // fooentry -> fooexit - // - // main: - // entry -> loop - // loop -> loop, merge - // loop calls foo() - // merge - // - // Since the callee has multiple blocks, it will split the calling block - // into at least two, resulting in a new "back-half" block that contains - // the instructions after the inlined function call. If the calling block - // has an OpLoopMerge that points back to the calling block itself, then - // the OpLoopMerge can't remain in the back-half block, but must be - // moved to the end of the original calling block, and it continue target - // operand updated to point to the back-half block. - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource OpenCL_C 120 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%void = OpTypeVoid -)"; - - const std::string nonEntryFuncs = - R"(%5 = OpTypeFunction %void -%6 = OpFunction %void None %5 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%1 = OpFunction %void None %5 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -%11 = OpFunctionCall %void %6 -OpLoopMerge %12 %10 None -OpBranchConditional %true %10 %12 -%12 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%1 = OpFunction %void None %5 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -OpLoopMerge %12 %10 None -OpBranch %13 -%13 = OpLabel -OpBranchConditional %true %10 %12 -%12 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, MultiBlockLoopHeaderCallsMultiBlockCallee) { - // Like SingleBlockLoopCallsMultiBlockCallee but the loop has several - // blocks, but the function call still occurs in the loop header. - // Example from https://github.com/KhronosGroup/SPIRV-Tools/issues/800 - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource OpenCL_C 120 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_3 = OpConstant %int 3 -%int_4 = OpConstant %int 4 -%int_5 = OpConstant %int 5 -%void = OpTypeVoid -%11 = OpTypeFunction %void -)"; - - const std::string nonEntryFuncs = - R"(%12 = OpFunction %void None %11 -%13 = OpLabel -%14 = OpCopyObject %int %int_1 -OpBranch %15 -%15 = OpLabel -%16 = OpCopyObject %int %int_2 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%1 = OpFunction %void None %11 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpCopyObject %int %int_3 -%20 = OpFunctionCall %void %12 -%21 = OpCopyObject %int %int_4 -OpLoopMerge %22 %23 None -OpBranchConditional %true %23 %22 -%23 = OpLabel -%24 = OpCopyObject %int %int_5 -OpBranchConditional %true %18 %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%1 = OpFunction %void None %11 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpCopyObject %int %int_3 -%25 = OpCopyObject %int %int_1 -OpLoopMerge %22 %23 None -OpBranch %26 -%26 = OpLabel -%27 = OpCopyObject %int %int_2 -%21 = OpCopyObject %int %int_4 -OpBranchConditional %true %23 %22 -%23 = OpLabel -%24 = OpCopyObject %int %int_5 -OpBranchConditional %true %18 %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge) { - // This is similar to SingleBlockLoopCallsMultiBlockCallee except - // that calleee block also has a merge instruction in its first block. - // That merge instruction must be an OpSelectionMerge (because the entry - // block of a function can't be the header of a loop since the entry - // block can't be the target of a branch). - // - // In this case the OpLoopMerge can't be placed in the same block as - // the OpSelectionMerge, so inlining must create a new block to contain - // the callee contents. - // - // Additionally, we have two dummy OpCopyObject instructions to prove that - // the OpLoopMerge is moved to the right location. - // - // Also ensure that OpPhis within the cloned callee code are valid. - // We need to test that the predecessor blocks are remapped correctly so that - // dominance rules are satisfied - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource OpenCL_C 120 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%void = OpTypeVoid -%6 = OpTypeFunction %void -)"; - - // This callee has multiple blocks, and an OpPhi in the last block - // that references a value from the first block. This tests that - // cloned block IDs are remapped appropriately. The OpPhi dominance - // requires that the remapped %9 must be in a block that dominates - // the remapped %8. - const std::string nonEntryFuncs = - R"(%7 = OpFunction %void None %6 -%8 = OpLabel -%9 = OpCopyObject %bool %true -OpSelectionMerge %10 None -OpBranchConditional %true %10 %10 -%10 = OpLabel -%11 = OpPhi %bool %9 %8 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%1 = OpFunction %void None %6 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%14 = OpCopyObject %bool %false -%15 = OpFunctionCall %void %7 -OpLoopMerge %16 %13 None -OpBranchConditional %true %13 %16 -%16 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // Note the remapped Phi uses %17 as the parent instead - // of %13, demonstrating that the parent block has been remapped - // correctly. - const std::string after = - R"(%1 = OpFunction %void None %6 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%14 = OpCopyObject %bool %false -OpLoopMerge %16 %13 None -OpBranch %17 -%17 = OpLabel -%18 = OpCopyObject %bool %true -OpSelectionMerge %19 None -OpBranchConditional %true %19 %19 -%19 = OpLabel -%20 = OpPhi %bool %18 %17 -OpBranchConditional %true %13 %16 -%16 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, - MultiBlockLoopHeaderCallsFromToMultiBlockCalleeHavingSelectionMerge) { - // This is similar to SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge - // but the call is in the header block of a multi block loop. - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource OpenCL_C 120 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_3 = OpConstant %int 3 -%int_4 = OpConstant %int 4 -%int_5 = OpConstant %int 5 -%void = OpTypeVoid -%11 = OpTypeFunction %void -)"; - - const std::string nonEntryFuncs = - R"(%12 = OpFunction %void None %11 -%13 = OpLabel -%14 = OpCopyObject %int %int_1 -OpSelectionMerge %15 None -OpBranchConditional %true %15 %15 -%15 = OpLabel -%16 = OpCopyObject %int %int_2 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%1 = OpFunction %void None %11 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpCopyObject %int %int_3 -%20 = OpFunctionCall %void %12 -%21 = OpCopyObject %int %int_4 -OpLoopMerge %22 %23 None -OpBranchConditional %true %23 %22 -%23 = OpLabel -%24 = OpCopyObject %int %int_5 -OpBranchConditional %true %18 %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%1 = OpFunction %void None %11 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpCopyObject %int %int_3 -OpLoopMerge %22 %23 None -OpBranch %25 -%25 = OpLabel -%26 = OpCopyObject %int %int_1 -OpSelectionMerge %27 None -OpBranchConditional %true %27 %27 -%27 = OpLabel -%28 = OpCopyObject %int %int_2 -%21 = OpCopyObject %int %int_4 -OpBranchConditional %true %23 %22 -%23 = OpLabel -%24 = OpCopyObject %int %int_5 -OpBranchConditional %true %18 %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F( - InlineTest, - SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMergeAndMultiReturns) { - // This is similar to SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge - // except that in addition to starting with a selection header, the - // callee also has multi returns. - // - // So now we have to accommodate: - // - The caller's OpLoopMerge (which must move to the first block) - // - The single-trip loop to wrap the multi returns, and - // - The callee's selection merge in its first block. - // Each of these must go into their own blocks. - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource OpenCL_C 120 -%bool = OpTypeBool -%int = OpTypeInt 32 1 -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%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 -%void = OpTypeVoid -%12 = OpTypeFunction %void -)"; - - const std::string nonEntryFuncs = - R"(%13 = OpFunction %void None %12 -%14 = OpLabel -%15 = OpCopyObject %int %int_0 -OpReturn -%16 = OpLabel -%17 = OpCopyObject %int %int_1 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%1 = OpFunction %void None %12 -%18 = OpLabel -OpBranch %19 -%19 = OpLabel -%20 = OpCopyObject %int %int_2 -%21 = OpFunctionCall %void %13 -%22 = OpCopyObject %int %int_3 -OpLoopMerge %23 %19 None -OpBranchConditional %true %19 %23 -%23 = OpLabel -%24 = OpCopyObject %int %int_4 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%1 = OpFunction %void None %12 -%18 = OpLabel -OpBranch %19 -%19 = OpLabel -%20 = OpCopyObject %int %int_2 -%25 = OpCopyObject %int %int_0 -OpLoopMerge %23 %19 None -OpBranch %26 -%27 = OpLabel -%28 = OpCopyObject %int %int_1 -OpBranch %26 -%26 = OpLabel -%22 = OpCopyObject %int %int_3 -OpBranchConditional %true %19 %23 -%23 = OpLabel -%24 = OpCopyObject %int %int_4 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, CalleeWithMultiReturnAndPhiRequiresEntryBlockRemapping) { - // The case from https://github.com/KhronosGroup/SPIRV-Tools/issues/790 - // - // The callee has multiple returns, and so must be wrapped with a single-trip - // loop. That code must remap the callee entry block ID to the introduced - // loop body's ID. Otherwise you can get a dominance error in a cloned OpPhi. - - const std::string predefs = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource OpenCL_C 120 -%int = OpTypeInt 32 1 -%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 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%bool = OpTypeBool -%false = OpConstantFalse %bool -)"; - - // This callee has multiple returns, and a Phi in the second block referencing - // a value generated in the entry block. - const std::string nonEntryFuncs = - R"(%12 = OpFunction %void None %9 -%13 = OpLabel -%14 = OpCopyObject %int %int_0 -OpBranch %15 -%15 = OpLabel -%16 = OpPhi %int %14 %13 -%17 = OpCopyObject %int %int_1 -OpReturn -%18 = OpLabel -%19 = OpCopyObject %int %int_2 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%1 = OpFunction %void None %9 -%20 = OpLabel -%21 = OpCopyObject %int %int_3 -%22 = OpFunctionCall %void %12 -%23 = OpCopyObject %int %int_4 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%1 = OpFunction %void None %9 -%20 = OpLabel -%21 = OpCopyObject %int %int_3 -%24 = OpCopyObject %int %int_0 -OpBranch %25 -%25 = OpLabel -%26 = OpPhi %int %24 %20 -%27 = OpCopyObject %int %int_1 -OpBranch %28 -%29 = OpLabel -%30 = OpCopyObject %int %int_2 -OpBranch %28 -%28 = OpLabel -%23 = OpCopyObject %int %int_4 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + nonEntryFuncs + before, - predefs + nonEntryFuncs + after, - false, true); -} - -TEST_F(InlineTest, NonInlinableCalleeWithSingleReturn) { - // The case from https://github.com/KhronosGroup/SPIRV-Tools/issues/2018 - // - // The callee has a single return, but cannot be inlined because the - // return is inside a loop. - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_GLF_color -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -OpName %f_ "f(" -OpName %i "i" -OpName %_GLF_color "_GLF_color" -OpDecorate %_GLF_color Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%9 = OpTypeFunction %float -%float_1 = OpConstant %float 1 -%bool = OpTypeBool -%false = OpConstantFalse %bool -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_GLF_color = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%20 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%21 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 -)"; - - const std::string caller = - R"(%main = OpFunction %void None %7 -%22 = OpLabel -%i = OpVariable %_ptr_Function_int Function -OpStore %i %int_0 -OpBranch %23 -%23 = OpLabel -OpLoopMerge %24 %25 None -OpBranch %26 -%26 = OpLabel -%27 = OpLoad %int %i -%28 = OpSLessThan %bool %27 %int_1 -OpBranchConditional %28 %29 %24 -%29 = OpLabel -OpStore %_GLF_color %20 -%30 = OpFunctionCall %float %f_ -OpBranch %25 -%25 = OpLabel -%31 = OpLoad %int %i -%32 = OpIAdd %int %31 %int_1 -OpStore %i %32 -OpBranch %23 -%24 = OpLabel -OpStore %_GLF_color %21 -OpReturn -OpFunctionEnd -)"; - - const std::string callee = - R"(%f_ = OpFunction %float None %9 -%33 = OpLabel -OpBranch %34 -%34 = OpLabel -OpLoopMerge %35 %36 None -OpBranch %37 -%37 = OpLabel -OpReturnValue %float_1 -%36 = OpLabel -OpBranch %34 -%35 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + caller + callee, predefs + caller + callee, false, true); -} - -TEST_F(InlineTest, CalleeWithSingleReturnNeedsSingleTripLoopWrapper) { - // The case from https://github.com/KhronosGroup/SPIRV-Tools/issues/2018 - // - // The callee has a single return, but needs single-trip loop wrapper - // to be inlined because the return is in a selection structure. - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_GLF_color -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -OpName %main "main" -OpName %f_ "f(" -OpName %i "i" -OpName %_GLF_color "_GLF_color" -OpDecorate %_GLF_color Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%9 = OpTypeFunction %float -%float_1 = OpConstant %float 1 -%bool = OpTypeBool -%false = OpConstantFalse %bool -%true = OpConstantTrue %bool -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_GLF_color = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%22 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 -)"; - - const std::string new_predefs = - R"(%_ptr_Function_float = OpTypePointer Function %float -)"; - - const std::string main_before = - R"(%main = OpFunction %void None %7 -%23 = OpLabel -%i = OpVariable %_ptr_Function_int Function -OpStore %i %int_0 -OpBranch %24 -%24 = OpLabel -OpLoopMerge %25 %26 None -OpBranch %27 -%27 = OpLabel -%28 = OpLoad %int %i -%29 = OpSLessThan %bool %28 %int_1 -OpBranchConditional %29 %30 %25 -%30 = OpLabel -OpStore %_GLF_color %21 -%31 = OpFunctionCall %float %f_ -OpBranch %26 -%26 = OpLabel -%32 = OpLoad %int %i -%33 = OpIAdd %int %32 %int_1 -OpStore %i %33 -OpBranch %24 -%25 = OpLabel -OpStore %_GLF_color %22 -OpReturn -OpFunctionEnd -)"; - - const std::string main_after = - R"(%main = OpFunction %void None %7 -%23 = OpLabel -%38 = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %i %int_0 -OpBranch %24 -%24 = OpLabel -OpLoopMerge %25 %26 None -OpBranch %27 -%27 = OpLabel -%28 = OpLoad %int %i -%29 = OpSLessThan %bool %28 %int_1 -OpBranchConditional %29 %30 %25 -%30 = OpLabel -OpStore %_GLF_color %21 -OpBranch %39 -%39 = OpLabel -OpLoopMerge %40 %41 None -OpBranch %42 -%42 = OpLabel -OpSelectionMerge %43 None -OpBranchConditional %true %44 %43 -%44 = OpLabel -OpStore %38 %float_1 -OpBranch %40 -%43 = OpLabel -OpStore %38 %float_1 -OpBranch %40 -%41 = OpLabel -OpBranchConditional %false %39 %40 -%40 = OpLabel -%31 = OpLoad %float %38 -OpBranch %26 -%26 = OpLabel -%32 = OpLoad %int %i -%33 = OpIAdd %int %32 %int_1 -OpStore %i %33 -OpBranch %24 -%25 = OpLabel -OpStore %_GLF_color %22 -OpReturn -OpFunctionEnd -)"; - - const std::string callee = - R"(%f_ = OpFunction %float None %9 -%34 = OpLabel -OpSelectionMerge %35 None -OpBranchConditional %true %36 %35 -%36 = OpLabel -OpReturnValue %float_1 -%35 = OpLabel -OpReturnValue %float_1 -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + main_before + callee, - predefs + new_predefs + main_after + callee, false, true); -} - -TEST_F(InlineTest, Decorated1) { - // Same test as Simple with the difference - // that OpFAdd in the outlined function is - // decorated with RelaxedPrecision - // Expected result is an equal decoration - // of the corresponding inlined instruction - // - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // return bar.x + bar.y; - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_ "foo(vf4;" -OpName %bar "bar" -OpName %color "color" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %9 RelaxedPrecision -)"; - - const std::string before = - R"(%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%15 = OpTypeFunction %float %_ptr_Function_v4float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %11 -%22 = OpLabel -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%23 = OpLoad %v4float %BaseColor -OpStore %param %23 -%24 = OpFunctionCall %float %foo_vf4_ %param -%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 -OpStore %color %25 -%26 = OpLoad %v4float %color -OpStore %gl_FragColor %26 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpDecorate %37 RelaxedPrecision -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%15 = OpTypeFunction %float %_ptr_Function_v4float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %11 -%22 = OpLabel -%32 = OpVariable %_ptr_Function_float Function -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%23 = OpLoad %v4float %BaseColor -OpStore %param %23 -%33 = OpAccessChain %_ptr_Function_float %param %uint_0 -%34 = OpLoad %float %33 -%35 = OpAccessChain %_ptr_Function_float %param %uint_1 -%36 = OpLoad %float %35 -%37 = OpFAdd %float %34 %36 -OpStore %32 %37 -%24 = OpLoad %float %32 -%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 -OpStore %color %25 -%26 = OpLoad %v4float %color -OpStore %gl_FragColor %26 -OpReturn -OpFunctionEnd -)"; - - const std::string nonEntryFuncs = - R"(%foo_vf4_ = OpFunction %float None %15 -%bar = OpFunctionParameter %_ptr_Function_v4float -%27 = OpLabel -%28 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%29 = OpLoad %float %28 -%30 = OpAccessChain %_ptr_Function_float %bar %uint_1 -%31 = OpLoad %float %30 -%9 = OpFAdd %float %29 %31 -OpReturnValue %9 -OpFunctionEnd -)"; - SinglePassRunAndCheck(predefs + before + nonEntryFuncs, - predefs + after + nonEntryFuncs, - false, true); -} - -TEST_F(InlineTest, Decorated2) { - // Same test as Simple with the difference - // that the Result of the outlined OpFunction - // is decorated with RelaxedPrecision - // Expected result is an equal decoration - // of the created return variable - // - // #version 140 - // - // in vec4 BaseColor; - // - // float foo(vec4 bar) - // { - // return bar.x + bar.y; - // } - // - // void main() - // { - // vec4 color = vec4(foo(BaseColor)); - // gl_FragColor = color; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_ "foo(vf4;" -OpName %bar "bar" -OpName %color "color" -OpName %BaseColor "BaseColor" -OpName %param "param" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %foo_vf4_ RelaxedPrecision -)"; - - const std::string before = - R"(%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%14 = OpTypeFunction %float %_ptr_Function_v4float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %10 -%21 = OpLabel -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %BaseColor -OpStore %param %22 -%23 = OpFunctionCall %float %foo_vf4_ %param -%24 = OpCompositeConstruct %v4float %23 %23 %23 %23 -OpStore %color %24 -%25 = OpLoad %v4float %color -OpStore %gl_FragColor %25 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpDecorate %32 RelaxedPrecision -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%14 = OpTypeFunction %float %_ptr_Function_v4float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%uint_1 = OpConstant %uint 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %10 -%21 = OpLabel -%32 = OpVariable %_ptr_Function_float Function -%color = OpVariable %_ptr_Function_v4float Function -%param = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %BaseColor -OpStore %param %22 -%33 = OpAccessChain %_ptr_Function_float %param %uint_0 -%34 = OpLoad %float %33 -%35 = OpAccessChain %_ptr_Function_float %param %uint_1 -%36 = OpLoad %float %35 -%37 = OpFAdd %float %34 %36 -OpStore %32 %37 -%23 = OpLoad %float %32 -%24 = OpCompositeConstruct %v4float %23 %23 %23 %23 -OpStore %color %24 -%25 = OpLoad %v4float %color -OpStore %gl_FragColor %25 -OpReturn -OpFunctionEnd -)"; - - const std::string nonEntryFuncs = - R"(%foo_vf4_ = OpFunction %float None %14 -%bar = OpFunctionParameter %_ptr_Function_v4float -%26 = OpLabel -%27 = OpAccessChain %_ptr_Function_float %bar %uint_0 -%28 = OpLoad %float %27 -%29 = OpAccessChain %_ptr_Function_float %bar %uint_1 -%30 = OpLoad %float %29 -%31 = OpFAdd %float %28 %30 -OpReturnValue %31 -OpFunctionEnd -)"; - SinglePassRunAndCheck(predefs + before + nonEntryFuncs, - predefs + after + nonEntryFuncs, - false, true); -} - -TEST_F(InlineTest, DeleteName) { - // Test that the name of the result id of the call is deleted. - const std::string before = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - OpName %main_entry "main_entry" - OpName %foo_result "foo_result" - OpName %void_fn "void_fn" - OpName %foo "foo" - OpName %foo_entry "foo_entry" - %void = OpTypeVoid - %void_fn = OpTypeFunction %void - %foo = OpFunction %void None %void_fn - %foo_entry = OpLabel - OpReturn - OpFunctionEnd - %main = OpFunction %void None %void_fn - %main_entry = OpLabel - %foo_result = OpFunctionCall %void %foo - OpReturn - OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpName %main "main" -OpName %main_entry "main_entry" -OpName %void_fn "void_fn" -OpName %foo "foo" -OpName %foo_entry "foo_entry" -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%foo_entry = OpLabel -OpReturn -OpFunctionEnd -%main = OpFunction %void None %void_fn -%main_entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(InlineTest, SetParent) { - // Test that after inlining all basic blocks have the correct parent. - const std::string text = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - OpName %main_entry "main_entry" - OpName %foo_result "foo_result" - OpName %void_fn "void_fn" - OpName %foo "foo" - OpName %foo_entry "foo_entry" - %void = OpTypeVoid - %void_fn = OpTypeFunction %void - %foo = OpFunction %void None %void_fn - %foo_entry = OpLabel - OpReturn - OpFunctionEnd - %main = OpFunction %void None %void_fn - %main_entry = OpLabel - %foo_result = OpFunctionCall %void %foo - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - InlineExhaustivePass pass; - pass.Run(context.get()); - - for (Function& func : *context->module()) { - for (BasicBlock& bb : func) { - EXPECT_TRUE(bb.GetParent() == &func); - } - } -} - -TEST_F(InlineTest, OpVariableWithInit) { - // Check that there is a store that corresponds to the initializer. This - // test makes sure that is a store to the variable in the loop and before any - // load. - const std::string text = R"( -; CHECK: OpFunction -; CHECK-NOT: OpFunctionEnd -; CHECK: [[var:%\w+]] = OpVariable %_ptr_Function_float Function %float_0 -; CHECK: OpLoopMerge [[outer_merge:%\w+]] -; CHECK-NOT: OpLoad %float [[var]] -; CHECK: OpStore [[var]] %float_0 -; CHECK: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %o - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpDecorate %o Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %7 = OpTypeFunction %float -%_ptr_Function_float = OpTypePointer Function %float - %float_0 = OpConstant %float 0 - %bool = OpTypeBool - %float_1 = OpConstant %float 1 -%_ptr_Output_float = OpTypePointer Output %float - %o = OpVariable %_ptr_Output_float Output - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_int = OpTypePointer Input %int - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %int_2 = OpConstant %int 2 - %main = OpFunction %void None %3 - %5 = OpLabel - OpStore %o %float_0 - OpBranch %34 - %34 = OpLabel - %39 = OpPhi %int %int_0 %5 %47 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %41 = OpSLessThan %bool %39 %int_2 - OpBranchConditional %41 %35 %36 - %35 = OpLabel - %42 = OpFunctionCall %float %foo_ - %43 = OpLoad %float %o - %44 = OpFAdd %float %43 %42 - OpStore %o %44 - OpBranch %37 - %37 = OpLabel - %47 = OpIAdd %int %39 %int_1 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - %foo_ = OpFunction %float None %7 - %9 = OpLabel - %n = OpVariable %_ptr_Function_float Function %float_0 - %13 = OpLoad %float %n - %15 = OpFOrdEqual %bool %13 %float_0 - OpSelectionMerge %17 None - OpBranchConditional %15 %16 %17 - %16 = OpLabel - %19 = OpLoad %float %n - %20 = OpFAdd %float %19 %float_1 - OpStore %n %20 - OpBranch %17 - %17 = OpLabel - %21 = OpLoad %float %n - OpReturnValue %21 - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(InlineTest, DontInlineDirectlyRecursiveFunc) { - // Test that the name of the result id of the call is deleted. - const std::string test = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 DescriptorSet 439418829 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%15 = OpConstantNull %_struct_6 -%7 = OpTypeFunction %_struct_6 -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %9 -OpReturnValue %15 -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, false, true); -} - -TEST_F(InlineTest, DontInlineInDirectlyRecursiveFunc) { - // Test that the name of the result id of the call is deleted. - const std::string test = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 DescriptorSet 439418829 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%15 = OpConstantNull %_struct_6 -%7 = OpTypeFunction %_struct_6 -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %12 -OpReturnValue %15 -OpFunctionEnd -%12 = OpFunction %_struct_6 None %7 -%13 = OpLabel -%14 = OpFunctionCall %_struct_6 %9 -OpReturnValue %15 -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, false, true); -} - -TEST_F(InlineTest, DontInlineFuncWithOpKillInContinue) { - const std::string test = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 330 -OpName %main "main" -OpName %kill_ "kill(" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %void None %3 -%5 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %11 %12 None -OpBranch %13 -%13 = OpLabel -OpBranchConditional %true %10 %11 -%10 = OpLabel -OpBranch %12 -%12 = OpLabel -%16 = OpFunctionCall %void %kill_ -OpBranch %9 -%11 = OpLabel -OpReturn -OpFunctionEnd -%kill_ = OpFunction %void None %3 -%7 = OpLabel -OpKill -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(test, test, false, true); -} - -TEST_F(InlineTest, InlineFuncWithOpKillNotInContinue) { - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 330 -OpName %main "main" -OpName %kill_ "kill(" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpFunctionCall %void %kill_ -OpReturn -OpFunctionEnd -%kill_ = OpFunction %void None %3 -%7 = OpLabel -OpKill -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 330 -OpName %main "main" -OpName %kill_ "kill(" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %void None %3 -%5 = OpLabel -OpKill -%17 = OpLabel -OpReturn -OpFunctionEnd -%kill_ = OpFunction %void None %3 -%7 = OpLabel -OpKill -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, false, true); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// Empty modules -// Modules without function definitions -// Modules in which all functions do not call other functions -// Caller and callee both accessing the same global variable -// Functions with OpLine & OpNoLine -// Others? - -// TODO(dneto): Test suggestions from code review -// https://github.com/KhronosGroup/SPIRV-Tools/pull/534 -// -// Callee function returns a value generated outside the callee, -// e.g. a constant value. This might exercise some logic not yet -// exercised by the current tests: the false branch in the "if" -// inside the SpvOpReturnValue case in InlinePass::GenInlineCode? -// SampledImage before function call, but callee is only single block. -// Then the SampledImage instruction is not cloned. Documents existing -// behaviour. -// SampledImage after function call. It is not cloned or changed. - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/insert_extract_elim_test.cpp b/3rdparty/spirv-tools/test/opt/insert_extract_elim_test.cpp deleted file mode 100644 index c5169750b..000000000 --- a/3rdparty/spirv-tools/test/opt/insert_extract_elim_test.cpp +++ /dev/null @@ -1,900 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "source/opt/simplification_pass.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using InsertExtractElimTest = PassTest<::testing::Test>; - -TEST_F(InsertExtractElimTest, Simple) { - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // gl_FragColor = s0.v1; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpLoad %S_t %s0 -%20 = OpCompositeInsert %S_t %18 %19 1 -OpStore %s0 %20 -%21 = OpCompositeExtract %v4float %20 1 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpLoad %S_t %s0 -%20 = OpCompositeInsert %S_t %18 %19 1 -OpStore %s0 %20 -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(InsertExtractElimTest, OptimizeAcrossNonConflictingInsert) { - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // s0.v0[2] = 0.0; - // gl_FragColor = s0.v1; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%18 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%19 = OpLoad %v4float %BaseColor -%20 = OpLoad %S_t %s0 -%21 = OpCompositeInsert %S_t %19 %20 1 -%22 = OpCompositeInsert %S_t %float_0 %21 0 2 -OpStore %s0 %22 -%23 = OpCompositeExtract %v4float %22 1 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%18 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%19 = OpLoad %v4float %BaseColor -%20 = OpLoad %S_t %s0 -%21 = OpCompositeInsert %S_t %19 %20 1 -%22 = OpCompositeInsert %S_t %float_0 %21 0 2 -OpStore %s0 %22 -OpStore %gl_FragColor %19 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(InsertExtractElimTest, OptimizeOpaque) { - // SPIR-V not representable in GLSL; not generatable from HLSL - // for the moment. - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpMemberName %S_t 2 "smp" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %s0 "s0" -OpName %texCoords "texCoords" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%14 = OpTypeImage %float 2D 0 0 0 1 Unknown -%15 = OpTypeSampledImage %14 -%S_t = OpTypeStruct %v2float %v2float %15 -%_ptr_Function_S_t = OpTypePointer Function %S_t -%17 = OpTypeFunction %void %_ptr_Function_S_t -%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 -%_ptr_Function_15 = OpTypePointer Function %15 -%sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%25 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%26 = OpLoad %v2float %texCoords -%27 = OpLoad %S_t %s0 -%28 = OpCompositeInsert %S_t %26 %27 0 -%29 = OpLoad %15 %sampler15 -%30 = OpCompositeInsert %S_t %29 %28 2 -OpStore %s0 %30 -%31 = OpCompositeExtract %15 %30 2 -%32 = OpCompositeExtract %v2float %30 0 -%33 = OpImageSampleImplicitLod %v4float %31 %32 -OpStore %outColor %33 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%25 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%26 = OpLoad %v2float %texCoords -%27 = OpLoad %S_t %s0 -%28 = OpCompositeInsert %S_t %26 %27 0 -%29 = OpLoad %15 %sampler15 -%30 = OpCompositeInsert %S_t %29 %28 2 -OpStore %s0 %30 -%33 = OpImageSampleImplicitLod %v4float %29 %26 -OpStore %outColor %33 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(InsertExtractElimTest, OptimizeNestedStruct) { - // The following HLSL has been pre-optimized to get the SPIR-V: - // struct S0 - // { - // int x; - // SamplerState ss; - // }; - // - // struct S1 - // { - // float b; - // S0 s0; - // }; - // - // struct S2 - // { - // int a1; - // S1 resources; - // }; - // - // SamplerState samp; - // Texture2D tex; - // - // float4 main(float4 vpos : VPOS) : COLOR0 - // { - // S1 s1; - // S2 s2; - // s1.s0.ss = samp; - // s2.resources = s1; - // return tex.Sample(s2.resources.s0.ss, float2(0.5)); - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %_entryPointOutput -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %S0 "S0" -OpMemberName %S0 0 "x" -OpMemberName %S0 1 "ss" -OpName %S1 "S1" -OpMemberName %S1 0 "b" -OpMemberName %S1 1 "s0" -OpName %samp "samp" -OpName %S2 "S2" -OpMemberName %S2 0 "a1" -OpMemberName %S2 1 "resources" -OpName %tex "tex" -OpName %_entryPointOutput "@entryPointOutput" -OpDecorate %samp DescriptorSet 0 -OpDecorate %tex DescriptorSet 0 -OpDecorate %_entryPointOutput Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%14 = OpTypeFunction %v4float %_ptr_Function_v4float -%int = OpTypeInt 32 1 -%16 = OpTypeSampler -%S0 = OpTypeStruct %int %16 -%S1 = OpTypeStruct %float %S0 -%_ptr_Function_S1 = OpTypePointer Function %S1 -%int_1 = OpConstant %int 1 -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%samp = OpVariable %_ptr_UniformConstant_16 UniformConstant -%_ptr_Function_16 = OpTypePointer Function %16 -%S2 = OpTypeStruct %int %S1 -%_ptr_Function_S2 = OpTypePointer Function %S2 -%22 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22 -%tex = OpVariable %_ptr_UniformConstant_22 UniformConstant -%24 = OpTypeSampledImage %22 -%v2float = OpTypeVector %float 2 -%float_0_5 = OpConstant %float 0.5 -%27 = OpConstantComposite %v2float %float_0_5 %float_0_5 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%30 = OpLabel -%31 = OpVariable %_ptr_Function_S1 Function -%32 = OpVariable %_ptr_Function_S2 Function -%33 = OpLoad %16 %samp -%34 = OpLoad %S1 %31 -%35 = OpCompositeInsert %S1 %33 %34 1 1 -OpStore %31 %35 -%36 = OpLoad %S2 %32 -%37 = OpCompositeInsert %S2 %35 %36 1 -OpStore %32 %37 -%38 = OpLoad %22 %tex -%39 = OpCompositeExtract %16 %37 1 1 1 -%40 = OpSampledImage %24 %38 %39 -%41 = OpImageSampleImplicitLod %v4float %40 %27 -OpStore %_entryPointOutput %41 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%30 = OpLabel -%31 = OpVariable %_ptr_Function_S1 Function -%32 = OpVariable %_ptr_Function_S2 Function -%33 = OpLoad %16 %samp -%34 = OpLoad %S1 %31 -%35 = OpCompositeInsert %S1 %33 %34 1 1 -OpStore %31 %35 -%36 = OpLoad %S2 %32 -%37 = OpCompositeInsert %S2 %35 %36 1 -OpStore %32 %37 -%38 = OpLoad %22 %tex -%40 = OpSampledImage %24 %38 %33 -%41 = OpImageSampleImplicitLod %v4float %40 %27 -OpStore %_entryPointOutput %41 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(InsertExtractElimTest, ConflictingInsertPreventsOptimization) { - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // s0.v1[2] = 0.0; - // gl_FragColor = s0.v1; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %8 -%18 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%19 = OpLoad %v4float %BaseColor -%20 = OpLoad %S_t %s0 -%21 = OpCompositeInsert %S_t %19 %20 1 -%22 = OpCompositeInsert %S_t %float_0 %21 1 2 -OpStore %s0 %22 -%23 = OpCompositeExtract %v4float %22 1 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, true); -} - -TEST_F(InsertExtractElimTest, ConflictingInsertPreventsOptimization2) { - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1[1] = 1.0; // dead - // s0.v1 = Baseline; - // gl_FragColor = vec4(s0.v1[1], 0.0, 0.0, 0.0); - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%float_1 = OpConstant %float 1 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%float_1 = OpConstant %float 1 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%23 = OpLoad %S_t %s0 -%24 = OpCompositeInsert %S_t %float_1 %23 1 1 -%25 = OpLoad %v4float %BaseColor -%26 = OpCompositeInsert %S_t %25 %24 1 -%27 = OpCompositeExtract %float %26 1 1 -%28 = OpCompositeConstruct %v4float %27 %float_0 %float_0 %float_0 -OpStore %gl_FragColor %28 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%23 = OpLoad %S_t %s0 -%24 = OpCompositeInsert %S_t %float_1 %23 1 1 -%25 = OpLoad %v4float %BaseColor -%26 = OpCompositeInsert %S_t %25 %24 1 -%27 = OpCompositeExtract %float %25 1 -%28 = OpCompositeConstruct %v4float %27 %float_0 %float_0 %float_0 -OpStore %gl_FragColor %28 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -TEST_F(InsertExtractElimTest, MixWithConstants) { - // Extract component of FMix with 0.0 or 1.0 as the a-value. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in float bc; - // layout (location=1) in float bc2; - // layout (location=2) in float m; - // layout (location=3) in float m2; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec4 bcv = vec4(bc, bc2, 0.0, 1.0); - // vec4 bcv2 = vec4(bc2, bc, 1.0, 0.0); - // vec4 v = mix(bcv, bcv2, vec4(0.0,1.0,m,m2)); - // OutColor = vec4(v.y); - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %bc %bc2 %m %m2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %bc "bc" -OpName %bc2 "bc2" -OpName %m "m" -OpName %m2 "m2" -OpName %OutColor "OutColor" -OpDecorate %bc Location 0 -OpDecorate %bc2 Location 1 -OpDecorate %m Location 2 -OpDecorate %m2 Location 3 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_float = OpTypePointer Input %float -%bc = OpVariable %_ptr_Input_float Input -%bc2 = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%m = OpVariable %_ptr_Input_float Input -%m2 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%20 = OpLoad %float %bc -%21 = OpLoad %float %bc2 -%22 = OpCompositeConstruct %v4float %20 %21 %float_0 %float_1 -%23 = OpLoad %float %bc2 -%24 = OpLoad %float %bc -%25 = OpCompositeConstruct %v4float %23 %24 %float_1 %float_0 -%26 = OpLoad %float %m -%27 = OpLoad %float %m2 -%28 = OpCompositeConstruct %v4float %float_0 %float_1 %26 %27 -%29 = OpExtInst %v4float %1 FMix %22 %25 %28 -%30 = OpCompositeExtract %float %29 1 -%31 = OpCompositeConstruct %v4float %30 %30 %30 %30 -OpStore %OutColor %31 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%20 = OpLoad %float %bc -%21 = OpLoad %float %bc2 -%22 = OpCompositeConstruct %v4float %20 %21 %float_0 %float_1 -%23 = OpLoad %float %bc2 -%24 = OpLoad %float %bc -%25 = OpCompositeConstruct %v4float %23 %24 %float_1 %float_0 -%26 = OpLoad %float %m -%27 = OpLoad %float %m2 -%28 = OpCompositeConstruct %v4float %float_0 %float_1 %26 %27 -%29 = OpExtInst %v4float %1 FMix %22 %25 %28 -%31 = OpCompositeConstruct %v4float %24 %24 %24 %24 -OpStore %OutColor %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - true, true); -} - -TEST_F(InsertExtractElimTest, VectorShuffle1) { - // Extract component from first vector in VectorShuffle - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in float bc; - // layout (location=1) in float bc2; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec4 bcv = vec4(bc, bc2, 0.0, 1.0); - // vec4 v = bcv.zwxy; - // OutColor = vec4(v.y); - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %bc "bc" -OpName %bc2 "bc2" -OpName %OutColor "OutColor" -OpDecorate %bc Location 0 -OpDecorate %bc2 Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_float = OpTypePointer Input %float -%bc = OpVariable %_ptr_Input_float Input -%bc2 = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -)"; - - const std::string predefs_after = predefs_before + - "%24 = OpConstantComposite %v4float " - "%float_1 %float_1 %float_1 %float_1\n"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%18 = OpLoad %float %bc -%19 = OpLoad %float %bc2 -%20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1 -%21 = OpVectorShuffle %v4float %20 %20 2 3 0 1 -%22 = OpCompositeExtract %float %21 1 -%23 = OpCompositeConstruct %v4float %22 %22 %22 %22 -OpStore %OutColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%18 = OpLoad %float %bc -%19 = OpLoad %float %bc2 -%20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1 -%21 = OpVectorShuffle %v4float %20 %20 2 3 0 1 -OpStore %OutColor %24 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs_before + before, - predefs_after + after, true, true); -} - -TEST_F(InsertExtractElimTest, VectorShuffle2) { - // Extract component from second vector in VectorShuffle - // Identical to test VectorShuffle1 except for the vector - // shuffle index of 7. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in float bc; - // layout (location=1) in float bc2; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec4 bcv = vec4(bc, bc2, 0.0, 1.0); - // vec4 v = bcv.zwxy; - // OutColor = vec4(v.y); - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %bc "bc" -OpName %bc2 "bc2" -OpName %OutColor "OutColor" -OpDecorate %bc Location 0 -OpDecorate %bc2 Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_float = OpTypePointer Input %float -%bc = OpVariable %_ptr_Input_float Input -%bc2 = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -)"; - - const std::string predefs_after = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %bc "bc" -OpName %bc2 "bc2" -OpName %OutColor "OutColor" -OpDecorate %bc Location 0 -OpDecorate %bc2 Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_float = OpTypePointer Input %float -%bc = OpVariable %_ptr_Input_float Input -%bc2 = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%24 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%18 = OpLoad %float %bc -%19 = OpLoad %float %bc2 -%20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1 -%21 = OpVectorShuffle %v4float %20 %20 2 7 0 1 -%22 = OpCompositeExtract %float %21 1 -%23 = OpCompositeConstruct %v4float %22 %22 %22 %22 -OpStore %OutColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%17 = OpLabel -%18 = OpLoad %float %bc -%19 = OpLoad %float %bc2 -%20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1 -%21 = OpVectorShuffle %v4float %20 %20 2 7 0 1 -OpStore %OutColor %24 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs_before + before, - predefs_after + after, true, true); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/inst_bindless_check_test.cpp b/3rdparty/spirv-tools/test/opt/inst_bindless_check_test.cpp deleted file mode 100644 index b4db2d50a..000000000 --- a/3rdparty/spirv-tools/test/opt/inst_bindless_check_test.cpp +++ /dev/null @@ -1,11243 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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. - -// Bindless Check Instrumentation Tests. -// Tests ending with V2 use version 2 record format. - -#include -#include - -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using InstBindlessTest = PassTest<::testing::Test>; - -TEST_F(InstBindlessTest, Simple) { - // Texture2D g_tColor[128]; - // - // layout(push_constant) cbuffer PerViewConstantBuffer_t - // { - // uint g_nDataIdx; - // }; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // ps_output.vColor = - // g_tColor[ g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy); - // return ps_output; - // } - - const std::string entry_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -)"; - - const std::string entry_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -)"; - - const std::string names_annots = - R"(OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -)"; - - const std::string new_annots = - R"(OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -)"; - - const std::string consts_types_vars = - R"(%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%16 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_16_uint_128 = OpTypeArray %16 %uint_128 -%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%24 = OpTypeSampler -%_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24 -%g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant -%26 = OpTypeSampledImage %16 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string new_consts_types_vars = - R"(%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%48 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_56 = OpConstant %uint 56 -%103 = OpConstantNull %v4float -)"; - - const std::string func_pt1 = - R"(%MainPs = OpFunction %void None %10 -%29 = OpLabel -%30 = OpLoad %v2float %i_vTextureCoords -%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%32 = OpLoad %uint %31 -%33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32 -%34 = OpLoad %16 %33 -%35 = OpLoad %24 %g_sAniso -%36 = OpSampledImage %26 %34 %35 -)"; - - const std::string func_pt2_before = - R"(%37 = OpImageSampleImplicitLod %v4float %36 %30 -OpStore %_entryPointOutput_vColor %37 -OpReturn -OpFunctionEnd -)"; - - const std::string func_pt2_after = - R"(%40 = OpULessThan %bool %32 %uint_128 -OpSelectionMerge %41 None -OpBranchConditional %40 %42 %43 -%42 = OpLabel -%44 = OpLoad %16 %33 -%45 = OpSampledImage %26 %44 %35 -%46 = OpImageSampleImplicitLod %v4float %45 %30 -OpBranch %41 -%43 = OpLabel -%102 = OpFunctionCall %void %47 %uint_56 %uint_0 %32 %uint_128 -OpBranch %41 -%41 = OpLabel -%104 = OpPhi %v4float %46 %42 %103 %43 -OpStore %_entryPointOutput_vColor %104 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%47 = OpFunction %void None %48 -%49 = OpFunctionParameter %uint -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpLabel -%59 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%62 = OpAtomicIAdd %uint %59 %uint_4 %uint_0 %uint_9 -%63 = OpIAdd %uint %62 %uint_9 -%64 = OpArrayLength %uint %57 1 -%65 = OpULessThanEqual %bool %63 %64 -OpSelectionMerge %66 None -OpBranchConditional %65 %67 %66 -%67 = OpLabel -%68 = OpIAdd %uint %62 %uint_0 -%70 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %68 -OpStore %70 %uint_9 -%72 = OpIAdd %uint %62 %uint_1 -%73 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %72 -OpStore %73 %uint_23 -%75 = OpIAdd %uint %62 %uint_2 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %49 -%78 = OpIAdd %uint %62 %uint_3 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %78 -OpStore %79 %uint_4 -%82 = OpLoad %v4float %gl_FragCoord -%84 = OpBitcast %v4uint %82 -%85 = OpCompositeExtract %uint %84 0 -%86 = OpIAdd %uint %62 %uint_4 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %86 -OpStore %87 %85 -%88 = OpCompositeExtract %uint %84 1 -%90 = OpIAdd %uint %62 %uint_5 -%91 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %90 -OpStore %91 %88 -%93 = OpIAdd %uint %62 %uint_6 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %93 -OpStore %94 %50 -%96 = OpIAdd %uint %62 %uint_7 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %96 -OpStore %97 %51 -%99 = OpIAdd %uint %62 %uint_8 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %99 -OpStore %100 %52 -OpBranch %66 -%66 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - entry_before + names_annots + consts_types_vars + func_pt1 + - func_pt2_before, - entry_after + names_annots + new_annots + consts_types_vars + - new_consts_types_vars + func_pt1 + func_pt2_after + output_func, - true, true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, NoInstrumentConstIndexInbounds) { - // Texture2D g_tColor[128]; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // - // ps_output.vColor = g_tColor[ 37 ].Sample(g_sAniso, i.vTextureCoords.xy); - // return ps_output; - // } - - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_37 = OpConstant %int 37 -%15 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_15_uint_128 = OpTypeArray %15 %uint_128 -%_ptr_UniformConstant__arr_15_uint_128 = OpTypePointer UniformConstant %_arr_15_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_15_uint_128 UniformConstant -%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 -%21 = OpTypeSampler -%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 -%g_sAniso = OpVariable %_ptr_UniformConstant_21 UniformConstant -%23 = OpTypeSampledImage %15 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%MainPs = OpFunction %void None %8 -%26 = OpLabel -%27 = OpLoad %v2float %i_vTextureCoords -%28 = OpAccessChain %_ptr_UniformConstant_15 %g_tColor %int_37 -%29 = OpLoad %15 %28 -%30 = OpLoad %21 %g_sAniso -%31 = OpSampledImage %23 %29 %30 -%32 = OpImageSampleImplicitLod %v4float %31 %27 -OpStore %_entryPointOutput_vColor %32 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, before, true, true, 7u, - 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, InstrumentMultipleInstructions) { - // Texture2D g_tColor[128]; - // - // layout(push_constant) cbuffer PerViewConstantBuffer_t - // { - // uint g_nDataIdx; - // uint g_nDataIdx2; - // }; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // - // float t = g_tColor[g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy); - // float t2 = g_tColor[g_nDataIdx2].Sample(g_sAniso, i.vTextureCoords.xy); - // ps_output.vColor = t + t2; - // return ps_output; - // } - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_17_uint_128 = OpTypeArray %17 %uint_128 -%_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%25 = OpTypeSampler -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 -%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant -%27 = OpTypeSampledImage %17 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_17_uint_128 = OpTypeArray %17 %uint_128 -%_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%25 = OpTypeSampler -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 -%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant -%27 = OpTypeSampledImage %17 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%56 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_58 = OpConstant %uint 58 -%111 = OpConstantNull %v4float -%uint_64 = OpConstant %uint 64 -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %10 -%30 = OpLabel -%31 = OpLoad %v2float %i_vTextureCoords -%32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%33 = OpLoad %uint %32 -%34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33 -%35 = OpLoad %17 %34 -%36 = OpLoad %25 %g_sAniso -%37 = OpSampledImage %27 %35 %36 -%38 = OpImageSampleImplicitLod %v4float %37 %31 -%39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -%40 = OpLoad %uint %39 -%41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40 -%42 = OpLoad %17 %41 -%43 = OpSampledImage %27 %42 %36 -%44 = OpImageSampleImplicitLod %v4float %43 %31 -%45 = OpFAdd %v4float %38 %44 -OpStore %_entryPointOutput_vColor %45 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %10 -%30 = OpLabel -%31 = OpLoad %v2float %i_vTextureCoords -%32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%33 = OpLoad %uint %32 -%34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33 -%35 = OpLoad %17 %34 -%36 = OpLoad %25 %g_sAniso -%37 = OpSampledImage %27 %35 %36 -%48 = OpULessThan %bool %33 %uint_128 -OpSelectionMerge %49 None -OpBranchConditional %48 %50 %51 -%50 = OpLabel -%52 = OpLoad %17 %34 -%53 = OpSampledImage %27 %52 %36 -%54 = OpImageSampleImplicitLod %v4float %53 %31 -OpBranch %49 -%51 = OpLabel -%110 = OpFunctionCall %void %55 %uint_58 %uint_0 %33 %uint_128 -OpBranch %49 -%49 = OpLabel -%112 = OpPhi %v4float %54 %50 %111 %51 -%39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -%40 = OpLoad %uint %39 -%41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40 -%42 = OpLoad %17 %41 -%43 = OpSampledImage %27 %42 %36 -%113 = OpULessThan %bool %40 %uint_128 -OpSelectionMerge %114 None -OpBranchConditional %113 %115 %116 -%115 = OpLabel -%117 = OpLoad %17 %41 -%118 = OpSampledImage %27 %117 %36 -%119 = OpImageSampleImplicitLod %v4float %118 %31 -OpBranch %114 -%116 = OpLabel -%121 = OpFunctionCall %void %55 %uint_64 %uint_0 %40 %uint_128 -OpBranch %114 -%114 = OpLabel -%122 = OpPhi %v4float %119 %115 %111 %116 -%45 = OpFAdd %v4float %112 %122 -OpStore %_entryPointOutput_vColor %45 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%55 = OpFunction %void None %56 -%57 = OpFunctionParameter %uint -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpLabel -%67 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%70 = OpAtomicIAdd %uint %67 %uint_4 %uint_0 %uint_9 -%71 = OpIAdd %uint %70 %uint_9 -%72 = OpArrayLength %uint %65 1 -%73 = OpULessThanEqual %bool %71 %72 -OpSelectionMerge %74 None -OpBranchConditional %73 %75 %74 -%75 = OpLabel -%76 = OpIAdd %uint %70 %uint_0 -%78 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %76 -OpStore %78 %uint_9 -%80 = OpIAdd %uint %70 %uint_1 -%81 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %80 -OpStore %81 %uint_23 -%83 = OpIAdd %uint %70 %uint_2 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %83 -OpStore %84 %57 -%86 = OpIAdd %uint %70 %uint_3 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %86 -OpStore %87 %uint_4 -%90 = OpLoad %v4float %gl_FragCoord -%92 = OpBitcast %v4uint %90 -%93 = OpCompositeExtract %uint %92 0 -%94 = OpIAdd %uint %70 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %93 -%96 = OpCompositeExtract %uint %92 1 -%98 = OpIAdd %uint %70 %uint_5 -%99 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %98 -OpStore %99 %96 -%101 = OpIAdd %uint %70 %uint_6 -%102 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %101 -OpStore %102 %58 -%104 = OpIAdd %uint %70 %uint_7 -%105 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %104 -OpStore %105 %59 -%107 = OpIAdd %uint %70 %uint_8 -%108 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %107 -OpStore %108 %60 -OpBranch %74 -%74 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, InstrumentOpImage) { - // This test verifies that the pass will correctly instrument shader - // using OpImage. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability StorageImageReadWithoutFormat -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%39 = OpTypeSampledImage %20 -%_arr_39_uint_128 = OpTypeArray %39 %uint_128 -%_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability StorageImageReadWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_51 Block -OpMemberDecorate %_struct_51 0 Offset 0 -OpMemberDecorate %_struct_51 1 Offset 4 -OpDecorate %53 DescriptorSet 7 -OpDecorate %53 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%15 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%18 = OpTypeSampledImage %15 -%_arr_18_uint_128 = OpTypeArray %18 %uint_128 -%_ptr_UniformConstant__arr_18_uint_128 = OpTypePointer UniformConstant %_arr_18_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_18_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%44 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_51 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_51 = OpTypePointer StorageBuffer %_struct_51 -%53 = OpVariable %_ptr_StorageBuffer__struct_51 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_51 = OpConstant %uint 51 -%99 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2int %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64 -%66 = OpLoad %39 %65 -%75 = OpImage %20 %66 -%71 = OpImageRead %v4float %75 %53 -OpStore %_entryPointOutput_vColor %71 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %9 -%26 = OpLabel -%27 = OpLoad %v2int %i_vTextureCoords -%28 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%29 = OpLoad %uint %28 -%30 = OpAccessChain %_ptr_UniformConstant_18 %g_tColor %29 -%31 = OpLoad %18 %30 -%32 = OpImage %15 %31 -%36 = OpULessThan %bool %29 %uint_128 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %39 -%38 = OpLabel -%40 = OpLoad %18 %30 -%41 = OpImage %15 %40 -%42 = OpImageRead %v4float %41 %27 -OpBranch %37 -%39 = OpLabel -%98 = OpFunctionCall %void %43 %uint_51 %uint_0 %29 %uint_128 -OpBranch %37 -%37 = OpLabel -%100 = OpPhi %v4float %42 %38 %99 %39 -OpStore %_entryPointOutput_vColor %100 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%43 = OpFunction %void None %44 -%45 = OpFunctionParameter %uint -%46 = OpFunctionParameter %uint -%47 = OpFunctionParameter %uint -%48 = OpFunctionParameter %uint -%49 = OpLabel -%55 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_0 -%58 = OpAtomicIAdd %uint %55 %uint_4 %uint_0 %uint_9 -%59 = OpIAdd %uint %58 %uint_9 -%60 = OpArrayLength %uint %53 1 -%61 = OpULessThanEqual %bool %59 %60 -OpSelectionMerge %62 None -OpBranchConditional %61 %63 %62 -%63 = OpLabel -%64 = OpIAdd %uint %58 %uint_0 -%66 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %64 -OpStore %66 %uint_9 -%68 = OpIAdd %uint %58 %uint_1 -%69 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %68 -OpStore %69 %uint_23 -%71 = OpIAdd %uint %58 %uint_2 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %71 -OpStore %72 %45 -%74 = OpIAdd %uint %58 %uint_3 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %74 -OpStore %75 %uint_4 -%78 = OpLoad %v4float %gl_FragCoord -%80 = OpBitcast %v4uint %78 -%81 = OpCompositeExtract %uint %80 0 -%82 = OpIAdd %uint %58 %uint_4 -%83 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %82 -OpStore %83 %81 -%84 = OpCompositeExtract %uint %80 1 -%86 = OpIAdd %uint %58 %uint_5 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %86 -OpStore %87 %84 -%89 = OpIAdd %uint %58 %uint_6 -%90 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %89 -OpStore %90 %46 -%92 = OpIAdd %uint %58 %uint_7 -%93 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %92 -OpStore %93 %47 -%95 = OpIAdd %uint %58 %uint_8 -%96 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %95 -OpStore %96 %48 -OpBranch %62 -%62 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, InstrumentSampledImage) { - // This test verifies that the pass will correctly instrument shader - // using sampled image. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%39 = OpTypeSampledImage %20 -%_arr_39_uint_128 = OpTypeArray %39 %uint_128 -%_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_49 Block -OpMemberDecorate %_struct_49 0 Offset 0 -OpMemberDecorate %_struct_49 1 Offset 4 -OpDecorate %51 DescriptorSet 7 -OpDecorate %51 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%15 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%18 = OpTypeSampledImage %15 -%_arr_18_uint_128 = OpTypeArray %18 %uint_128 -%_ptr_UniformConstant__arr_18_uint_128 = OpTypePointer UniformConstant %_arr_18_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_18_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%42 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_49 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_49 = OpTypePointer StorageBuffer %_struct_49 -%51 = OpVariable %_ptr_StorageBuffer__struct_49 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_49 = OpConstant %uint 49 -%97 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2float %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64 -%66 = OpLoad %39 %65 -%71 = OpImageSampleImplicitLod %v4float %66 %53 -OpStore %_entryPointOutput_vColor %71 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %9 -%26 = OpLabel -%27 = OpLoad %v2float %i_vTextureCoords -%28 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%29 = OpLoad %uint %28 -%30 = OpAccessChain %_ptr_UniformConstant_18 %g_tColor %29 -%31 = OpLoad %18 %30 -%35 = OpULessThan %bool %29 %uint_128 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %38 -%37 = OpLabel -%39 = OpLoad %18 %30 -%40 = OpImageSampleImplicitLod %v4float %39 %27 -OpBranch %36 -%38 = OpLabel -%96 = OpFunctionCall %void %41 %uint_49 %uint_0 %29 %uint_128 -OpBranch %36 -%36 = OpLabel -%98 = OpPhi %v4float %40 %37 %97 %38 -OpStore %_entryPointOutput_vColor %98 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%41 = OpFunction %void None %42 -%43 = OpFunctionParameter %uint -%44 = OpFunctionParameter %uint -%45 = OpFunctionParameter %uint -%46 = OpFunctionParameter %uint -%47 = OpLabel -%53 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_0 -%56 = OpAtomicIAdd %uint %53 %uint_4 %uint_0 %uint_9 -%57 = OpIAdd %uint %56 %uint_9 -%58 = OpArrayLength %uint %51 1 -%59 = OpULessThanEqual %bool %57 %58 -OpSelectionMerge %60 None -OpBranchConditional %59 %61 %60 -%61 = OpLabel -%62 = OpIAdd %uint %56 %uint_0 -%64 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %62 -OpStore %64 %uint_9 -%66 = OpIAdd %uint %56 %uint_1 -%67 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %66 -OpStore %67 %uint_23 -%69 = OpIAdd %uint %56 %uint_2 -%70 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %69 -OpStore %70 %43 -%72 = OpIAdd %uint %56 %uint_3 -%73 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %72 -OpStore %73 %uint_4 -%76 = OpLoad %v4float %gl_FragCoord -%78 = OpBitcast %v4uint %76 -%79 = OpCompositeExtract %uint %78 0 -%80 = OpIAdd %uint %56 %uint_4 -%81 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %80 -OpStore %81 %79 -%82 = OpCompositeExtract %uint %78 1 -%84 = OpIAdd %uint %56 %uint_5 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %84 -OpStore %85 %82 -%87 = OpIAdd %uint %56 %uint_6 -%88 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %87 -OpStore %88 %44 -%90 = OpIAdd %uint %56 %uint_7 -%91 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %90 -OpStore %91 %45 -%93 = OpIAdd %uint %56 %uint_8 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %93 -OpStore %94 %46 -OpBranch %60 -%60 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, InstrumentImageWrite) { - // This test verifies that the pass will correctly instrument shader - // doing bindless image write. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability StorageImageWriteWithoutFormat -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%80 = OpConstantNull %v4float -%_arr_20_uint_128 = OpTypeArray %20 %uint_128 -%_ptr_UniformConstant__arr_20_uint_128 = OpTypePointer UniformConstant %_arr_20_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_20_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability StorageImageWriteWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_48 Block -OpMemberDecorate %_struct_48 0 Offset 0 -OpMemberDecorate %_struct_48 1 Offset 4 -OpDecorate %50 DescriptorSet 7 -OpDecorate %50 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%16 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%19 = OpConstantNull %v4float -%_arr_16_uint_128 = OpTypeArray %16 %uint_128 -%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%41 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_48 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_48 = OpTypePointer StorageBuffer %_struct_48 -%50 = OpVariable %_ptr_StorageBuffer__struct_48 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_51 = OpConstant %uint 51 -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2int %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64 -%66 = OpLoad %20 %65 -OpImageWrite %66 %53 %80 -OpStore %_entryPointOutput_vColor %80 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %9 -%27 = OpLabel -%28 = OpLoad %v2int %i_vTextureCoords -%29 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%30 = OpLoad %uint %29 -%31 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %30 -%32 = OpLoad %16 %31 -%35 = OpULessThan %bool %30 %uint_128 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %38 -%37 = OpLabel -%39 = OpLoad %16 %31 -OpImageWrite %39 %28 %19 -OpBranch %36 -%38 = OpLabel -%95 = OpFunctionCall %void %40 %uint_51 %uint_0 %30 %uint_128 -OpBranch %36 -%36 = OpLabel -OpStore %_entryPointOutput_vColor %19 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%40 = OpFunction %void None %41 -%42 = OpFunctionParameter %uint -%43 = OpFunctionParameter %uint -%44 = OpFunctionParameter %uint -%45 = OpFunctionParameter %uint -%46 = OpLabel -%52 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_0 -%55 = OpAtomicIAdd %uint %52 %uint_4 %uint_0 %uint_9 -%56 = OpIAdd %uint %55 %uint_9 -%57 = OpArrayLength %uint %50 1 -%58 = OpULessThanEqual %bool %56 %57 -OpSelectionMerge %59 None -OpBranchConditional %58 %60 %59 -%60 = OpLabel -%61 = OpIAdd %uint %55 %uint_0 -%63 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %61 -OpStore %63 %uint_9 -%65 = OpIAdd %uint %55 %uint_1 -%66 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %65 -OpStore %66 %uint_23 -%68 = OpIAdd %uint %55 %uint_2 -%69 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %68 -OpStore %69 %42 -%71 = OpIAdd %uint %55 %uint_3 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %71 -OpStore %72 %uint_4 -%75 = OpLoad %v4float %gl_FragCoord -%77 = OpBitcast %v4uint %75 -%78 = OpCompositeExtract %uint %77 0 -%79 = OpIAdd %uint %55 %uint_4 -%80 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %79 -OpStore %80 %78 -%81 = OpCompositeExtract %uint %77 1 -%83 = OpIAdd %uint %55 %uint_5 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %83 -OpStore %84 %81 -%86 = OpIAdd %uint %55 %uint_6 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %86 -OpStore %87 %43 -%89 = OpIAdd %uint %55 %uint_7 -%90 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %89 -OpStore %90 %44 -%92 = OpIAdd %uint %55 %uint_8 -%93 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %92 -OpStore %93 %45 -OpBranch %59 -%59 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, InstrumentVertexSimple) { - // This test verifies that the pass will correctly instrument shader - // doing bindless image write. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" %_ %coords2D -OpSource GLSL 450 -OpName %main "main" -OpName %lod "lod" -OpName %coords1D "coords1D" -OpName %gl_PerVertex "gl_PerVertex" -OpMemberName %gl_PerVertex 0 "gl_Position" -OpMemberName %gl_PerVertex 1 "gl_PointSize" -OpMemberName %gl_PerVertex 2 "gl_ClipDistance" -OpMemberName %gl_PerVertex 3 "gl_CullDistance" -OpName %_ "" -OpName %texSampler1D "texSampler1D" -OpName %foo "foo" -OpMemberName %foo 0 "g_idx" -OpName %__0 "" -OpName %coords2D "coords2D" -OpMemberDecorate %gl_PerVertex 0 BuiltIn Position -OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize -OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance -OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance -OpDecorate %gl_PerVertex Block -OpDecorate %texSampler1D DescriptorSet 0 -OpDecorate %texSampler1D Binding 3 -OpMemberDecorate %foo 0 Offset 0 -OpDecorate %foo Block -OpDecorate %__0 DescriptorSet 0 -OpDecorate %__0 Binding 5 -OpDecorate %coords2D Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_3 = OpConstant %float 3 -%float_1_78900003 = OpConstant %float 1.78900003 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex -%_ = OpVariable %_ptr_Output_gl_PerVertex Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%21 = OpTypeImage %float 1D 0 0 0 1 Unknown -%22 = OpTypeSampledImage %21 -%uint_128 = OpConstant %uint 128 -%_arr_22_uint_128 = OpTypeArray %22 %uint_128 -%_ptr_UniformConstant__arr_22_uint_128 = OpTypePointer UniformConstant %_arr_22_uint_128 -%texSampler1D = OpVariable %_ptr_UniformConstant__arr_22_uint_128 UniformConstant -%foo = OpTypeStruct %int -%_ptr_Uniform_foo = OpTypePointer Uniform %foo -%__0 = OpVariable %_ptr_Uniform_foo Uniform -%_ptr_Uniform_int = OpTypePointer Uniform %int -%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%coords2D = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" %_ %coords2D %gl_VertexIndex %gl_InstanceIndex -OpSource GLSL 450 -OpName %main "main" -OpName %lod "lod" -OpName %coords1D "coords1D" -OpName %gl_PerVertex "gl_PerVertex" -OpMemberName %gl_PerVertex 0 "gl_Position" -OpMemberName %gl_PerVertex 1 "gl_PointSize" -OpMemberName %gl_PerVertex 2 "gl_ClipDistance" -OpMemberName %gl_PerVertex 3 "gl_CullDistance" -OpName %_ "" -OpName %texSampler1D "texSampler1D" -OpName %foo "foo" -OpMemberName %foo 0 "g_idx" -OpName %__0 "" -OpName %coords2D "coords2D" -OpMemberDecorate %gl_PerVertex 0 BuiltIn Position -OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize -OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance -OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance -OpDecorate %gl_PerVertex Block -OpDecorate %texSampler1D DescriptorSet 0 -OpDecorate %texSampler1D Binding 3 -OpMemberDecorate %foo 0 Offset 0 -OpDecorate %foo Block -OpDecorate %__0 DescriptorSet 0 -OpDecorate %__0 Binding 5 -OpDecorate %coords2D Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_61 Block -OpMemberDecorate %_struct_61 0 Offset 0 -OpMemberDecorate %_struct_61 1 Offset 4 -OpDecorate %63 DescriptorSet 7 -OpDecorate %63 Binding 0 -OpDecorate %gl_VertexIndex BuiltIn VertexIndex -OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_3 = OpConstant %float 3 -%float_1_78900003 = OpConstant %float 1.78900003 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex -%_ = OpVariable %_ptr_Output_gl_PerVertex Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%24 = OpTypeImage %float 1D 0 0 0 1 Unknown -%25 = OpTypeSampledImage %24 -%uint_128 = OpConstant %uint 128 -%_arr_25_uint_128 = OpTypeArray %25 %uint_128 -%_ptr_UniformConstant__arr_25_uint_128 = OpTypePointer UniformConstant %_arr_25_uint_128 -%texSampler1D = OpVariable %_ptr_UniformConstant__arr_25_uint_128 UniformConstant -%foo = OpTypeStruct %int -%_ptr_Uniform_foo = OpTypePointer Uniform %foo -%__0 = OpVariable %_ptr_Uniform_foo Uniform -%_ptr_Uniform_int = OpTypePointer Uniform %int -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%coords2D = OpVariable %_ptr_Input_v2float Input -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%54 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_61 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_61 = OpTypePointer StorageBuffer %_struct_61 -%63 = OpVariable %_ptr_StorageBuffer__struct_61 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_uint = OpTypePointer Input %uint -%gl_VertexIndex = OpVariable %_ptr_Input_uint Input -%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_74 = OpConstant %uint 74 -%106 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%lod = OpVariable %_ptr_Function_float Function -%coords1D = OpVariable %_ptr_Function_float Function -OpStore %lod %float_3 -OpStore %coords1D %float_1_78900003 -%31 = OpAccessChain %_ptr_Uniform_int %__0 %int_0 -%32 = OpLoad %int %31 -%34 = OpAccessChain %_ptr_UniformConstant_22 %texSampler1D %32 -%35 = OpLoad %22 %34 -%36 = OpLoad %float %coords1D -%37 = OpLoad %float %lod -%38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37 -%40 = OpAccessChain %_ptr_Output_v4float %_ %int_0 -OpStore %40 %38 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %12 -%35 = OpLabel -%lod = OpVariable %_ptr_Function_float Function -%coords1D = OpVariable %_ptr_Function_float Function -OpStore %lod %float_3 -OpStore %coords1D %float_1_78900003 -%36 = OpAccessChain %_ptr_Uniform_int %__0 %int_0 -%37 = OpLoad %int %36 -%38 = OpAccessChain %_ptr_UniformConstant_25 %texSampler1D %37 -%39 = OpLoad %25 %38 -%40 = OpLoad %float %coords1D -%41 = OpLoad %float %lod -%46 = OpULessThan %bool %37 %uint_128 -OpSelectionMerge %47 None -OpBranchConditional %46 %48 %49 -%48 = OpLabel -%50 = OpLoad %25 %38 -%51 = OpImageSampleExplicitLod %v4float %50 %40 Lod %41 -OpBranch %47 -%49 = OpLabel -%52 = OpBitcast %uint %37 -%105 = OpFunctionCall %void %53 %uint_74 %uint_0 %52 %uint_128 -OpBranch %47 -%47 = OpLabel -%107 = OpPhi %v4float %51 %48 %106 %49 -%43 = OpAccessChain %_ptr_Output_v4float %_ %int_0 -OpStore %43 %107 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%53 = OpFunction %void None %54 -%55 = OpFunctionParameter %uint -%56 = OpFunctionParameter %uint -%57 = OpFunctionParameter %uint -%58 = OpFunctionParameter %uint -%59 = OpLabel -%65 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_0 -%68 = OpAtomicIAdd %uint %65 %uint_4 %uint_0 %uint_9 -%69 = OpIAdd %uint %68 %uint_9 -%70 = OpArrayLength %uint %63 1 -%71 = OpULessThanEqual %bool %69 %70 -OpSelectionMerge %72 None -OpBranchConditional %71 %73 %72 -%73 = OpLabel -%74 = OpIAdd %uint %68 %uint_0 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %74 -OpStore %75 %uint_9 -%77 = OpIAdd %uint %68 %uint_1 -%78 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %77 -OpStore %78 %uint_23 -%80 = OpIAdd %uint %68 %uint_2 -%81 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %80 -OpStore %81 %55 -%83 = OpIAdd %uint %68 %uint_3 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %83 -OpStore %84 %uint_0 -%87 = OpLoad %uint %gl_VertexIndex -%88 = OpIAdd %uint %68 %uint_4 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %88 -OpStore %89 %87 -%91 = OpLoad %uint %gl_InstanceIndex -%93 = OpIAdd %uint %68 %uint_5 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %93 -OpStore %94 %91 -%96 = OpIAdd %uint %68 %uint_6 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %96 -OpStore %97 %56 -%99 = OpIAdd %uint %68 %uint_7 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %99 -OpStore %100 %57 -%102 = OpIAdd %uint %68 %uint_8 -%103 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %102 -OpStore %103 %58 -OpBranch %72 -%72 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, MultipleDebugFunctions) { - // Same source as Simple, but compiled -g and not optimized, especially not - // inlined. The OpSource has had the source extracted for the sake of brevity. - - const std::string defs_before = - R"(OpCapability Shader -%2 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -%1 = OpString "foo5.frag" -OpSource HLSL 500 %1 -OpName %MainPs "MainPs" -OpName %PS_INPUT "PS_INPUT" -OpMemberName %PS_INPUT 0 "vTextureCoords" -OpName %PS_OUTPUT "PS_OUTPUT" -OpMemberName %PS_OUTPUT 0 "vColor" -OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" -OpName %i "i" -OpName %ps_output "ps_output" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_0 "i" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpName %param "param" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 1 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%PS_INPUT = OpTypeStruct %v2float -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -%v4float = OpTypeVector %float 4 -%PS_OUTPUT = OpTypeStruct %v4float -%13 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%21 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_21_uint_128 = OpTypeArray %21 %uint_128 -%_ptr_UniformConstant__arr_21_uint_128 = OpTypePointer UniformConstant %_arr_21_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_21_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 -%36 = OpTypeSampler -%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 -%g_sAniso = OpVariable %_ptr_UniformConstant_36 UniformConstant -%40 = OpTypeSampledImage %21 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -%5 = OpString "foo5.frag" -OpSource HLSL 500 %5 -OpName %MainPs "MainPs" -OpName %PS_INPUT "PS_INPUT" -OpMemberName %PS_INPUT 0 "vTextureCoords" -OpName %PS_OUTPUT "PS_OUTPUT" -OpMemberName %PS_OUTPUT 0 "vColor" -OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" -OpName %i "i" -OpName %ps_output "ps_output" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_0 "i" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpName %param "param" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 1 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_77 Block -OpMemberDecorate %_struct_77 0 Offset 0 -OpMemberDecorate %_struct_77 1 Offset 4 -OpDecorate %79 DescriptorSet 7 -OpDecorate %79 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%18 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%PS_INPUT = OpTypeStruct %v2float -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -%v4float = OpTypeVector %float 4 -%PS_OUTPUT = OpTypeStruct %v4float -%23 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%27 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_27_uint_128 = OpTypeArray %27 %uint_128 -%_ptr_UniformConstant__arr_27_uint_128 = OpTypePointer UniformConstant %_arr_27_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_27_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27 -%35 = OpTypeSampler -%_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35 -%g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant -%37 = OpTypeSampledImage %27 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%70 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_77 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_77 = OpTypePointer StorageBuffer %_struct_77 -%79 = OpVariable %_ptr_StorageBuffer__struct_77 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_93 = OpConstant %uint 93 -%125 = OpConstantNull %v4float -)"; - - const std::string func1_before = - R"(%MainPs = OpFunction %void None %4 -%6 = OpLabel -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %1 21 0 -%54 = OpLoad %v2float %i_vTextureCoords -%55 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpStore %55 %54 -%59 = OpLoad %PS_INPUT %i_0 -OpStore %param %59 -%60 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -%61 = OpCompositeExtract %v4float %60 0 -OpStore %_entryPointOutput_vColor %61 -OpReturn -OpFunctionEnd -)"; - - const std::string func1_after = - R"(%MainPs = OpFunction %void None %18 -%42 = OpLabel -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %5 21 0 -%43 = OpLoad %v2float %i_vTextureCoords -%44 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpStore %44 %43 -%45 = OpLoad %PS_INPUT %i_0 -OpStore %param %45 -%46 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -%47 = OpCompositeExtract %v4float %46 0 -OpStore %_entryPointOutput_vColor %47 -OpReturn -OpFunctionEnd -)"; - - const std::string func2_before = - R"(%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %13 -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -%16 = OpLabel -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %1 24 0 -%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%32 = OpLoad %uint %31 -%34 = OpAccessChain %_ptr_UniformConstant_21 %g_tColor %32 -%35 = OpLoad %21 %34 -%39 = OpLoad %36 %g_sAniso -%41 = OpSampledImage %40 %35 %39 -%43 = OpAccessChain %_ptr_Function_v2float %i %int_0 -%44 = OpLoad %v2float %43 -%45 = OpImageSampleImplicitLod %v4float %41 %44 -%47 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpStore %47 %45 -OpLine %1 25 0 -%48 = OpLoad %PS_OUTPUT %ps_output -OpReturnValue %48 -OpFunctionEnd -)"; - - const std::string func2_after = - R"(%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %23 -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -%48 = OpLabel -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %5 24 0 -%49 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%50 = OpLoad %uint %49 -%51 = OpAccessChain %_ptr_UniformConstant_27 %g_tColor %50 -%52 = OpLoad %27 %51 -%53 = OpLoad %35 %g_sAniso -%54 = OpSampledImage %37 %52 %53 -%55 = OpAccessChain %_ptr_Function_v2float %i %int_0 -%56 = OpLoad %v2float %55 -%62 = OpULessThan %bool %50 %uint_128 -OpSelectionMerge %63 None -OpBranchConditional %62 %64 %65 -%64 = OpLabel -%66 = OpLoad %27 %51 -%67 = OpSampledImage %37 %66 %53 -%68 = OpImageSampleImplicitLod %v4float %67 %56 -OpBranch %63 -%65 = OpLabel -%124 = OpFunctionCall %void %69 %uint_93 %uint_0 %50 %uint_128 -OpBranch %63 -%63 = OpLabel -%126 = OpPhi %v4float %68 %64 %125 %65 -%58 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpStore %58 %126 -OpLine %5 25 0 -%59 = OpLoad %PS_OUTPUT %ps_output -OpReturnValue %59 -OpFunctionEnd -)"; - - const std::string output_func = - R"(%69 = OpFunction %void None %70 -%71 = OpFunctionParameter %uint -%72 = OpFunctionParameter %uint -%73 = OpFunctionParameter %uint -%74 = OpFunctionParameter %uint -%75 = OpLabel -%81 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_0 -%84 = OpAtomicIAdd %uint %81 %uint_4 %uint_0 %uint_9 -%85 = OpIAdd %uint %84 %uint_9 -%86 = OpArrayLength %uint %79 1 -%87 = OpULessThanEqual %bool %85 %86 -OpSelectionMerge %88 None -OpBranchConditional %87 %89 %88 -%89 = OpLabel -%90 = OpIAdd %uint %84 %uint_0 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %90 -OpStore %92 %uint_9 -%94 = OpIAdd %uint %84 %uint_1 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %94 -OpStore %95 %uint_23 -%97 = OpIAdd %uint %84 %uint_2 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %97 -OpStore %98 %71 -%100 = OpIAdd %uint %84 %uint_3 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %100 -OpStore %101 %uint_4 -%104 = OpLoad %v4float %gl_FragCoord -%106 = OpBitcast %v4uint %104 -%107 = OpCompositeExtract %uint %106 0 -%108 = OpIAdd %uint %84 %uint_4 -%109 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %108 -OpStore %109 %107 -%110 = OpCompositeExtract %uint %106 1 -%112 = OpIAdd %uint %84 %uint_5 -%113 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %112 -OpStore %113 %110 -%115 = OpIAdd %uint %84 %uint_6 -%116 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %115 -OpStore %116 %72 -%118 = OpIAdd %uint %84 %uint_7 -%119 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %118 -OpStore %119 %73 -%121 = OpIAdd %uint %84 %uint_8 -%122 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %121 -OpStore %122 %74 -OpBranch %88 -%88 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func1_before + func2_before, - defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u, - false, false, 1u); -} - -TEST_F(InstBindlessTest, RuntimeArray) { - // This test verifies that the pass will correctly instrument shader - // with runtime descriptor array. This test was created by editing the - // SPIR-V from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability RuntimeDescriptorArray -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 1 -OpDecorate %g_tColor Binding 2 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 1 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_rarr_20 = OpTypeRuntimeArray %20 -%_ptr_UniformConstant__arr_20 = OpTypePointer UniformConstant %_rarr_20 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_20 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 -%35 = OpTypeSampler -%_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35 -%g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant -%39 = OpTypeSampledImage %20 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability RuntimeDescriptorArray -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 1 -OpDecorate %g_tColor Binding 2 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 1 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_46 Block -OpMemberDecorate %_struct_46 0 Offset 0 -OpDecorate %48 DescriptorSet 7 -OpDecorate %48 Binding 1 -OpDecorate %_struct_71 Block -OpMemberDecorate %_struct_71 0 Offset 0 -OpMemberDecorate %_struct_71 1 Offset 4 -OpDecorate %73 DescriptorSet 7 -OpDecorate %73 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%16 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_runtimearr_16 = OpTypeRuntimeArray %16 -%_ptr_UniformConstant__runtimearr_16 = OpTypePointer UniformConstant %_runtimearr_16 -%g_tColor = OpVariable %_ptr_UniformConstant__runtimearr_16 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%24 = OpTypeSampler -%_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24 -%g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant -%26 = OpTypeSampledImage %16 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%uint_2 = OpConstant %uint 2 -%41 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_46 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_46 = OpTypePointer StorageBuffer %_struct_46 -%48 = OpVariable %_ptr_StorageBuffer__struct_46 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%65 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_71 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_71 = OpTypePointer StorageBuffer %_struct_71 -%73 = OpVariable %_ptr_StorageBuffer__struct_71 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_59 = OpConstant %uint 59 -%116 = OpConstantNull %v4float -%119 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2float %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64 -%66 = OpLoad %20 %65 -%67 = OpLoad %35 %g_sAniso -%68 = OpSampledImage %39 %66 %67 -%71 = OpImageSampleImplicitLod %v4float %68 %53 -OpStore %_entryPointOutput_vColor %71 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %10 -%29 = OpLabel -%30 = OpLoad %v2float %i_vTextureCoords -%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%32 = OpLoad %uint %31 -%33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32 -%34 = OpLoad %16 %33 -%35 = OpLoad %24 %g_sAniso -%36 = OpSampledImage %26 %34 %35 -%55 = OpFunctionCall %uint %40 %uint_2 %uint_2 -%57 = OpULessThan %bool %32 %55 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %60 -%59 = OpLabel -%61 = OpLoad %16 %33 -%62 = OpSampledImage %26 %61 %35 -%136 = OpFunctionCall %uint %118 %uint_0 %uint_1 %uint_2 %32 -%137 = OpINotEqual %bool %136 %uint_0 -OpSelectionMerge %138 None -OpBranchConditional %137 %139 %140 -%139 = OpLabel -%141 = OpLoad %16 %33 -%142 = OpSampledImage %26 %141 %35 -%143 = OpImageSampleImplicitLod %v4float %142 %30 -OpBranch %138 -%140 = OpLabel -%144 = OpFunctionCall %void %64 %uint_59 %uint_1 %32 %uint_0 -OpBranch %138 -%138 = OpLabel -%145 = OpPhi %v4float %143 %139 %116 %140 -OpBranch %58 -%60 = OpLabel -%115 = OpFunctionCall %void %64 %uint_59 %uint_0 %32 %55 -OpBranch %58 -%58 = OpLabel -%117 = OpPhi %v4float %145 %138 %116 %60 -OpStore %_entryPointOutput_vColor %117 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%40 = OpFunction %uint None %41 -%42 = OpFunctionParameter %uint -%43 = OpFunctionParameter %uint -%44 = OpLabel -%50 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %42 -%51 = OpLoad %uint %50 -%52 = OpIAdd %uint %51 %43 -%53 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %52 -%54 = OpLoad %uint %53 -OpReturnValue %54 -OpFunctionEnd -%64 = OpFunction %void None %65 -%66 = OpFunctionParameter %uint -%67 = OpFunctionParameter %uint -%68 = OpFunctionParameter %uint -%69 = OpFunctionParameter %uint -%70 = OpLabel -%74 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_0 -%77 = OpAtomicIAdd %uint %74 %uint_4 %uint_0 %uint_9 -%78 = OpIAdd %uint %77 %uint_9 -%79 = OpArrayLength %uint %73 1 -%80 = OpULessThanEqual %bool %78 %79 -OpSelectionMerge %81 None -OpBranchConditional %80 %82 %81 -%82 = OpLabel -%83 = OpIAdd %uint %77 %uint_0 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %83 -OpStore %84 %uint_9 -%86 = OpIAdd %uint %77 %uint_1 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %86 -OpStore %87 %uint_23 -%88 = OpIAdd %uint %77 %uint_2 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %88 -OpStore %89 %66 -%91 = OpIAdd %uint %77 %uint_3 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %91 -OpStore %92 %uint_4 -%95 = OpLoad %v4float %gl_FragCoord -%97 = OpBitcast %v4uint %95 -%98 = OpCompositeExtract %uint %97 0 -%99 = OpIAdd %uint %77 %uint_4 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %99 -OpStore %100 %98 -%101 = OpCompositeExtract %uint %97 1 -%103 = OpIAdd %uint %77 %uint_5 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %103 -OpStore %104 %101 -%106 = OpIAdd %uint %77 %uint_6 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %106 -OpStore %107 %67 -%109 = OpIAdd %uint %77 %uint_7 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %109 -OpStore %110 %68 -%112 = OpIAdd %uint %77 %uint_8 -%113 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %112 -OpStore %113 %69 -OpBranch %81 -%81 = OpLabel -OpReturn -OpFunctionEnd -%118 = OpFunction %uint None %119 -%120 = OpFunctionParameter %uint -%121 = OpFunctionParameter %uint -%122 = OpFunctionParameter %uint -%123 = OpFunctionParameter %uint -%124 = OpLabel -%125 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %120 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %121 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %122 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %130 -%132 = OpLoad %uint %131 -%133 = OpIAdd %uint %132 %123 -%134 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %133 -%135 = OpLoad %uint %134 -OpReturnValue %135 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, NoInstrumentNonBindless) { - // This test verifies that the pass will correctly not instrument vanilla - // texture sample. - // - // Texture2D g_tColor; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // ps_output.vColor = - // g_tColor.Sample(g_sAniso, i.vTextureCoords.xy); - // return ps_output; - // } - - const std::string whole_file = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%12 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 -%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant -%14 = OpTypeSampler -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant -%16 = OpTypeSampledImage %12 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%MainPs = OpFunction %void None %8 -%19 = OpLabel -%20 = OpLoad %v2float %i_vTextureCoords -%21 = OpLoad %12 %g_tColor -%22 = OpLoad %14 %g_sAniso -%23 = OpSampledImage %16 %21 %22 -%24 = OpImageSampleImplicitLod %v4float %23 %20 -OpStore %_entryPointOutput_vColor %24 -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(whole_file, whole_file, true, - true, 7u, 23u, false, false, 1u); -} - -TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) { - // This test verifies that the pass will correctly instrument vanilla - // texture sample on a scalar descriptor with an initialization check if the - // input_init_enable argument is set to true. This can happen when the - // descriptor indexing extension is enabled in the API but the SPIR-V - // does not have the extension enabled because it does not contain a - // runtime array. This is the same shader as NoInstrumentNonBindless. - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%12 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 -%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant -%14 = OpTypeSampler -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant -%16 = OpTypeSampledImage %12 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_35 Block -OpMemberDecorate %_struct_35 0 Offset 0 -OpDecorate %37 DescriptorSet 7 -OpDecorate %37 Binding 1 -OpDecorate %_struct_67 Block -OpMemberDecorate %_struct_67 0 Offset 0 -OpMemberDecorate %_struct_67 1 Offset 4 -OpDecorate %69 DescriptorSet 7 -OpDecorate %69 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%12 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 -%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant -%14 = OpTypeSampler -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant -%16 = OpTypeSampledImage %12 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%28 = OpTypeFunction %uint %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_35 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_35 = OpTypePointer StorageBuffer %_struct_35 -%37 = OpVariable %_ptr_StorageBuffer__struct_35 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%uint_1 = OpConstant %uint 1 -%61 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_67 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_67 = OpTypePointer StorageBuffer %_struct_67 -%69 = OpVariable %_ptr_StorageBuffer__struct_67 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_39 = OpConstant %uint 39 -%113 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %8 -%19 = OpLabel -%20 = OpLoad %v2float %i_vTextureCoords -%21 = OpLoad %12 %g_tColor -%22 = OpLoad %14 %g_sAniso -%23 = OpSampledImage %16 %21 %22 -%24 = OpImageSampleImplicitLod %v4float %23 %20 -OpStore %_entryPointOutput_vColor %24 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %8 -%19 = OpLabel -%20 = OpLoad %v2float %i_vTextureCoords -%21 = OpLoad %12 %g_tColor -%22 = OpLoad %14 %g_sAniso -%23 = OpSampledImage %16 %21 %22 -%50 = OpFunctionCall %uint %27 %uint_0 %uint_0 %uint_0 %uint_0 -%52 = OpINotEqual %bool %50 %uint_0 -OpSelectionMerge %54 None -OpBranchConditional %52 %55 %56 -%55 = OpLabel -%57 = OpLoad %12 %g_tColor -%58 = OpSampledImage %16 %57 %22 -%59 = OpImageSampleImplicitLod %v4float %58 %20 -OpBranch %54 -%56 = OpLabel -%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0 -OpBranch %54 -%54 = OpLabel -%114 = OpPhi %v4float %59 %55 %113 %56 -OpStore %_entryPointOutput_vColor %114 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%27 = OpFunction %uint None %28 -%29 = OpFunctionParameter %uint -%30 = OpFunctionParameter %uint -%31 = OpFunctionParameter %uint -%32 = OpFunctionParameter %uint -%33 = OpLabel -%39 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %29 -%40 = OpLoad %uint %39 -%41 = OpIAdd %uint %40 %30 -%42 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %41 -%43 = OpLoad %uint %42 -%44 = OpIAdd %uint %43 %31 -%45 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %44 -%46 = OpLoad %uint %45 -%47 = OpIAdd %uint %46 %32 -%48 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %47 -%49 = OpLoad %uint %48 -OpReturnValue %49 -OpFunctionEnd -%60 = OpFunction %void None %61 -%62 = OpFunctionParameter %uint -%63 = OpFunctionParameter %uint -%64 = OpFunctionParameter %uint -%65 = OpFunctionParameter %uint -%66 = OpLabel -%70 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 -%73 = OpAtomicIAdd %uint %70 %uint_4 %uint_0 %uint_9 -%74 = OpIAdd %uint %73 %uint_9 -%75 = OpArrayLength %uint %69 1 -%76 = OpULessThanEqual %bool %74 %75 -OpSelectionMerge %77 None -OpBranchConditional %76 %78 %77 -%78 = OpLabel -%79 = OpIAdd %uint %73 %uint_0 -%80 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %79 -OpStore %80 %uint_9 -%82 = OpIAdd %uint %73 %uint_1 -%83 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %82 -OpStore %83 %uint_23 -%85 = OpIAdd %uint %73 %uint_2 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %85 -OpStore %86 %62 -%88 = OpIAdd %uint %73 %uint_3 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %88 -OpStore %89 %uint_4 -%92 = OpLoad %v4float %gl_FragCoord -%94 = OpBitcast %v4uint %92 -%95 = OpCompositeExtract %uint %94 0 -%96 = OpIAdd %uint %73 %uint_4 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %96 -OpStore %97 %95 -%98 = OpCompositeExtract %uint %94 1 -%100 = OpIAdd %uint %73 %uint_5 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %100 -OpStore %101 %98 -%103 = OpIAdd %uint %73 %uint_6 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %103 -OpStore %104 %63 -%106 = OpIAdd %uint %73 %uint_7 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %106 -OpStore %107 %64 -%109 = OpIAdd %uint %73 %uint_8 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %109 -OpStore %110 %65 -OpBranch %77 -%77 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, SPV14AddToEntryPoint) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]] -; CHECK: OpDecorate [[v1]] DescriptorSet 7 -; CHECK: OpDecorate [[v2]] DescriptorSet 7 -; CHECK: [[v1]] = OpVariable {{%\w+}} StorageBuffer -; CHECK: [[v2]] = OpVariable {{%\w+}} StorageBuffer -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var -OpExecutionMode %foo OriginUpperLeft -OpDecorate %image_var DescriptorSet 0 -OpDecorate %image_var Binding 0 -OpDecorate %sampler_var DescriptorSet 0 -OpDecorate %sampler_var Binding 1 -OpDecorate %gid DescriptorSet 0 -OpDecorate %gid Binding 2 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%v3int = OpTypeVector %int 3 -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%v4float = OpTypeVector %float 4 -%struct = OpTypeStruct %v3int -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int -%gid = OpVariable %ptr_ssbo_struct StorageBuffer -%image = OpTypeImage %float 3D 0 0 0 1 Unknown -%ptr_uc_image = OpTypePointer UniformConstant %image -%sampler = OpTypeSampler -%ptr_uc_sampler = OpTypePointer UniformConstant %sampler -%image_var = OpVariable %ptr_uc_image UniformConstant -%sampler_var = OpVariable %ptr_uc_sampler UniformConstant -%sampled = OpTypeSampledImage %image -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%ld_image = OpLoad %image %image_var -%ld_sampler = OpLoad %sampler %sampler_var -%gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0 -%ld_gid = OpLoad %v3int %gep -%convert = OpConvertUToF %v3float %ld_gid -%sampled_image = OpSampledImage %sampled %ld_image %ld_sampler -%sample = OpImageSampleImplicitLod %v4float %sampled_image %convert -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(InstBindlessTest, SPV14AddToEntryPoints) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]] -; CHECK: OpEntryPoint Fragment {{%\w+}} "bar" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]] -; CHECK: OpDecorate [[v1]] DescriptorSet 7 -; CHECK: OpDecorate [[v2]] DescriptorSet 7 -; CHECK: [[v1]] = OpVariable {{%\w+}} StorageBuffer -; CHECK: [[v2]] = OpVariable {{%\w+}} StorageBuffer -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var -OpEntryPoint Fragment %foo "bar" %gid %image_var %sampler_var -OpExecutionMode %foo OriginUpperLeft -OpDecorate %image_var DescriptorSet 0 -OpDecorate %image_var Binding 0 -OpDecorate %sampler_var DescriptorSet 0 -OpDecorate %sampler_var Binding 1 -OpDecorate %gid DescriptorSet 0 -OpDecorate %gid Binding 2 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%v3int = OpTypeVector %int 3 -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%v4float = OpTypeVector %float 4 -%struct = OpTypeStruct %v3int -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int -%gid = OpVariable %ptr_ssbo_struct StorageBuffer -%image = OpTypeImage %float 3D 0 0 0 1 Unknown -%ptr_uc_image = OpTypePointer UniformConstant %image -%sampler = OpTypeSampler -%ptr_uc_sampler = OpTypePointer UniformConstant %sampler -%image_var = OpVariable %ptr_uc_image UniformConstant -%sampler_var = OpVariable %ptr_uc_sampler UniformConstant -%sampled = OpTypeSampledImage %image -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%ld_image = OpLoad %image %image_var -%ld_sampler = OpLoad %sampler %sampler_var -%gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0 -%ld_gid = OpLoad %v3int %gep -%convert = OpConvertUToF %v3float %ld_gid -%sampled_image = OpSampledImage %sampled %ld_image %ld_sampler -%sample = OpImageSampleImplicitLod %v4float %sampled_image %convert -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedUBOArray) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=0) out float b; - // - // layout(binding=3) uniform uname { float a; } uniformBuffer[]; - // - // void main() - // { - // b = uniformBuffer[nu_ii].a; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %16 NonUniform -OpDecorate %20 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_runtimearr_uname = OpTypeRuntimeArray %uname -%_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname -%uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %102 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %130 NonUniform -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %127 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_runtimearr_uname = OpTypeRuntimeArray %uname -%_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname -%uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_3 = OpConstant %uint 3 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%49 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_45 = OpConstant %uint 45 -%101 = OpConstantNull %float -%105 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpLoad %int %nu_ii -%19 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %16 %int_0 -%20 = OpLoad %float %19 -OpStore %b %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%19 = OpLabel -%7 = OpLoad %int %nu_ii -%20 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_3 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%103 = OpBitcast %uint %7 -%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103 -%123 = OpINotEqual %bool %122 %uint_0 -OpSelectionMerge %124 None -OpBranchConditional %123 %125 %126 -%125 = OpLabel -%127 = OpLoad %float %20 -OpBranch %124 -%126 = OpLabel -%128 = OpBitcast %uint %7 -%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0 -OpBranch %124 -%124 = OpLabel -%130 = OpPhi %float %127 %125 %101 %126 -OpBranch %43 -%45 = OpLabel -%47 = OpBitcast %uint %7 -%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40 -OpBranch %43 -%43 = OpLabel -%102 = OpPhi %float %130 %124 %101 %45 -OpStore %b %102 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%48 = OpFunction %void None %49 -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpFunctionParameter %uint -%54 = OpLabel -%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_9 -%62 = OpIAdd %uint %61 %uint_9 -%63 = OpArrayLength %uint %57 1 -%64 = OpULessThanEqual %bool %62 %63 -OpSelectionMerge %65 None -OpBranchConditional %64 %66 %65 -%66 = OpLabel -%67 = OpIAdd %uint %61 %uint_0 -%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67 -OpStore %68 %uint_9 -%70 = OpIAdd %uint %61 %uint_1 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70 -OpStore %71 %uint_23 -%73 = OpIAdd %uint %61 %uint_2 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73 -OpStore %74 %50 -%75 = OpIAdd %uint %61 %uint_3 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %uint_4 -%80 = OpLoad %v4float %gl_FragCoord -%82 = OpBitcast %v4uint %80 -%83 = OpCompositeExtract %uint %82 0 -%84 = OpIAdd %uint %61 %uint_4 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84 -OpStore %85 %83 -%86 = OpCompositeExtract %uint %82 1 -%88 = OpIAdd %uint %61 %uint_5 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88 -OpStore %89 %86 -%91 = OpIAdd %uint %61 %uint_6 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91 -OpStore %92 %51 -%94 = OpIAdd %uint %61 %uint_7 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94 -OpStore %95 %52 -%97 = OpIAdd %uint %61 %uint_8 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97 -OpStore %98 %53 -OpBranch %65 -%65 = OpLabel -OpReturn -OpFunctionEnd -%104 = OpFunction %uint None %105 -%106 = OpFunctionParameter %uint -%107 = OpFunctionParameter %uint -%108 = OpFunctionParameter %uint -%109 = OpFunctionParameter %uint -%110 = OpLabel -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %107 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %108 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -%119 = OpIAdd %uint %118 %109 -%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119 -%121 = OpLoad %uint %120 -OpReturnValue %121 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayDeprecated) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=0) out float b; - // - // layout(binding=3) buffer bname { float b; } storageBuffer[]; - // - // void main() - // { - // b = storageBuffer[nu_ii].b; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname BufferBlock -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %16 NonUniform -OpDecorate %20 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname BufferBlock -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %102 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %130 NonUniform -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %127 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_3 = OpConstant %uint 3 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%49 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_45 = OpConstant %uint 45 -%101 = OpConstantNull %float -%105 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpLoad %int %nu_ii -%19 = OpAccessChain %_ptr_Uniform_float %storageBuffer %16 %int_0 -%20 = OpLoad %float %19 -OpStore %b %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%19 = OpLabel -%7 = OpLoad %int %nu_ii -%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_3 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%103 = OpBitcast %uint %7 -%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103 -%123 = OpINotEqual %bool %122 %uint_0 -OpSelectionMerge %124 None -OpBranchConditional %123 %125 %126 -%125 = OpLabel -%127 = OpLoad %float %20 -OpBranch %124 -%126 = OpLabel -%128 = OpBitcast %uint %7 -%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0 -OpBranch %124 -%124 = OpLabel -%130 = OpPhi %float %127 %125 %101 %126 -OpBranch %43 -%45 = OpLabel -%47 = OpBitcast %uint %7 -%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40 -OpBranch %43 -%43 = OpLabel -%102 = OpPhi %float %130 %124 %101 %45 -OpStore %b %102 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%48 = OpFunction %void None %49 -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpFunctionParameter %uint -%54 = OpLabel -%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_9 -%62 = OpIAdd %uint %61 %uint_9 -%63 = OpArrayLength %uint %57 1 -%64 = OpULessThanEqual %bool %62 %63 -OpSelectionMerge %65 None -OpBranchConditional %64 %66 %65 -%66 = OpLabel -%67 = OpIAdd %uint %61 %uint_0 -%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67 -OpStore %68 %uint_9 -%70 = OpIAdd %uint %61 %uint_1 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70 -OpStore %71 %uint_23 -%73 = OpIAdd %uint %61 %uint_2 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73 -OpStore %74 %50 -%75 = OpIAdd %uint %61 %uint_3 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %uint_4 -%80 = OpLoad %v4float %gl_FragCoord -%82 = OpBitcast %v4uint %80 -%83 = OpCompositeExtract %uint %82 0 -%84 = OpIAdd %uint %61 %uint_4 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84 -OpStore %85 %83 -%86 = OpCompositeExtract %uint %82 1 -%88 = OpIAdd %uint %61 %uint_5 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88 -OpStore %89 %86 -%91 = OpIAdd %uint %61 %uint_6 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91 -OpStore %92 %51 -%94 = OpIAdd %uint %61 %uint_7 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94 -OpStore %95 %52 -%97 = OpIAdd %uint %61 %uint_8 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97 -OpStore %98 %53 -OpBranch %65 -%65 = OpLabel -OpReturn -OpFunctionEnd -%104 = OpFunction %uint None %105 -%106 = OpFunctionParameter %uint -%107 = OpFunctionParameter %uint -%108 = OpFunctionParameter %uint -%109 = OpFunctionParameter %uint -%110 = OpLabel -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %107 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %108 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -%119 = OpIAdd %uint %118 %109 -%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119 -%121 = OpLoad %uint %120 -OpReturnValue %121 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArray) { - // Same as Deprecated but declaring as StorageBuffer Block - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname Block -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %16 NonUniform -OpDecorate %20 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname Block -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %102 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %130 NonUniform -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %127 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_3 = OpConstant %uint 3 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%49 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_45 = OpConstant %uint 45 -%101 = OpConstantNull %float -%105 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpLoad %int %nu_ii -%19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0 -%20 = OpLoad %float %19 -OpStore %b %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%19 = OpLabel -%7 = OpLoad %int %nu_ii -%20 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_3 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%103 = OpBitcast %uint %7 -%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103 -%123 = OpINotEqual %bool %122 %uint_0 -OpSelectionMerge %124 None -OpBranchConditional %123 %125 %126 -%125 = OpLabel -%127 = OpLoad %float %20 -OpBranch %124 -%126 = OpLabel -%128 = OpBitcast %uint %7 -%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0 -OpBranch %124 -%124 = OpLabel -%130 = OpPhi %float %127 %125 %101 %126 -OpBranch %43 -%45 = OpLabel -%47 = OpBitcast %uint %7 -%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40 -OpBranch %43 -%43 = OpLabel -%102 = OpPhi %float %130 %124 %101 %45 -OpStore %b %102 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%48 = OpFunction %void None %49 -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpFunctionParameter %uint -%54 = OpLabel -%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_9 -%62 = OpIAdd %uint %61 %uint_9 -%63 = OpArrayLength %uint %57 1 -%64 = OpULessThanEqual %bool %62 %63 -OpSelectionMerge %65 None -OpBranchConditional %64 %66 %65 -%66 = OpLabel -%67 = OpIAdd %uint %61 %uint_0 -%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67 -OpStore %68 %uint_9 -%70 = OpIAdd %uint %61 %uint_1 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70 -OpStore %71 %uint_23 -%73 = OpIAdd %uint %61 %uint_2 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73 -OpStore %74 %50 -%75 = OpIAdd %uint %61 %uint_3 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %uint_4 -%80 = OpLoad %v4float %gl_FragCoord -%82 = OpBitcast %v4uint %80 -%83 = OpCompositeExtract %uint %82 0 -%84 = OpIAdd %uint %61 %uint_4 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84 -OpStore %85 %83 -%86 = OpCompositeExtract %uint %82 1 -%88 = OpIAdd %uint %61 %uint_5 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88 -OpStore %89 %86 -%91 = OpIAdd %uint %61 %uint_6 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91 -OpStore %92 %51 -%94 = OpIAdd %uint %61 %uint_7 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94 -OpStore %95 %52 -%97 = OpIAdd %uint %61 %uint_8 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97 -OpStore %98 %53 -OpBranch %65 -%65 = OpLabel -OpReturn -OpFunctionEnd -%104 = OpFunction %uint None %105 -%106 = OpFunctionParameter %uint -%107 = OpFunctionParameter %uint -%108 = OpFunctionParameter %uint -%109 = OpFunctionParameter %uint -%110 = OpLabel -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %107 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %108 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -%119 = OpIAdd %uint %118 %109 -%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119 -%121 = OpLoad %uint %120 -OpReturnValue %121 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, InstInitLoadUBOScalar) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) out float b; - // layout(binding=3) uniform uname { float a; } uniformBuffer; - // - // void main() - // { - // b = uniformBuffer.a; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_ptr_Uniform_uname = OpTypePointer Uniform %uname -%uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_28 Block -OpMemberDecorate %_struct_28 0 Offset 0 -OpDecorate %30 DescriptorSet 7 -OpDecorate %30 Binding 1 -OpDecorate %_struct_58 Block -OpMemberDecorate %_struct_58 0 Offset 0 -OpMemberDecorate %_struct_58 1 Offset 4 -OpDecorate %60 DescriptorSet 7 -OpDecorate %60 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_ptr_Uniform_uname = OpTypePointer Uniform %uname -%uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%21 = OpTypeFunction %uint %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_28 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_28 = OpTypePointer StorageBuffer %_struct_28 -%30 = OpVariable %_ptr_StorageBuffer__struct_28 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%uint_1 = OpConstant %uint 1 -%52 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_58 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_58 = OpTypePointer StorageBuffer %_struct_58 -%60 = OpVariable %_ptr_StorageBuffer__struct_58 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_32 = OpConstant %uint 32 -%104 = OpConstantNull %float -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0 -%16 = OpLoad %float %15 -OpStore %b %16 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%14 = OpLabel -%15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0 -%43 = OpFunctionCall %uint %20 %uint_0 %uint_0 %uint_3 %uint_0 -%45 = OpINotEqual %bool %43 %uint_0 -OpSelectionMerge %47 None -OpBranchConditional %45 %48 %49 -%48 = OpLabel -%50 = OpLoad %float %15 -OpBranch %47 -%49 = OpLabel -%103 = OpFunctionCall %void %51 %uint_32 %uint_1 %uint_0 %uint_0 -OpBranch %47 -%47 = OpLabel -%105 = OpPhi %float %50 %48 %104 %49 -OpStore %b %105 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%20 = OpFunction %uint None %21 -%22 = OpFunctionParameter %uint -%23 = OpFunctionParameter %uint -%24 = OpFunctionParameter %uint -%25 = OpFunctionParameter %uint -%26 = OpLabel -%32 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %22 -%33 = OpLoad %uint %32 -%34 = OpIAdd %uint %33 %23 -%35 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %34 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %24 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %37 -%39 = OpLoad %uint %38 -%40 = OpIAdd %uint %39 %25 -%41 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %40 -%42 = OpLoad %uint %41 -OpReturnValue %42 -OpFunctionEnd -%51 = OpFunction %void None %52 -%53 = OpFunctionParameter %uint -%54 = OpFunctionParameter %uint -%55 = OpFunctionParameter %uint -%56 = OpFunctionParameter %uint -%57 = OpLabel -%61 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_0 -%64 = OpAtomicIAdd %uint %61 %uint_4 %uint_0 %uint_9 -%65 = OpIAdd %uint %64 %uint_9 -%66 = OpArrayLength %uint %60 1 -%67 = OpULessThanEqual %bool %65 %66 -OpSelectionMerge %68 None -OpBranchConditional %67 %69 %68 -%69 = OpLabel -%70 = OpIAdd %uint %64 %uint_0 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %70 -OpStore %71 %uint_9 -%73 = OpIAdd %uint %64 %uint_1 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %73 -OpStore %74 %uint_23 -%76 = OpIAdd %uint %64 %uint_2 -%77 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %76 -OpStore %77 %53 -%78 = OpIAdd %uint %64 %uint_3 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %78 -OpStore %79 %uint_4 -%83 = OpLoad %v4float %gl_FragCoord -%85 = OpBitcast %v4uint %83 -%86 = OpCompositeExtract %uint %85 0 -%87 = OpIAdd %uint %64 %uint_4 -%88 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %87 -OpStore %88 %86 -%89 = OpCompositeExtract %uint %85 1 -%91 = OpIAdd %uint %64 %uint_5 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %91 -OpStore %92 %89 -%94 = OpIAdd %uint %64 %uint_6 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %94 -OpStore %95 %54 -%97 = OpIAdd %uint %64 %uint_7 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %97 -OpStore %98 %55 -%100 = OpIAdd %uint %64 %uint_8 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %100 -OpStore %101 %56 -OpBranch %68 -%68 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, InstBoundsInitStoreUnsizedSSBOArray) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=1) in float b; - // - // layout(binding=4) buffer bname { float b; } storageBuffer[]; - // - // void main() - // { - // storageBuffer[nu_ii].b = b; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %nu_ii %b -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %bname "bname" -OpMemberName %bname 0 "b" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpName %b "b" -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname BufferBlock -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 4 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %14 NonUniform -OpDecorate %b Location 1 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Input_float = OpTypePointer Input %float -%b = OpVariable %_ptr_Input_float Input -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %nu_ii %b %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %bname "bname" -OpMemberName %bname 0 "b" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpName %b "b" -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname BufferBlock -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 4 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %b Location 1 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %_struct_54 Block -OpMemberDecorate %_struct_54 0 Offset 0 -OpMemberDecorate %_struct_54 1 Offset 4 -OpDecorate %56 DescriptorSet 7 -OpDecorate %56 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Input_float = OpTypePointer Input %float -%b = OpVariable %_ptr_Input_float Input -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_4 = OpConstant %uint 4 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%48 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_54 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_54 = OpTypePointer StorageBuffer %_struct_54 -%56 = OpVariable %_ptr_StorageBuffer__struct_54 StorageBuffer -%uint_9 = OpConstant %uint 9 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_45 = OpConstant %uint 45 -%102 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%14 = OpLoad %int %nu_ii -%18 = OpLoad %float %b -%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %14 %int_0 -OpStore %20 %18 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %9 -%18 = OpLabel -%7 = OpLoad %int %nu_ii -%19 = OpLoad %float %b -%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_4 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%100 = OpBitcast %uint %7 -%119 = OpFunctionCall %uint %101 %uint_0 %uint_0 %uint_4 %100 -%120 = OpINotEqual %bool %119 %uint_0 -OpSelectionMerge %121 None -OpBranchConditional %120 %122 %123 -%122 = OpLabel -OpStore %20 %19 -OpBranch %121 -%123 = OpLabel -%124 = OpBitcast %uint %7 -%125 = OpFunctionCall %void %47 %uint_45 %uint_1 %124 %uint_0 -OpBranch %121 -%121 = OpLabel -OpBranch %43 -%45 = OpLabel -%46 = OpBitcast %uint %7 -%99 = OpFunctionCall %void %47 %uint_45 %uint_0 %46 %40 -OpBranch %43 -%43 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%47 = OpFunction %void None %48 -%49 = OpFunctionParameter %uint -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpLabel -%57 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_0 -%59 = OpAtomicIAdd %uint %57 %uint_4 %uint_0 %uint_9 -%60 = OpIAdd %uint %59 %uint_9 -%61 = OpArrayLength %uint %56 1 -%62 = OpULessThanEqual %bool %60 %61 -OpSelectionMerge %63 None -OpBranchConditional %62 %64 %63 -%64 = OpLabel -%65 = OpIAdd %uint %59 %uint_0 -%66 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %65 -OpStore %66 %uint_9 -%68 = OpIAdd %uint %59 %uint_1 -%69 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %68 -OpStore %69 %uint_23 -%71 = OpIAdd %uint %59 %uint_2 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %71 -OpStore %72 %49 -%74 = OpIAdd %uint %59 %uint_3 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %74 -OpStore %75 %uint_4 -%79 = OpLoad %v4float %gl_FragCoord -%81 = OpBitcast %v4uint %79 -%82 = OpCompositeExtract %uint %81 0 -%83 = OpIAdd %uint %59 %uint_4 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %83 -OpStore %84 %82 -%85 = OpCompositeExtract %uint %81 1 -%87 = OpIAdd %uint %59 %uint_5 -%88 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %87 -OpStore %88 %85 -%90 = OpIAdd %uint %59 %uint_6 -%91 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %90 -OpStore %91 %50 -%93 = OpIAdd %uint %59 %uint_7 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %93 -OpStore %94 %51 -%96 = OpIAdd %uint %59 %uint_8 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %96 -OpStore %97 %52 -OpBranch %63 -%63 = OpLabel -OpReturn -OpFunctionEnd -%101 = OpFunction %uint None %102 -%103 = OpFunctionParameter %uint -%104 = OpFunctionParameter %uint -%105 = OpFunctionParameter %uint -%106 = OpFunctionParameter %uint -%107 = OpLabel -%108 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %103 -%109 = OpLoad %uint %108 -%110 = OpIAdd %uint %109 %104 -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %110 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %105 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %106 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -OpReturnValue %118 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, InstBoundsInitLoadSizedUBOArray) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=0) out float b; - // - // layout(binding=3) uniform uname { float a; } uniformBuffer[128]; - // - // void main() - // { - // b = uniformBuffer[nu_ii].a; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %18 NonUniform -OpDecorate %22 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_uname_uint_128 = OpTypeArray %uname %uint_128 -%_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128 -%uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %89 NonUniform -OpDecorate %120 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpMemberDecorate %_struct_39 1 Offset 4 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %_struct_98 Block -OpMemberDecorate %_struct_98 0 Offset 0 -OpDecorate %100 DescriptorSet 7 -OpDecorate %100 Binding 1 -OpDecorate %117 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_uname_uint_128 = OpTypeArray %uname %uint_128 -%_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128 -%uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%32 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_9 = OpConstant %uint 9 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_46 = OpConstant %uint 46 -%88 = OpConstantNull %float -%92 = OpTypeFunction %uint %uint %uint %uint %uint -%_struct_98 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_98 = OpTypePointer StorageBuffer %_struct_98 -%100 = OpVariable %_ptr_StorageBuffer__struct_98 StorageBuffer -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%18 = OpLoad %int %nu_ii -%21 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %18 %int_0 -%22 = OpLoad %float %21 -OpStore %b %22 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%21 = OpLabel -%7 = OpLoad %int %nu_ii -%22 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %7 %int_0 -%25 = OpULessThan %bool %7 %uint_128 -OpSelectionMerge %26 None -OpBranchConditional %25 %27 %28 -%27 = OpLabel -%90 = OpBitcast %uint %7 -%112 = OpFunctionCall %uint %91 %uint_0 %uint_0 %uint_3 %90 -%113 = OpINotEqual %bool %112 %uint_0 -OpSelectionMerge %114 None -OpBranchConditional %113 %115 %116 -%115 = OpLabel -%117 = OpLoad %float %22 -OpBranch %114 -%116 = OpLabel -%118 = OpBitcast %uint %7 -%119 = OpFunctionCall %void %31 %uint_46 %uint_1 %118 %uint_0 -OpBranch %114 -%114 = OpLabel -%120 = OpPhi %float %117 %115 %88 %116 -OpBranch %26 -%28 = OpLabel -%30 = OpBitcast %uint %7 -%87 = OpFunctionCall %void %31 %uint_46 %uint_0 %30 %uint_128 -OpBranch %26 -%26 = OpLabel -%89 = OpPhi %float %120 %114 %88 %28 -OpStore %b %89 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%31 = OpFunction %void None %32 -%33 = OpFunctionParameter %uint -%34 = OpFunctionParameter %uint -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 -%46 = OpAtomicIAdd %uint %43 %uint_4 %uint_0 %uint_9 -%47 = OpIAdd %uint %46 %uint_9 -%48 = OpArrayLength %uint %41 1 -%49 = OpULessThanEqual %bool %47 %48 -OpSelectionMerge %50 None -OpBranchConditional %49 %51 %50 -%51 = OpLabel -%52 = OpIAdd %uint %46 %uint_0 -%54 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %52 -OpStore %54 %uint_9 -%56 = OpIAdd %uint %46 %uint_1 -%57 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %56 -OpStore %57 %uint_23 -%59 = OpIAdd %uint %46 %uint_2 -%60 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %59 -OpStore %60 %33 -%62 = OpIAdd %uint %46 %uint_3 -%63 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %62 -OpStore %63 %uint_4 -%67 = OpLoad %v4float %gl_FragCoord -%69 = OpBitcast %v4uint %67 -%70 = OpCompositeExtract %uint %69 0 -%71 = OpIAdd %uint %46 %uint_4 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %71 -OpStore %72 %70 -%73 = OpCompositeExtract %uint %69 1 -%75 = OpIAdd %uint %46 %uint_5 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %75 -OpStore %76 %73 -%78 = OpIAdd %uint %46 %uint_6 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %78 -OpStore %79 %34 -%81 = OpIAdd %uint %46 %uint_7 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %81 -OpStore %82 %35 -%84 = OpIAdd %uint %46 %uint_8 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %84 -OpStore %85 %36 -OpBranch %50 -%50 = OpLabel -OpReturn -OpFunctionEnd -%91 = OpFunction %uint None %92 -%93 = OpFunctionParameter %uint -%94 = OpFunctionParameter %uint -%95 = OpFunctionParameter %uint -%96 = OpFunctionParameter %uint -%97 = OpLabel -%101 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %93 -%102 = OpLoad %uint %101 -%103 = OpIAdd %uint %102 %94 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %103 -%105 = OpLoad %uint %104 -%106 = OpIAdd %uint %105 %95 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %106 -%108 = OpLoad %uint %107 -%109 = OpIAdd %uint %108 %96 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %109 -%111 = OpLoad %uint %110 -OpReturnValue %111 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true); -} - -TEST_F(InstBindlessTest, SimpleV2) { - // Texture2D g_tColor[128]; - // - // layout(push_constant) cbuffer PerViewConstantBuffer_t - // { - // uint g_nDataIdx; - // }; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // ps_output.vColor = - // g_tColor[ g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy); - // return ps_output; - // } - - const std::string entry_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -)"; - - const std::string entry_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -)"; - - const std::string names_annots = - R"(OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -)"; - - const std::string new_annots = - R"(OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -)"; - - const std::string consts_types_vars = - R"(%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%16 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_16_uint_128 = OpTypeArray %16 %uint_128 -%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%24 = OpTypeSampler -%_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24 -%g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant -%26 = OpTypeSampledImage %16 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string new_consts_types_vars = - R"(%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%48 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_56 = OpConstant %uint 56 -%103 = OpConstantNull %v4float -)"; - - const std::string func_pt1 = - R"(%MainPs = OpFunction %void None %10 -%29 = OpLabel -%30 = OpLoad %v2float %i_vTextureCoords -%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%32 = OpLoad %uint %31 -%33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32 -%34 = OpLoad %16 %33 -%35 = OpLoad %24 %g_sAniso -%36 = OpSampledImage %26 %34 %35 -)"; - - const std::string func_pt2_before = - R"(%37 = OpImageSampleImplicitLod %v4float %36 %30 -OpStore %_entryPointOutput_vColor %37 -OpReturn -OpFunctionEnd -)"; - - const std::string func_pt2_after = - R"(%40 = OpULessThan %bool %32 %uint_128 -OpSelectionMerge %41 None -OpBranchConditional %40 %42 %43 -%42 = OpLabel -%44 = OpLoad %16 %33 -%45 = OpSampledImage %26 %44 %35 -%46 = OpImageSampleImplicitLod %v4float %45 %30 -OpBranch %41 -%43 = OpLabel -%102 = OpFunctionCall %void %47 %uint_56 %uint_0 %32 %uint_128 -OpBranch %41 -%41 = OpLabel -%104 = OpPhi %v4float %46 %42 %103 %43 -OpStore %_entryPointOutput_vColor %104 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%47 = OpFunction %void None %48 -%49 = OpFunctionParameter %uint -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpLabel -%59 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%62 = OpAtomicIAdd %uint %59 %uint_4 %uint_0 %uint_10 -%63 = OpIAdd %uint %62 %uint_10 -%64 = OpArrayLength %uint %57 1 -%65 = OpULessThanEqual %bool %63 %64 -OpSelectionMerge %66 None -OpBranchConditional %65 %67 %66 -%67 = OpLabel -%68 = OpIAdd %uint %62 %uint_0 -%70 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %68 -OpStore %70 %uint_10 -%72 = OpIAdd %uint %62 %uint_1 -%73 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %72 -OpStore %73 %uint_23 -%75 = OpIAdd %uint %62 %uint_2 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %49 -%78 = OpIAdd %uint %62 %uint_3 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %78 -OpStore %79 %uint_4 -%82 = OpLoad %v4float %gl_FragCoord -%84 = OpBitcast %v4uint %82 -%85 = OpCompositeExtract %uint %84 0 -%86 = OpIAdd %uint %62 %uint_4 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %86 -OpStore %87 %85 -%88 = OpCompositeExtract %uint %84 1 -%90 = OpIAdd %uint %62 %uint_5 -%91 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %90 -OpStore %91 %88 -%93 = OpIAdd %uint %62 %uint_7 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %93 -OpStore %94 %50 -%96 = OpIAdd %uint %62 %uint_8 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %96 -OpStore %97 %51 -%99 = OpIAdd %uint %62 %uint_9 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %99 -OpStore %100 %52 -OpBranch %66 -%66 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - entry_before + names_annots + consts_types_vars + func_pt1 + - func_pt2_before, - entry_after + names_annots + new_annots + consts_types_vars + - new_consts_types_vars + func_pt1 + func_pt2_after + output_func, - true, true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, InstrumentMultipleInstructionsV2) { - // Texture2D g_tColor[128]; - // - // layout(push_constant) cbuffer PerViewConstantBuffer_t - // { - // uint g_nDataIdx; - // uint g_nDataIdx2; - // }; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // - // float t = g_tColor[g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy); - // float t2 = g_tColor[g_nDataIdx2].Sample(g_sAniso, i.vTextureCoords.xy); - // ps_output.vColor = t + t2; - // return ps_output; - // } - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_17_uint_128 = OpTypeArray %17 %uint_128 -%_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%25 = OpTypeSampler -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 -%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant -%27 = OpTypeSampledImage %17 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_17_uint_128 = OpTypeArray %17 %uint_128 -%_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%25 = OpTypeSampler -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 -%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant -%27 = OpTypeSampledImage %17 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%56 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_58 = OpConstant %uint 58 -%111 = OpConstantNull %v4float -%uint_64 = OpConstant %uint 64 -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %10 -%30 = OpLabel -%31 = OpLoad %v2float %i_vTextureCoords -%32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%33 = OpLoad %uint %32 -%34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33 -%35 = OpLoad %17 %34 -%36 = OpLoad %25 %g_sAniso -%37 = OpSampledImage %27 %35 %36 -%38 = OpImageSampleImplicitLod %v4float %37 %31 -%39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -%40 = OpLoad %uint %39 -%41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40 -%42 = OpLoad %17 %41 -%43 = OpSampledImage %27 %42 %36 -%44 = OpImageSampleImplicitLod %v4float %43 %31 -%45 = OpFAdd %v4float %38 %44 -OpStore %_entryPointOutput_vColor %45 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %10 -%30 = OpLabel -%31 = OpLoad %v2float %i_vTextureCoords -%32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%33 = OpLoad %uint %32 -%34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33 -%35 = OpLoad %17 %34 -%36 = OpLoad %25 %g_sAniso -%37 = OpSampledImage %27 %35 %36 -%48 = OpULessThan %bool %33 %uint_128 -OpSelectionMerge %49 None -OpBranchConditional %48 %50 %51 -%50 = OpLabel -%52 = OpLoad %17 %34 -%53 = OpSampledImage %27 %52 %36 -%54 = OpImageSampleImplicitLod %v4float %53 %31 -OpBranch %49 -%51 = OpLabel -%110 = OpFunctionCall %void %55 %uint_58 %uint_0 %33 %uint_128 -OpBranch %49 -%49 = OpLabel -%112 = OpPhi %v4float %54 %50 %111 %51 -%39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -%40 = OpLoad %uint %39 -%41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40 -%42 = OpLoad %17 %41 -%43 = OpSampledImage %27 %42 %36 -%113 = OpULessThan %bool %40 %uint_128 -OpSelectionMerge %114 None -OpBranchConditional %113 %115 %116 -%115 = OpLabel -%117 = OpLoad %17 %41 -%118 = OpSampledImage %27 %117 %36 -%119 = OpImageSampleImplicitLod %v4float %118 %31 -OpBranch %114 -%116 = OpLabel -%121 = OpFunctionCall %void %55 %uint_64 %uint_0 %40 %uint_128 -OpBranch %114 -%114 = OpLabel -%122 = OpPhi %v4float %119 %115 %111 %116 -%45 = OpFAdd %v4float %112 %122 -OpStore %_entryPointOutput_vColor %45 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%55 = OpFunction %void None %56 -%57 = OpFunctionParameter %uint -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpLabel -%67 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%70 = OpAtomicIAdd %uint %67 %uint_4 %uint_0 %uint_10 -%71 = OpIAdd %uint %70 %uint_10 -%72 = OpArrayLength %uint %65 1 -%73 = OpULessThanEqual %bool %71 %72 -OpSelectionMerge %74 None -OpBranchConditional %73 %75 %74 -%75 = OpLabel -%76 = OpIAdd %uint %70 %uint_0 -%78 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %76 -OpStore %78 %uint_10 -%80 = OpIAdd %uint %70 %uint_1 -%81 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %80 -OpStore %81 %uint_23 -%83 = OpIAdd %uint %70 %uint_2 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %83 -OpStore %84 %57 -%86 = OpIAdd %uint %70 %uint_3 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %86 -OpStore %87 %uint_4 -%90 = OpLoad %v4float %gl_FragCoord -%92 = OpBitcast %v4uint %90 -%93 = OpCompositeExtract %uint %92 0 -%94 = OpIAdd %uint %70 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %93 -%96 = OpCompositeExtract %uint %92 1 -%98 = OpIAdd %uint %70 %uint_5 -%99 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %98 -OpStore %99 %96 -%101 = OpIAdd %uint %70 %uint_7 -%102 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %101 -OpStore %102 %58 -%104 = OpIAdd %uint %70 %uint_8 -%105 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %104 -OpStore %105 %59 -%107 = OpIAdd %uint %70 %uint_9 -%108 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %107 -OpStore %108 %60 -OpBranch %74 -%74 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, InstrumentOpImageV2) { - // This test verifies that the pass will correctly instrument shader - // using OpImage. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability StorageImageReadWithoutFormat -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%39 = OpTypeSampledImage %20 -%_arr_39_uint_128 = OpTypeArray %39 %uint_128 -%_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability StorageImageReadWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_51 Block -OpMemberDecorate %_struct_51 0 Offset 0 -OpMemberDecorate %_struct_51 1 Offset 4 -OpDecorate %53 DescriptorSet 7 -OpDecorate %53 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%15 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%18 = OpTypeSampledImage %15 -%_arr_18_uint_128 = OpTypeArray %18 %uint_128 -%_ptr_UniformConstant__arr_18_uint_128 = OpTypePointer UniformConstant %_arr_18_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_18_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%44 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_51 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_51 = OpTypePointer StorageBuffer %_struct_51 -%53 = OpVariable %_ptr_StorageBuffer__struct_51 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%99 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2int %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64 -%66 = OpLoad %39 %65 -%75 = OpImage %20 %66 -%71 = OpImageRead %v4float %75 %53 -OpStore %_entryPointOutput_vColor %71 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %9 -%26 = OpLabel -%27 = OpLoad %v2int %i_vTextureCoords -%28 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%29 = OpLoad %uint %28 -%30 = OpAccessChain %_ptr_UniformConstant_18 %g_tColor %29 -%31 = OpLoad %18 %30 -%32 = OpImage %15 %31 -%36 = OpULessThan %bool %29 %uint_128 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %39 -%38 = OpLabel -%40 = OpLoad %18 %30 -%41 = OpImage %15 %40 -%42 = OpImageRead %v4float %41 %27 -OpBranch %37 -%39 = OpLabel -%98 = OpFunctionCall %void %43 %uint_51 %uint_0 %29 %uint_128 -OpBranch %37 -%37 = OpLabel -%100 = OpPhi %v4float %42 %38 %99 %39 -OpStore %_entryPointOutput_vColor %100 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%43 = OpFunction %void None %44 -%45 = OpFunctionParameter %uint -%46 = OpFunctionParameter %uint -%47 = OpFunctionParameter %uint -%48 = OpFunctionParameter %uint -%49 = OpLabel -%55 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_0 -%58 = OpAtomicIAdd %uint %55 %uint_4 %uint_0 %uint_10 -%59 = OpIAdd %uint %58 %uint_10 -%60 = OpArrayLength %uint %53 1 -%61 = OpULessThanEqual %bool %59 %60 -OpSelectionMerge %62 None -OpBranchConditional %61 %63 %62 -%63 = OpLabel -%64 = OpIAdd %uint %58 %uint_0 -%66 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %64 -OpStore %66 %uint_10 -%68 = OpIAdd %uint %58 %uint_1 -%69 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %68 -OpStore %69 %uint_23 -%71 = OpIAdd %uint %58 %uint_2 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %71 -OpStore %72 %45 -%74 = OpIAdd %uint %58 %uint_3 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %74 -OpStore %75 %uint_4 -%78 = OpLoad %v4float %gl_FragCoord -%80 = OpBitcast %v4uint %78 -%81 = OpCompositeExtract %uint %80 0 -%82 = OpIAdd %uint %58 %uint_4 -%83 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %82 -OpStore %83 %81 -%84 = OpCompositeExtract %uint %80 1 -%86 = OpIAdd %uint %58 %uint_5 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %86 -OpStore %87 %84 -%89 = OpIAdd %uint %58 %uint_7 -%90 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %89 -OpStore %90 %46 -%92 = OpIAdd %uint %58 %uint_8 -%93 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %92 -OpStore %93 %47 -%95 = OpIAdd %uint %58 %uint_9 -%96 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %95 -OpStore %96 %48 -OpBranch %62 -%62 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, InstrumentSampledImageV2) { - // This test verifies that the pass will correctly instrument shader - // using sampled image. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%39 = OpTypeSampledImage %20 -%_arr_39_uint_128 = OpTypeArray %39 %uint_128 -%_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_49 Block -OpMemberDecorate %_struct_49 0 Offset 0 -OpMemberDecorate %_struct_49 1 Offset 4 -OpDecorate %51 DescriptorSet 7 -OpDecorate %51 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%15 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%18 = OpTypeSampledImage %15 -%_arr_18_uint_128 = OpTypeArray %18 %uint_128 -%_ptr_UniformConstant__arr_18_uint_128 = OpTypePointer UniformConstant %_arr_18_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_18_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%42 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_49 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_49 = OpTypePointer StorageBuffer %_struct_49 -%51 = OpVariable %_ptr_StorageBuffer__struct_49 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_49 = OpConstant %uint 49 -%97 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2float %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64 -%66 = OpLoad %39 %65 -%71 = OpImageSampleImplicitLod %v4float %66 %53 -OpStore %_entryPointOutput_vColor %71 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %9 -%26 = OpLabel -%27 = OpLoad %v2float %i_vTextureCoords -%28 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%29 = OpLoad %uint %28 -%30 = OpAccessChain %_ptr_UniformConstant_18 %g_tColor %29 -%31 = OpLoad %18 %30 -%35 = OpULessThan %bool %29 %uint_128 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %38 -%37 = OpLabel -%39 = OpLoad %18 %30 -%40 = OpImageSampleImplicitLod %v4float %39 %27 -OpBranch %36 -%38 = OpLabel -%96 = OpFunctionCall %void %41 %uint_49 %uint_0 %29 %uint_128 -OpBranch %36 -%36 = OpLabel -%98 = OpPhi %v4float %40 %37 %97 %38 -OpStore %_entryPointOutput_vColor %98 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%41 = OpFunction %void None %42 -%43 = OpFunctionParameter %uint -%44 = OpFunctionParameter %uint -%45 = OpFunctionParameter %uint -%46 = OpFunctionParameter %uint -%47 = OpLabel -%53 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_0 -%56 = OpAtomicIAdd %uint %53 %uint_4 %uint_0 %uint_10 -%57 = OpIAdd %uint %56 %uint_10 -%58 = OpArrayLength %uint %51 1 -%59 = OpULessThanEqual %bool %57 %58 -OpSelectionMerge %60 None -OpBranchConditional %59 %61 %60 -%61 = OpLabel -%62 = OpIAdd %uint %56 %uint_0 -%64 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %62 -OpStore %64 %uint_10 -%66 = OpIAdd %uint %56 %uint_1 -%67 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %66 -OpStore %67 %uint_23 -%69 = OpIAdd %uint %56 %uint_2 -%70 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %69 -OpStore %70 %43 -%72 = OpIAdd %uint %56 %uint_3 -%73 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %72 -OpStore %73 %uint_4 -%76 = OpLoad %v4float %gl_FragCoord -%78 = OpBitcast %v4uint %76 -%79 = OpCompositeExtract %uint %78 0 -%80 = OpIAdd %uint %56 %uint_4 -%81 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %80 -OpStore %81 %79 -%82 = OpCompositeExtract %uint %78 1 -%84 = OpIAdd %uint %56 %uint_5 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %84 -OpStore %85 %82 -%87 = OpIAdd %uint %56 %uint_7 -%88 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %87 -OpStore %88 %44 -%90 = OpIAdd %uint %56 %uint_8 -%91 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %90 -OpStore %91 %45 -%93 = OpIAdd %uint %56 %uint_9 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %93 -OpStore %94 %46 -OpBranch %60 -%60 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, InstrumentImageWriteV2) { - // This test verifies that the pass will correctly instrument shader - // doing bindless image write. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability StorageImageWriteWithoutFormat -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%80 = OpConstantNull %v4float -%_arr_20_uint_128 = OpTypeArray %20 %uint_128 -%_ptr_UniformConstant__arr_20_uint_128 = OpTypePointer UniformConstant %_arr_20_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_20_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability StorageImageWriteWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 3 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_48 Block -OpMemberDecorate %_struct_48 0 Offset 0 -OpMemberDecorate %_struct_48 1 Offset 4 -OpDecorate %50 DescriptorSet 7 -OpDecorate %50 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%16 = OpTypeImage %float 2D 0 0 0 0 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%19 = OpConstantNull %v4float -%_arr_16_uint_128 = OpTypeArray %16 %uint_128 -%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%_ptr_Input_v2int = OpTypePointer Input %v2int -%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%41 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_48 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_48 = OpTypePointer StorageBuffer %_struct_48 -%50 = OpVariable %_ptr_StorageBuffer__struct_48 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2int %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64 -%66 = OpLoad %20 %65 -OpImageWrite %66 %53 %80 -OpStore %_entryPointOutput_vColor %80 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %9 -%27 = OpLabel -%28 = OpLoad %v2int %i_vTextureCoords -%29 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%30 = OpLoad %uint %29 -%31 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %30 -%32 = OpLoad %16 %31 -%35 = OpULessThan %bool %30 %uint_128 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %38 -%37 = OpLabel -%39 = OpLoad %16 %31 -OpImageWrite %39 %28 %19 -OpBranch %36 -%38 = OpLabel -%95 = OpFunctionCall %void %40 %uint_51 %uint_0 %30 %uint_128 -OpBranch %36 -%36 = OpLabel -OpStore %_entryPointOutput_vColor %19 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%40 = OpFunction %void None %41 -%42 = OpFunctionParameter %uint -%43 = OpFunctionParameter %uint -%44 = OpFunctionParameter %uint -%45 = OpFunctionParameter %uint -%46 = OpLabel -%52 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_0 -%55 = OpAtomicIAdd %uint %52 %uint_4 %uint_0 %uint_10 -%56 = OpIAdd %uint %55 %uint_10 -%57 = OpArrayLength %uint %50 1 -%58 = OpULessThanEqual %bool %56 %57 -OpSelectionMerge %59 None -OpBranchConditional %58 %60 %59 -%60 = OpLabel -%61 = OpIAdd %uint %55 %uint_0 -%63 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %61 -OpStore %63 %uint_10 -%65 = OpIAdd %uint %55 %uint_1 -%66 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %65 -OpStore %66 %uint_23 -%68 = OpIAdd %uint %55 %uint_2 -%69 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %68 -OpStore %69 %42 -%71 = OpIAdd %uint %55 %uint_3 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %71 -OpStore %72 %uint_4 -%75 = OpLoad %v4float %gl_FragCoord -%77 = OpBitcast %v4uint %75 -%78 = OpCompositeExtract %uint %77 0 -%79 = OpIAdd %uint %55 %uint_4 -%80 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %79 -OpStore %80 %78 -%81 = OpCompositeExtract %uint %77 1 -%83 = OpIAdd %uint %55 %uint_5 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %83 -OpStore %84 %81 -%86 = OpIAdd %uint %55 %uint_7 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %86 -OpStore %87 %43 -%89 = OpIAdd %uint %55 %uint_8 -%90 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %89 -OpStore %90 %44 -%92 = OpIAdd %uint %55 %uint_9 -%93 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %92 -OpStore %93 %45 -OpBranch %59 -%59 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, InstrumentVertexSimpleV2) { - // This test verifies that the pass will correctly instrument shader - // doing bindless image write. This test was created by editing the SPIR-V - // from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" %_ %coords2D -OpSource GLSL 450 -OpName %main "main" -OpName %lod "lod" -OpName %coords1D "coords1D" -OpName %gl_PerVertex "gl_PerVertex" -OpMemberName %gl_PerVertex 0 "gl_Position" -OpMemberName %gl_PerVertex 1 "gl_PointSize" -OpMemberName %gl_PerVertex 2 "gl_ClipDistance" -OpMemberName %gl_PerVertex 3 "gl_CullDistance" -OpName %_ "" -OpName %texSampler1D "texSampler1D" -OpName %foo "foo" -OpMemberName %foo 0 "g_idx" -OpName %__0 "" -OpName %coords2D "coords2D" -OpMemberDecorate %gl_PerVertex 0 BuiltIn Position -OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize -OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance -OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance -OpDecorate %gl_PerVertex Block -OpDecorate %texSampler1D DescriptorSet 0 -OpDecorate %texSampler1D Binding 3 -OpMemberDecorate %foo 0 Offset 0 -OpDecorate %foo Block -OpDecorate %__0 DescriptorSet 0 -OpDecorate %__0 Binding 5 -OpDecorate %coords2D Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_3 = OpConstant %float 3 -%float_1_78900003 = OpConstant %float 1.78900003 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex -%_ = OpVariable %_ptr_Output_gl_PerVertex Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%21 = OpTypeImage %float 1D 0 0 0 1 Unknown -%22 = OpTypeSampledImage %21 -%uint_128 = OpConstant %uint 128 -%_arr_22_uint_128 = OpTypeArray %22 %uint_128 -%_ptr_UniformConstant__arr_22_uint_128 = OpTypePointer UniformConstant %_arr_22_uint_128 -%texSampler1D = OpVariable %_ptr_UniformConstant__arr_22_uint_128 UniformConstant -%foo = OpTypeStruct %int -%_ptr_Uniform_foo = OpTypePointer Uniform %foo -%__0 = OpVariable %_ptr_Uniform_foo Uniform -%_ptr_Uniform_int = OpTypePointer Uniform %int -%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%coords2D = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability Sampled1D -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" %_ %coords2D %gl_VertexIndex %gl_InstanceIndex -OpSource GLSL 450 -OpName %main "main" -OpName %lod "lod" -OpName %coords1D "coords1D" -OpName %gl_PerVertex "gl_PerVertex" -OpMemberName %gl_PerVertex 0 "gl_Position" -OpMemberName %gl_PerVertex 1 "gl_PointSize" -OpMemberName %gl_PerVertex 2 "gl_ClipDistance" -OpMemberName %gl_PerVertex 3 "gl_CullDistance" -OpName %_ "" -OpName %texSampler1D "texSampler1D" -OpName %foo "foo" -OpMemberName %foo 0 "g_idx" -OpName %__0 "" -OpName %coords2D "coords2D" -OpMemberDecorate %gl_PerVertex 0 BuiltIn Position -OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize -OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance -OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance -OpDecorate %gl_PerVertex Block -OpDecorate %texSampler1D DescriptorSet 0 -OpDecorate %texSampler1D Binding 3 -OpMemberDecorate %foo 0 Offset 0 -OpDecorate %foo Block -OpDecorate %__0 DescriptorSet 0 -OpDecorate %__0 Binding 5 -OpDecorate %coords2D Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_61 Block -OpMemberDecorate %_struct_61 0 Offset 0 -OpMemberDecorate %_struct_61 1 Offset 4 -OpDecorate %63 DescriptorSet 7 -OpDecorate %63 Binding 0 -OpDecorate %gl_VertexIndex BuiltIn VertexIndex -OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_3 = OpConstant %float 3 -%float_1_78900003 = OpConstant %float 1.78900003 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex -%_ = OpVariable %_ptr_Output_gl_PerVertex Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%24 = OpTypeImage %float 1D 0 0 0 1 Unknown -%25 = OpTypeSampledImage %24 -%uint_128 = OpConstant %uint 128 -%_arr_25_uint_128 = OpTypeArray %25 %uint_128 -%_ptr_UniformConstant__arr_25_uint_128 = OpTypePointer UniformConstant %_arr_25_uint_128 -%texSampler1D = OpVariable %_ptr_UniformConstant__arr_25_uint_128 UniformConstant -%foo = OpTypeStruct %int -%_ptr_Uniform_foo = OpTypePointer Uniform %foo -%__0 = OpVariable %_ptr_Uniform_foo Uniform -%_ptr_Uniform_int = OpTypePointer Uniform %int -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%coords2D = OpVariable %_ptr_Input_v2float Input -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%54 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_61 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_61 = OpTypePointer StorageBuffer %_struct_61 -%63 = OpVariable %_ptr_StorageBuffer__struct_61 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_uint = OpTypePointer Input %uint -%gl_VertexIndex = OpVariable %_ptr_Input_uint Input -%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_74 = OpConstant %uint 74 -%106 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%lod = OpVariable %_ptr_Function_float Function -%coords1D = OpVariable %_ptr_Function_float Function -OpStore %lod %float_3 -OpStore %coords1D %float_1_78900003 -%31 = OpAccessChain %_ptr_Uniform_int %__0 %int_0 -%32 = OpLoad %int %31 -%34 = OpAccessChain %_ptr_UniformConstant_22 %texSampler1D %32 -%35 = OpLoad %22 %34 -%36 = OpLoad %float %coords1D -%37 = OpLoad %float %lod -%38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37 -%40 = OpAccessChain %_ptr_Output_v4float %_ %int_0 -OpStore %40 %38 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %12 -%35 = OpLabel -%lod = OpVariable %_ptr_Function_float Function -%coords1D = OpVariable %_ptr_Function_float Function -OpStore %lod %float_3 -OpStore %coords1D %float_1_78900003 -%36 = OpAccessChain %_ptr_Uniform_int %__0 %int_0 -%37 = OpLoad %int %36 -%38 = OpAccessChain %_ptr_UniformConstant_25 %texSampler1D %37 -%39 = OpLoad %25 %38 -%40 = OpLoad %float %coords1D -%41 = OpLoad %float %lod -%46 = OpULessThan %bool %37 %uint_128 -OpSelectionMerge %47 None -OpBranchConditional %46 %48 %49 -%48 = OpLabel -%50 = OpLoad %25 %38 -%51 = OpImageSampleExplicitLod %v4float %50 %40 Lod %41 -OpBranch %47 -%49 = OpLabel -%52 = OpBitcast %uint %37 -%105 = OpFunctionCall %void %53 %uint_74 %uint_0 %52 %uint_128 -OpBranch %47 -%47 = OpLabel -%107 = OpPhi %v4float %51 %48 %106 %49 -%43 = OpAccessChain %_ptr_Output_v4float %_ %int_0 -OpStore %43 %107 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%53 = OpFunction %void None %54 -%55 = OpFunctionParameter %uint -%56 = OpFunctionParameter %uint -%57 = OpFunctionParameter %uint -%58 = OpFunctionParameter %uint -%59 = OpLabel -%65 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_0 -%68 = OpAtomicIAdd %uint %65 %uint_4 %uint_0 %uint_10 -%69 = OpIAdd %uint %68 %uint_10 -%70 = OpArrayLength %uint %63 1 -%71 = OpULessThanEqual %bool %69 %70 -OpSelectionMerge %72 None -OpBranchConditional %71 %73 %72 -%73 = OpLabel -%74 = OpIAdd %uint %68 %uint_0 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %74 -OpStore %75 %uint_10 -%77 = OpIAdd %uint %68 %uint_1 -%78 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %77 -OpStore %78 %uint_23 -%80 = OpIAdd %uint %68 %uint_2 -%81 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %80 -OpStore %81 %55 -%83 = OpIAdd %uint %68 %uint_3 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %83 -OpStore %84 %uint_0 -%87 = OpLoad %uint %gl_VertexIndex -%88 = OpIAdd %uint %68 %uint_4 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %88 -OpStore %89 %87 -%91 = OpLoad %uint %gl_InstanceIndex -%93 = OpIAdd %uint %68 %uint_5 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %93 -OpStore %94 %91 -%96 = OpIAdd %uint %68 %uint_7 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %96 -OpStore %97 %56 -%99 = OpIAdd %uint %68 %uint_8 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %99 -OpStore %100 %57 -%102 = OpIAdd %uint %68 %uint_9 -%103 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %102 -OpStore %103 %58 -OpBranch %72 -%72 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, InstrumentTeseSimpleV2) { - // This test verifies that the pass will correctly instrument tessellation - // evaluation shader doing bindless buffer load. - // - // clang-format off - // - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(std140, set = 0, binding = 0) uniform ufoo { uint index; } uniform_index_buffer; - // - // layout(set = 0, binding = 1) buffer bfoo { vec4 val; } adds[11]; - // - // layout(triangles, equal_spacing, cw) in; - // - // void main() { - // gl_Position = adds[uniform_index_buffer.index].val; - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Tessellation -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" %_ -OpExecutionMode %main Triangles -OpExecutionMode %main SpacingEqual -OpExecutionMode %main VertexOrderCw -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %gl_PerVertex "gl_PerVertex" -OpMemberName %gl_PerVertex 0 "gl_Position" -OpMemberName %gl_PerVertex 1 "gl_PointSize" -OpMemberName %gl_PerVertex 2 "gl_ClipDistance" -OpMemberName %gl_PerVertex 3 "gl_CullDistance" -OpName %_ "" -OpName %bfoo "bfoo" -OpMemberName %bfoo 0 "val" -OpName %adds "adds" -OpName %ufoo "ufoo" -OpMemberName %ufoo 0 "index" -OpName %uniform_index_buffer "uniform_index_buffer" -OpMemberDecorate %gl_PerVertex 0 BuiltIn Position -OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize -OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance -OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance -OpDecorate %gl_PerVertex Block -OpMemberDecorate %bfoo 0 Offset 0 -OpDecorate %bfoo Block -OpDecorate %adds DescriptorSet 0 -OpDecorate %adds Binding 1 -OpMemberDecorate %ufoo 0 Offset 0 -OpDecorate %ufoo Block -OpDecorate %uniform_index_buffer DescriptorSet 0 -OpDecorate %uniform_index_buffer Binding 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex -%_ = OpVariable %_ptr_Output_gl_PerVertex Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%bfoo = OpTypeStruct %v4float -%uint_11 = OpConstant %uint 11 -%_arr_bfoo_uint_11 = OpTypeArray %bfoo %uint_11 -%_ptr_StorageBuffer__arr_bfoo_uint_11 = OpTypePointer StorageBuffer %_arr_bfoo_uint_11 -%adds = OpVariable %_ptr_StorageBuffer__arr_bfoo_uint_11 StorageBuffer -%ufoo = OpTypeStruct %uint -%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo -%uniform_index_buffer = OpVariable %_ptr_Uniform_ufoo Uniform -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -)"; - - const std::string defs_after = - R"(OpCapability Tessellation -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" %_ %gl_PrimitiveID %gl_TessCoord -OpExecutionMode %main Triangles -OpExecutionMode %main SpacingEqual -OpExecutionMode %main VertexOrderCw -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %gl_PerVertex "gl_PerVertex" -OpMemberName %gl_PerVertex 0 "gl_Position" -OpMemberName %gl_PerVertex 1 "gl_PointSize" -OpMemberName %gl_PerVertex 2 "gl_ClipDistance" -OpMemberName %gl_PerVertex 3 "gl_CullDistance" -OpName %_ "" -OpName %bfoo "bfoo" -OpMemberName %bfoo 0 "val" -OpName %adds "adds" -OpName %ufoo "ufoo" -OpMemberName %ufoo 0 "index" -OpName %uniform_index_buffer "uniform_index_buffer" -OpMemberDecorate %gl_PerVertex 0 BuiltIn Position -OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize -OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance -OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance -OpDecorate %gl_PerVertex Block -OpMemberDecorate %bfoo 0 Offset 0 -OpDecorate %bfoo Block -OpDecorate %adds DescriptorSet 0 -OpDecorate %adds Binding 1 -OpMemberDecorate %ufoo 0 Offset 0 -OpDecorate %ufoo Block -OpDecorate %uniform_index_buffer DescriptorSet 0 -OpDecorate %uniform_index_buffer Binding 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_47 Block -OpMemberDecorate %_struct_47 0 Offset 0 -OpMemberDecorate %_struct_47 1 Offset 4 -OpDecorate %49 DescriptorSet 7 -OpDecorate %49 Binding 0 -OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId -OpDecorate %gl_TessCoord BuiltIn TessCoord -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex -%_ = OpVariable %_ptr_Output_gl_PerVertex Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%bfoo = OpTypeStruct %v4float -%uint_11 = OpConstant %uint 11 -%_arr_bfoo_uint_11 = OpTypeArray %bfoo %uint_11 -%_ptr_StorageBuffer__arr_bfoo_uint_11 = OpTypePointer StorageBuffer %_arr_bfoo_uint_11 -%adds = OpVariable %_ptr_StorageBuffer__arr_bfoo_uint_11 StorageBuffer -%ufoo = OpTypeStruct %uint -%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo -%uniform_index_buffer = OpVariable %_ptr_Uniform_ufoo Uniform -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%40 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_47 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_47 = OpTypePointer StorageBuffer %_struct_47 -%49 = OpVariable %_ptr_StorageBuffer__struct_47 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_uint = OpTypePointer Input %uint -%gl_PrimitiveID = OpVariable %_ptr_Input_uint Input -%v3float = OpTypeVector %float 3 -%_ptr_Input_v3float = OpTypePointer Input %v3float -%gl_TessCoord = OpVariable %_ptr_Input_v3float Input -%v3uint = OpTypeVector %uint 3 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_63 = OpConstant %uint 63 -%101 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0 -%26 = OpLoad %uint %25 -%28 = OpAccessChain %_ptr_StorageBuffer_v4float %adds %26 %int_0 -%29 = OpLoad %v4float %28 -%31 = OpAccessChain %_ptr_Output_v4float %_ %int_0 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%26 = OpLabel -%27 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0 -%28 = OpLoad %uint %27 -%29 = OpAccessChain %_ptr_StorageBuffer_v4float %adds %28 %int_0 -%34 = OpULessThan %bool %28 %uint_11 -OpSelectionMerge %35 None -OpBranchConditional %34 %36 %37 -%36 = OpLabel -%38 = OpLoad %v4float %29 -OpBranch %35 -%37 = OpLabel -%100 = OpFunctionCall %void %39 %uint_63 %uint_0 %28 %uint_11 -OpBranch %35 -%35 = OpLabel -%102 = OpPhi %v4float %38 %36 %101 %37 -%31 = OpAccessChain %_ptr_Output_v4float %_ %int_0 -OpStore %31 %102 -OpReturn -OpFunctionEnd -)"; - - const std::string output_func = - R"(%39 = OpFunction %void None %40 -%41 = OpFunctionParameter %uint -%42 = OpFunctionParameter %uint -%43 = OpFunctionParameter %uint -%44 = OpFunctionParameter %uint -%45 = OpLabel -%51 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_0 -%54 = OpAtomicIAdd %uint %51 %uint_4 %uint_0 %uint_10 -%55 = OpIAdd %uint %54 %uint_10 -%56 = OpArrayLength %uint %49 1 -%57 = OpULessThanEqual %bool %55 %56 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %58 -%59 = OpLabel -%60 = OpIAdd %uint %54 %uint_0 -%61 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %60 -OpStore %61 %uint_10 -%63 = OpIAdd %uint %54 %uint_1 -%64 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %63 -OpStore %64 %uint_23 -%66 = OpIAdd %uint %54 %uint_2 -%67 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %66 -OpStore %67 %41 -%69 = OpIAdd %uint %54 %uint_3 -%70 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %69 -OpStore %70 %uint_2 -%73 = OpLoad %uint %gl_PrimitiveID -%74 = OpIAdd %uint %54 %uint_4 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %74 -OpStore %75 %73 -%79 = OpLoad %v3float %gl_TessCoord -%81 = OpBitcast %v3uint %79 -%82 = OpCompositeExtract %uint %81 0 -%83 = OpCompositeExtract %uint %81 1 -%85 = OpIAdd %uint %54 %uint_5 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %85 -OpStore %86 %82 -%88 = OpIAdd %uint %54 %uint_6 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %88 -OpStore %89 %83 -%91 = OpIAdd %uint %54 %uint_7 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %91 -OpStore %92 %42 -%94 = OpIAdd %uint %54 %uint_8 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %94 -OpStore %95 %43 -%97 = OpIAdd %uint %54 %uint_9 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %97 -OpStore %98 %44 -OpBranch %58 -%58 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + output_func, true, - true, 7u, 23u, false, false, 2u); -} - -TEST_F(InstBindlessTest, MultipleDebugFunctionsV2) { - // Same source as Simple, but compiled -g and not optimized, especially not - // inlined. The OpSource has had the source extracted for the sake of brevity. - - const std::string defs_before = - R"(OpCapability Shader -%2 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -%1 = OpString "foo5.frag" -OpSource HLSL 500 %1 -OpName %MainPs "MainPs" -OpName %PS_INPUT "PS_INPUT" -OpMemberName %PS_INPUT 0 "vTextureCoords" -OpName %PS_OUTPUT "PS_OUTPUT" -OpMemberName %PS_OUTPUT 0 "vColor" -OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" -OpName %i "i" -OpName %ps_output "ps_output" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_0 "i" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpName %param "param" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 1 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%PS_INPUT = OpTypeStruct %v2float -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -%v4float = OpTypeVector %float 4 -%PS_OUTPUT = OpTypeStruct %v4float -%13 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%21 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_21_uint_128 = OpTypeArray %21 %uint_128 -%_ptr_UniformConstant__arr_21_uint_128 = OpTypePointer UniformConstant %_arr_21_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_21_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 -%36 = OpTypeSampler -%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 -%g_sAniso = OpVariable %_ptr_UniformConstant_36 UniformConstant -%40 = OpTypeSampledImage %21 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -%5 = OpString "foo5.frag" -OpSource HLSL 500 %5 -OpName %MainPs "MainPs" -OpName %PS_INPUT "PS_INPUT" -OpMemberName %PS_INPUT 0 "vTextureCoords" -OpName %PS_OUTPUT "PS_OUTPUT" -OpMemberName %PS_OUTPUT 0 "vColor" -OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" -OpName %i "i" -OpName %ps_output "ps_output" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_0 "i" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpName %param "param" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 1 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_77 Block -OpMemberDecorate %_struct_77 0 Offset 0 -OpMemberDecorate %_struct_77 1 Offset 4 -OpDecorate %79 DescriptorSet 7 -OpDecorate %79 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%18 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%PS_INPUT = OpTypeStruct %v2float -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -%v4float = OpTypeVector %float 4 -%PS_OUTPUT = OpTypeStruct %v4float -%23 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%27 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_27_uint_128 = OpTypeArray %27 %uint_128 -%_ptr_UniformConstant__arr_27_uint_128 = OpTypePointer UniformConstant %_arr_27_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_27_uint_128 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27 -%35 = OpTypeSampler -%_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35 -%g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant -%37 = OpTypeSampledImage %27 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%70 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_77 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_77 = OpTypePointer StorageBuffer %_struct_77 -%79 = OpVariable %_ptr_StorageBuffer__struct_77 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_93 = OpConstant %uint 93 -%125 = OpConstantNull %v4float -)"; - - const std::string func1_before = - R"(%MainPs = OpFunction %void None %4 -%6 = OpLabel -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %1 21 0 -%54 = OpLoad %v2float %i_vTextureCoords -%55 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpStore %55 %54 -%59 = OpLoad %PS_INPUT %i_0 -OpStore %param %59 -%60 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -%61 = OpCompositeExtract %v4float %60 0 -OpStore %_entryPointOutput_vColor %61 -OpReturn -OpFunctionEnd -)"; - - const std::string func1_after = - R"(%MainPs = OpFunction %void None %18 -%42 = OpLabel -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %5 21 0 -%43 = OpLoad %v2float %i_vTextureCoords -%44 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpStore %44 %43 -%45 = OpLoad %PS_INPUT %i_0 -OpStore %param %45 -%46 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -%47 = OpCompositeExtract %v4float %46 0 -OpStore %_entryPointOutput_vColor %47 -OpReturn -OpFunctionEnd -)"; - - const std::string func2_before = - R"(%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %13 -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -%16 = OpLabel -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %1 24 0 -%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%32 = OpLoad %uint %31 -%34 = OpAccessChain %_ptr_UniformConstant_21 %g_tColor %32 -%35 = OpLoad %21 %34 -%39 = OpLoad %36 %g_sAniso -%41 = OpSampledImage %40 %35 %39 -%43 = OpAccessChain %_ptr_Function_v2float %i %int_0 -%44 = OpLoad %v2float %43 -%45 = OpImageSampleImplicitLod %v4float %41 %44 -%47 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpStore %47 %45 -OpLine %1 25 0 -%48 = OpLoad %PS_OUTPUT %ps_output -OpReturnValue %48 -OpFunctionEnd -)"; - - const std::string func2_after = - R"(%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %23 -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -%48 = OpLabel -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %5 24 0 -%49 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%50 = OpLoad %uint %49 -%51 = OpAccessChain %_ptr_UniformConstant_27 %g_tColor %50 -%52 = OpLoad %27 %51 -%53 = OpLoad %35 %g_sAniso -%54 = OpSampledImage %37 %52 %53 -%55 = OpAccessChain %_ptr_Function_v2float %i %int_0 -%56 = OpLoad %v2float %55 -%62 = OpULessThan %bool %50 %uint_128 -OpSelectionMerge %63 None -OpBranchConditional %62 %64 %65 -%64 = OpLabel -%66 = OpLoad %27 %51 -%67 = OpSampledImage %37 %66 %53 -%68 = OpImageSampleImplicitLod %v4float %67 %56 -OpBranch %63 -%65 = OpLabel -%124 = OpFunctionCall %void %69 %uint_93 %uint_0 %50 %uint_128 -OpBranch %63 -%63 = OpLabel -%126 = OpPhi %v4float %68 %64 %125 %65 -%58 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpStore %58 %126 -OpLine %5 25 0 -%59 = OpLoad %PS_OUTPUT %ps_output -OpReturnValue %59 -OpFunctionEnd -)"; - - const std::string output_func = - R"(%69 = OpFunction %void None %70 -%71 = OpFunctionParameter %uint -%72 = OpFunctionParameter %uint -%73 = OpFunctionParameter %uint -%74 = OpFunctionParameter %uint -%75 = OpLabel -%81 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_0 -%84 = OpAtomicIAdd %uint %81 %uint_4 %uint_0 %uint_10 -%85 = OpIAdd %uint %84 %uint_10 -%86 = OpArrayLength %uint %79 1 -%87 = OpULessThanEqual %bool %85 %86 -OpSelectionMerge %88 None -OpBranchConditional %87 %89 %88 -%89 = OpLabel -%90 = OpIAdd %uint %84 %uint_0 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %90 -OpStore %92 %uint_10 -%94 = OpIAdd %uint %84 %uint_1 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %94 -OpStore %95 %uint_23 -%97 = OpIAdd %uint %84 %uint_2 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %97 -OpStore %98 %71 -%100 = OpIAdd %uint %84 %uint_3 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %100 -OpStore %101 %uint_4 -%104 = OpLoad %v4float %gl_FragCoord -%106 = OpBitcast %v4uint %104 -%107 = OpCompositeExtract %uint %106 0 -%108 = OpIAdd %uint %84 %uint_4 -%109 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %108 -OpStore %109 %107 -%110 = OpCompositeExtract %uint %106 1 -%112 = OpIAdd %uint %84 %uint_5 -%113 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %112 -OpStore %113 %110 -%115 = OpIAdd %uint %84 %uint_7 -%116 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %115 -OpStore %116 %72 -%118 = OpIAdd %uint %84 %uint_8 -%119 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %118 -OpStore %119 %73 -%121 = OpIAdd %uint %84 %uint_9 -%122 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %121 -OpStore %122 %74 -OpBranch %88 -%88 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func1_before + func2_before, - defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u, - false, false, 2u); -} - -TEST_F(InstBindlessTest, RuntimeArrayV2) { - // This test verifies that the pass will correctly instrument shader - // with runtime descriptor array. This test was created by editing the - // SPIR-V from the Simple test. - - const std::string defs_before = - R"(OpCapability Shader -OpCapability RuntimeDescriptorArray -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 1 -OpDecorate %g_tColor Binding 2 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 1 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%20 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_rarr_20 = OpTypeRuntimeArray %20 -%_ptr_UniformConstant__arr_20 = OpTypePointer UniformConstant %_rarr_20 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_20 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 -%35 = OpTypeSampler -%_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35 -%g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant -%39 = OpTypeSampledImage %20 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability RuntimeDescriptorArray -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpName %_ "" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 1 -OpDecorate %g_tColor Binding 2 -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_sAniso DescriptorSet 1 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_46 Block -OpMemberDecorate %_struct_46 0 Offset 0 -OpDecorate %48 DescriptorSet 7 -OpDecorate %48 Binding 1 -OpDecorate %_struct_71 Block -OpMemberDecorate %_struct_71 0 Offset 0 -OpMemberDecorate %_struct_71 1 Offset 4 -OpDecorate %73 DescriptorSet 7 -OpDecorate %73 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%16 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_runtimearr_16 = OpTypeRuntimeArray %16 -%_ptr_UniformConstant__runtimearr_16 = OpTypePointer UniformConstant %_runtimearr_16 -%g_tColor = OpVariable %_ptr_UniformConstant__runtimearr_16 UniformConstant -%PerViewConstantBuffer_t = OpTypeStruct %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 -%24 = OpTypeSampler -%_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24 -%g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant -%26 = OpTypeSampledImage %16 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint_0 = OpConstant %uint 0 -%uint_2 = OpConstant %uint 2 -%41 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_46 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_46 = OpTypePointer StorageBuffer %_struct_46 -%48 = OpVariable %_ptr_StorageBuffer__struct_46 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%65 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_71 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_71 = OpTypePointer StorageBuffer %_struct_71 -%73 = OpVariable %_ptr_StorageBuffer__struct_71 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_59 = OpConstant %uint 59 -%116 = OpConstantNull %v4float -%119 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %3 -%5 = OpLabel -%53 = OpLoad %v2float %i_vTextureCoords -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%64 = OpLoad %uint %63 -%65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64 -%66 = OpLoad %20 %65 -%67 = OpLoad %35 %g_sAniso -%68 = OpSampledImage %39 %66 %67 -%71 = OpImageSampleImplicitLod %v4float %68 %53 -OpStore %_entryPointOutput_vColor %71 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %10 -%29 = OpLabel -%30 = OpLoad %v2float %i_vTextureCoords -%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%32 = OpLoad %uint %31 -%33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32 -%34 = OpLoad %16 %33 -%35 = OpLoad %24 %g_sAniso -%36 = OpSampledImage %26 %34 %35 -%55 = OpFunctionCall %uint %40 %uint_2 %uint_2 -%57 = OpULessThan %bool %32 %55 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %60 -%59 = OpLabel -%61 = OpLoad %16 %33 -%62 = OpSampledImage %26 %61 %35 -%136 = OpFunctionCall %uint %118 %uint_0 %uint_1 %uint_2 %32 -%137 = OpINotEqual %bool %136 %uint_0 -OpSelectionMerge %138 None -OpBranchConditional %137 %139 %140 -%139 = OpLabel -%141 = OpLoad %16 %33 -%142 = OpSampledImage %26 %141 %35 -%143 = OpImageSampleImplicitLod %v4float %142 %30 -OpBranch %138 -%140 = OpLabel -%144 = OpFunctionCall %void %64 %uint_59 %uint_1 %32 %uint_0 -OpBranch %138 -%138 = OpLabel -%145 = OpPhi %v4float %143 %139 %116 %140 -OpBranch %58 -%60 = OpLabel -%115 = OpFunctionCall %void %64 %uint_59 %uint_0 %32 %55 -OpBranch %58 -%58 = OpLabel -%117 = OpPhi %v4float %145 %138 %116 %60 -OpStore %_entryPointOutput_vColor %117 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%40 = OpFunction %uint None %41 -%42 = OpFunctionParameter %uint -%43 = OpFunctionParameter %uint -%44 = OpLabel -%50 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %42 -%51 = OpLoad %uint %50 -%52 = OpIAdd %uint %51 %43 -%53 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %52 -%54 = OpLoad %uint %53 -OpReturnValue %54 -OpFunctionEnd -%64 = OpFunction %void None %65 -%66 = OpFunctionParameter %uint -%67 = OpFunctionParameter %uint -%68 = OpFunctionParameter %uint -%69 = OpFunctionParameter %uint -%70 = OpLabel -%74 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_0 -%77 = OpAtomicIAdd %uint %74 %uint_4 %uint_0 %uint_10 -%78 = OpIAdd %uint %77 %uint_10 -%79 = OpArrayLength %uint %73 1 -%80 = OpULessThanEqual %bool %78 %79 -OpSelectionMerge %81 None -OpBranchConditional %80 %82 %81 -%82 = OpLabel -%83 = OpIAdd %uint %77 %uint_0 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %83 -OpStore %84 %uint_10 -%86 = OpIAdd %uint %77 %uint_1 -%87 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %86 -OpStore %87 %uint_23 -%88 = OpIAdd %uint %77 %uint_2 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %88 -OpStore %89 %66 -%91 = OpIAdd %uint %77 %uint_3 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %91 -OpStore %92 %uint_4 -%95 = OpLoad %v4float %gl_FragCoord -%97 = OpBitcast %v4uint %95 -%98 = OpCompositeExtract %uint %97 0 -%99 = OpIAdd %uint %77 %uint_4 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %99 -OpStore %100 %98 -%101 = OpCompositeExtract %uint %97 1 -%103 = OpIAdd %uint %77 %uint_5 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %103 -OpStore %104 %101 -%106 = OpIAdd %uint %77 %uint_7 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %106 -OpStore %107 %67 -%109 = OpIAdd %uint %77 %uint_8 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %109 -OpStore %110 %68 -%112 = OpIAdd %uint %77 %uint_9 -%113 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %112 -OpStore %113 %69 -OpBranch %81 -%81 = OpLabel -OpReturn -OpFunctionEnd -%118 = OpFunction %uint None %119 -%120 = OpFunctionParameter %uint -%121 = OpFunctionParameter %uint -%122 = OpFunctionParameter %uint -%123 = OpFunctionParameter %uint -%124 = OpLabel -%125 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %120 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %121 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %122 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %130 -%132 = OpLoad %uint %131 -%133 = OpIAdd %uint %132 %123 -%134 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %133 -%135 = OpLoad %uint %134 -OpReturnValue %135 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptorV2) { - // This test verifies that the pass will correctly instrument vanilla - // texture sample on a scalar descriptor with an initialization check if the - // input_init_enable argument is set to true. This can happen when the - // descriptor indexing extension is enabled in the API but the SPIR-V - // does not have the extension enabled because it does not contain a - // runtime array. This is the same shader as NoInstrumentNonBindless. - - const std::string defs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%12 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 -%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant -%14 = OpTypeSampler -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant -%16 = OpTypeSampledImage %12 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord -OpExecutionMode %MainPs OriginUpperLeft -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_tColor Binding 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %g_sAniso Binding 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_35 Block -OpMemberDecorate %_struct_35 0 Offset 0 -OpDecorate %37 DescriptorSet 7 -OpDecorate %37 Binding 1 -OpDecorate %_struct_67 Block -OpMemberDecorate %_struct_67 0 Offset 0 -OpMemberDecorate %_struct_67 1 Offset 4 -OpDecorate %69 DescriptorSet 7 -OpDecorate %69 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%12 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 -%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant -%14 = OpTypeSampler -%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 -%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant -%16 = OpTypeSampledImage %12 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%28 = OpTypeFunction %uint %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_35 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_35 = OpTypePointer StorageBuffer %_struct_35 -%37 = OpVariable %_ptr_StorageBuffer__struct_35 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%uint_1 = OpConstant %uint 1 -%61 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_67 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_67 = OpTypePointer StorageBuffer %_struct_67 -%69 = OpVariable %_ptr_StorageBuffer__struct_67 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_39 = OpConstant %uint 39 -%113 = OpConstantNull %v4float -)"; - - const std::string func_before = - R"(%MainPs = OpFunction %void None %8 -%19 = OpLabel -%20 = OpLoad %v2float %i_vTextureCoords -%21 = OpLoad %12 %g_tColor -%22 = OpLoad %14 %g_sAniso -%23 = OpSampledImage %16 %21 %22 -%24 = OpImageSampleImplicitLod %v4float %23 %20 -OpStore %_entryPointOutput_vColor %24 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%MainPs = OpFunction %void None %8 -%19 = OpLabel -%20 = OpLoad %v2float %i_vTextureCoords -%21 = OpLoad %12 %g_tColor -%22 = OpLoad %14 %g_sAniso -%23 = OpSampledImage %16 %21 %22 -%50 = OpFunctionCall %uint %27 %uint_0 %uint_0 %uint_0 %uint_0 -%52 = OpINotEqual %bool %50 %uint_0 -OpSelectionMerge %54 None -OpBranchConditional %52 %55 %56 -%55 = OpLabel -%57 = OpLoad %12 %g_tColor -%58 = OpSampledImage %16 %57 %22 -%59 = OpImageSampleImplicitLod %v4float %58 %20 -OpBranch %54 -%56 = OpLabel -%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0 -OpBranch %54 -%54 = OpLabel -%114 = OpPhi %v4float %59 %55 %113 %56 -OpStore %_entryPointOutput_vColor %114 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%27 = OpFunction %uint None %28 -%29 = OpFunctionParameter %uint -%30 = OpFunctionParameter %uint -%31 = OpFunctionParameter %uint -%32 = OpFunctionParameter %uint -%33 = OpLabel -%39 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %29 -%40 = OpLoad %uint %39 -%41 = OpIAdd %uint %40 %30 -%42 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %41 -%43 = OpLoad %uint %42 -%44 = OpIAdd %uint %43 %31 -%45 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %44 -%46 = OpLoad %uint %45 -%47 = OpIAdd %uint %46 %32 -%48 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %47 -%49 = OpLoad %uint %48 -OpReturnValue %49 -OpFunctionEnd -%60 = OpFunction %void None %61 -%62 = OpFunctionParameter %uint -%63 = OpFunctionParameter %uint -%64 = OpFunctionParameter %uint -%65 = OpFunctionParameter %uint -%66 = OpLabel -%70 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 -%73 = OpAtomicIAdd %uint %70 %uint_4 %uint_0 %uint_10 -%74 = OpIAdd %uint %73 %uint_10 -%75 = OpArrayLength %uint %69 1 -%76 = OpULessThanEqual %bool %74 %75 -OpSelectionMerge %77 None -OpBranchConditional %76 %78 %77 -%78 = OpLabel -%79 = OpIAdd %uint %73 %uint_0 -%80 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %79 -OpStore %80 %uint_10 -%82 = OpIAdd %uint %73 %uint_1 -%83 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %82 -OpStore %83 %uint_23 -%85 = OpIAdd %uint %73 %uint_2 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %85 -OpStore %86 %62 -%88 = OpIAdd %uint %73 %uint_3 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %88 -OpStore %89 %uint_4 -%92 = OpLoad %v4float %gl_FragCoord -%94 = OpBitcast %v4uint %92 -%95 = OpCompositeExtract %uint %94 0 -%96 = OpIAdd %uint %73 %uint_4 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %96 -OpStore %97 %95 -%98 = OpCompositeExtract %uint %94 1 -%100 = OpIAdd %uint %73 %uint_5 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %100 -OpStore %101 %98 -%103 = OpIAdd %uint %73 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %103 -OpStore %104 %63 -%106 = OpIAdd %uint %73 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %106 -OpStore %107 %64 -%109 = OpIAdd %uint %73 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %109 -OpStore %110 %65 -OpBranch %77 -%77 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, SPV14AddToEntryPointV2) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]] -; CHECK: OpDecorate [[v1]] DescriptorSet 7 -; CHECK: OpDecorate [[v2]] DescriptorSet 7 -; CHECK: [[v1]] = OpVariable {{%\w+}} StorageBuffer -; CHECK: [[v2]] = OpVariable {{%\w+}} StorageBuffer -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var -OpExecutionMode %foo OriginUpperLeft -OpDecorate %image_var DescriptorSet 0 -OpDecorate %image_var Binding 0 -OpDecorate %sampler_var DescriptorSet 0 -OpDecorate %sampler_var Binding 1 -OpDecorate %gid DescriptorSet 0 -OpDecorate %gid Binding 2 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%v3int = OpTypeVector %int 3 -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%v4float = OpTypeVector %float 4 -%struct = OpTypeStruct %v3int -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int -%gid = OpVariable %ptr_ssbo_struct StorageBuffer -%image = OpTypeImage %float 3D 0 0 0 1 Unknown -%ptr_uc_image = OpTypePointer UniformConstant %image -%sampler = OpTypeSampler -%ptr_uc_sampler = OpTypePointer UniformConstant %sampler -%image_var = OpVariable %ptr_uc_image UniformConstant -%sampler_var = OpVariable %ptr_uc_sampler UniformConstant -%sampled = OpTypeSampledImage %image -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%ld_image = OpLoad %image %image_var -%ld_sampler = OpLoad %sampler %sampler_var -%gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0 -%ld_gid = OpLoad %v3int %gep -%convert = OpConvertUToF %v3float %ld_gid -%sampled_image = OpSampledImage %sampled %ld_image %ld_sampler -%sample = OpImageSampleImplicitLod %v4float %sampled_image %convert -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4); - SinglePassRunAndMatch(text, true, 7u, 23u, true, true, - 2u); -} - -TEST_F(InstBindlessTest, SPV14AddToEntryPointsV2) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]] -; CHECK: OpEntryPoint Fragment {{%\w+}} "bar" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]] -; CHECK: OpDecorate [[v1]] DescriptorSet 7 -; CHECK: OpDecorate [[v2]] DescriptorSet 7 -; CHECK: [[v1]] = OpVariable {{%\w+}} StorageBuffer -; CHECK: [[v2]] = OpVariable {{%\w+}} StorageBuffer -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var -OpEntryPoint Fragment %foo "bar" %gid %image_var %sampler_var -OpExecutionMode %foo OriginUpperLeft -OpDecorate %image_var DescriptorSet 0 -OpDecorate %image_var Binding 0 -OpDecorate %sampler_var DescriptorSet 0 -OpDecorate %sampler_var Binding 1 -OpDecorate %gid DescriptorSet 0 -OpDecorate %gid Binding 2 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%v3int = OpTypeVector %int 3 -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%v4float = OpTypeVector %float 4 -%struct = OpTypeStruct %v3int -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int -%gid = OpVariable %ptr_ssbo_struct StorageBuffer -%image = OpTypeImage %float 3D 0 0 0 1 Unknown -%ptr_uc_image = OpTypePointer UniformConstant %image -%sampler = OpTypeSampler -%ptr_uc_sampler = OpTypePointer UniformConstant %sampler -%image_var = OpVariable %ptr_uc_image UniformConstant -%sampler_var = OpVariable %ptr_uc_sampler UniformConstant -%sampled = OpTypeSampledImage %image -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%ld_image = OpLoad %image %image_var -%ld_sampler = OpLoad %sampler %sampler_var -%gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0 -%ld_gid = OpLoad %v3int %gep -%convert = OpConvertUToF %v3float %ld_gid -%sampled_image = OpSampledImage %sampled %ld_image %ld_sampler -%sample = OpImageSampleImplicitLod %v4float %sampled_image %convert -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4); - SinglePassRunAndMatch(text, true, 7u, 23u, true, true, - 2u); -} - -TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedUBOArrayV2) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=0) out float b; - // - // layout(binding=3) uniform uname { float a; } uniformBuffer[]; - // - // void main() - // { - // b = uniformBuffer[nu_ii].a; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %16 NonUniform -OpDecorate %20 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_runtimearr_uname = OpTypeRuntimeArray %uname -%_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname -%uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %102 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %130 NonUniform -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %127 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_runtimearr_uname = OpTypeRuntimeArray %uname -%_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname -%uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_3 = OpConstant %uint 3 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%49 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_45 = OpConstant %uint 45 -%101 = OpConstantNull %float -%105 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpLoad %int %nu_ii -%19 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %16 %int_0 -%20 = OpLoad %float %19 -OpStore %b %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%19 = OpLabel -%7 = OpLoad %int %nu_ii -%20 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_3 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%103 = OpBitcast %uint %7 -%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103 -%123 = OpINotEqual %bool %122 %uint_0 -OpSelectionMerge %124 None -OpBranchConditional %123 %125 %126 -%125 = OpLabel -%127 = OpLoad %float %20 -OpBranch %124 -%126 = OpLabel -%128 = OpBitcast %uint %7 -%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0 -OpBranch %124 -%124 = OpLabel -%130 = OpPhi %float %127 %125 %101 %126 -OpBranch %43 -%45 = OpLabel -%47 = OpBitcast %uint %7 -%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40 -OpBranch %43 -%43 = OpLabel -%102 = OpPhi %float %130 %124 %101 %45 -OpStore %b %102 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%48 = OpFunction %void None %49 -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpFunctionParameter %uint -%54 = OpLabel -%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_10 -%62 = OpIAdd %uint %61 %uint_10 -%63 = OpArrayLength %uint %57 1 -%64 = OpULessThanEqual %bool %62 %63 -OpSelectionMerge %65 None -OpBranchConditional %64 %66 %65 -%66 = OpLabel -%67 = OpIAdd %uint %61 %uint_0 -%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67 -OpStore %68 %uint_10 -%70 = OpIAdd %uint %61 %uint_1 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70 -OpStore %71 %uint_23 -%73 = OpIAdd %uint %61 %uint_2 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73 -OpStore %74 %50 -%75 = OpIAdd %uint %61 %uint_3 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %uint_4 -%80 = OpLoad %v4float %gl_FragCoord -%82 = OpBitcast %v4uint %80 -%83 = OpCompositeExtract %uint %82 0 -%84 = OpIAdd %uint %61 %uint_4 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84 -OpStore %85 %83 -%86 = OpCompositeExtract %uint %82 1 -%88 = OpIAdd %uint %61 %uint_5 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88 -OpStore %89 %86 -%91 = OpIAdd %uint %61 %uint_7 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91 -OpStore %92 %51 -%94 = OpIAdd %uint %61 %uint_8 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94 -OpStore %95 %52 -%97 = OpIAdd %uint %61 %uint_9 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97 -OpStore %98 %53 -OpBranch %65 -%65 = OpLabel -OpReturn -OpFunctionEnd -%104 = OpFunction %uint None %105 -%106 = OpFunctionParameter %uint -%107 = OpFunctionParameter %uint -%108 = OpFunctionParameter %uint -%109 = OpFunctionParameter %uint -%110 = OpLabel -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %107 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %108 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -%119 = OpIAdd %uint %118 %109 -%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119 -%121 = OpLoad %uint %120 -OpReturnValue %121 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayDeprecatedV2) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=0) out float b; - // - // layout(binding=3) buffer bname { float b; } storageBuffer[]; - // - // void main() - // { - // b = storageBuffer[nu_ii].b; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname Block -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %16 NonUniform -OpDecorate %20 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname Block -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %102 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %130 NonUniform -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %127 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_3 = OpConstant %uint 3 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%49 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_45 = OpConstant %uint 45 -%101 = OpConstantNull %float -%105 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpLoad %int %nu_ii -%19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0 -%20 = OpLoad %float %19 -OpStore %b %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%19 = OpLabel -%7 = OpLoad %int %nu_ii -%20 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_3 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%103 = OpBitcast %uint %7 -%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103 -%123 = OpINotEqual %bool %122 %uint_0 -OpSelectionMerge %124 None -OpBranchConditional %123 %125 %126 -%125 = OpLabel -%127 = OpLoad %float %20 -OpBranch %124 -%126 = OpLabel -%128 = OpBitcast %uint %7 -%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0 -OpBranch %124 -%124 = OpLabel -%130 = OpPhi %float %127 %125 %101 %126 -OpBranch %43 -%45 = OpLabel -%47 = OpBitcast %uint %7 -%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40 -OpBranch %43 -%43 = OpLabel -%102 = OpPhi %float %130 %124 %101 %45 -OpStore %b %102 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%48 = OpFunction %void None %49 -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpFunctionParameter %uint -%54 = OpLabel -%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_10 -%62 = OpIAdd %uint %61 %uint_10 -%63 = OpArrayLength %uint %57 1 -%64 = OpULessThanEqual %bool %62 %63 -OpSelectionMerge %65 None -OpBranchConditional %64 %66 %65 -%66 = OpLabel -%67 = OpIAdd %uint %61 %uint_0 -%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67 -OpStore %68 %uint_10 -%70 = OpIAdd %uint %61 %uint_1 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70 -OpStore %71 %uint_23 -%73 = OpIAdd %uint %61 %uint_2 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73 -OpStore %74 %50 -%75 = OpIAdd %uint %61 %uint_3 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %uint_4 -%80 = OpLoad %v4float %gl_FragCoord -%82 = OpBitcast %v4uint %80 -%83 = OpCompositeExtract %uint %82 0 -%84 = OpIAdd %uint %61 %uint_4 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84 -OpStore %85 %83 -%86 = OpCompositeExtract %uint %82 1 -%88 = OpIAdd %uint %61 %uint_5 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88 -OpStore %89 %86 -%91 = OpIAdd %uint %61 %uint_7 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91 -OpStore %92 %51 -%94 = OpIAdd %uint %61 %uint_8 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94 -OpStore %95 %52 -%97 = OpIAdd %uint %61 %uint_9 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97 -OpStore %98 %53 -OpBranch %65 -%65 = OpLabel -OpReturn -OpFunctionEnd -%104 = OpFunction %uint None %105 -%106 = OpFunctionParameter %uint -%107 = OpFunctionParameter %uint -%108 = OpFunctionParameter %uint -%109 = OpFunctionParameter %uint -%110 = OpLabel -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %107 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %108 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -%119 = OpIAdd %uint %118 %109 -%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119 -%121 = OpLoad %uint %120 -OpReturnValue %121 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayV2) { - // Same as Deprecated but declaring as StorageBuffer Block - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname Block -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %16 NonUniform -OpDecorate %20 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %bname "bname" -OpMemberName %bname 0 "a" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname Block -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %102 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %130 NonUniform -OpDecorate %_struct_55 Block -OpMemberDecorate %_struct_55 0 Offset 0 -OpMemberDecorate %_struct_55 1 Offset 4 -OpDecorate %57 DescriptorSet 7 -OpDecorate %57 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %127 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_3 = OpConstant %uint 3 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%49 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_55 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55 -%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_45 = OpConstant %uint 45 -%101 = OpConstantNull %float -%105 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpLoad %int %nu_ii -%19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0 -%20 = OpLoad %float %19 -OpStore %b %20 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%19 = OpLabel -%7 = OpLoad %int %nu_ii -%20 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_3 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%103 = OpBitcast %uint %7 -%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103 -%123 = OpINotEqual %bool %122 %uint_0 -OpSelectionMerge %124 None -OpBranchConditional %123 %125 %126 -%125 = OpLabel -%127 = OpLoad %float %20 -OpBranch %124 -%126 = OpLabel -%128 = OpBitcast %uint %7 -%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0 -OpBranch %124 -%124 = OpLabel -%130 = OpPhi %float %127 %125 %101 %126 -OpBranch %43 -%45 = OpLabel -%47 = OpBitcast %uint %7 -%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40 -OpBranch %43 -%43 = OpLabel -%102 = OpPhi %float %130 %124 %101 %45 -OpStore %b %102 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%48 = OpFunction %void None %49 -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpFunctionParameter %uint -%54 = OpLabel -%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0 -%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_10 -%62 = OpIAdd %uint %61 %uint_10 -%63 = OpArrayLength %uint %57 1 -%64 = OpULessThanEqual %bool %62 %63 -OpSelectionMerge %65 None -OpBranchConditional %64 %66 %65 -%66 = OpLabel -%67 = OpIAdd %uint %61 %uint_0 -%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67 -OpStore %68 %uint_10 -%70 = OpIAdd %uint %61 %uint_1 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70 -OpStore %71 %uint_23 -%73 = OpIAdd %uint %61 %uint_2 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73 -OpStore %74 %50 -%75 = OpIAdd %uint %61 %uint_3 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75 -OpStore %76 %uint_4 -%80 = OpLoad %v4float %gl_FragCoord -%82 = OpBitcast %v4uint %80 -%83 = OpCompositeExtract %uint %82 0 -%84 = OpIAdd %uint %61 %uint_4 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84 -OpStore %85 %83 -%86 = OpCompositeExtract %uint %82 1 -%88 = OpIAdd %uint %61 %uint_5 -%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88 -OpStore %89 %86 -%91 = OpIAdd %uint %61 %uint_7 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91 -OpStore %92 %51 -%94 = OpIAdd %uint %61 %uint_8 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94 -OpStore %95 %52 -%97 = OpIAdd %uint %61 %uint_9 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97 -OpStore %98 %53 -OpBranch %65 -%65 = OpLabel -OpReturn -OpFunctionEnd -%104 = OpFunction %uint None %105 -%106 = OpFunctionParameter %uint -%107 = OpFunctionParameter %uint -%108 = OpFunctionParameter %uint -%109 = OpFunctionParameter %uint -%110 = OpLabel -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %107 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %108 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -%119 = OpIAdd %uint %118 %109 -%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119 -%121 = OpLoad %uint %120 -OpReturnValue %121 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstInitLoadUBOScalarV2) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) out float b; - // layout(binding=3) uniform uname { float a; } uniformBuffer; - // - // void main() - // { - // b = uniformBuffer.a; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_ptr_Uniform_uname = OpTypePointer Uniform %uname -%uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_28 Block -OpMemberDecorate %_struct_28 0 Offset 0 -OpDecorate %30 DescriptorSet 7 -OpDecorate %30 Binding 1 -OpDecorate %_struct_58 Block -OpMemberDecorate %_struct_58 0 Offset 0 -OpMemberDecorate %_struct_58 1 Offset 4 -OpDecorate %60 DescriptorSet 7 -OpDecorate %60 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%_ptr_Uniform_uname = OpTypePointer Uniform %uname -%uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_3 = OpConstant %uint 3 -%21 = OpTypeFunction %uint %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_28 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_28 = OpTypePointer StorageBuffer %_struct_28 -%30 = OpVariable %_ptr_StorageBuffer__struct_28 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%uint_1 = OpConstant %uint 1 -%52 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_58 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_58 = OpTypePointer StorageBuffer %_struct_58 -%60 = OpVariable %_ptr_StorageBuffer__struct_58 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_32 = OpConstant %uint 32 -%104 = OpConstantNull %float -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0 -%16 = OpLoad %float %15 -OpStore %b %16 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%14 = OpLabel -%15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0 -%43 = OpFunctionCall %uint %20 %uint_0 %uint_0 %uint_3 %uint_0 -%45 = OpINotEqual %bool %43 %uint_0 -OpSelectionMerge %47 None -OpBranchConditional %45 %48 %49 -%48 = OpLabel -%50 = OpLoad %float %15 -OpBranch %47 -%49 = OpLabel -%103 = OpFunctionCall %void %51 %uint_32 %uint_1 %uint_0 %uint_0 -OpBranch %47 -%47 = OpLabel -%105 = OpPhi %float %50 %48 %104 %49 -OpStore %b %105 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%20 = OpFunction %uint None %21 -%22 = OpFunctionParameter %uint -%23 = OpFunctionParameter %uint -%24 = OpFunctionParameter %uint -%25 = OpFunctionParameter %uint -%26 = OpLabel -%32 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %22 -%33 = OpLoad %uint %32 -%34 = OpIAdd %uint %33 %23 -%35 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %34 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %24 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %37 -%39 = OpLoad %uint %38 -%40 = OpIAdd %uint %39 %25 -%41 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %40 -%42 = OpLoad %uint %41 -OpReturnValue %42 -OpFunctionEnd -%51 = OpFunction %void None %52 -%53 = OpFunctionParameter %uint -%54 = OpFunctionParameter %uint -%55 = OpFunctionParameter %uint -%56 = OpFunctionParameter %uint -%57 = OpLabel -%61 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_0 -%64 = OpAtomicIAdd %uint %61 %uint_4 %uint_0 %uint_10 -%65 = OpIAdd %uint %64 %uint_10 -%66 = OpArrayLength %uint %60 1 -%67 = OpULessThanEqual %bool %65 %66 -OpSelectionMerge %68 None -OpBranchConditional %67 %69 %68 -%69 = OpLabel -%70 = OpIAdd %uint %64 %uint_0 -%71 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %70 -OpStore %71 %uint_10 -%73 = OpIAdd %uint %64 %uint_1 -%74 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %73 -OpStore %74 %uint_23 -%76 = OpIAdd %uint %64 %uint_2 -%77 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %76 -OpStore %77 %53 -%78 = OpIAdd %uint %64 %uint_3 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %78 -OpStore %79 %uint_4 -%83 = OpLoad %v4float %gl_FragCoord -%85 = OpBitcast %v4uint %83 -%86 = OpCompositeExtract %uint %85 0 -%87 = OpIAdd %uint %64 %uint_4 -%88 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %87 -OpStore %88 %86 -%89 = OpCompositeExtract %uint %85 1 -%91 = OpIAdd %uint %64 %uint_5 -%92 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %91 -OpStore %92 %89 -%94 = OpIAdd %uint %64 %uint_7 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %94 -OpStore %95 %54 -%97 = OpIAdd %uint %64 %uint_8 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %97 -OpStore %98 %55 -%100 = OpIAdd %uint %64 %uint_9 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %100 -OpStore %101 %56 -OpBranch %68 -%68 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstBoundsInitStoreUnsizedSSBOArrayV2) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=1) in float b; - // - // layout(binding=4) buffer bname { float b; } storageBuffer[]; - // - // void main() - // { - // storageBuffer[nu_ii].b = b; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %nu_ii %b -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %bname "bname" -OpMemberName %bname 0 "b" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpName %b "b" -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname BufferBlock -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 4 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %14 NonUniform -OpDecorate %b Location 1 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Input_float = OpTypePointer Input %float -%b = OpVariable %_ptr_Input_float Input -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability RuntimeDescriptorArray -OpCapability StorageBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %nu_ii %b %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %bname "bname" -OpMemberName %bname 0 "b" -OpName %storageBuffer "storageBuffer" -OpName %nu_ii "nu_ii" -OpName %b "b" -OpMemberDecorate %bname 0 Offset 0 -OpDecorate %bname BufferBlock -OpDecorate %storageBuffer DescriptorSet 0 -OpDecorate %storageBuffer Binding 4 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %b Location 1 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_31 Block -OpMemberDecorate %_struct_31 0 Offset 0 -OpDecorate %33 DescriptorSet 7 -OpDecorate %33 Binding 1 -OpDecorate %_struct_54 Block -OpMemberDecorate %_struct_54 0 Offset 0 -OpMemberDecorate %_struct_54 1 Offset 4 -OpDecorate %56 DescriptorSet 7 -OpDecorate %56 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%bname = OpTypeStruct %float -%_runtimearr_bname = OpTypeRuntimeArray %bname -%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname -%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Input_float = OpTypePointer Input %float -%b = OpVariable %_ptr_Input_float Input -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_4 = OpConstant %uint 4 -%26 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_31 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31 -%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%48 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_54 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_54 = OpTypePointer StorageBuffer %_struct_54 -%56 = OpVariable %_ptr_StorageBuffer__struct_54 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_45 = OpConstant %uint 45 -%102 = OpTypeFunction %uint %uint %uint %uint %uint -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%14 = OpLoad %int %nu_ii -%18 = OpLoad %float %b -%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %14 %int_0 -OpStore %20 %18 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %9 -%18 = OpLabel -%7 = OpLoad %int %nu_ii -%19 = OpLoad %float %b -%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %7 %int_0 -%40 = OpFunctionCall %uint %25 %uint_1 %uint_4 -%42 = OpULessThan %bool %7 %40 -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -%100 = OpBitcast %uint %7 -%119 = OpFunctionCall %uint %101 %uint_0 %uint_0 %uint_4 %100 -%120 = OpINotEqual %bool %119 %uint_0 -OpSelectionMerge %121 None -OpBranchConditional %120 %122 %123 -%122 = OpLabel -OpStore %20 %19 -OpBranch %121 -%123 = OpLabel -%124 = OpBitcast %uint %7 -%125 = OpFunctionCall %void %47 %uint_45 %uint_1 %124 %uint_0 -OpBranch %121 -%121 = OpLabel -OpBranch %43 -%45 = OpLabel -%46 = OpBitcast %uint %7 -%99 = OpFunctionCall %void %47 %uint_45 %uint_0 %46 %40 -OpBranch %43 -%43 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%25 = OpFunction %uint None %26 -%27 = OpFunctionParameter %uint -%28 = OpFunctionParameter %uint -%29 = OpLabel -%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27 -%36 = OpLoad %uint %35 -%37 = OpIAdd %uint %36 %28 -%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37 -%39 = OpLoad %uint %38 -OpReturnValue %39 -OpFunctionEnd -%47 = OpFunction %void None %48 -%49 = OpFunctionParameter %uint -%50 = OpFunctionParameter %uint -%51 = OpFunctionParameter %uint -%52 = OpFunctionParameter %uint -%53 = OpLabel -%57 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_0 -%59 = OpAtomicIAdd %uint %57 %uint_4 %uint_0 %uint_10 -%60 = OpIAdd %uint %59 %uint_10 -%61 = OpArrayLength %uint %56 1 -%62 = OpULessThanEqual %bool %60 %61 -OpSelectionMerge %63 None -OpBranchConditional %62 %64 %63 -%64 = OpLabel -%65 = OpIAdd %uint %59 %uint_0 -%66 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %65 -OpStore %66 %uint_10 -%68 = OpIAdd %uint %59 %uint_1 -%69 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %68 -OpStore %69 %uint_23 -%71 = OpIAdd %uint %59 %uint_2 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %71 -OpStore %72 %49 -%74 = OpIAdd %uint %59 %uint_3 -%75 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %74 -OpStore %75 %uint_4 -%79 = OpLoad %v4float %gl_FragCoord -%81 = OpBitcast %v4uint %79 -%82 = OpCompositeExtract %uint %81 0 -%83 = OpIAdd %uint %59 %uint_4 -%84 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %83 -OpStore %84 %82 -%85 = OpCompositeExtract %uint %81 1 -%87 = OpIAdd %uint %59 %uint_5 -%88 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %87 -OpStore %88 %85 -%90 = OpIAdd %uint %59 %uint_7 -%91 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %90 -OpStore %91 %50 -%93 = OpIAdd %uint %59 %uint_8 -%94 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %93 -OpStore %94 %51 -%96 = OpIAdd %uint %59 %uint_9 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %96 -OpStore %97 %52 -OpBranch %63 -%63 = OpLabel -OpReturn -OpFunctionEnd -%101 = OpFunction %uint None %102 -%103 = OpFunctionParameter %uint -%104 = OpFunctionParameter %uint -%105 = OpFunctionParameter %uint -%106 = OpFunctionParameter %uint -%107 = OpLabel -%108 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %103 -%109 = OpLoad %uint %108 -%110 = OpIAdd %uint %109 %104 -%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %110 -%112 = OpLoad %uint %111 -%113 = OpIAdd %uint %112 %105 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113 -%115 = OpLoad %uint %114 -%116 = OpIAdd %uint %115 %106 -%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116 -%118 = OpLoad %uint %117 -OpReturnValue %118 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstBoundsInitLoadSizedUBOArrayV2) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location=0) in nonuniformEXT flat int nu_ii; - // layout(location=0) out float b; - // - // layout(binding=3) uniform uname { float a; } uniformBuffer[128]; - // - // void main() - // { - // b = uniformBuffer[nu_ii].a; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %18 NonUniform -OpDecorate %22 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_uname_uint_128 = OpTypeArray %uname %uint_128 -%_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128 -%uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability UniformBufferArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %b "b" -OpName %uname "uname" -OpMemberName %uname 0 "a" -OpName %uniformBuffer "uniformBuffer" -OpName %nu_ii "nu_ii" -OpDecorate %b Location 0 -OpMemberDecorate %uname 0 Offset 0 -OpDecorate %uname Block -OpDecorate %uniformBuffer DescriptorSet 0 -OpDecorate %uniformBuffer Binding 3 -OpDecorate %nu_ii Flat -OpDecorate %nu_ii Location 0 -OpDecorate %nu_ii NonUniform -OpDecorate %7 NonUniform -OpDecorate %89 NonUniform -OpDecorate %120 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpMemberDecorate %_struct_39 1 Offset 4 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %_struct_98 Block -OpMemberDecorate %_struct_98 0 Offset 0 -OpDecorate %100 DescriptorSet 7 -OpDecorate %100 Binding 1 -OpDecorate %117 NonUniform -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float -%b = OpVariable %_ptr_Output_float Output -%uname = OpTypeStruct %float -%uint = OpTypeInt 32 0 -%uint_128 = OpConstant %uint 128 -%_arr_uname_uint_128 = OpTypeArray %uname %uint_128 -%_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128 -%uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%nu_ii = OpVariable %_ptr_Input_int Input -%int_0 = OpConstant %int 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_0 = OpConstant %uint 0 -%bool = OpTypeBool -%32 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_46 = OpConstant %uint 46 -%88 = OpConstantNull %float -%92 = OpTypeFunction %uint %uint %uint %uint %uint -%_struct_98 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_98 = OpTypePointer StorageBuffer %_struct_98 -%100 = OpVariable %_ptr_StorageBuffer__struct_98 StorageBuffer -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%18 = OpLoad %int %nu_ii -%21 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %18 %int_0 -%22 = OpLoad %float %21 -OpStore %b %22 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %10 -%21 = OpLabel -%7 = OpLoad %int %nu_ii -%22 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %7 %int_0 -%25 = OpULessThan %bool %7 %uint_128 -OpSelectionMerge %26 None -OpBranchConditional %25 %27 %28 -%27 = OpLabel -%90 = OpBitcast %uint %7 -%112 = OpFunctionCall %uint %91 %uint_0 %uint_0 %uint_3 %90 -%113 = OpINotEqual %bool %112 %uint_0 -OpSelectionMerge %114 None -OpBranchConditional %113 %115 %116 -%115 = OpLabel -%117 = OpLoad %float %22 -OpBranch %114 -%116 = OpLabel -%118 = OpBitcast %uint %7 -%119 = OpFunctionCall %void %31 %uint_46 %uint_1 %118 %uint_0 -OpBranch %114 -%114 = OpLabel -%120 = OpPhi %float %117 %115 %88 %116 -OpBranch %26 -%28 = OpLabel -%30 = OpBitcast %uint %7 -%87 = OpFunctionCall %void %31 %uint_46 %uint_0 %30 %uint_128 -OpBranch %26 -%26 = OpLabel -%89 = OpPhi %float %120 %114 %88 %28 -OpStore %b %89 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%31 = OpFunction %void None %32 -%33 = OpFunctionParameter %uint -%34 = OpFunctionParameter %uint -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 -%46 = OpAtomicIAdd %uint %43 %uint_4 %uint_0 %uint_10 -%47 = OpIAdd %uint %46 %uint_10 -%48 = OpArrayLength %uint %41 1 -%49 = OpULessThanEqual %bool %47 %48 -OpSelectionMerge %50 None -OpBranchConditional %49 %51 %50 -%51 = OpLabel -%52 = OpIAdd %uint %46 %uint_0 -%54 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %52 -OpStore %54 %uint_10 -%56 = OpIAdd %uint %46 %uint_1 -%57 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %56 -OpStore %57 %uint_23 -%59 = OpIAdd %uint %46 %uint_2 -%60 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %59 -OpStore %60 %33 -%62 = OpIAdd %uint %46 %uint_3 -%63 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %62 -OpStore %63 %uint_4 -%67 = OpLoad %v4float %gl_FragCoord -%69 = OpBitcast %v4uint %67 -%70 = OpCompositeExtract %uint %69 0 -%71 = OpIAdd %uint %46 %uint_4 -%72 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %71 -OpStore %72 %70 -%73 = OpCompositeExtract %uint %69 1 -%75 = OpIAdd %uint %46 %uint_5 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %75 -OpStore %76 %73 -%78 = OpIAdd %uint %46 %uint_7 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %78 -OpStore %79 %34 -%81 = OpIAdd %uint %46 %uint_8 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %81 -OpStore %82 %35 -%84 = OpIAdd %uint %46 %uint_9 -%85 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %84 -OpStore %85 %36 -OpBranch %50 -%50 = OpLabel -OpReturn -OpFunctionEnd -%91 = OpFunction %uint None %92 -%93 = OpFunctionParameter %uint -%94 = OpFunctionParameter %uint -%95 = OpFunctionParameter %uint -%96 = OpFunctionParameter %uint -%97 = OpLabel -%101 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %93 -%102 = OpLoad %uint %101 -%103 = OpIAdd %uint %102 %94 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %103 -%105 = OpLoad %uint %104 -%106 = OpIAdd %uint %105 %95 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %106 -%108 = OpLoad %uint %107 -%109 = OpIAdd %uint %108 %96 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %109 -%111 = OpLoad %uint %110 -OpReturnValue %111 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsComputeShaderInitLoadVariableSizedSampledImagesArray) { - // #version 450 - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout (local_size_x = 1, local_size_y = 1) in; - // - // layout(set = 0, binding = 0, std140) buffer Input { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability RuntimeDescriptorArray -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %Input "Input" -OpMemberName %Input 0 "index" -OpMemberName %Input 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %Input 0 Offset 0 -OpMemberDecorate %Input 1 Offset 4 -OpDecorate %Input BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%Input = OpTypeStruct %uint %float -%_ptr_Uniform_Input = OpTypePointer Uniform %Input -%sbo = OpVariable %_ptr_Uniform_Input Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability RuntimeDescriptorArray -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %Input "Input" -OpMemberName %Input 0 "index" -OpMemberName %Input 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %Input 0 Offset 0 -OpMemberDecorate %Input 1 Offset 4 -OpDecorate %Input BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId -%void = OpTypeVoid -%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%Input = OpTypeStruct %uint %float -%_ptr_Uniform_Input = OpTypePointer Uniform %Input -%sbo = OpVariable %_ptr_Uniform_Input Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5 = OpConstant %uint 5 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_50 = OpConstant %uint 50 -%112 = OpConstantNull %v4float -%115 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_47 = OpConstant %uint 47 -%140 = OpConstantNull %uint -%uint_53 = OpConstant %uint 53 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%132 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_0 %uint_0 -%133 = OpINotEqual %bool %132 %uint_0 -OpSelectionMerge %134 None -OpBranchConditional %133 %135 %136 -%135 = OpLabel -%137 = OpLoad %uint %25 -OpBranch %134 -%136 = OpLabel -%139 = OpFunctionCall %void %56 %uint_47 %uint_1 %uint_0 %uint_0 -OpBranch %134 -%134 = OpLabel -%141 = OpPhi %uint %137 %135 %140 %136 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %141 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %141 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%142 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_1 %141 -%143 = OpINotEqual %bool %142 %uint_0 -OpSelectionMerge %144 None -OpBranchConditional %143 %145 %146 -%145 = OpLabel -%147 = OpLoad %13 %27 -%148 = OpImageRead %v4float %147 %20 -OpBranch %144 -%146 = OpLabel -%149 = OpFunctionCall %void %56 %uint_50 %uint_1 %141 %uint_0 -OpBranch %144 -%144 = OpLabel -%150 = OpPhi %v4float %148 %145 %112 %146 -OpBranch %51 -%53 = OpLabel -%111 = OpFunctionCall %void %56 %uint_50 %uint_0 %141 %48 -OpBranch %51 -%51 = OpLabel -%113 = OpPhi %v4float %150 %144 %112 %53 -%30 = OpCompositeExtract %float %113 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%151 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_0 %uint_0 -%152 = OpINotEqual %bool %151 %uint_0 -OpSelectionMerge %153 None -OpBranchConditional %152 %154 %155 -%154 = OpLabel -OpStore %31 %30 -OpBranch %153 -%155 = OpLabel -%157 = OpFunctionCall %void %56 %uint_53 %uint_1 %uint_0 %uint_0 -OpBranch %153 -%153 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5 -%90 = OpLoad %v3uint %gl_GlobalInvocationID -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%96 = OpIAdd %uint %69 %uint_5 -%97 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %96 -OpStore %97 %92 -%99 = OpIAdd %uint %69 %uint_6 -%100 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %99 -OpStore %100 %93 -%102 = OpIAdd %uint %69 %uint_7 -%103 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %102 -OpStore %103 %59 -%105 = OpIAdd %uint %69 %uint_8 -%106 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %105 -OpStore %106 %60 -%108 = OpIAdd %uint %69 %uint_9 -%109 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %108 -OpStore %109 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%114 = OpFunction %uint None %115 -%116 = OpFunctionParameter %uint -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpLabel -%121 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %116 -%122 = OpLoad %uint %121 -%123 = OpIAdd %uint %122 %117 -%124 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %123 -%125 = OpLoad %uint %124 -%126 = OpIAdd %uint %125 %118 -%127 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %126 -%128 = OpLoad %uint %127 -%129 = OpIAdd %uint %128 %119 -%130 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %129 -%131 = OpLoad %uint %130 -OpReturnValue %131 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsRayGenerationInitLoadVariableSizedSampledImagesArray) { - // #version 460 - // #extension GL_EXT_nonuniform_qualifier : require - // #extension GL_NV_ray_tracing : require - // - // layout(set = 0, binding = 0, std140) buffer StorageBuffer { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint RayGenerationNV %main "main" -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -)"; - - const std::string defs_after = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint RayGenerationNV %main "main" %89 -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %89 BuiltIn LaunchIdNV -%void = OpTypeVoid -)"; - - const std::string func_before = - R"(%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5313 = OpConstant %uint 5313 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%89 = OpVariable %_ptr_Input_v3uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%113 = OpConstantNull %v4float -%116 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_48 = OpConstant %uint 48 -%141 = OpConstantNull %uint -%uint_54 = OpConstant %uint 54 -%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%134 = OpINotEqual %bool %133 %uint_0 -OpSelectionMerge %135 None -OpBranchConditional %134 %136 %137 -%136 = OpLabel -%138 = OpLoad %uint %25 -OpBranch %135 -%137 = OpLabel -%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0 -OpBranch %135 -%135 = OpLabel -%142 = OpPhi %uint %138 %136 %141 %137 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %142 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142 -%144 = OpINotEqual %bool %143 %uint_0 -OpSelectionMerge %145 None -OpBranchConditional %144 %146 %147 -%146 = OpLabel -%148 = OpLoad %13 %27 -%149 = OpImageRead %v4float %148 %20 -OpBranch %145 -%147 = OpLabel -%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0 -OpBranch %145 -%145 = OpLabel -%151 = OpPhi %v4float %149 %146 %113 %147 -OpBranch %51 -%53 = OpLabel -%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48 -OpBranch %51 -%51 = OpLabel -%114 = OpPhi %v4float %151 %145 %113 %53 -%30 = OpCompositeExtract %float %114 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%153 = OpINotEqual %bool %152 %uint_0 -OpSelectionMerge %154 None -OpBranchConditional %153 %155 %156 -%155 = OpLabel -OpStore %31 %30 -OpBranch %154 -%156 = OpLabel -%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0 -OpBranch %154 -%154 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5313 -%90 = OpLoad %v3uint %89 -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%97 = OpIAdd %uint %69 %uint_5 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97 -OpStore %98 %92 -%100 = OpIAdd %uint %69 %uint_6 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100 -OpStore %101 %93 -%103 = OpIAdd %uint %69 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103 -OpStore %104 %59 -%106 = OpIAdd %uint %69 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106 -OpStore %107 %60 -%109 = OpIAdd %uint %69 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109 -OpStore %110 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%115 = OpFunction %uint None %116 -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpFunctionParameter %uint -%121 = OpLabel -%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117 -%123 = OpLoad %uint %122 -%124 = OpIAdd %uint %123 %118 -%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %119 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %120 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130 -%132 = OpLoad %uint %131 -OpReturnValue %132 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsIntersectionInitLoadVariableSizedSampledImagesArray) { - // #version 460 - // #extension GL_EXT_nonuniform_qualifier : require - // #extension GL_NV_ray_tracing : require - // - // layout(set = 0, binding = 0, std140) buffer StorageBuffer { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint IntersectionNV %main "main" -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -)"; - - const std::string defs_after = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint IntersectionNV %main "main" %89 -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %89 BuiltIn LaunchIdNV -%void = OpTypeVoid -)"; - - const std::string func_before = - R"(%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5314 = OpConstant %uint 5314 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%89 = OpVariable %_ptr_Input_v3uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%113 = OpConstantNull %v4float -%116 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_48 = OpConstant %uint 48 -%141 = OpConstantNull %uint -%uint_54 = OpConstant %uint 54 -%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%134 = OpINotEqual %bool %133 %uint_0 -OpSelectionMerge %135 None -OpBranchConditional %134 %136 %137 -%136 = OpLabel -%138 = OpLoad %uint %25 -OpBranch %135 -%137 = OpLabel -%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0 -OpBranch %135 -%135 = OpLabel -%142 = OpPhi %uint %138 %136 %141 %137 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %142 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142 -%144 = OpINotEqual %bool %143 %uint_0 -OpSelectionMerge %145 None -OpBranchConditional %144 %146 %147 -%146 = OpLabel -%148 = OpLoad %13 %27 -%149 = OpImageRead %v4float %148 %20 -OpBranch %145 -%147 = OpLabel -%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0 -OpBranch %145 -%145 = OpLabel -%151 = OpPhi %v4float %149 %146 %113 %147 -OpBranch %51 -%53 = OpLabel -%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48 -OpBranch %51 -%51 = OpLabel -%114 = OpPhi %v4float %151 %145 %113 %53 -%30 = OpCompositeExtract %float %114 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%153 = OpINotEqual %bool %152 %uint_0 -OpSelectionMerge %154 None -OpBranchConditional %153 %155 %156 -%155 = OpLabel -OpStore %31 %30 -OpBranch %154 -%156 = OpLabel -%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0 -OpBranch %154 -%154 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5314 -%90 = OpLoad %v3uint %89 -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%97 = OpIAdd %uint %69 %uint_5 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97 -OpStore %98 %92 -%100 = OpIAdd %uint %69 %uint_6 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100 -OpStore %101 %93 -%103 = OpIAdd %uint %69 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103 -OpStore %104 %59 -%106 = OpIAdd %uint %69 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106 -OpStore %107 %60 -%109 = OpIAdd %uint %69 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109 -OpStore %110 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%115 = OpFunction %uint None %116 -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpFunctionParameter %uint -%121 = OpLabel -%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117 -%123 = OpLoad %uint %122 -%124 = OpIAdd %uint %123 %118 -%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %119 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %120 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130 -%132 = OpLoad %uint %131 -OpReturnValue %132 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsAnyHitInitLoadVariableSizedSampledImagesArray) { - // #version 460 - // #extension GL_EXT_nonuniform_qualifier : require - // #extension GL_NV_ray_tracing : require - // - // layout(set = 0, binding = 0, std140) buffer StorageBuffer { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint AnyHitNV %main "main" -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -)"; - - const std::string defs_after = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint AnyHitNV %main "main" %89 -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %89 BuiltIn LaunchIdNV -%void = OpTypeVoid -)"; - - const std::string func_before = - R"(%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5315 = OpConstant %uint 5315 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%89 = OpVariable %_ptr_Input_v3uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%113 = OpConstantNull %v4float -%116 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_48 = OpConstant %uint 48 -%141 = OpConstantNull %uint -%uint_54 = OpConstant %uint 54 -%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%134 = OpINotEqual %bool %133 %uint_0 -OpSelectionMerge %135 None -OpBranchConditional %134 %136 %137 -%136 = OpLabel -%138 = OpLoad %uint %25 -OpBranch %135 -%137 = OpLabel -%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0 -OpBranch %135 -%135 = OpLabel -%142 = OpPhi %uint %138 %136 %141 %137 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %142 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142 -%144 = OpINotEqual %bool %143 %uint_0 -OpSelectionMerge %145 None -OpBranchConditional %144 %146 %147 -%146 = OpLabel -%148 = OpLoad %13 %27 -%149 = OpImageRead %v4float %148 %20 -OpBranch %145 -%147 = OpLabel -%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0 -OpBranch %145 -%145 = OpLabel -%151 = OpPhi %v4float %149 %146 %113 %147 -OpBranch %51 -%53 = OpLabel -%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48 -OpBranch %51 -%51 = OpLabel -%114 = OpPhi %v4float %151 %145 %113 %53 -%30 = OpCompositeExtract %float %114 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%153 = OpINotEqual %bool %152 %uint_0 -OpSelectionMerge %154 None -OpBranchConditional %153 %155 %156 -%155 = OpLabel -OpStore %31 %30 -OpBranch %154 -%156 = OpLabel -%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0 -OpBranch %154 -%154 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5315 -%90 = OpLoad %v3uint %89 -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%97 = OpIAdd %uint %69 %uint_5 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97 -OpStore %98 %92 -%100 = OpIAdd %uint %69 %uint_6 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100 -OpStore %101 %93 -%103 = OpIAdd %uint %69 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103 -OpStore %104 %59 -%106 = OpIAdd %uint %69 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106 -OpStore %107 %60 -%109 = OpIAdd %uint %69 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109 -OpStore %110 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%115 = OpFunction %uint None %116 -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpFunctionParameter %uint -%121 = OpLabel -%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117 -%123 = OpLoad %uint %122 -%124 = OpIAdd %uint %123 %118 -%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %119 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %120 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130 -%132 = OpLoad %uint %131 -OpReturnValue %132 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsClosestHitInitLoadVariableSizedSampledImagesArray) { - // #version 460 - // #extension GL_EXT_nonuniform_qualifier : require - // #extension GL_NV_ray_tracing : require - // - // layout(set = 0, binding = 0, std140) buffer StorageBuffer { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint ClosestHitNV %main "main" -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -)"; - - const std::string defs_after = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint ClosestHitNV %main "main" %89 -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %89 BuiltIn LaunchIdNV -%void = OpTypeVoid -)"; - - const std::string func_before = - R"(%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5316 = OpConstant %uint 5316 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%89 = OpVariable %_ptr_Input_v3uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%113 = OpConstantNull %v4float -%116 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_48 = OpConstant %uint 48 -%141 = OpConstantNull %uint -%uint_54 = OpConstant %uint 54 -%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%134 = OpINotEqual %bool %133 %uint_0 -OpSelectionMerge %135 None -OpBranchConditional %134 %136 %137 -%136 = OpLabel -%138 = OpLoad %uint %25 -OpBranch %135 -%137 = OpLabel -%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0 -OpBranch %135 -%135 = OpLabel -%142 = OpPhi %uint %138 %136 %141 %137 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %142 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142 -%144 = OpINotEqual %bool %143 %uint_0 -OpSelectionMerge %145 None -OpBranchConditional %144 %146 %147 -%146 = OpLabel -%148 = OpLoad %13 %27 -%149 = OpImageRead %v4float %148 %20 -OpBranch %145 -%147 = OpLabel -%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0 -OpBranch %145 -%145 = OpLabel -%151 = OpPhi %v4float %149 %146 %113 %147 -OpBranch %51 -%53 = OpLabel -%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48 -OpBranch %51 -%51 = OpLabel -%114 = OpPhi %v4float %151 %145 %113 %53 -%30 = OpCompositeExtract %float %114 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%153 = OpINotEqual %bool %152 %uint_0 -OpSelectionMerge %154 None -OpBranchConditional %153 %155 %156 -%155 = OpLabel -OpStore %31 %30 -OpBranch %154 -%156 = OpLabel -%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0 -OpBranch %154 -%154 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5316 -%90 = OpLoad %v3uint %89 -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%97 = OpIAdd %uint %69 %uint_5 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97 -OpStore %98 %92 -%100 = OpIAdd %uint %69 %uint_6 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100 -OpStore %101 %93 -%103 = OpIAdd %uint %69 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103 -OpStore %104 %59 -%106 = OpIAdd %uint %69 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106 -OpStore %107 %60 -%109 = OpIAdd %uint %69 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109 -OpStore %110 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%115 = OpFunction %uint None %116 -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpFunctionParameter %uint -%121 = OpLabel -%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117 -%123 = OpLoad %uint %122 -%124 = OpIAdd %uint %123 %118 -%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %119 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %120 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130 -%132 = OpLoad %uint %131 -OpReturnValue %132 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsMissInitLoadVariableSizedSampledImagesArray) { - // #version 460 - // #extension GL_EXT_nonuniform_qualifier : require - // #extension GL_NV_ray_tracing : require - // - // layout(set = 0, binding = 0, std140) buffer StorageBuffer { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint MissNV %main "main" -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -)"; - - const std::string defs_after = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint MissNV %main "main" %89 -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %89 BuiltIn LaunchIdNV -%void = OpTypeVoid -)"; - - const std::string func_before = - R"(%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5317 = OpConstant %uint 5317 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%89 = OpVariable %_ptr_Input_v3uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%113 = OpConstantNull %v4float -%116 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_48 = OpConstant %uint 48 -%141 = OpConstantNull %uint -%uint_54 = OpConstant %uint 54 -%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%134 = OpINotEqual %bool %133 %uint_0 -OpSelectionMerge %135 None -OpBranchConditional %134 %136 %137 -%136 = OpLabel -%138 = OpLoad %uint %25 -OpBranch %135 -%137 = OpLabel -%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0 -OpBranch %135 -%135 = OpLabel -%142 = OpPhi %uint %138 %136 %141 %137 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %142 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142 -%144 = OpINotEqual %bool %143 %uint_0 -OpSelectionMerge %145 None -OpBranchConditional %144 %146 %147 -%146 = OpLabel -%148 = OpLoad %13 %27 -%149 = OpImageRead %v4float %148 %20 -OpBranch %145 -%147 = OpLabel -%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0 -OpBranch %145 -%145 = OpLabel -%151 = OpPhi %v4float %149 %146 %113 %147 -OpBranch %51 -%53 = OpLabel -%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48 -OpBranch %51 -%51 = OpLabel -%114 = OpPhi %v4float %151 %145 %113 %53 -%30 = OpCompositeExtract %float %114 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%153 = OpINotEqual %bool %152 %uint_0 -OpSelectionMerge %154 None -OpBranchConditional %153 %155 %156 -%155 = OpLabel -OpStore %31 %30 -OpBranch %154 -%156 = OpLabel -%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0 -OpBranch %154 -%154 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5317 -%90 = OpLoad %v3uint %89 -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%97 = OpIAdd %uint %69 %uint_5 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97 -OpStore %98 %92 -%100 = OpIAdd %uint %69 %uint_6 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100 -OpStore %101 %93 -%103 = OpIAdd %uint %69 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103 -OpStore %104 %59 -%106 = OpIAdd %uint %69 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106 -OpStore %107 %60 -%109 = OpIAdd %uint %69 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109 -OpStore %110 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%115 = OpFunction %uint None %116 -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpFunctionParameter %uint -%121 = OpLabel -%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117 -%123 = OpLoad %uint %122 -%124 = OpIAdd %uint %123 %118 -%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %119 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %120 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130 -%132 = OpLoad %uint %131 -OpReturnValue %132 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, - InstBoundsCallableInitLoadVariableSizedSampledImagesArray) { - // #version 460 - // #extension GL_EXT_nonuniform_qualifier : require - // #extension GL_NV_ray_tracing : require - // - // layout(set = 0, binding = 0, std140) buffer StorageBuffer { - // uint index; - // float red; - // } sbo; - // - // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[]; - // - // void main() - // { - // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; - // } - - const std::string defs_before = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint CallableNV %main "main" -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -%void = OpTypeVoid -)"; - - const std::string defs_after = - R"(OpCapability RuntimeDescriptorArray -OpCapability RayTracingNV -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_NV_ray_tracing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint CallableNV %main "main" %89 -OpSource GLSL 460 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpSourceExtension "GL_NV_ray_tracing" -OpName %main "main" -OpName %StorageBuffer "StorageBuffer" -OpMemberName %StorageBuffer 0 "index" -OpMemberName %StorageBuffer 1 "red" -OpName %sbo "sbo" -OpName %images "images" -OpMemberDecorate %StorageBuffer 0 Offset 0 -OpMemberDecorate %StorageBuffer 1 Offset 4 -OpDecorate %StorageBuffer BufferBlock -OpDecorate %sbo DescriptorSet 0 -OpDecorate %sbo Binding 0 -OpDecorate %images DescriptorSet 0 -OpDecorate %images Binding 1 -OpDecorate %images NonWritable -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 1 -OpDecorate %_struct_63 Block -OpMemberDecorate %_struct_63 0 Offset 0 -OpMemberDecorate %_struct_63 1 Offset 4 -OpDecorate %65 DescriptorSet 7 -OpDecorate %65 Binding 0 -OpDecorate %89 BuiltIn LaunchIdNV -%void = OpTypeVoid -)"; - - const std::string func_before = - R"(%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%25 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%main = OpFunction %void None %3 -%5 = OpLabel -%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%20 = OpLoad %uint %19 -%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 -%23 = OpLoad %13 %22 -%27 = OpImageRead %v4float %23 %25 -%29 = OpCompositeExtract %float %27 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -OpStore %31 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%7 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%StorageBuffer = OpTypeStruct %uint %float -%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer -%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f -%_runtimearr_13 = OpTypeRuntimeArray %13 -%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 -%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%v2int = OpTypeVector %int 2 -%20 = OpConstantComposite %v2int %int_0 %int_0 -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%uint_1 = OpConstant %uint 1 -%34 = OpTypeFunction %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_39 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%bool = OpTypeBool -%57 = OpTypeFunction %void %uint %uint %uint %uint -%_struct_63 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63 -%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_5318 = OpConstant %uint 5318 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%89 = OpVariable %_ptr_Input_v3uint Input -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_51 = OpConstant %uint 51 -%113 = OpConstantNull %v4float -%116 = OpTypeFunction %uint %uint %uint %uint %uint -%uint_48 = OpConstant %uint 48 -%141 = OpConstantNull %uint -%uint_54 = OpConstant %uint 54 -%main = OpFunction %void None %7 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 -%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%134 = OpINotEqual %bool %133 %uint_0 -OpSelectionMerge %135 None -OpBranchConditional %134 %136 %137 -%136 = OpLabel -%138 = OpLoad %uint %25 -OpBranch %135 -%137 = OpLabel -%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0 -OpBranch %135 -%135 = OpLabel -%142 = OpPhi %uint %138 %136 %141 %137 -%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142 -%28 = OpLoad %13 %27 -%48 = OpFunctionCall %uint %33 %uint_1 %uint_1 -%50 = OpULessThan %bool %142 %48 -OpSelectionMerge %51 None -OpBranchConditional %50 %52 %53 -%52 = OpLabel -%54 = OpLoad %13 %27 -%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142 -%144 = OpINotEqual %bool %143 %uint_0 -OpSelectionMerge %145 None -OpBranchConditional %144 %146 %147 -%146 = OpLabel -%148 = OpLoad %13 %27 -%149 = OpImageRead %v4float %148 %20 -OpBranch %145 -%147 = OpLabel -%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0 -OpBranch %145 -%145 = OpLabel -%151 = OpPhi %v4float %149 %146 %113 %147 -OpBranch %51 -%53 = OpLabel -%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48 -OpBranch %51 -%51 = OpLabel -%114 = OpPhi %v4float %151 %145 %113 %53 -%30 = OpCompositeExtract %float %114 0 -%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 -%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0 -%153 = OpINotEqual %bool %152 %uint_0 -OpSelectionMerge %154 None -OpBranchConditional %153 %155 %156 -%155 = OpLabel -OpStore %31 %30 -OpBranch %154 -%156 = OpLabel -%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0 -OpBranch %154 -%154 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%33 = OpFunction %uint None %34 -%35 = OpFunctionParameter %uint -%36 = OpFunctionParameter %uint -%37 = OpLabel -%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35 -%44 = OpLoad %uint %43 -%45 = OpIAdd %uint %44 %36 -%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45 -%47 = OpLoad %uint %46 -OpReturnValue %47 -OpFunctionEnd -%56 = OpFunction %void None %57 -%58 = OpFunctionParameter %uint -%59 = OpFunctionParameter %uint -%60 = OpFunctionParameter %uint -%61 = OpFunctionParameter %uint -%62 = OpLabel -%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0 -%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10 -%70 = OpIAdd %uint %69 %uint_10 -%71 = OpArrayLength %uint %65 1 -%72 = OpULessThanEqual %bool %70 %71 -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %73 -%74 = OpLabel -%75 = OpIAdd %uint %69 %uint_0 -%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75 -OpStore %76 %uint_10 -%78 = OpIAdd %uint %69 %uint_1 -%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78 -OpStore %79 %uint_23 -%81 = OpIAdd %uint %69 %uint_2 -%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81 -OpStore %82 %58 -%85 = OpIAdd %uint %69 %uint_3 -%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85 -OpStore %86 %uint_5318 -%90 = OpLoad %v3uint %89 -%91 = OpCompositeExtract %uint %90 0 -%92 = OpCompositeExtract %uint %90 1 -%93 = OpCompositeExtract %uint %90 2 -%94 = OpIAdd %uint %69 %uint_4 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94 -OpStore %95 %91 -%97 = OpIAdd %uint %69 %uint_5 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97 -OpStore %98 %92 -%100 = OpIAdd %uint %69 %uint_6 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100 -OpStore %101 %93 -%103 = OpIAdd %uint %69 %uint_7 -%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103 -OpStore %104 %59 -%106 = OpIAdd %uint %69 %uint_8 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106 -OpStore %107 %60 -%109 = OpIAdd %uint %69 %uint_9 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109 -OpStore %110 %61 -OpBranch %73 -%73 = OpLabel -OpReturn -OpFunctionEnd -%115 = OpFunction %uint None %116 -%117 = OpFunctionParameter %uint -%118 = OpFunctionParameter %uint -%119 = OpFunctionParameter %uint -%120 = OpFunctionParameter %uint -%121 = OpLabel -%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117 -%123 = OpLoad %uint %122 -%124 = OpIAdd %uint %123 %118 -%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124 -%126 = OpLoad %uint %125 -%127 = OpIAdd %uint %126 %119 -%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127 -%129 = OpLoad %uint %128 -%130 = OpIAdd %uint %129 %120 -%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130 -%132 = OpLoad %uint %131 -OpReturnValue %132 -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -TEST_F(InstBindlessTest, InstBoundsInitSameBlockOpReplication) { - // Test that same block ops like OpSampledImage are replicated properly - // where needed. - // - // clang-format off - // - // #version 450 core - // #extension GL_EXT_nonuniform_qualifier : enable - // - // layout(location = 0) in vec2 inTexcoord; - // layout(location = 0) out vec4 outColor; - // - // layout(set = 0, binding = 0) uniform Uniforms { - // vec2 var0; - // } uniforms; - // - // layout(set = 0, binding = 1) uniform sampler uniformSampler; - // layout(set = 0, binding = 2) uniform texture2D uniformTex; - // layout(set = 0, binding = 3) uniform texture2D uniformTexArr[8]; - // - // void main() { - // int index = 0; - // float x = texture(sampler2D(uniformTexArr[nonuniformEXT(index)], uniformSampler), inTexcoord.xy).x; - // float y = texture(sampler2D(uniformTex, uniformSampler), inTexcoord.xy * uniforms.var0.xy).x; - // outColor = vec4(x, y, 0.0, 0.0); - // } - // - // clang-format on - - const std::string defs_before = - R"(OpCapability Shader -OpCapability ShaderNonUniformEXT -OpCapability SampledImageArrayNonUniformIndexingEXT -OpExtension "SPV_EXT_descriptor_indexing" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %inTexcoord %outColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %index "index" -OpName %x "x" -OpName %uniformTexArr "uniformTexArr" -OpName %uniformSampler "uniformSampler" -OpName %inTexcoord "inTexcoord" -OpName %y "y" -OpName %uniformTex "uniformTex" -OpName %Uniforms "Uniforms" -OpMemberName %Uniforms 0 "var0" -OpName %uniforms "uniforms" -OpName %outColor "outColor" -OpDecorate %uniformTexArr DescriptorSet 0 -OpDecorate %uniformTexArr Binding 3 -OpDecorate %19 NonUniformEXT -OpDecorate %22 NonUniformEXT -OpDecorate %uniformSampler DescriptorSet 0 -OpDecorate %uniformSampler Binding 1 -OpDecorate %inTexcoord Location 0 -OpDecorate %uniformTex DescriptorSet 0 -OpDecorate %uniformTex Binding 2 -OpMemberDecorate %Uniforms 0 Offset 0 -OpDecorate %Uniforms Block -OpDecorate %uniforms DescriptorSet 0 -OpDecorate %uniforms Binding 0 -OpDecorate %outColor Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%13 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_13_uint_8 = OpTypeArray %13 %uint_8 -%_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8 -%uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%23 = OpTypeSampler -%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 -%uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant -%27 = OpTypeSampledImage %13 -%v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%inTexcoord = OpVariable %_ptr_Input_v2float Input -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant -%Uniforms = OpTypeStruct %v2float -%_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms -%uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform -%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability ShaderNonUniform -OpCapability SampledImageArrayNonUniformIndexing -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %inTexcoord %outColor %gl_FragCoord -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_EXT_nonuniform_qualifier" -OpName %main "main" -OpName %index "index" -OpName %x "x" -OpName %uniformTexArr "uniformTexArr" -OpName %uniformSampler "uniformSampler" -OpName %inTexcoord "inTexcoord" -OpName %y "y" -OpName %uniformTex "uniformTex" -OpName %Uniforms "Uniforms" -OpMemberName %Uniforms 0 "var0" -OpName %uniforms "uniforms" -OpName %outColor "outColor" -OpDecorate %uniformTexArr DescriptorSet 0 -OpDecorate %uniformTexArr Binding 3 -OpDecorate %19 NonUniform -OpDecorate %22 NonUniform -OpDecorate %uniformSampler DescriptorSet 0 -OpDecorate %uniformSampler Binding 1 -OpDecorate %inTexcoord Location 0 -OpDecorate %uniformTex DescriptorSet 0 -OpDecorate %uniformTex Binding 2 -OpMemberDecorate %Uniforms 0 Offset 0 -OpDecorate %Uniforms Block -OpDecorate %uniforms DescriptorSet 0 -OpDecorate %uniforms Binding 0 -OpDecorate %outColor Location 0 -OpDecorate %63 NonUniform -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_75 Block -OpMemberDecorate %_struct_75 0 Offset 0 -OpMemberDecorate %_struct_75 1 Offset 4 -OpDecorate %77 DescriptorSet 7 -OpDecorate %77 Binding 0 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %_struct_132 Block -OpMemberDecorate %_struct_132 0 Offset 0 -OpDecorate %134 DescriptorSet 7 -OpDecorate %134 Binding 1 -OpDecorate %151 NonUniform -%void = OpTypeVoid -%3 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%13 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint = OpTypeInt 32 0 -%uint_8 = OpConstant %uint 8 -%_arr_13_uint_8 = OpTypeArray %13 %uint_8 -%_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8 -%uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 -%23 = OpTypeSampler -%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 -%uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant -%27 = OpTypeSampledImage %13 -%v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%inTexcoord = OpVariable %_ptr_Input_v2float Input -%v4float = OpTypeVector %float 4 -%uint_0 = OpConstant %uint 0 -%uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant -%Uniforms = OpTypeStruct %v2float -%_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms -%uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform -%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%68 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_75 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_75 = OpTypePointer StorageBuffer %_struct_75 -%77 = OpVariable %_ptr_StorageBuffer__struct_75 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_1 = OpConstant %uint 1 -%uint_23 = OpConstant %uint 23 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%v4uint = OpTypeVector %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_7 = OpConstant %uint 7 -%uint_9 = OpConstant %uint 9 -%uint_79 = OpConstant %uint 79 -%122 = OpConstantNull %v4float -%126 = OpTypeFunction %uint %uint %uint %uint %uint -%_struct_132 = OpTypeStruct %_runtimearr_uint -%_ptr_StorageBuffer__struct_132 = OpTypePointer StorageBuffer %_struct_132 -%134 = OpVariable %_ptr_StorageBuffer__struct_132 StorageBuffer -%uint_87 = OpConstant %uint 87 -%165 = OpConstantNull %v2float -%uint_89 = OpConstant %uint 89 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%index = OpVariable %_ptr_Function_int Function -%x = OpVariable %_ptr_Function_float Function -%y = OpVariable %_ptr_Function_float Function -OpStore %index %int_0 -%19 = OpLoad %int %index -%21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19 -%22 = OpLoad %13 %21 -%26 = OpLoad %23 %uniformSampler -%28 = OpSampledImage %27 %22 %26 -%32 = OpLoad %v2float %inTexcoord -%34 = OpImageSampleImplicitLod %v4float %28 %32 -%36 = OpCompositeExtract %float %34 0 -OpStore %x %36 -%39 = OpLoad %13 %uniformTex -%40 = OpLoad %23 %uniformSampler -%41 = OpSampledImage %27 %39 %40 -%42 = OpLoad %v2float %inTexcoord -%47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0 -%48 = OpLoad %v2float %47 -%49 = OpFMul %v2float %42 %48 -%50 = OpImageSampleImplicitLod %v4float %41 %49 -%51 = OpCompositeExtract %float %50 0 -OpStore %y %51 -%54 = OpLoad %float %x -%55 = OpLoad %float %y -%57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0 -OpStore %outColor %57 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%index = OpVariable %_ptr_Function_int Function -%x = OpVariable %_ptr_Function_float Function -%y = OpVariable %_ptr_Function_float Function -OpStore %index %int_0 -%19 = OpLoad %int %index -%21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19 -%22 = OpLoad %13 %21 -%26 = OpLoad %23 %uniformSampler -%28 = OpSampledImage %27 %22 %26 -%32 = OpLoad %v2float %inTexcoord -%59 = OpULessThan %bool %19 %uint_8 -OpSelectionMerge %60 None -OpBranchConditional %59 %61 %62 -%61 = OpLabel -%63 = OpLoad %13 %21 -%64 = OpSampledImage %27 %63 %26 -%124 = OpBitcast %uint %19 -%146 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_3 %124 -%147 = OpINotEqual %bool %146 %uint_0 -OpSelectionMerge %148 None -OpBranchConditional %147 %149 %150 -%149 = OpLabel -%151 = OpLoad %13 %21 -%152 = OpSampledImage %27 %151 %26 -%153 = OpImageSampleImplicitLod %v4float %152 %32 -OpBranch %148 -%150 = OpLabel -%154 = OpBitcast %uint %19 -%155 = OpFunctionCall %void %67 %uint_79 %uint_1 %154 %uint_0 -OpBranch %148 -%148 = OpLabel -%156 = OpPhi %v4float %153 %149 %122 %150 -OpBranch %60 -%62 = OpLabel -%66 = OpBitcast %uint %19 -%121 = OpFunctionCall %void %67 %uint_79 %uint_0 %66 %uint_8 -OpBranch %60 -%60 = OpLabel -%123 = OpPhi %v4float %156 %148 %122 %62 -%36 = OpCompositeExtract %float %123 0 -OpStore %x %36 -%39 = OpLoad %13 %uniformTex -%40 = OpLoad %23 %uniformSampler -%41 = OpSampledImage %27 %39 %40 -%42 = OpLoad %v2float %inTexcoord -%47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0 -%157 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_0 %uint_0 -%158 = OpINotEqual %bool %157 %uint_0 -OpSelectionMerge %159 None -OpBranchConditional %158 %160 %161 -%160 = OpLabel -%162 = OpLoad %v2float %47 -OpBranch %159 -%161 = OpLabel -%164 = OpFunctionCall %void %67 %uint_87 %uint_1 %uint_0 %uint_0 -OpBranch %159 -%159 = OpLabel -%166 = OpPhi %v2float %162 %160 %165 %161 -%49 = OpFMul %v2float %42 %166 -%167 = OpSampledImage %27 %39 %40 -%168 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_2 %uint_0 -%169 = OpINotEqual %bool %168 %uint_0 -OpSelectionMerge %170 None -OpBranchConditional %169 %171 %172 -%171 = OpLabel -%173 = OpLoad %13 %uniformTex -%174 = OpSampledImage %27 %173 %40 -%175 = OpImageSampleImplicitLod %v4float %174 %49 -OpBranch %170 -%172 = OpLabel -%177 = OpFunctionCall %void %67 %uint_89 %uint_1 %uint_0 %uint_0 -OpBranch %170 -%170 = OpLabel -%178 = OpPhi %v4float %175 %171 %122 %172 -%51 = OpCompositeExtract %float %178 0 -OpStore %y %51 -%54 = OpLoad %float %x -%55 = OpLoad %float %y -%57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0 -OpStore %outColor %57 -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%67 = OpFunction %void None %68 -%69 = OpFunctionParameter %uint -%70 = OpFunctionParameter %uint -%71 = OpFunctionParameter %uint -%72 = OpFunctionParameter %uint -%73 = OpLabel -%79 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_0 -%82 = OpAtomicIAdd %uint %79 %uint_4 %uint_0 %uint_10 -%83 = OpIAdd %uint %82 %uint_10 -%84 = OpArrayLength %uint %77 1 -%85 = OpULessThanEqual %bool %83 %84 -OpSelectionMerge %86 None -OpBranchConditional %85 %87 %86 -%87 = OpLabel -%88 = OpIAdd %uint %82 %uint_0 -%90 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %88 -OpStore %90 %uint_10 -%92 = OpIAdd %uint %82 %uint_1 -%93 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %92 -OpStore %93 %uint_23 -%95 = OpIAdd %uint %82 %uint_2 -%96 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %95 -OpStore %96 %69 -%98 = OpIAdd %uint %82 %uint_3 -%99 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %98 -OpStore %99 %uint_4 -%102 = OpLoad %v4float %gl_FragCoord -%104 = OpBitcast %v4uint %102 -%105 = OpCompositeExtract %uint %104 0 -%106 = OpIAdd %uint %82 %uint_4 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %106 -OpStore %107 %105 -%108 = OpCompositeExtract %uint %104 1 -%110 = OpIAdd %uint %82 %uint_5 -%111 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %110 -OpStore %111 %108 -%113 = OpIAdd %uint %82 %uint_7 -%114 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %113 -OpStore %114 %70 -%115 = OpIAdd %uint %82 %uint_8 -%116 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %115 -OpStore %116 %71 -%118 = OpIAdd %uint %82 %uint_9 -%119 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %118 -OpStore %119 %72 -OpBranch %86 -%86 = OpLabel -OpReturn -OpFunctionEnd -%125 = OpFunction %uint None %126 -%127 = OpFunctionParameter %uint -%128 = OpFunctionParameter %uint -%129 = OpFunctionParameter %uint -%130 = OpFunctionParameter %uint -%131 = OpLabel -%135 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %127 -%136 = OpLoad %uint %135 -%137 = OpIAdd %uint %136 %128 -%138 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %137 -%139 = OpLoad %uint %138 -%140 = OpIAdd %uint %139 %129 -%141 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %140 -%142 = OpLoad %uint %141 -%143 = OpIAdd %uint %142 %130 -%144 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %143 -%145 = OpLoad %uint %144 -OpReturnValue %145 -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, true, true, 2u); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// Compute shader -// Geometry shader -// Tesselation control shader -// Tesselation eval shader -// OpImage -// SampledImage variable - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/inst_buff_addr_check_test.cpp b/3rdparty/spirv-tools/test/opt/inst_buff_addr_check_test.cpp deleted file mode 100644 index f8448a98f..000000000 --- a/3rdparty/spirv-tools/test/opt/inst_buff_addr_check_test.cpp +++ /dev/null @@ -1,620 +0,0 @@ -// Copyright (c) 2019 Valve Corporation -// Copyright (c) 2019 LunarG 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. - -// Bindless Check Instrumentation Tests. -// Tests ending with V2 use version 2 record format. - -#include -#include - -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using InstBuffAddrTest = PassTest<::testing::Test>; - -TEST_F(InstBuffAddrTest, InstPhysicalStorageBufferStore) { - // #version 450 - // #extension GL_EXT_buffer_reference : enable - // - // layout(buffer_reference, buffer_reference_align = 16) buffer bufStruct; - // - // layout(set = 0, binding = 0) uniform ufoo { - // bufStruct data; - // uint offset; - // } u_info; - // - // layout(buffer_reference, std140) buffer bufStruct { - // layout(offset = 0) int a[2]; - // layout(offset = 32) int b; - // }; - // - // void main() { - // u_info.data.b = 0xca7; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability PhysicalStorageBufferAddresses -OpExtension "SPV_EXT_physical_storage_buffer" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_buffer_reference" -OpName %main "main" -OpName %ufoo "ufoo" -OpMemberName %ufoo 0 "data" -OpMemberName %ufoo 1 "offset" -OpName %bufStruct "bufStruct" -OpMemberName %bufStruct 0 "a" -OpMemberName %bufStruct 1 "b" -OpName %u_info "u_info" -OpMemberDecorate %ufoo 0 Offset 0 -OpMemberDecorate %ufoo 1 Offset 8 -OpDecorate %ufoo Block -OpDecorate %_arr_int_uint_2 ArrayStride 16 -OpMemberDecorate %bufStruct 0 Offset 0 -OpMemberDecorate %bufStruct 1 Offset 32 -OpDecorate %bufStruct Block -OpDecorate %u_info DescriptorSet 0 -OpDecorate %u_info Binding 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer -%uint = OpTypeInt 32 0 -%ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %uint -%int = OpTypeInt 32 1 -%uint_2 = OpConstant %uint 2 -%_arr_int_uint_2 = OpTypeArray %int %uint_2 -%bufStruct = OpTypeStruct %_arr_int_uint_2 %int -%_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct -%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo -%u_info = OpVariable %_ptr_Uniform_ufoo Uniform -%int_0 = OpConstant %int 0 -%_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct -%int_1 = OpConstant %int 1 -%int_3239 = OpConstant %int 3239 -%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability PhysicalStorageBufferAddresses -OpCapability Int64 -OpExtension "SPV_EXT_physical_storage_buffer" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_buffer_reference" -OpName %main "main" -OpName %ufoo "ufoo" -OpMemberName %ufoo 0 "data" -OpMemberName %ufoo 1 "offset" -OpName %bufStruct "bufStruct" -OpMemberName %bufStruct 0 "a" -OpMemberName %bufStruct 1 "b" -OpName %u_info "u_info" -OpMemberDecorate %ufoo 0 Offset 0 -OpMemberDecorate %ufoo 1 Offset 8 -OpDecorate %ufoo Block -OpDecorate %_arr_int_uint_2 ArrayStride 16 -OpMemberDecorate %bufStruct 0 Offset 0 -OpMemberDecorate %bufStruct 1 Offset 32 -OpDecorate %bufStruct Block -OpDecorate %u_info DescriptorSet 0 -OpDecorate %u_info Binding 0 -OpDecorate %_runtimearr_ulong ArrayStride 8 -OpDecorate %_struct_39 Block -OpMemberDecorate %_struct_39 0 Offset 0 -OpDecorate %41 DescriptorSet 7 -OpDecorate %41 Binding 2 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_77 Block -OpMemberDecorate %_struct_77 0 Offset 0 -OpMemberDecorate %_struct_77 1 Offset 4 -OpDecorate %79 DescriptorSet 7 -OpDecorate %79 Binding 0 -OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId -%void = OpTypeVoid -%8 = OpTypeFunction %void -OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer -%uint = OpTypeInt 32 0 -%ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %uint -%int = OpTypeInt 32 1 -%uint_2 = OpConstant %uint 2 -%_arr_int_uint_2 = OpTypeArray %int %uint_2 -%bufStruct = OpTypeStruct %_arr_int_uint_2 %int -%_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct -%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo -%u_info = OpVariable %_ptr_Uniform_ufoo Uniform -%int_0 = OpConstant %int 0 -%_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct -%int_1 = OpConstant %int 1 -%int_3239 = OpConstant %int 3239 -%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int -%ulong = OpTypeInt 64 0 -%uint_4 = OpConstant %uint 4 -%bool = OpTypeBool -%28 = OpTypeFunction %bool %ulong %uint -%uint_1 = OpConstant %uint 1 -%_runtimearr_ulong = OpTypeRuntimeArray %ulong -%_struct_39 = OpTypeStruct %_runtimearr_ulong -%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39 -%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer -%_ptr_StorageBuffer_ulong = OpTypePointer StorageBuffer %ulong -%uint_0 = OpConstant %uint 0 -%uint_32 = OpConstant %uint 32 -%70 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_77 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_77 = OpTypePointer StorageBuffer %_struct_77 -%79 = OpVariable %_ptr_StorageBuffer__struct_77 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_23 = OpConstant %uint 23 -%uint_5 = OpConstant %uint 5 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_9 = OpConstant %uint 9 -%uint_48 = OpConstant %uint 48 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%17 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0 -%18 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %17 -%22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %18 %int_1 -OpStore %22 %int_3239 Aligned 16 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %8 -%19 = OpLabel -%20 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0 -%21 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %20 -%22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %21 %int_1 -%24 = OpConvertPtrToU %ulong %22 -%61 = OpFunctionCall %bool %26 %24 %uint_4 -OpSelectionMerge %62 None -OpBranchConditional %61 %63 %64 -%63 = OpLabel -OpStore %22 %int_3239 Aligned 16 -OpBranch %62 -%64 = OpLabel -%65 = OpUConvert %uint %24 -%67 = OpShiftRightLogical %ulong %24 %uint_32 -%68 = OpUConvert %uint %67 -%124 = OpFunctionCall %void %69 %uint_48 %uint_2 %65 %68 -OpBranch %62 -%62 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%26 = OpFunction %bool None %28 -%29 = OpFunctionParameter %ulong -%30 = OpFunctionParameter %uint -%31 = OpLabel -OpBranch %32 -%32 = OpLabel -%34 = OpPhi %uint %uint_1 %31 %35 %33 -OpLoopMerge %37 %33 None -OpBranch %33 -%33 = OpLabel -%35 = OpIAdd %uint %34 %uint_1 -%44 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %35 -%45 = OpLoad %ulong %44 -%46 = OpUGreaterThan %bool %45 %29 -OpBranchConditional %46 %37 %32 -%37 = OpLabel -%47 = OpISub %uint %35 %uint_1 -%48 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %47 -%49 = OpLoad %ulong %48 -%50 = OpISub %ulong %29 %49 -%51 = OpUConvert %ulong %30 -%52 = OpIAdd %ulong %50 %51 -%53 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %uint_0 -%54 = OpLoad %ulong %53 -%55 = OpUConvert %uint %54 -%56 = OpISub %uint %47 %uint_1 -%57 = OpIAdd %uint %56 %55 -%58 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %57 -%59 = OpLoad %ulong %58 -%60 = OpULessThanEqual %bool %52 %59 -OpReturnValue %60 -OpFunctionEnd -%69 = OpFunction %void None %70 -%71 = OpFunctionParameter %uint -%72 = OpFunctionParameter %uint -%73 = OpFunctionParameter %uint -%74 = OpFunctionParameter %uint -%75 = OpLabel -%81 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_0 -%83 = OpAtomicIAdd %uint %81 %uint_4 %uint_0 %uint_10 -%84 = OpIAdd %uint %83 %uint_10 -%85 = OpArrayLength %uint %79 1 -%86 = OpULessThanEqual %bool %84 %85 -OpSelectionMerge %87 None -OpBranchConditional %86 %88 %87 -%88 = OpLabel -%89 = OpIAdd %uint %83 %uint_0 -%90 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %89 -OpStore %90 %uint_10 -%92 = OpIAdd %uint %83 %uint_1 -%93 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %92 -OpStore %93 %uint_23 -%94 = OpIAdd %uint %83 %uint_2 -%95 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %94 -OpStore %95 %71 -%98 = OpIAdd %uint %83 %uint_3 -%99 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %98 -OpStore %99 %uint_5 -%103 = OpLoad %v3uint %gl_GlobalInvocationID -%104 = OpCompositeExtract %uint %103 0 -%105 = OpCompositeExtract %uint %103 1 -%106 = OpCompositeExtract %uint %103 2 -%107 = OpIAdd %uint %83 %uint_4 -%108 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %107 -OpStore %108 %104 -%109 = OpIAdd %uint %83 %uint_5 -%110 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %109 -OpStore %110 %105 -%112 = OpIAdd %uint %83 %uint_6 -%113 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %112 -OpStore %113 %106 -%115 = OpIAdd %uint %83 %uint_7 -%116 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %115 -OpStore %116 %72 -%118 = OpIAdd %uint %83 %uint_8 -%119 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %118 -OpStore %119 %73 -%121 = OpIAdd %uint %83 %uint_9 -%122 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %121 -OpStore %122 %74 -OpBranch %87 -%87 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, 2u); -} - -TEST_F(InstBuffAddrTest, InstPhysicalStorageBufferLoadAndStore) { - // #version 450 - // #extension GL_EXT_buffer_reference : enable - - // // forward reference - // layout(buffer_reference) buffer blockType; - - // layout(buffer_reference, std430, buffer_reference_align = 16) buffer - // blockType { - // int x; - // blockType next; - // }; - - // layout(std430) buffer rootBlock { - // blockType root; - // } r; - - // void main() - // { - // blockType b = r.root; - // b = b.next; - // b.x = 531; - // } - - const std::string defs_before = - R"(OpCapability Shader -OpCapability PhysicalStorageBufferAddresses -OpExtension "SPV_EXT_physical_storage_buffer" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_buffer_reference" -OpName %main "main" -OpName %blockType "blockType" -OpMemberName %blockType 0 "x" -OpMemberName %blockType 1 "next" -OpName %rootBlock "rootBlock" -OpMemberName %rootBlock 0 "root" -OpName %r "r" -OpMemberDecorate %blockType 0 Offset 0 -OpMemberDecorate %blockType 1 Offset 8 -OpDecorate %blockType Block -OpMemberDecorate %rootBlock 0 Offset 0 -OpDecorate %rootBlock Block -OpDecorate %r DescriptorSet 0 -OpDecorate %r Binding 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer -%int = OpTypeInt 32 1 -%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType -%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType -%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType -%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock -%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_1 = OpConstant %int 1 -%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_531 = OpConstant %int 531 -%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int -)"; - - const std::string defs_after = - R"(OpCapability Shader -OpCapability PhysicalStorageBufferAddresses -OpCapability Int64 -OpExtension "SPV_EXT_physical_storage_buffer" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 450 -OpSourceExtension "GL_EXT_buffer_reference" -OpName %main "main" -OpName %blockType "blockType" -OpMemberName %blockType 0 "x" -OpMemberName %blockType 1 "next" -OpName %rootBlock "rootBlock" -OpMemberName %rootBlock 0 "root" -OpName %r "r" -OpMemberDecorate %blockType 0 Offset 0 -OpMemberDecorate %blockType 1 Offset 8 -OpDecorate %blockType Block -OpMemberDecorate %rootBlock 0 Offset 0 -OpDecorate %rootBlock Block -OpDecorate %r DescriptorSet 0 -OpDecorate %r Binding 0 -OpDecorate %_runtimearr_ulong ArrayStride 8 -OpDecorate %_struct_45 Block -OpMemberDecorate %_struct_45 0 Offset 0 -OpDecorate %47 DescriptorSet 7 -OpDecorate %47 Binding 2 -OpDecorate %_runtimearr_uint ArrayStride 4 -OpDecorate %_struct_84 Block -OpMemberDecorate %_struct_84 0 Offset 0 -OpMemberDecorate %_struct_84 1 Offset 4 -OpDecorate %86 DescriptorSet 7 -OpDecorate %86 Binding 0 -OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId -%void = OpTypeVoid -%3 = OpTypeFunction %void -OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer -%int = OpTypeInt 32 1 -%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType -%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType -%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType -%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock -%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer -%int_0 = OpConstant %int 0 -%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_1 = OpConstant %int 1 -%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType -%int_531 = OpConstant %int 531 -%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int -%uint = OpTypeInt 32 0 -%uint_2 = OpConstant %uint 2 -%ulong = OpTypeInt 64 0 -%uint_8 = OpConstant %uint 8 -%bool = OpTypeBool -%34 = OpTypeFunction %bool %ulong %uint -%uint_1 = OpConstant %uint 1 -%_runtimearr_ulong = OpTypeRuntimeArray %ulong -%_struct_45 = OpTypeStruct %_runtimearr_ulong -%_ptr_StorageBuffer__struct_45 = OpTypePointer StorageBuffer %_struct_45 -%47 = OpVariable %_ptr_StorageBuffer__struct_45 StorageBuffer -%_ptr_StorageBuffer_ulong = OpTypePointer StorageBuffer %ulong -%uint_0 = OpConstant %uint 0 -%uint_32 = OpConstant %uint 32 -%77 = OpTypeFunction %void %uint %uint %uint %uint -%_runtimearr_uint = OpTypeRuntimeArray %uint -%_struct_84 = OpTypeStruct %uint %_runtimearr_uint -%_ptr_StorageBuffer__struct_84 = OpTypePointer StorageBuffer %_struct_84 -%86 = OpVariable %_ptr_StorageBuffer__struct_84 StorageBuffer -%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -%uint_10 = OpConstant %uint 10 -%uint_4 = OpConstant %uint 4 -%uint_23 = OpConstant %uint 23 -%uint_5 = OpConstant %uint 5 -%uint_3 = OpConstant %uint 3 -%v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_9 = OpConstant %uint 9 -%uint_44 = OpConstant %uint 44 -%132 = OpConstantNull %ulong -%uint_46 = OpConstant %uint 46 -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0 -%17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16 -%21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1 -%22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8 -%26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0 -OpStore %26 %int_531 Aligned 16 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0 -%17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16 -%21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1 -%30 = OpConvertPtrToU %ulong %21 -%67 = OpFunctionCall %bool %32 %30 %uint_8 -OpSelectionMerge %68 None -OpBranchConditional %67 %69 %70 -%69 = OpLabel -%71 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8 -OpBranch %68 -%70 = OpLabel -%72 = OpUConvert %uint %30 -%74 = OpShiftRightLogical %ulong %30 %uint_32 -%75 = OpUConvert %uint %74 -%131 = OpFunctionCall %void %76 %uint_44 %uint_2 %72 %75 -%133 = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_blockType %132 -OpBranch %68 -%68 = OpLabel -%134 = OpPhi %_ptr_PhysicalStorageBuffer_blockType %71 %69 %133 %70 -%26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %134 %int_0 -%135 = OpConvertPtrToU %ulong %26 -%136 = OpFunctionCall %bool %32 %135 %uint_4 -OpSelectionMerge %137 None -OpBranchConditional %136 %138 %139 -%138 = OpLabel -OpStore %26 %int_531 Aligned 16 -OpBranch %137 -%139 = OpLabel -%140 = OpUConvert %uint %135 -%141 = OpShiftRightLogical %ulong %135 %uint_32 -%142 = OpUConvert %uint %141 -%144 = OpFunctionCall %void %76 %uint_46 %uint_2 %140 %142 -OpBranch %137 -%137 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string new_funcs = - R"(%32 = OpFunction %bool None %34 -%35 = OpFunctionParameter %ulong -%36 = OpFunctionParameter %uint -%37 = OpLabel -OpBranch %38 -%38 = OpLabel -%40 = OpPhi %uint %uint_1 %37 %41 %39 -OpLoopMerge %43 %39 None -OpBranch %39 -%39 = OpLabel -%41 = OpIAdd %uint %40 %uint_1 -%50 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %41 -%51 = OpLoad %ulong %50 -%52 = OpUGreaterThan %bool %51 %35 -OpBranchConditional %52 %43 %38 -%43 = OpLabel -%53 = OpISub %uint %41 %uint_1 -%54 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %53 -%55 = OpLoad %ulong %54 -%56 = OpISub %ulong %35 %55 -%57 = OpUConvert %ulong %36 -%58 = OpIAdd %ulong %56 %57 -%59 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %uint_0 -%60 = OpLoad %ulong %59 -%61 = OpUConvert %uint %60 -%62 = OpISub %uint %53 %uint_1 -%63 = OpIAdd %uint %62 %61 -%64 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %63 -%65 = OpLoad %ulong %64 -%66 = OpULessThanEqual %bool %58 %65 -OpReturnValue %66 -OpFunctionEnd -%76 = OpFunction %void None %77 -%78 = OpFunctionParameter %uint -%79 = OpFunctionParameter %uint -%80 = OpFunctionParameter %uint -%81 = OpFunctionParameter %uint -%82 = OpLabel -%88 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_0 -%91 = OpAtomicIAdd %uint %88 %uint_4 %uint_0 %uint_10 -%92 = OpIAdd %uint %91 %uint_10 -%93 = OpArrayLength %uint %86 1 -%94 = OpULessThanEqual %bool %92 %93 -OpSelectionMerge %95 None -OpBranchConditional %94 %96 %95 -%96 = OpLabel -%97 = OpIAdd %uint %91 %uint_0 -%98 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %97 -OpStore %98 %uint_10 -%100 = OpIAdd %uint %91 %uint_1 -%101 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %100 -OpStore %101 %uint_23 -%102 = OpIAdd %uint %91 %uint_2 -%103 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %102 -OpStore %103 %78 -%106 = OpIAdd %uint %91 %uint_3 -%107 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %106 -OpStore %107 %uint_5 -%111 = OpLoad %v3uint %gl_GlobalInvocationID -%112 = OpCompositeExtract %uint %111 0 -%113 = OpCompositeExtract %uint %111 1 -%114 = OpCompositeExtract %uint %111 2 -%115 = OpIAdd %uint %91 %uint_4 -%116 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %115 -OpStore %116 %112 -%117 = OpIAdd %uint %91 %uint_5 -%118 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %117 -OpStore %118 %113 -%120 = OpIAdd %uint %91 %uint_6 -%121 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %120 -OpStore %121 %114 -%123 = OpIAdd %uint %91 %uint_7 -%124 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %123 -OpStore %124 %79 -%125 = OpIAdd %uint %91 %uint_8 -%126 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %125 -OpStore %126 %80 -%128 = OpIAdd %uint %91 %uint_9 -%129 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %128 -OpStore %129 %81 -OpBranch %95 -%95 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs_before + func_before, defs_after + func_after + new_funcs, true, - true, 7u, 23u, 2u); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/instruction_list_test.cpp b/3rdparty/spirv-tools/test/opt/instruction_list_test.cpp deleted file mode 100644 index e745790a3..000000000 --- a/3rdparty/spirv-tools/test/opt/instruction_list_test.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/instruction.h" -#include "source/opt/instruction_list.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::ContainerEq; -using ::testing::ElementsAre; -using InstructionListTest = ::testing::Test; - -// A class that overrides the destructor, so we can trace it. -class TestInstruction : public Instruction { - public: - TestInstruction() : Instruction() { created_instructions_.push_back(this); } - - ~TestInstruction() { deleted_instructions_.push_back(this); } - - static std::vector created_instructions_; - static std::vector deleted_instructions_; -}; - -std::vector TestInstruction::created_instructions_; -std::vector TestInstruction::deleted_instructions_; - -// Test that the destructor for InstructionList is calling the destructor -// for every element that is in the list. -TEST(InstructionListTest, Destructor) { - InstructionList* list = new InstructionList(); - list->push_back(std::unique_ptr(new Instruction())); - list->push_back(std::unique_ptr(new Instruction())); - delete list; - - // Sorting because we do not care if the order of create and destruction is - // the same. Using generic sort just incase things are changed above. - std::sort(TestInstruction::created_instructions_.begin(), - TestInstruction::created_instructions_.end()); - std::sort(TestInstruction::deleted_instructions_.begin(), - TestInstruction::deleted_instructions_.end()); - EXPECT_THAT(TestInstruction::created_instructions_, - ContainerEq(TestInstruction::deleted_instructions_)); -} - -// Test the |InsertBefore| with a single instruction in the iterator class. -// Need to make sure the elements are inserted in the correct order, and the -// return value points to the correct location. -// -// Comparing addresses to make sure they remain stable, so other data structures -// can have pointers to instructions in InstructionList. -TEST(InstructionListTest, InsertBefore1) { - InstructionList list; - std::vector inserted_instructions; - for (int i = 0; i < 4; i++) { - std::unique_ptr inst(new Instruction()); - inserted_instructions.push_back(inst.get()); - auto new_element = list.end().InsertBefore(std::move(inst)); - EXPECT_EQ(&*new_element, inserted_instructions.back()); - } - - std::vector output; - for (auto& i : list) { - output.push_back(&i); - } - EXPECT_THAT(output, ContainerEq(inserted_instructions)); -} - -// Test inserting an entire vector of instructions using InsertBefore. Checking -// the order of insertion and the return value. -// -// Comparing addresses to make sure they remain stable, so other data structures -// can have pointers to instructions in InstructionList. -TEST(InstructionListTest, InsertBefore2) { - InstructionList list; - std::vector> new_instructions; - std::vector created_instructions; - for (int i = 0; i < 4; i++) { - std::unique_ptr inst(new Instruction()); - created_instructions.push_back(inst.get()); - new_instructions.push_back(std::move(inst)); - } - auto new_element = list.begin().InsertBefore(std::move(new_instructions)); - EXPECT_TRUE(new_instructions.empty()); - EXPECT_EQ(&*new_element, created_instructions.front()); - - std::vector output; - for (auto& i : list) { - output.push_back(&i); - } - EXPECT_THAT(output, ContainerEq(created_instructions)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/instruction_test.cpp b/3rdparty/spirv-tools/test/opt/instruction_test.cpp deleted file mode 100644 index a6972011f..000000000 --- a/3rdparty/spirv-tools/test/opt/instruction_test.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -// 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 "gmock/gmock.h" -#include "source/opt/instruction.h" -#include "source/opt/ir_context.h" -#include "spirv-tools/libspirv.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace opt { -namespace { - -using spvtest::MakeInstruction; -using ::testing::Eq; -using DescriptorTypeTest = PassTest<::testing::Test>; -using OpaqueTypeTest = PassTest<::testing::Test>; -using GetBaseTest = PassTest<::testing::Test>; -using ValidBasePointerTest = PassTest<::testing::Test>; - -TEST(InstructionTest, CreateTrivial) { - Instruction empty; - EXPECT_EQ(SpvOpNop, empty.opcode()); - EXPECT_EQ(0u, empty.type_id()); - EXPECT_EQ(0u, empty.result_id()); - EXPECT_EQ(0u, empty.NumOperands()); - EXPECT_EQ(0u, empty.NumOperandWords()); - EXPECT_EQ(0u, empty.NumInOperandWords()); - EXPECT_EQ(empty.cend(), empty.cbegin()); - EXPECT_EQ(empty.end(), empty.begin()); -} - -TEST(InstructionTest, CreateWithOpcodeAndNoOperands) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, SpvOpReturn); - EXPECT_EQ(SpvOpReturn, inst.opcode()); - EXPECT_EQ(0u, inst.type_id()); - EXPECT_EQ(0u, inst.result_id()); - EXPECT_EQ(0u, inst.NumOperands()); - EXPECT_EQ(0u, inst.NumOperandWords()); - EXPECT_EQ(0u, inst.NumInOperandWords()); - EXPECT_EQ(inst.cend(), inst.cbegin()); - EXPECT_EQ(inst.end(), inst.begin()); -} - -// The words for an OpTypeInt for 32-bit signed integer resulting in Id 44. -uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44, - 32, 1}; -// The operands that would be parsed from kSampleInstructionWords -spv_parsed_operand_t kSampleParsedOperands[] = { - {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0}, - {2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32}, - {3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1}, -}; - -// A valid parse of kSampleParsedOperands. -spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords, - uint16_t(4), - uint16_t(SpvOpTypeInt), - SPV_EXT_INST_TYPE_NONE, - 0, // type id - 44, // result id - kSampleParsedOperands, - 3}; - -// The words for an OpAccessChain instruction. -uint32_t kSampleAccessChainInstructionWords[] = { - (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105}; - -// The operands that would be parsed from kSampleAccessChainInstructionWords. -spv_parsed_operand_t kSampleAccessChainOperands[] = { - {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0}, - {2, 1, SPV_OPERAND_TYPE_TYPE_ID, SPV_NUMBER_NONE, 0}, - {3, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0}, - {4, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0}, - {5, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0}, - {6, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0}, -}; - -// A valid parse of kSampleAccessChainInstructionWords -spv_parsed_instruction_t kSampleAccessChainInstruction = { - kSampleAccessChainInstructionWords, - uint16_t(7), - uint16_t(SpvOpAccessChain), - SPV_EXT_INST_TYPE_NONE, - 100, // type id - 101, // result id - kSampleAccessChainOperands, - 6}; - -// The words for an OpControlBarrier instruction. -uint32_t kSampleControlBarrierInstructionWords[] = { - (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102}; - -// The operands that would be parsed from kSampleControlBarrierInstructionWords. -spv_parsed_operand_t kSampleControlBarrierOperands[] = { - {1, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0}, // Execution - {2, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0}, // Memory - {3, 1, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_NUMBER_NONE, - 0}, // Semantics -}; - -// A valid parse of kSampleControlBarrierInstructionWords -spv_parsed_instruction_t kSampleControlBarrierInstruction = { - kSampleControlBarrierInstructionWords, - uint16_t(4), - uint16_t(SpvOpControlBarrier), - SPV_EXT_INST_TYPE_NONE, - 0, // type id - 0, // result id - kSampleControlBarrierOperands, - 3}; - -TEST(InstructionTest, CreateWithOpcodeAndOperands) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleParsedInstruction); - EXPECT_EQ(SpvOpTypeInt, inst.opcode()); - EXPECT_EQ(0u, inst.type_id()); - EXPECT_EQ(44u, inst.result_id()); - EXPECT_EQ(3u, inst.NumOperands()); - EXPECT_EQ(3u, inst.NumOperandWords()); - EXPECT_EQ(2u, inst.NumInOperandWords()); -} - -TEST(InstructionTest, GetOperand) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleParsedInstruction); - EXPECT_THAT(inst.GetOperand(0).words, Eq(std::vector{44})); - EXPECT_THAT(inst.GetOperand(1).words, Eq(std::vector{32})); - EXPECT_THAT(inst.GetOperand(2).words, Eq(std::vector{1})); -} - -TEST(InstructionTest, GetInOperand) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleParsedInstruction); - EXPECT_THAT(inst.GetInOperand(0).words, Eq(std::vector{32})); - EXPECT_THAT(inst.GetInOperand(1).words, Eq(std::vector{1})); -} - -TEST(InstructionTest, OperandConstIterators) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleParsedInstruction); - // Spot check iteration across operands. - auto cbegin = inst.cbegin(); - auto cend = inst.cend(); - EXPECT_NE(cend, inst.cbegin()); - - auto citer = inst.cbegin(); - for (int i = 0; i < 3; ++i, ++citer) { - const auto& operand = *citer; - EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type)); - EXPECT_THAT(operand.words, - Eq(std::vector{kSampleInstructionWords[i + 1]})); - EXPECT_NE(cend, citer); - } - EXPECT_EQ(cend, citer); - - // Check that cbegin and cend have not changed. - EXPECT_EQ(cbegin, inst.cbegin()); - EXPECT_EQ(cend, inst.cend()); - - // Check arithmetic. - const Operand& operand2 = *(inst.cbegin() + 2); - EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type); -} - -TEST(InstructionTest, OperandIterators) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleParsedInstruction); - // Spot check iteration across operands, with mutable iterators. - auto begin = inst.begin(); - auto end = inst.end(); - EXPECT_NE(end, inst.begin()); - - auto iter = inst.begin(); - for (int i = 0; i < 3; ++i, ++iter) { - const auto& operand = *iter; - EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type)); - EXPECT_THAT(operand.words, - Eq(std::vector{kSampleInstructionWords[i + 1]})); - EXPECT_NE(end, iter); - } - EXPECT_EQ(end, iter); - - // Check that begin and end have not changed. - EXPECT_EQ(begin, inst.begin()); - EXPECT_EQ(end, inst.end()); - - // Check arithmetic. - Operand& operand2 = *(inst.begin() + 2); - EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type); - - // Check mutation through an iterator. - operand2.type = SPV_OPERAND_TYPE_TYPE_ID; - EXPECT_EQ(SPV_OPERAND_TYPE_TYPE_ID, (*(inst.cbegin() + 2)).type); -} - -TEST(InstructionTest, ForInIdStandardIdTypes) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleAccessChainInstruction); - - std::vector ids; - inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); }); - EXPECT_THAT(ids, Eq(std::vector{102, 103, 104, 105})); - - ids.clear(); - inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); }); - EXPECT_THAT(ids, Eq(std::vector{102, 103, 104, 105})); -} - -TEST(InstructionTest, ForInIdNonstandardIdTypes) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context, kSampleControlBarrierInstruction); - - std::vector ids; - inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); }); - EXPECT_THAT(ids, Eq(std::vector{100, 101, 102})); - - ids.clear(); - inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); }); - EXPECT_THAT(ids, Eq(std::vector{100, 101, 102})); -} - -TEST(InstructionTest, UniqueIds) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst1(&context); - Instruction inst2(&context); - EXPECT_NE(inst1.unique_id(), inst2.unique_id()); -} - -TEST(InstructionTest, CloneUniqueIdDifferent) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&context); - std::unique_ptr clone(inst.Clone(&context)); - EXPECT_EQ(inst.context(), clone->context()); - EXPECT_NE(inst.unique_id(), clone->unique_id()); -} - -TEST(InstructionTest, CloneDifferentContext) { - IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr); - IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&c1); - std::unique_ptr clone(inst.Clone(&c2)); - EXPECT_EQ(&c1, inst.context()); - EXPECT_EQ(&c2, clone->context()); - EXPECT_NE(&c1, &c2); -} - -TEST(InstructionTest, CloneDifferentContextDifferentUniqueId) { - IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr); - IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction inst(&c1); - Instruction other(&c2); - std::unique_ptr clone(inst.Clone(&c2)); - EXPECT_EQ(&c2, clone->context()); - EXPECT_NE(other.unique_id(), clone->unique_id()); -} - -TEST(InstructionTest, EqualsEqualsOperator) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction i1(&context); - Instruction i2(&context); - std::unique_ptr clone(i1.Clone(&context)); - EXPECT_TRUE(i1 == i1); - EXPECT_FALSE(i1 == i2); - EXPECT_FALSE(i1 == *clone); - EXPECT_FALSE(i2 == *clone); -} - -TEST(InstructionTest, LessThanOperator) { - IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr); - Instruction i1(&context); - Instruction i2(&context); - std::unique_ptr clone(i1.Clone(&context)); - EXPECT_TRUE(i1 < i2); - EXPECT_TRUE(i1 < *clone); - EXPECT_TRUE(i2 < *clone); -} - -TEST_F(DescriptorTypeTest, StorageImage) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeImage %6 2D 0 0 0 2 R32f - %8 = OpTypePointer UniformConstant %7 - %3 = OpVariable %8 UniformConstant - %2 = OpFunction %4 None %5 - %9 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* type = context->get_def_use_mgr()->GetDef(8); - EXPECT_TRUE(type->IsVulkanStorageImage()); - EXPECT_FALSE(type->IsVulkanSampledImage()); - EXPECT_FALSE(type->IsVulkanStorageTexelBuffer()); - EXPECT_FALSE(type->IsVulkanStorageBuffer()); - EXPECT_FALSE(type->IsVulkanUniformBuffer()); - - Instruction* variable = context->get_def_use_mgr()->GetDef(3); - EXPECT_FALSE(variable->IsReadOnlyVariable()); -} - -TEST_F(DescriptorTypeTest, SampledImage) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeImage %6 2D 0 0 0 1 Unknown - %8 = OpTypePointer UniformConstant %7 - %3 = OpVariable %8 UniformConstant - %2 = OpFunction %4 None %5 - %9 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* type = context->get_def_use_mgr()->GetDef(8); - EXPECT_FALSE(type->IsVulkanStorageImage()); - EXPECT_TRUE(type->IsVulkanSampledImage()); - EXPECT_FALSE(type->IsVulkanStorageTexelBuffer()); - EXPECT_FALSE(type->IsVulkanStorageBuffer()); - EXPECT_FALSE(type->IsVulkanUniformBuffer()); - - Instruction* variable = context->get_def_use_mgr()->GetDef(3); - EXPECT_TRUE(variable->IsReadOnlyVariable()); -} - -TEST_F(DescriptorTypeTest, StorageTexelBuffer) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeImage %6 Buffer 0 0 0 2 R32f - %8 = OpTypePointer UniformConstant %7 - %3 = OpVariable %8 UniformConstant - %2 = OpFunction %4 None %5 - %9 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* type = context->get_def_use_mgr()->GetDef(8); - EXPECT_FALSE(type->IsVulkanStorageImage()); - EXPECT_FALSE(type->IsVulkanSampledImage()); - EXPECT_TRUE(type->IsVulkanStorageTexelBuffer()); - EXPECT_FALSE(type->IsVulkanStorageBuffer()); - EXPECT_FALSE(type->IsVulkanUniformBuffer()); - - Instruction* variable = context->get_def_use_mgr()->GetDef(3); - EXPECT_FALSE(variable->IsReadOnlyVariable()); -} - -TEST_F(DescriptorTypeTest, StorageBuffer) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - OpDecorate %9 BufferBlock - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeRuntimeArray %7 - %9 = OpTypeStruct %8 - %10 = OpTypePointer Uniform %9 - %3 = OpVariable %10 Uniform - %2 = OpFunction %4 None %5 - %11 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* type = context->get_def_use_mgr()->GetDef(10); - EXPECT_FALSE(type->IsVulkanStorageImage()); - EXPECT_FALSE(type->IsVulkanSampledImage()); - EXPECT_FALSE(type->IsVulkanStorageTexelBuffer()); - EXPECT_TRUE(type->IsVulkanStorageBuffer()); - EXPECT_FALSE(type->IsVulkanUniformBuffer()); - - Instruction* variable = context->get_def_use_mgr()->GetDef(3); - EXPECT_FALSE(variable->IsReadOnlyVariable()); -} - -TEST_F(DescriptorTypeTest, UniformBuffer) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - OpDecorate %9 Block - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeRuntimeArray %7 - %9 = OpTypeStruct %8 - %10 = OpTypePointer Uniform %9 - %3 = OpVariable %10 Uniform - %2 = OpFunction %4 None %5 - %11 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* type = context->get_def_use_mgr()->GetDef(10); - EXPECT_FALSE(type->IsVulkanStorageImage()); - EXPECT_FALSE(type->IsVulkanSampledImage()); - EXPECT_FALSE(type->IsVulkanStorageTexelBuffer()); - EXPECT_FALSE(type->IsVulkanStorageBuffer()); - EXPECT_TRUE(type->IsVulkanUniformBuffer()); - - Instruction* variable = context->get_def_use_mgr()->GetDef(3); - EXPECT_TRUE(variable->IsReadOnlyVariable()); -} - -TEST_F(DescriptorTypeTest, NonWritableIsReadOnly) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - OpDecorate %9 BufferBlock - OpDecorate %3 NonWritable - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeRuntimeArray %7 - %9 = OpTypeStruct %8 - %10 = OpTypePointer Uniform %9 - %3 = OpVariable %10 Uniform - %2 = OpFunction %4 None %5 - %11 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* variable = context->get_def_use_mgr()->GetDef(3); - EXPECT_TRUE(variable->IsReadOnlyVariable()); -} - -TEST_F(OpaqueTypeTest, BaseOpaqueTypesShader) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypeImage %5 2D 1 0 0 1 Unknown - %7 = OpTypeSampler - %8 = OpTypeSampledImage %6 - %9 = OpTypeRuntimeArray %5 - %2 = OpFunction %3 None %4 - %10 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* image_type = context->get_def_use_mgr()->GetDef(6); - EXPECT_TRUE(image_type->IsOpaqueType()); - Instruction* sampler_type = context->get_def_use_mgr()->GetDef(7); - EXPECT_TRUE(sampler_type->IsOpaqueType()); - Instruction* sampled_image_type = context->get_def_use_mgr()->GetDef(8); - EXPECT_TRUE(sampled_image_type->IsOpaqueType()); - Instruction* runtime_array_type = context->get_def_use_mgr()->GetDef(9); - EXPECT_TRUE(runtime_array_type->IsOpaqueType()); - Instruction* float_type = context->get_def_use_mgr()->GetDef(5); - EXPECT_FALSE(float_type->IsOpaqueType()); - Instruction* void_type = context->get_def_use_mgr()->GetDef(3); - EXPECT_FALSE(void_type->IsOpaqueType()); -} - -TEST_F(OpaqueTypeTest, OpaqueStructTypes) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypeRuntimeArray %5 - %7 = OpTypeStruct %6 %6 - %8 = OpTypeStruct %5 %6 - %9 = OpTypeStruct %6 %5 - %10 = OpTypeStruct %7 - %2 = OpFunction %3 None %4 - %11 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - for (int i = 7; i <= 10; i++) { - Instruction* type = context->get_def_use_mgr()->GetDef(i); - EXPECT_TRUE(type->IsOpaqueType()); - } -} - -TEST_F(GetBaseTest, SampleImage) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypeVector %6 4 - %9 = OpConstant %6 0 - %10 = OpConstantComposite %7 %9 %9 - %11 = OpTypeImage %6 2D 0 0 0 1 R32f - %12 = OpTypePointer UniformConstant %11 - %3 = OpVariable %12 UniformConstant - %13 = OpTypeSampledImage %11 - %14 = OpTypeSampler - %15 = OpTypePointer UniformConstant %14 - %16 = OpVariable %15 UniformConstant - %2 = OpFunction %4 None %5 - %17 = OpLabel - %18 = OpLoad %11 %3 - %19 = OpLoad %14 %16 - %20 = OpSampledImage %13 %18 %19 - %21 = OpImageSampleImplicitLod %8 %20 %10 - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* load = context->get_def_use_mgr()->GetDef(21); - Instruction* base = context->get_def_use_mgr()->GetDef(20); - EXPECT_TRUE(load->GetBaseAddress() == base); -} - -TEST_F(GetBaseTest, PtrAccessChain) { - const std::string text = R"( - OpCapability VariablePointers - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "PSMain" %2 - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 8388353 - %int_0 = OpConstant %int 0 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %2 = OpVariable %_ptr_Function_v4float Input - %1 = OpFunction %void None %4 - %10 = OpLabel - %11 = OpPtrAccessChain %_ptr_Function_v4float %2 %int_0 - %12 = OpLoad %v4float %11 - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* load = context->get_def_use_mgr()->GetDef(12); - Instruction* base = context->get_def_use_mgr()->GetDef(2); - EXPECT_TRUE(load->GetBaseAddress() == base); -} - -TEST_F(GetBaseTest, ImageRead) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "myStorageImage" - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeInt 32 0 - %7 = OpTypeVector %6 2 - %8 = OpConstant %6 0 - %9 = OpConstantComposite %7 %8 %8 - %10 = OpTypeImage %6 2D 0 0 0 2 R32f - %11 = OpTypePointer UniformConstant %10 - %3 = OpVariable %11 UniformConstant - %2 = OpFunction %4 None %5 - %12 = OpLabel - %13 = OpLoad %10 %3 - %14 = OpImageRead %6 %13 %9 - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - Instruction* load = context->get_def_use_mgr()->GetDef(14); - Instruction* base = context->get_def_use_mgr()->GetDef(13); - EXPECT_TRUE(load->GetBaseAddress() == base); -} - -TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpVariable %4 StorageBuffer -%6 = OpTypeFunction %2 -%7 = OpTypeBool -%8 = OpConstantTrue %7 -%1 = OpFunction %2 None %6 -%9 = OpLabel -%10 = OpSelect %4 %8 %5 %5 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* select = context->get_def_use_mgr()->GetDef(10); - EXPECT_NE(select, nullptr); - EXPECT_FALSE(select->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpVariable %4 Workgroup -%6 = OpTypeFunction %2 -%7 = OpTypeBool -%8 = OpConstantTrue %7 -%1 = OpFunction %2 None %6 -%9 = OpLabel -%10 = OpSelect %4 %8 %5 %5 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* select = context->get_def_use_mgr()->GetDef(10); - EXPECT_NE(select, nullptr); - EXPECT_FALSE(select->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpVariable %4 StorageBuffer -%6 = OpTypeFunction %2 -%7 = OpTypeBool -%8 = OpConstantTrue %7 -%1 = OpFunction %2 None %6 -%9 = OpLabel -%10 = OpSelect %4 %8 %5 %5 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* select = context->get_def_use_mgr()->GetDef(10); - EXPECT_NE(select, nullptr); - EXPECT_TRUE(select->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointers -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpVariable %4 Workgroup -%6 = OpTypeFunction %2 -%7 = OpTypeBool -%8 = OpConstantTrue %7 -%1 = OpFunction %2 None %6 -%9 = OpLabel -%10 = OpSelect %4 %8 %5 %5 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* select = context->get_def_use_mgr()->GetDef(10); - EXPECT_NE(select, nullptr); - EXPECT_TRUE(select->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(5); - EXPECT_NE(null_inst, nullptr); - EXPECT_FALSE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(5); - EXPECT_NE(null_inst, nullptr); - EXPECT_FALSE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(5); - EXPECT_NE(null_inst, nullptr); - EXPECT_TRUE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointers -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(5); - EXPECT_NE(null_inst, nullptr); - EXPECT_TRUE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpVariable %4 StorageBuffer -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %4 %5 %7 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* phi = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(phi, nullptr); - EXPECT_FALSE(phi->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpVariable %4 Workgroup -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %4 %5 %7 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* phi = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(phi, nullptr); - EXPECT_FALSE(phi->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpVariable %4 StorageBuffer -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %4 %5 %7 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* phi = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(phi, nullptr); - EXPECT_TRUE(phi->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointers -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpVariable %4 Workgroup -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %4 %5 %7 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* phi = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(phi, nullptr); - EXPECT_TRUE(phi->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%7 = OpTypeFunction %4 -%1 = OpFunction %2 None %6 -%8 = OpLabel -%9 = OpFunctionCall %4 %10 -OpReturn -OpFunctionEnd -%10 = OpFunction %4 None %7 -%11 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(null_inst, nullptr); - EXPECT_FALSE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%7 = OpTypeFunction %4 -%1 = OpFunction %2 None %6 -%8 = OpLabel -%9 = OpFunctionCall %4 %10 -OpReturn -OpFunctionEnd -%10 = OpFunction %4 None %7 -%11 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(null_inst, nullptr); - EXPECT_FALSE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointersStorageBuffer) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer StorageBuffer %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%7 = OpTypeFunction %4 -%1 = OpFunction %2 None %6 -%8 = OpLabel -%9 = OpFunctionCall %4 %10 -OpReturn -OpFunctionEnd -%10 = OpFunction %4 None %7 -%11 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(null_inst, nullptr); - EXPECT_TRUE(null_inst->IsValidBasePointer()); -} - -TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointers) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointers -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Workgroup %3 -%5 = OpConstantNull %4 -%6 = OpTypeFunction %2 -%7 = OpTypeFunction %4 -%1 = OpFunction %2 None %6 -%8 = OpLabel -%9 = OpFunctionCall %4 %10 -OpReturn -OpFunctionEnd -%10 = OpFunction %4 None %7 -%11 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text); - EXPECT_NE(context, nullptr); - Instruction* null_inst = context->get_def_use_mgr()->GetDef(9); - EXPECT_NE(null_inst, nullptr); - EXPECT_TRUE(null_inst->IsValidBasePointer()); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/ir_builder.cpp b/3rdparty/spirv-tools/test/opt/ir_builder.cpp deleted file mode 100644 index f800ca437..000000000 --- a/3rdparty/spirv-tools/test/opt/ir_builder.cpp +++ /dev/null @@ -1,439 +0,0 @@ -// Copyright (c) 2018 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 "effcee/effcee.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/basic_block.h" -#include "source/opt/build_module.h" -#include "source/opt/instruction.h" -#include "source/opt/ir_builder.h" -#include "source/opt/type_manager.h" -#include "spirv-tools/libspirv.hpp" - -namespace spvtools { -namespace opt { -namespace { - -using Analysis = IRContext::Analysis; -using IRBuilderTest = ::testing::Test; - -bool Validate(const std::vector& bin) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - spv_context spvContext = spvContextCreate(target_env); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {bin.data(), bin.size()}; - spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - return error == 0; -} - -void Match(const std::string& original, IRContext* context, - bool do_validation = true) { - std::vector bin; - context->module()->ToBinary(&bin, true); - if (do_validation) { - EXPECT_TRUE(Validate(bin)); - } - std::string assembly; - SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); - EXPECT_TRUE( - tools.Disassemble(bin, &assembly, SpirvTools::kDefaultDisassembleOption)) - << "Disassembling failed for shader:\n" - << assembly << std::endl; - auto match_result = effcee::Match(assembly, original); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking result:\n" - << assembly; -} - -TEST_F(IRBuilderTest, TestInsnAddition) { - const std::string text = R"( -; CHECK: %18 = OpLabel -; CHECK: OpPhi %int %int_0 %14 -; CHECK: OpPhi %bool %16 %14 -; CHECK: OpBranch %17 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - OpName %3 "c" - OpDecorate %3 Location 0 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeInt 32 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %10 = OpTypeBool - %11 = OpTypeFloat 32 - %12 = OpTypeVector %11 4 - %13 = OpTypePointer Output %12 - %3 = OpVariable %13 Output - %2 = OpFunction %5 None %6 - %14 = OpLabel - %4 = OpVariable %8 Function - OpStore %4 %9 - %15 = OpLoad %7 %4 - %16 = OpINotEqual %10 %15 %9 - OpSelectionMerge %17 None - OpBranchConditional %16 %18 %17 - %18 = OpLabel - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd -)"; - - { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - BasicBlock* bb = context->cfg()->block(18); - - // Build managers. - context->get_def_use_mgr(); - context->get_instr_block(nullptr); - - InstructionBuilder builder(context.get(), &*bb->begin()); - Instruction* phi1 = builder.AddPhi(7, {9, 14}); - Instruction* phi2 = builder.AddPhi(10, {16, 14}); - - // Make sure the InstructionBuilder did not update the def/use manager. - EXPECT_EQ(context->get_def_use_mgr()->GetDef(phi1->result_id()), nullptr); - EXPECT_EQ(context->get_def_use_mgr()->GetDef(phi2->result_id()), nullptr); - EXPECT_EQ(context->get_instr_block(phi1), nullptr); - EXPECT_EQ(context->get_instr_block(phi2), nullptr); - - Match(text, context.get()); - } - - { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - // Build managers. - context->get_def_use_mgr(); - context->get_instr_block(nullptr); - - BasicBlock* bb = context->cfg()->block(18); - InstructionBuilder builder( - context.get(), &*bb->begin(), - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - Instruction* phi1 = builder.AddPhi(7, {9, 14}); - Instruction* phi2 = builder.AddPhi(10, {16, 14}); - - // Make sure InstructionBuilder updated the def/use manager - EXPECT_NE(context->get_def_use_mgr()->GetDef(phi1->result_id()), nullptr); - EXPECT_NE(context->get_def_use_mgr()->GetDef(phi2->result_id()), nullptr); - EXPECT_NE(context->get_instr_block(phi1), nullptr); - EXPECT_NE(context->get_instr_block(phi2), nullptr); - - Match(text, context.get()); - } -} - -TEST_F(IRBuilderTest, TestCondBranchAddition) { - const std::string text = R"( -; CHECK: %main = OpFunction %void None %6 -; CHECK-NEXT: %15 = OpLabel -; CHECK-NEXT: OpSelectionMerge %13 None -; CHECK-NEXT: OpBranchConditional %true %14 %13 -; CHECK-NEXT: %14 = OpLabel -; CHECK-NEXT: OpBranch %13 -; CHECK-NEXT: %13 = OpLabel -; CHECK-NEXT: OpReturn - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - OpName %3 "c" - OpDecorate %3 Location 0 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeBool - %8 = OpTypePointer Private %7 - %9 = OpConstantTrue %7 - %10 = OpTypeFloat 32 - %11 = OpTypeVector %10 4 - %12 = OpTypePointer Output %11 - %3 = OpVariable %12 Output - %4 = OpVariable %8 Private - %2 = OpFunction %5 None %6 - %13 = OpLabel - OpReturn - OpFunctionEnd -)"; - - { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - Function& fn = *context->module()->begin(); - - BasicBlock& bb_merge = *fn.begin(); - - // TODO(1841): Handle id overflow. - fn.begin().InsertBefore(std::unique_ptr( - new BasicBlock(std::unique_ptr(new Instruction( - context.get(), SpvOpLabel, 0, context->TakeNextId(), {}))))); - BasicBlock& bb_true = *fn.begin(); - { - InstructionBuilder builder(context.get(), &*bb_true.begin()); - builder.AddBranch(bb_merge.id()); - } - - // TODO(1841): Handle id overflow. - fn.begin().InsertBefore(std::unique_ptr( - new BasicBlock(std::unique_ptr(new Instruction( - context.get(), SpvOpLabel, 0, context->TakeNextId(), {}))))); - BasicBlock& bb_cond = *fn.begin(); - - InstructionBuilder builder(context.get(), &bb_cond); - // This also test consecutive instruction insertion: merge selection + - // branch. - builder.AddConditionalBranch(9, bb_true.id(), bb_merge.id(), bb_merge.id()); - - Match(text, context.get()); - } -} - -TEST_F(IRBuilderTest, AddSelect) { - const std::string text = R"( -; CHECK: [[bool:%\w+]] = OpTypeBool -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[true:%\w+]] = OpConstantTrue [[bool]] -; CHECK: [[u0:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[u1:%\w+]] = OpConstant [[uint]] 1 -; CHECK: OpSelect [[uint]] [[true]] [[u0]] [[u1]] -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpTypeInt 32 0 -%4 = OpConstantTrue %2 -%5 = OpConstant %3 0 -%6 = OpConstant %3 1 -%7 = OpTypeFunction %1 -%8 = OpFunction %1 None %7 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(nullptr, context); - - InstructionBuilder builder(context.get(), - &*context->module()->begin()->begin()->begin()); - EXPECT_NE(nullptr, builder.AddSelect(3u, 4u, 5u, 6u)); - - Match(text, context.get()); -} - -TEST_F(IRBuilderTest, AddCompositeConstruct) { - const std::string text = R"( -; CHECK: [[uint:%\w+]] = OpTypeInt -; CHECK: [[u0:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[u1:%\w+]] = OpConstant [[uint]] 1 -; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]] [[uint]] [[uint]] [[uint]] -; CHECK: OpCompositeConstruct [[struct]] [[u0]] [[u1]] [[u1]] [[u0]] -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpConstant %2 1 -%5 = OpTypeStruct %2 %2 %2 %2 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(nullptr, context); - - InstructionBuilder builder(context.get(), - &*context->module()->begin()->begin()->begin()); - std::vector ids = {3u, 4u, 4u, 3u}; - EXPECT_NE(nullptr, builder.AddCompositeConstruct(5u, ids)); - - Match(text, context.get()); -} - -TEST_F(IRBuilderTest, ConstantAdder) { - const std::string text = R"( -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: OpConstant [[uint]] 13 -; CHECK: [[sint:%\w+]] = OpTypeInt 32 1 -; CHECK: OpConstant [[sint]] -1 -; CHECK: OpConstant [[uint]] 1 -; CHECK: OpConstant [[sint]] 34 -; CHECK: OpConstant [[uint]] 0 -; CHECK: OpConstant [[sint]] 0 -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(nullptr, context); - - InstructionBuilder builder(context.get(), - &*context->module()->begin()->begin()->begin()); - EXPECT_NE(nullptr, builder.GetUintConstant(13)); - EXPECT_NE(nullptr, builder.GetSintConstant(-1)); - - // Try adding the same constants again to make sure they aren't added. - EXPECT_NE(nullptr, builder.GetUintConstant(13)); - EXPECT_NE(nullptr, builder.GetSintConstant(-1)); - - // Try adding different constants to make sure the type is reused. - EXPECT_NE(nullptr, builder.GetUintConstant(1)); - EXPECT_NE(nullptr, builder.GetSintConstant(34)); - - // Try adding 0 as both signed and unsigned. - EXPECT_NE(nullptr, builder.GetUintConstant(0)); - EXPECT_NE(nullptr, builder.GetSintConstant(0)); - - Match(text, context.get()); -} - -TEST_F(IRBuilderTest, ConstantAdderTypeAlreadyExists) { - const std::string text = R"( -; CHECK: OpConstant %uint 13 -; CHECK: OpConstant %int -1 -; CHECK: OpConstant %uint 1 -; CHECK: OpConstant %int 34 -; CHECK: OpConstant %uint 0 -; CHECK: OpConstant %int 0 -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%uint = OpTypeInt 32 0 -%int = OpTypeInt 32 1 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(nullptr, context); - - InstructionBuilder builder(context.get(), - &*context->module()->begin()->begin()->begin()); - Instruction* const_1 = builder.GetUintConstant(13); - Instruction* const_2 = builder.GetSintConstant(-1); - - EXPECT_NE(nullptr, const_1); - EXPECT_NE(nullptr, const_2); - - // Try adding the same constants again to make sure they aren't added. - EXPECT_EQ(const_1, builder.GetUintConstant(13)); - EXPECT_EQ(const_2, builder.GetSintConstant(-1)); - - Instruction* const_3 = builder.GetUintConstant(1); - Instruction* const_4 = builder.GetSintConstant(34); - - // Try adding different constants to make sure the type is reused. - EXPECT_NE(nullptr, const_3); - EXPECT_NE(nullptr, const_4); - - Instruction* const_5 = builder.GetUintConstant(0); - Instruction* const_6 = builder.GetSintConstant(0); - - // Try adding 0 as both signed and unsigned. - EXPECT_NE(nullptr, const_5); - EXPECT_NE(nullptr, const_6); - - // They have the same value but different types so should be unique. - EXPECT_NE(const_5, const_6); - - // Check the types are correct. - uint32_t type_id_unsigned = const_1->GetSingleWordOperand(0); - uint32_t type_id_signed = const_2->GetSingleWordOperand(0); - - EXPECT_NE(type_id_unsigned, type_id_signed); - - EXPECT_EQ(const_3->GetSingleWordOperand(0), type_id_unsigned); - EXPECT_EQ(const_5->GetSingleWordOperand(0), type_id_unsigned); - - EXPECT_EQ(const_4->GetSingleWordOperand(0), type_id_signed); - EXPECT_EQ(const_6->GetSingleWordOperand(0), type_id_signed); - - Match(text, context.get()); -} - -TEST_F(IRBuilderTest, AccelerationStructureNV) { - const std::string text = R"( -; CHECK: OpTypeAccelerationStructureNV -OpCapability Shader -OpCapability RayTracingNV -OpExtension "SPV_NV_ray_tracing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %8 "main" -OpExecutionMode %8 OriginUpperLeft -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpTypeAccelerationStructureNV -%7 = OpTypeFunction %1 -%8 = OpFunction %1 None %7 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(nullptr, context); - - InstructionBuilder builder(context.get(), - &*context->module()->begin()->begin()->begin()); - Match(text, context.get()); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/ir_context_test.cpp b/3rdparty/spirv-tools/test/opt/ir_context_test.cpp deleted file mode 100644 index d5710fc46..000000000 --- a/3rdparty/spirv-tools/test/opt/ir_context_test.cpp +++ /dev/null @@ -1,754 +0,0 @@ -// Copyright (c) 2017 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 "source/opt/ir_context.h" - -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/pass.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using Analysis = IRContext::Analysis; -using ::testing::Each; -using ::testing::UnorderedElementsAre; - -class DummyPassPreservesNothing : public Pass { - public: - DummyPassPreservesNothing(Status s) : Pass(), status_to_return_(s) {} - - const char* name() const override { return "dummy-pass"; } - Status Process() override { return status_to_return_; } - - private: - Status status_to_return_; -}; - -class DummyPassPreservesAll : public Pass { - public: - DummyPassPreservesAll(Status s) : Pass(), status_to_return_(s) {} - - const char* name() const override { return "dummy-pass"; } - Status Process() override { return status_to_return_; } - - Analysis GetPreservedAnalyses() override { - return Analysis(IRContext::kAnalysisEnd - 1); - } - - private: - Status status_to_return_; -}; - -class DummyPassPreservesFirst : public Pass { - public: - DummyPassPreservesFirst(Status s) : Pass(), status_to_return_(s) {} - - const char* name() const override { return "dummy-pass"; } - Status Process() override { return status_to_return_; } - - Analysis GetPreservedAnalyses() override { return IRContext::kAnalysisBegin; } - - private: - Status status_to_return_; -}; - -using IRContextTest = PassTest<::testing::Test>; - -TEST_F(IRContextTest, IndividualValidAfterBuild) { - std::unique_ptr module(new Module()); - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module), - spvtools::MessageConsumer()); - - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - localContext.BuildInvalidAnalyses(i); - EXPECT_TRUE(localContext.AreAnalysesValid(i)); - } -} - -TEST_F(IRContextTest, AllValidAfterBuild) { - std::unique_ptr module = MakeUnique(); - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module), - spvtools::MessageConsumer()); - - Analysis built_analyses = IRContext::kAnalysisNone; - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - localContext.BuildInvalidAnalyses(i); - built_analyses |= i; - } - EXPECT_TRUE(localContext.AreAnalysesValid(built_analyses)); -} - -TEST_F(IRContextTest, AllValidAfterPassNoChange) { - std::unique_ptr module = MakeUnique(); - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module), - spvtools::MessageConsumer()); - - Analysis built_analyses = IRContext::kAnalysisNone; - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - localContext.BuildInvalidAnalyses(i); - built_analyses |= i; - } - - DummyPassPreservesNothing pass(Pass::Status::SuccessWithoutChange); - Pass::Status s = pass.Run(&localContext); - EXPECT_EQ(s, Pass::Status::SuccessWithoutChange); - EXPECT_TRUE(localContext.AreAnalysesValid(built_analyses)); -} - -TEST_F(IRContextTest, NoneValidAfterPassWithChange) { - std::unique_ptr module = MakeUnique(); - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module), - spvtools::MessageConsumer()); - - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - localContext.BuildInvalidAnalyses(i); - } - - DummyPassPreservesNothing pass(Pass::Status::SuccessWithChange); - Pass::Status s = pass.Run(&localContext); - EXPECT_EQ(s, Pass::Status::SuccessWithChange); - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - EXPECT_FALSE(localContext.AreAnalysesValid(i)); - } -} - -TEST_F(IRContextTest, AllPreservedAfterPassWithChange) { - std::unique_ptr module = MakeUnique(); - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module), - spvtools::MessageConsumer()); - - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - localContext.BuildInvalidAnalyses(i); - } - - DummyPassPreservesAll pass(Pass::Status::SuccessWithChange); - Pass::Status s = pass.Run(&localContext); - EXPECT_EQ(s, Pass::Status::SuccessWithChange); - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - EXPECT_TRUE(localContext.AreAnalysesValid(i)); - } -} - -TEST_F(IRContextTest, PreserveFirstOnlyAfterPassWithChange) { - std::unique_ptr module = MakeUnique(); - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module), - spvtools::MessageConsumer()); - - for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd; - i <<= 1) { - localContext.BuildInvalidAnalyses(i); - } - - DummyPassPreservesFirst pass(Pass::Status::SuccessWithChange); - Pass::Status s = pass.Run(&localContext); - EXPECT_EQ(s, Pass::Status::SuccessWithChange); - EXPECT_TRUE(localContext.AreAnalysesValid(IRContext::kAnalysisBegin)); - for (Analysis i = IRContext::kAnalysisBegin << 1; i < IRContext::kAnalysisEnd; - i <<= 1) { - EXPECT_FALSE(localContext.AreAnalysesValid(i)); - } -} - -TEST_F(IRContextTest, KillMemberName) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %3 "stuff" - OpMemberName %3 0 "refZ" - OpMemberDecorate %3 0 Offset 0 - OpDecorate %3 Block - %4 = OpTypeFloat 32 - %3 = OpTypeStruct %4 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %2 = OpFunction %5 None %6 - %7 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - // Build the decoration manager. - context->get_decoration_mgr(); - - // Delete the OpTypeStruct. Should delete the OpName, OpMemberName, and - // OpMemberDecorate associated with it. - context->KillDef(3); - - // Make sure all of the name are removed. - for (auto& inst : context->debugs2()) { - EXPECT_EQ(inst.opcode(), SpvOpNop); - } - - // Make sure all of the decorations are removed. - for (auto& inst : context->annotations()) { - EXPECT_EQ(inst.opcode(), SpvOpNop); - } -} - -TEST_F(IRContextTest, KillGroupDecoration) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpDecorate %3 Restrict - %3 = OpDecorationGroup - OpGroupDecorate %3 %4 %5 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %8 = OpTypeStruct %6 - %9 = OpTypeVoid - %10 = OpTypeFunction %9 - %2 = OpFunction %9 None %10 - %11 = OpLabel - %4 = OpVariable %7 Function - %5 = OpVariable %7 Function - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - // Build the decoration manager. - context->get_decoration_mgr(); - - // Delete the second variable. - context->KillDef(5); - - // The three decorations instructions should still be there. The first two - // should be the same, but the third should have %5 removed. - - // Check the OpDecorate instruction - auto inst = context->annotation_begin(); - EXPECT_EQ(inst->opcode(), SpvOpDecorate); - EXPECT_EQ(inst->GetSingleWordInOperand(0), 3); - - // Check the OpDecorationGroup Instruction - ++inst; - EXPECT_EQ(inst->opcode(), SpvOpDecorationGroup); - EXPECT_EQ(inst->result_id(), 3); - - // Check that %5 is no longer part of the group. - ++inst; - EXPECT_EQ(inst->opcode(), SpvOpGroupDecorate); - EXPECT_EQ(inst->NumInOperands(), 2); - EXPECT_EQ(inst->GetSingleWordInOperand(0), 3); - EXPECT_EQ(inst->GetSingleWordInOperand(1), 4); - - // Check that we are at the end. - ++inst; - EXPECT_EQ(inst, context->annotation_end()); -} - -TEST_F(IRContextTest, TakeNextUniqueIdIncrementing) { - const uint32_t NUM_TESTS = 1000; - IRContext localContext(SPV_ENV_UNIVERSAL_1_2, nullptr); - for (uint32_t i = 1; i < NUM_TESTS; ++i) - EXPECT_EQ(i, localContext.TakeNextUniqueId()); -} - -TEST_F(IRContextTest, KillGroupDecorationWitNoDecorations) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpDecorationGroup - OpGroupDecorate %3 %4 %5 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %8 = OpTypeStruct %6 - %9 = OpTypeVoid - %10 = OpTypeFunction %9 - %2 = OpFunction %9 None %10 - %11 = OpLabel - %4 = OpVariable %7 Function - %5 = OpVariable %7 Function - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - // Build the decoration manager. - context->get_decoration_mgr(); - - // Delete the second variable. - context->KillDef(5); - - // The two decoration instructions should still be there. The first one - // should be the same, but the second should have %5 removed. - - // Check the OpDecorationGroup Instruction - auto inst = context->annotation_begin(); - EXPECT_EQ(inst->opcode(), SpvOpDecorationGroup); - EXPECT_EQ(inst->result_id(), 3); - - // Check that %5 is no longer part of the group. - ++inst; - EXPECT_EQ(inst->opcode(), SpvOpGroupDecorate); - EXPECT_EQ(inst->NumInOperands(), 2); - EXPECT_EQ(inst->GetSingleWordInOperand(0), 3); - EXPECT_EQ(inst->GetSingleWordInOperand(1), 4); - - // Check that we are at the end. - ++inst; - EXPECT_EQ(inst, context->annotation_end()); -} - -TEST_F(IRContextTest, KillDecorationGroup) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpDecorationGroup - OpGroupDecorate %3 %4 %5 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %8 = OpTypeStruct %6 - %9 = OpTypeVoid - %10 = OpTypeFunction %9 - %2 = OpFunction %9 None %10 - %11 = OpLabel - %4 = OpVariable %7 Function - %5 = OpVariable %7 Function - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - - // Build the decoration manager. - context->get_decoration_mgr(); - - // Delete the second variable. - context->KillDef(3); - - // Check the OpDecorationGroup Instruction is still there. - EXPECT_TRUE(context->annotations().empty()); -} - -TEST_F(IRContextTest, BasicVisitFromEntryPoint) { - // Make sure we visit the entry point, and the function it calls. - // Do not visit Dead or Exported. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %10 "main" - OpName %10 "main" - OpName %Dead "Dead" - OpName %11 "Constant" - OpName %ExportedFunc "ExportedFunc" - OpDecorate %ExportedFunc LinkageAttributes "ExportedFunc" Export - %void = OpTypeVoid - %6 = OpTypeFunction %void - %10 = OpFunction %void None %6 - %14 = OpLabel - %15 = OpFunctionCall %void %11 - %16 = OpFunctionCall %void %11 - OpReturn - OpFunctionEnd - %11 = OpFunction %void None %6 - %18 = OpLabel - OpReturn - OpFunctionEnd - %Dead = OpFunction %void None %6 - %19 = OpLabel - OpReturn - OpFunctionEnd -%ExportedFunc = OpFunction %void None %7 - %20 = OpLabel - %21 = OpFunctionCall %void %11 - OpReturn - OpFunctionEnd -)"; - // clang-format on - - std::unique_ptr localContext = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n" - << text << std::endl; - std::vector processed; - Pass::ProcessFunction mark_visited = [&processed](Function* fp) { - processed.push_back(fp->result_id()); - return false; - }; - localContext->ProcessEntryPointCallTree(mark_visited); - EXPECT_THAT(processed, UnorderedElementsAre(10, 11)); -} - -TEST_F(IRContextTest, BasicVisitReachable) { - // Make sure we visit the entry point, exported function, and the function - // they call. Do not visit Dead. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %10 "main" - OpName %10 "main" - OpName %Dead "Dead" - OpName %11 "Constant" - OpName %12 "ExportedFunc" - OpName %13 "Constant2" - OpDecorate %12 LinkageAttributes "ExportedFunc" Export - %void = OpTypeVoid - %6 = OpTypeFunction %void - %10 = OpFunction %void None %6 - %14 = OpLabel - %15 = OpFunctionCall %void %11 - %16 = OpFunctionCall %void %11 - OpReturn - OpFunctionEnd - %11 = OpFunction %void None %6 - %18 = OpLabel - OpReturn - OpFunctionEnd - %Dead = OpFunction %void None %6 - %19 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %void None %6 - %20 = OpLabel - %21 = OpFunctionCall %void %13 - OpReturn - OpFunctionEnd - %13 = OpFunction %void None %6 - %22 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - - std::unique_ptr localContext = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n" - << text << std::endl; - - std::vector processed; - Pass::ProcessFunction mark_visited = [&processed](Function* fp) { - processed.push_back(fp->result_id()); - return false; - }; - localContext->ProcessReachableCallTree(mark_visited); - EXPECT_THAT(processed, UnorderedElementsAre(10, 11, 12, 13)); -} - -TEST_F(IRContextTest, BasicVisitOnlyOnce) { - // Make sure we visit %12 only once, even if it is called from two different - // functions. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %10 "main" - OpName %10 "main" - OpName %Dead "Dead" - OpName %11 "Constant" - OpName %12 "ExportedFunc" - OpDecorate %12 LinkageAttributes "ExportedFunc" Export - %void = OpTypeVoid - %6 = OpTypeFunction %void - %10 = OpFunction %void None %6 - %14 = OpLabel - %15 = OpFunctionCall %void %11 - %16 = OpFunctionCall %void %12 - OpReturn - OpFunctionEnd - %11 = OpFunction %void None %6 - %18 = OpLabel - %19 = OpFunctionCall %void %12 - OpReturn - OpFunctionEnd - %Dead = OpFunction %void None %6 - %20 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %void None %6 - %21 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - - std::unique_ptr localContext = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n" - << text << std::endl; - - std::vector processed; - Pass::ProcessFunction mark_visited = [&processed](Function* fp) { - processed.push_back(fp->result_id()); - return false; - }; - localContext->ProcessReachableCallTree(mark_visited); - EXPECT_THAT(processed, UnorderedElementsAre(10, 11, 12)); -} - -TEST_F(IRContextTest, BasicDontVisitExportedVariable) { - // Make sure we only visit functions and not exported variables. - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %10 "main" - OpExecutionMode %10 OriginUpperLeft - OpSource GLSL 150 - OpName %10 "main" - OpName %12 "export_var" - OpDecorate %12 LinkageAttributes "export_var" Export - %void = OpTypeVoid - %6 = OpTypeFunction %void - %float = OpTypeFloat 32 - %float_1 = OpConstant %float 1 - %12 = OpVariable %float Output - %10 = OpFunction %void None %6 - %14 = OpLabel - OpStore %12 %float_1 - OpReturn - OpFunctionEnd -)"; - // clang-format on - - std::unique_ptr localContext = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n" - << text << std::endl; - - std::vector processed; - Pass::ProcessFunction mark_visited = [&processed](Function* fp) { - processed.push_back(fp->result_id()); - return false; - }; - localContext->ProcessReachableCallTree(mark_visited); - EXPECT_THAT(processed, UnorderedElementsAre(10)); -} - -TEST_F(IRContextTest, IdBoundTestAtLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound); - uint32_t next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, 0); - EXPECT_EQ(current_bound, context->module()->id_bound()); - next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, 0); -} - -TEST_F(IRContextTest, IdBoundTestBelowLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound + 100); - uint32_t next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, current_bound); - EXPECT_EQ(current_bound + 1, context->module()->id_bound()); - next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, current_bound + 1); -} - -TEST_F(IRContextTest, IdBoundTestNearLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound + 1); - uint32_t next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, current_bound); - EXPECT_EQ(current_bound + 1, context->module()->id_bound()); - next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, 0); -} - -TEST_F(IRContextTest, IdBoundTestUIntMax) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4294967294 = OpLabel ; ID is UINT_MAX-1 -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - uint32_t current_bound = context->module()->id_bound(); - - // Expecting |BuildModule| to preserve the numeric ids. - EXPECT_EQ(current_bound, std::numeric_limits::max()); - - context->set_max_id_bound(current_bound); - uint32_t next_id_bound = context->TakeNextId(); - EXPECT_EQ(next_id_bound, 0); - EXPECT_EQ(current_bound, context->module()->id_bound()); -} - -TEST_F(IRContextTest, CfgAndDomAnalysis) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr ctx = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - // Building the dominator analysis should build the CFG. - ASSERT_TRUE(ctx->module()->begin() != ctx->module()->end()); - ctx->GetDominatorAnalysis(&*ctx->module()->begin()); - - EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisCFG)); - EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDominatorAnalysis)); - - // Invalidating the CFG analysis should invalidate the dominator analysis. - ctx->InvalidateAnalyses(IRContext::kAnalysisCFG); - EXPECT_FALSE(ctx->AreAnalysesValid(IRContext::kAnalysisCFG)); - EXPECT_FALSE(ctx->AreAnalysesValid(IRContext::kAnalysisDominatorAnalysis)); -} - -TEST_F(IRContextTest, AsanErrorTest) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - OpDecorate %8 RelaxedPrecision - OpDecorate %10 RelaxedPrecision - OpDecorate %11 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpBranch %20 - %20 = OpLabel - %21 = OpPhi %6 %11 %5 - OpStore %10 %21 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = BuildModule( - env, consumer, shader, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - opt::Function* fun = - context->cfg()->block(5)->GetParent(); // Computes the CFG analysis - opt::DominatorAnalysis* dom = nullptr; - dom = context->GetDominatorAnalysis(fun); // Computes the dominator analysis, - // which depends on the CFG - // analysis - context->InvalidateAnalysesExceptFor( - opt::IRContext::Analysis::kAnalysisDominatorAnalysis); // Invalidates the - // CFG analysis - dom = context->GetDominatorAnalysis( - fun); // Recompute the CFG analysis because the Dominator tree uses it. - auto bb = dom->ImmediateDominator(5); - std::cout - << bb->id(); // Make sure asan does not complain about use after free. -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/ir_loader_test.cpp b/3rdparty/spirv-tools/test/opt/ir_loader_test.cpp deleted file mode 100644 index ac5c52075..000000000 --- a/3rdparty/spirv-tools/test/opt/ir_loader_test.cpp +++ /dev/null @@ -1,451 +0,0 @@ -// 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 - -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/ir_context.h" -#include "spirv-tools/libspirv.hpp" - -namespace spvtools { -namespace opt { -namespace { - -void DoRoundTripCheck(const std::string& text) { - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - ASSERT_NE(nullptr, context) << "Failed to assemble\n" << text; - - std::vector binary; - context->module()->ToBinary(&binary, /* skip_nop = */ false); - - std::string disassembled_text; - EXPECT_TRUE(t.Disassemble(binary, &disassembled_text)); - EXPECT_EQ(text, disassembled_text); -} - -TEST(IrBuilder, RoundTrip) { - // #version 310 es - // int add(int a, int b) { return a + b; } - // void main() { add(1, 2); } - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "%1 = OpExtInstImport \"GLSL.std.450\"\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\"\n" - "OpSource ESSL 310\n" - "OpSourceExtension \"GL_GOOGLE_cpp_style_line_directive\"\n" - "OpSourceExtension \"GL_GOOGLE_include_directive\"\n" - "OpName %main \"main\"\n" - "OpName %add_i1_i1_ \"add(i1;i1;\"\n" - "OpName %a \"a\"\n" - "OpName %b \"b\"\n" - "OpName %param \"param\"\n" - "OpName %param_0 \"param\"\n" - "%void = OpTypeVoid\n" - "%9 = OpTypeFunction %void\n" - "%int = OpTypeInt 32 1\n" - "%_ptr_Function_int = OpTypePointer Function %int\n" - "%12 = OpTypeFunction %int %_ptr_Function_int %_ptr_Function_int\n" - "%int_1 = OpConstant %int 1\n" - "%int_2 = OpConstant %int 2\n" - "%main = OpFunction %void None %9\n" - "%15 = OpLabel\n" - "%param = OpVariable %_ptr_Function_int Function\n" - "%param_0 = OpVariable %_ptr_Function_int Function\n" - "OpStore %param %int_1\n" - "OpStore %param_0 %int_2\n" - "%16 = OpFunctionCall %int %add_i1_i1_ %param %param_0\n" - "OpReturn\n" - "OpFunctionEnd\n" - "%add_i1_i1_ = OpFunction %int None %12\n" - "%a = OpFunctionParameter %_ptr_Function_int\n" - "%b = OpFunctionParameter %_ptr_Function_int\n" - "%17 = OpLabel\n" - "%18 = OpLoad %int %a\n" - "%19 = OpLoad %int %b\n" - "%20 = OpIAdd %int %18 %19\n" - "OpReturnValue %20\n" - "OpFunctionEnd\n"); - // clang-format on -} - -TEST(IrBuilder, RoundTripIncompleteBasicBlock) { - DoRoundTripCheck( - "%2 = OpFunction %1 None %3\n" - "%4 = OpLabel\n" - "OpNop\n"); -} - -TEST(IrBuilder, RoundTripIncompleteFunction) { - DoRoundTripCheck("%2 = OpFunction %1 None %3\n"); -} - -TEST(IrBuilder, KeepLineDebugInfo) { - // #version 310 es - // void main() {} - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "%1 = OpExtInstImport \"GLSL.std.450\"\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\"\n" - "%3 = OpString \"minimal.vert\"\n" - "OpSource ESSL 310\n" - "OpName %main \"main\"\n" - "OpLine %3 10 10\n" - "%void = OpTypeVoid\n" - "OpLine %3 100 100\n" - "%5 = OpTypeFunction %void\n" - "%main = OpFunction %void None %5\n" - "OpLine %3 1 1\n" - "OpNoLine\n" - "OpLine %3 2 2\n" - "OpLine %3 3 3\n" - "%6 = OpLabel\n" - "OpLine %3 4 4\n" - "OpNoLine\n" - "OpReturn\n" - "OpFunctionEnd\n"); - // clang-format on -} - -TEST(IrBuilder, LocalGlobalVariables) { - // #version 310 es - // - // float gv1 = 10.; - // float gv2 = 100.; - // - // float f() { - // float lv1 = gv1 + gv2; - // float lv2 = gv1 * gv2; - // return lv1 / lv2; - // } - // - // void main() { - // float lv1 = gv1 - gv2; - // } - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "%1 = OpExtInstImport \"GLSL.std.450\"\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\"\n" - "OpSource ESSL 310\n" - "OpName %main \"main\"\n" - "OpName %f_ \"f(\"\n" - "OpName %gv1 \"gv1\"\n" - "OpName %gv2 \"gv2\"\n" - "OpName %lv1 \"lv1\"\n" - "OpName %lv2 \"lv2\"\n" - "OpName %lv1_0 \"lv1\"\n" - "%void = OpTypeVoid\n" - "%10 = OpTypeFunction %void\n" - "%float = OpTypeFloat 32\n" - "%12 = OpTypeFunction %float\n" - "%_ptr_Private_float = OpTypePointer Private %float\n" - "%gv1 = OpVariable %_ptr_Private_float Private\n" - "%float_10 = OpConstant %float 10\n" - "%gv2 = OpVariable %_ptr_Private_float Private\n" - "%float_100 = OpConstant %float 100\n" - "%_ptr_Function_float = OpTypePointer Function %float\n" - "%main = OpFunction %void None %10\n" - "%17 = OpLabel\n" - "%lv1_0 = OpVariable %_ptr_Function_float Function\n" - "OpStore %gv1 %float_10\n" - "OpStore %gv2 %float_100\n" - "%18 = OpLoad %float %gv1\n" - "%19 = OpLoad %float %gv2\n" - "%20 = OpFSub %float %18 %19\n" - "OpStore %lv1_0 %20\n" - "OpReturn\n" - "OpFunctionEnd\n" - "%f_ = OpFunction %float None %12\n" - "%21 = OpLabel\n" - "%lv1 = OpVariable %_ptr_Function_float Function\n" - "%lv2 = OpVariable %_ptr_Function_float Function\n" - "%22 = OpLoad %float %gv1\n" - "%23 = OpLoad %float %gv2\n" - "%24 = OpFAdd %float %22 %23\n" - "OpStore %lv1 %24\n" - "%25 = OpLoad %float %gv1\n" - "%26 = OpLoad %float %gv2\n" - "%27 = OpFMul %float %25 %26\n" - "OpStore %lv2 %27\n" - "%28 = OpLoad %float %lv1\n" - "%29 = OpLoad %float %lv2\n" - "%30 = OpFDiv %float %28 %29\n" - "OpReturnValue %30\n" - "OpFunctionEnd\n"); - // clang-format on -} - -TEST(IrBuilder, OpUndefOutsideFunction) { - // #version 310 es - // void main() {} - const std::string text = - // clang-format off - "OpMemoryModel Logical GLSL450\n" - "%int = OpTypeInt 32 1\n" - "%uint = OpTypeInt 32 0\n" - "%float = OpTypeFloat 32\n" - "%4 = OpUndef %int\n" - "%int_10 = OpConstant %int 10\n" - "%6 = OpUndef %uint\n" - "%bool = OpTypeBool\n" - "%8 = OpUndef %float\n" - "%double = OpTypeFloat 64\n"; - // clang-format on - - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - ASSERT_NE(nullptr, context); - - const auto opundef_count = std::count_if( - context->module()->types_values_begin(), - context->module()->types_values_end(), - [](const Instruction& inst) { return inst.opcode() == SpvOpUndef; }); - EXPECT_EQ(3, opundef_count); - - std::vector binary; - context->module()->ToBinary(&binary, /* skip_nop = */ false); - - std::string disassembled_text; - EXPECT_TRUE(t.Disassemble(binary, &disassembled_text)); - EXPECT_EQ(text, disassembled_text); -} - -TEST(IrBuilder, OpUndefInBasicBlock) { - DoRoundTripCheck( - // clang-format off - "OpMemoryModel Logical GLSL450\n" - "OpName %main \"main\"\n" - "%void = OpTypeVoid\n" - "%uint = OpTypeInt 32 0\n" - "%double = OpTypeFloat 64\n" - "%5 = OpTypeFunction %void\n" - "%main = OpFunction %void None %5\n" - "%6 = OpLabel\n" - "%7 = OpUndef %uint\n" - "%8 = OpUndef %double\n" - "OpReturn\n" - "OpFunctionEnd\n"); - // clang-format on -} - -TEST(IrBuilder, KeepLineDebugInfoBeforeType) { - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "%1 = OpString \"minimal.vert\"\n" - "OpLine %1 1 1\n" - "OpNoLine\n" - "%void = OpTypeVoid\n" - "OpLine %1 2 2\n" - "%3 = OpTypeFunction %void\n"); - // clang-format on -} - -TEST(IrBuilder, KeepLineDebugInfoBeforeLabel) { - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "%1 = OpString \"minimal.vert\"\n" - "%void = OpTypeVoid\n" - "%3 = OpTypeFunction %void\n" - "%4 = OpFunction %void None %3\n" - "%5 = OpLabel\n" - "OpBranch %6\n" - "OpLine %1 1 1\n" - "OpLine %1 2 2\n" - "%6 = OpLabel\n" - "OpBranch %7\n" - "OpLine %1 100 100\n" - "%7 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n"); - // clang-format on -} - -TEST(IrBuilder, KeepLineDebugInfoBeforeFunctionEnd) { - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "%1 = OpString \"minimal.vert\"\n" - "%void = OpTypeVoid\n" - "%3 = OpTypeFunction %void\n" - "%4 = OpFunction %void None %3\n" - "OpLine %1 1 1\n" - "OpLine %1 2 2\n" - "OpFunctionEnd\n"); - // clang-format on -} - -TEST(IrBuilder, KeepModuleProcessedInRightPlace) { - DoRoundTripCheck( - // clang-format off - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "%1 = OpString \"minimal.vert\"\n" - "OpName %void \"void\"\n" - "OpModuleProcessed \"Made it faster\"\n" - "OpModuleProcessed \".. and smaller\"\n" - "%void = OpTypeVoid\n"); - // clang-format on -} - -// Checks the given |error_message| is reported when trying to build a module -// from the given |assembly|. -void DoErrorMessageCheck(const std::string& assembly, - const std::string& error_message, uint32_t line_num) { - auto consumer = [error_message, line_num](spv_message_level_t, const char*, - const spv_position_t& position, - const char* m) { - EXPECT_EQ(error_message, m); - EXPECT_EQ(line_num, position.line); - }; - - SpirvTools t(SPV_ENV_UNIVERSAL_1_1); - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, std::move(consumer), assembly); - EXPECT_EQ(nullptr, context); -} - -TEST(IrBuilder, FunctionInsideFunction) { - DoErrorMessageCheck("%2 = OpFunction %1 None %3\n%5 = OpFunction %4 None %6", - "function inside function", 2); -} - -TEST(IrBuilder, MismatchOpFunctionEnd) { - DoErrorMessageCheck("OpFunctionEnd", - "OpFunctionEnd without corresponding OpFunction", 1); -} - -TEST(IrBuilder, OpFunctionEndInsideBasicBlock) { - DoErrorMessageCheck( - "%2 = OpFunction %1 None %3\n" - "%4 = OpLabel\n" - "OpFunctionEnd", - "OpFunctionEnd inside basic block", 3); -} - -TEST(IrBuilder, BasicBlockOutsideFunction) { - DoErrorMessageCheck("OpCapability Shader\n%1 = OpLabel", - "OpLabel outside function", 2); -} - -TEST(IrBuilder, OpLabelInsideBasicBlock) { - DoErrorMessageCheck( - "%2 = OpFunction %1 None %3\n" - "%4 = OpLabel\n" - "%5 = OpLabel", - "OpLabel inside basic block", 3); -} - -TEST(IrBuilder, TerminatorOutsideFunction) { - DoErrorMessageCheck("OpReturn", "terminator instruction outside function", 1); -} - -TEST(IrBuilder, TerminatorOutsideBasicBlock) { - DoErrorMessageCheck("%2 = OpFunction %1 None %3\nOpReturn", - "terminator instruction outside basic block", 2); -} - -TEST(IrBuilder, NotAllowedInstAppearingInFunction) { - DoErrorMessageCheck("%2 = OpFunction %1 None %3\n%5 = OpVariable %4 Function", - "Non-OpFunctionParameter (opcode: 59) found inside " - "function but outside basic block", - 2); -} - -TEST(IrBuilder, UniqueIds) { - const std::string text = - // clang-format off - "OpCapability Shader\n" - "%1 = OpExtInstImport \"GLSL.std.450\"\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\"\n" - "OpSource ESSL 310\n" - "OpName %main \"main\"\n" - "OpName %f_ \"f(\"\n" - "OpName %gv1 \"gv1\"\n" - "OpName %gv2 \"gv2\"\n" - "OpName %lv1 \"lv1\"\n" - "OpName %lv2 \"lv2\"\n" - "OpName %lv1_0 \"lv1\"\n" - "%void = OpTypeVoid\n" - "%10 = OpTypeFunction %void\n" - "%float = OpTypeFloat 32\n" - "%12 = OpTypeFunction %float\n" - "%_ptr_Private_float = OpTypePointer Private %float\n" - "%gv1 = OpVariable %_ptr_Private_float Private\n" - "%float_10 = OpConstant %float 10\n" - "%gv2 = OpVariable %_ptr_Private_float Private\n" - "%float_100 = OpConstant %float 100\n" - "%_ptr_Function_float = OpTypePointer Function %float\n" - "%main = OpFunction %void None %10\n" - "%17 = OpLabel\n" - "%lv1_0 = OpVariable %_ptr_Function_float Function\n" - "OpStore %gv1 %float_10\n" - "OpStore %gv2 %float_100\n" - "%18 = OpLoad %float %gv1\n" - "%19 = OpLoad %float %gv2\n" - "%20 = OpFSub %float %18 %19\n" - "OpStore %lv1_0 %20\n" - "OpReturn\n" - "OpFunctionEnd\n" - "%f_ = OpFunction %float None %12\n" - "%21 = OpLabel\n" - "%lv1 = OpVariable %_ptr_Function_float Function\n" - "%lv2 = OpVariable %_ptr_Function_float Function\n" - "%22 = OpLoad %float %gv1\n" - "%23 = OpLoad %float %gv2\n" - "%24 = OpFAdd %float %22 %23\n" - "OpStore %lv1 %24\n" - "%25 = OpLoad %float %gv1\n" - "%26 = OpLoad %float %gv2\n" - "%27 = OpFMul %float %25 %26\n" - "OpStore %lv2 %27\n" - "%28 = OpLoad %float %lv1\n" - "%29 = OpLoad %float %lv2\n" - "%30 = OpFDiv %float %28 %29\n" - "OpReturnValue %30\n" - "OpFunctionEnd\n"; - // clang-format on - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - ASSERT_NE(nullptr, context); - - std::unordered_set ids; - context->module()->ForEachInst([&ids](const Instruction* inst) { - EXPECT_TRUE(ids.insert(inst->unique_id()).second); - }); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/iterator_test.cpp b/3rdparty/spirv-tools/test/opt/iterator_test.cpp deleted file mode 100644 index d61bc1ab8..000000000 --- a/3rdparty/spirv-tools/test/opt/iterator_test.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// 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 "gmock/gmock.h" - -#include "source/opt/iterator.h" -#include "source/util/make_unique.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::ContainerEq; - -TEST(Iterator, IncrementDeref) { - const int count = 100; - std::vector> data; - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - } - - UptrVectorIterator it(&data, data.begin()); - UptrVectorIterator end(&data, data.end()); - - EXPECT_EQ(*data[0], *it); - for (int i = 1; i < count; ++i) { - EXPECT_NE(end, it); - EXPECT_EQ(*data[i], *(++it)); - } - EXPECT_EQ(end, ++it); -} - -TEST(Iterator, DecrementDeref) { - const int count = 100; - std::vector> data; - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - } - - UptrVectorIterator begin(&data, data.begin()); - UptrVectorIterator it(&data, data.end()); - - for (int i = count - 1; i >= 0; --i) { - EXPECT_NE(begin, it); - EXPECT_EQ(*data[i], *(--it)); - } - EXPECT_EQ(begin, it); -} - -TEST(Iterator, PostIncrementDeref) { - const int count = 100; - std::vector> data; - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - } - - UptrVectorIterator it(&data, data.begin()); - UptrVectorIterator end(&data, data.end()); - - for (int i = 0; i < count; ++i) { - EXPECT_NE(end, it); - EXPECT_EQ(*data[i], *(it++)); - } - EXPECT_EQ(end, it); -} - -TEST(Iterator, PostDecrementDeref) { - const int count = 100; - std::vector> data; - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - } - - UptrVectorIterator begin(&data, data.begin()); - UptrVectorIterator end(&data, data.end()); - UptrVectorIterator it(&data, data.end()); - - EXPECT_EQ(end, it--); - for (int i = count - 1; i >= 1; --i) { - EXPECT_EQ(*data[i], *(it--)); - } - // Decrementing .begin() is undefined behavior. - EXPECT_EQ(*data[0], *it); -} - -TEST(Iterator, Access) { - const int count = 100; - std::vector> data; - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - } - - UptrVectorIterator it(&data, data.begin()); - - for (int i = 0; i < count; ++i) EXPECT_EQ(*data[i], it[i]); -} - -TEST(Iterator, Comparison) { - const int count = 100; - std::vector> data; - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - } - - UptrVectorIterator it(&data, data.begin()); - UptrVectorIterator end(&data, data.end()); - - for (int i = 0; i < count; ++i, ++it) EXPECT_TRUE(it < end); - EXPECT_EQ(end, it); -} - -TEST(Iterator, InsertBeginEnd) { - const int count = 100; - - std::vector> data; - std::vector expected; - std::vector actual; - - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - expected.push_back(i); - } - - // Insert at the beginning - expected.insert(expected.begin(), -100); - UptrVectorIterator begin(&data, data.begin()); - auto insert_point = begin.InsertBefore(MakeUnique(-100)); - for (int i = 0; i < count + 1; ++i) { - actual.push_back(*(insert_point++)); - } - EXPECT_THAT(actual, ContainerEq(expected)); - - // Insert at the end - expected.push_back(-42); - expected.push_back(-36); - expected.push_back(-77); - UptrVectorIterator end(&data, data.end()); - end = end.InsertBefore(MakeUnique(-77)); - end = end.InsertBefore(MakeUnique(-36)); - end = end.InsertBefore(MakeUnique(-42)); - - actual.clear(); - begin = UptrVectorIterator(&data, data.begin()); - for (int i = 0; i < count + 4; ++i) { - actual.push_back(*(begin++)); - } - EXPECT_THAT(actual, ContainerEq(expected)); -} - -TEST(Iterator, InsertMiddle) { - const int count = 100; - - std::vector> data; - std::vector expected; - std::vector actual; - - for (int i = 0; i < count; ++i) { - data.emplace_back(new int(i)); - expected.push_back(i); - } - - const int insert_pos = 42; - expected.insert(expected.begin() + insert_pos, -100); - expected.insert(expected.begin() + insert_pos, -42); - - UptrVectorIterator it(&data, data.begin()); - for (int i = 0; i < insert_pos; ++i) ++it; - it = it.InsertBefore(MakeUnique(-100)); - it = it.InsertBefore(MakeUnique(-42)); - auto begin = UptrVectorIterator(&data, data.begin()); - for (int i = 0; i < count + 2; ++i) { - actual.push_back(*(begin++)); - } - EXPECT_THAT(actual, ContainerEq(expected)); -} - -TEST(IteratorRange, Interface) { - const uint32_t count = 100; - - std::vector> data; - - for (uint32_t i = 0; i < count; ++i) { - data.emplace_back(new uint32_t(i)); - } - - auto b = UptrVectorIterator(&data, data.begin()); - auto e = UptrVectorIterator(&data, data.end()); - auto range = IteratorRange(b, e); - - EXPECT_EQ(b, range.begin()); - EXPECT_EQ(e, range.end()); - EXPECT_FALSE(range.empty()); - EXPECT_EQ(count, range.size()); - EXPECT_EQ(0u, *range.begin()); - EXPECT_EQ(99u, *(--range.end())); - - // IteratorRange itself is immutable. - ++b, --e; - EXPECT_EQ(count, range.size()); - ++range.begin(), --range.end(); - EXPECT_EQ(count, range.size()); -} - -TEST(Iterator, FilterIterator) { - struct Placeholder { - int val; - }; - std::vector data = {{1}, {2}, {3}, {4}, {5}, - {6}, {7}, {8}, {9}, {10}}; - - // Predicate to only consider odd values. - struct Predicate { - bool operator()(const Placeholder& data) { return data.val % 2; } - }; - Predicate pred; - - auto filter_range = MakeFilterIteratorRange(data.begin(), data.end(), pred); - - EXPECT_EQ(filter_range.begin().Get(), data.begin()); - EXPECT_EQ(filter_range.end(), filter_range.begin().GetEnd()); - - for (Placeholder& data : filter_range) { - EXPECT_EQ(data.val % 2, 1); - } - - for (auto it = filter_range.begin(); it != filter_range.end(); it++) { - EXPECT_EQ(it->val % 2, 1); - EXPECT_EQ((*it).val % 2, 1); - } - - for (auto it = filter_range.begin(); it != filter_range.end(); ++it) { - EXPECT_EQ(it->val % 2, 1); - EXPECT_EQ((*it).val % 2, 1); - } - - EXPECT_EQ(MakeFilterIterator(data.begin(), data.end(), pred).Get(), - data.begin()); - EXPECT_EQ(MakeFilterIterator(data.end(), data.end(), pred).Get(), data.end()); - EXPECT_EQ(MakeFilterIterator(data.begin(), data.end(), pred).GetEnd(), - MakeFilterIterator(data.end(), data.end(), pred)); - EXPECT_NE(MakeFilterIterator(data.begin(), data.end(), pred), - MakeFilterIterator(data.end(), data.end(), pred)); - - // Empty range: no values satisfies the predicate. - auto empty_range = MakeFilterIteratorRange( - data.begin(), data.end(), - [](const Placeholder& data) { return data.val > 10; }); - EXPECT_EQ(empty_range.begin(), empty_range.end()); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/legalize_vector_shuffle_test.cpp b/3rdparty/spirv-tools/test/opt/legalize_vector_shuffle_test.cpp deleted file mode 100644 index 07d96eb37..000000000 --- a/3rdparty/spirv-tools/test/opt/legalize_vector_shuffle_test.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using LegalizeVectorShuffleTest = PassTest<::testing::Test>; - -void operator+=(std::vector& lhs, const char* rhs) { - lhs.push_back(rhs); -} - -void operator+=(std::vector& lhs, - const std::vector rhs) { - for (auto elem : rhs) lhs.push_back(elem); -} - -std::vector header = { - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", - "%v3uint = OpTypeVector %uint 3"}; - -std::string GetTestString(const char* shuffle) { - std::vector result = header; - result += {"%_ptr_Function_v3uint = OpTypePointer Function %v3uint", - "%void = OpTypeVoid", - "%6 = OpTypeFunction %void", - "%1 = OpFunction %void None %6", - "%7 = OpLabel", - "%8 = OpVariable %_ptr_Function_v3uint Function", - "%9 = OpLoad %v3uint %8", - "%10 = OpLoad %v3uint %8"}; - result += shuffle; - result += {"OpReturn", "OpFunctionEnd"}; - return JoinAllInsts(result); -} - -TEST_F(LegalizeVectorShuffleTest, Changed) { - std::string input = - GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0xFFFFFFFF"); - std::string expected = - GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0"); - - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -TEST_F(LegalizeVectorShuffleTest, FunctionUnchanged) { - std::string input = - GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0"); - std::string expected = - GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0"); - - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/line_debug_info_test.cpp b/3rdparty/spirv-tools/test/opt/line_debug_info_test.cpp deleted file mode 100644 index 6a20a0136..000000000 --- a/3rdparty/spirv-tools/test/opt/line_debug_info_test.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -// A pass turning all none debug line instructions into Nop. -class NopifyPass : public Pass { - public: - const char* name() const override { return "NopifyPass"; } - Status Process() override { - bool modified = false; - context()->module()->ForEachInst( - [&modified](Instruction* inst) { - inst->ToNop(); - modified = true; - }, - /* run_on_debug_line_insts = */ false); - return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; - } -}; - -using PassTestForLineDebugInfo = PassTest<::testing::Test>; - -// This test's purpose to show our implementation choice: line debug info is -// preserved even if the following instruction is killed. It serves as a guard -// of potential behavior changes. -TEST_F(PassTestForLineDebugInfo, KeepLineDebugInfo) { - // clang-format off - const char* text = - "OpCapability Shader " - "%1 = OpExtInstImport \"GLSL.std.450\" " - "OpMemoryModel Logical GLSL450 " - "OpEntryPoint Vertex %2 \"main\" " - "%3 = OpString \"minimal.vert\" " - "OpNoLine " - "OpLine %3 10 10 " - "%void = OpTypeVoid " - "OpLine %3 100 100 " - "%5 = OpTypeFunction %void " - "%2 = OpFunction %void None %5 " - "OpLine %3 1 1 " - "OpNoLine " - "OpLine %3 2 2 " - "OpLine %3 3 3 " - "%6 = OpLabel " - "OpLine %3 4 4 " - "OpNoLine " - "OpReturn " - "OpLine %3 4 4 " - "OpNoLine " - "OpFunctionEnd "; - // clang-format on - - const char* result_keep_nop = - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNoLine\n" - "OpLine %3 10 10\n" - "OpNop\n" - "OpLine %3 100 100\n" - "OpNop\n" - "OpNop\n" - "OpLine %3 1 1\n" - "OpNoLine\n" - "OpLine %3 2 2\n" - "OpLine %3 3 3\n" - "OpNop\n" - "OpLine %3 4 4\n" - "OpNoLine\n" - "OpNop\n" - "OpLine %3 4 4\n" - "OpNoLine\n" - "OpNop\n"; - SinglePassRunAndCheck(text, result_keep_nop, - /* skip_nop = */ false); - const char* result_skip_nop = - "OpNoLine\n" - "OpLine %3 10 10\n" - "OpLine %3 100 100\n" - "OpLine %3 1 1\n" - "OpNoLine\n" - "OpLine %3 2 2\n" - "OpLine %3 3 3\n" - "OpLine %3 4 4\n" - "OpNoLine\n" - "OpLine %3 4 4\n" - "OpNoLine\n"; - SinglePassRunAndCheck(text, result_skip_nop, - /* skip_nop = */ true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/local_access_chain_convert_test.cpp b/3rdparty/spirv-tools/test/opt/local_access_chain_convert_test.cpp deleted file mode 100644 index 39899e3ee..000000000 --- a/3rdparty/spirv-tools/test/opt/local_access_chain_convert_test.cpp +++ /dev/null @@ -1,941 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using LocalAccessChainConvertTest = PassTest<::testing::Test>; - -TEST_F(LocalAccessChainConvertTest, StructOfVecsOfFloatConverted) { - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // gl_FragColor = s0.v1; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"( -; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor -; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 -; CHECK: OpStore %s0 [[ex1]] -; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 -; CHECK: OpStore %gl_FragColor [[ex2]] -%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -OpStore %19 %18 -%20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -%21 = OpLoad %v4float %20 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs_before + before, - true); -} - -TEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) { - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // gl_FragColor = s0.v1; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"( -; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor -; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 -; CHECK: OpStore %s0 [[ex1]] -; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 -; CHECK: OpStore %gl_FragColor [[ex2]] -%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1 -OpStore %19 %18 -%20 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1 -%21 = OpLoad %v4float %20 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs_before + before, - true); -} - -TEST_F(LocalAccessChainConvertTest, TwoUsesofSingleChainConverted) { - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // gl_FragColor = s0.v1; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"( -; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor -; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 -; CHECK: OpStore %s0 [[ex1]] -; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 -; CHECK: OpStore %gl_FragColor [[ex2]] -%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -OpStore %19 %18 -%20 = OpLoad %v4float %19 -OpStore %gl_FragColor %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs_before + before, - true); -} - -TEST_F(LocalAccessChainConvertTest, OpaqueConverted) { - // SPIR-V not representable in GLSL; not generatable from HLSL - // at the moment - - const std::string predefs = - R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpMemberName %S_t 2 "smp" -OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" -OpName %s "s" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %s0 "s0" -OpName %texCoords "texCoords" -OpName %param "param" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%18 = OpTypeSampledImage %17 -%S_t = OpTypeStruct %v2float %v2float %18 -%_ptr_Function_S_t = OpTypePointer Function %S_t -%20 = OpTypeFunction %void %_ptr_Function_S_t -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Function_18 = OpTypePointer Function %18 -%sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string before = - R"( -; CHECK: [[l1:%\w+]] = OpLoad %S_t %param -; CHECK: [[e1:%\w+]] = OpCompositeExtract {{%\w+}} [[l1]] 2 -; CHECK: [[l2:%\w+]] = OpLoad %S_t %param -; CHECK: [[e2:%\w+]] = OpCompositeExtract {{%\w+}} [[l2]] 0 -; CHECK: OpImageSampleImplicitLod {{%\w+}} [[e1]] [[e2]] -%main = OpFunction %void None %12 -%28 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%29 = OpLoad %v2float %texCoords -%30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 -OpStore %30 %29 -%31 = OpLoad %18 %sampler15 -%32 = OpAccessChain %_ptr_Function_18 %s0 %int_2 -OpStore %32 %31 -%33 = OpLoad %S_t %s0 -OpStore %param %33 -%34 = OpAccessChain %_ptr_Function_18 %param %int_2 -%35 = OpLoad %18 %34 -%36 = OpAccessChain %_ptr_Function_v2float %param %int_0 -%37 = OpLoad %v2float %36 -%38 = OpImageSampleImplicitLod %v4float %35 %37 -OpStore %outColor %38 -OpReturn -OpFunctionEnd -)"; - - const std::string remain = - R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20 -%s = OpFunctionParameter %_ptr_Function_S_t -%39 = OpLabel -%40 = OpAccessChain %_ptr_Function_18 %s %int_2 -%41 = OpLoad %18 %40 -%42 = OpAccessChain %_ptr_Function_v2float %s %int_0 -%43 = OpLoad %v2float %42 -%44 = OpImageSampleImplicitLod %v4float %41 %43 -OpStore %outColor %44 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + before + remain, - true); -} - -TEST_F(LocalAccessChainConvertTest, NestedStructsConverted) { - // #version 140 - // - // in vec4 BaseColor; - // - // struct S1_t { - // vec4 v1; - // }; - // - // struct S2_t { - // vec4 v2; - // S1_t s1; - // }; - // - // void main() - // { - // S2_t s2; - // s2.s1.v1 = BaseColor; - // gl_FragColor = s2.s1.v1; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S1_t "S1_t" -OpMemberName %S1_t 0 "v1" -OpName %S2_t "S2_t" -OpMemberName %S2_t 0 "v2" -OpMemberName %S2_t 1 "s1" -OpName %s2 "s2" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S1_t = OpTypeStruct %v4float -%S2_t = OpTypeStruct %v4float %S1_t -%_ptr_Function_S2_t = OpTypePointer Function %S2_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%int_0 = OpConstant %int 0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"( -; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor -; CHECK: [[ld1:%\w+]] = OpLoad %S2_t %s2 -; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S2_t [[st_id]] [[ld1]] 1 0 -; CHECK: OpStore %s2 [[ex1]] -; CHECK: [[ld2:%\w+]] = OpLoad %S2_t %s2 -; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 0 -; CHECK: OpStore %gl_FragColor [[ex2]] -%main = OpFunction %void None %9 -%19 = OpLabel -%s2 = OpVariable %_ptr_Function_S2_t Function -%20 = OpLoad %v4float %BaseColor -%21 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0 -OpStore %21 %20 -%22 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0 -%23 = OpLoad %v4float %22 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs_before + before, - true); -} - -TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) { - // Based on HLSL source code: - // struct S { - // float f; - // }; - - // float main(float input : A) : B { - // S local = { input }; - // return local.f; - // } - - const std::string predefs = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" %in_var_A %out_var_B -OpName %main "main" -OpName %in_var_A "in.var.A" -OpName %out_var_B "out.var.B" -OpName %S "S" -OpName %local "local" -%int = OpTypeInt 32 1 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Input_float = OpTypePointer Input %float -%_ptr_Output_float = OpTypePointer Output %float -%S = OpTypeStruct %float -%_ptr_Function_S = OpTypePointer Function %S -%int_0 = OpConstant %int 0 -%in_var_A = OpVariable %_ptr_Input_float Input -%out_var_B = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %8 -%15 = OpLabel -%local = OpVariable %_ptr_Function_S Function -%16 = OpLoad %float %in_var_A -%17 = OpCompositeConstruct %S %16 -OpStore %local %17 -)"; - - const std::string before = - R"( -; CHECK: [[ld:%\w+]] = OpLoad %S %local -; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 -; CHECK: OpStore %out_var_B [[ex]] -%18 = OpAccessChain %_ptr_Function_float %local %int_0 -%19 = OpAccessChain %_ptr_Function_float %local %int_0 -%20 = OpLoad %float %18 -OpStore %out_var_B %20 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + before, true); -} - -TEST_F(LocalAccessChainConvertTest, - StructOfVecsOfFloatConvertedWithDecorationOnLoad) { - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // gl_FragColor = s0.v1; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %21 RelaxedPrecision -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"( -; CHECK: OpDecorate -; CHECK: OpDecorate [[ld2:%\w+]] RelaxedPrecision -; CHECK-NOT: OpDecorate -; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor -; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ins:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 -; CHECK: OpStore %s0 [[ins]] -; CHECK: [[ld2]] = OpLoad %S_t %s0 -; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 -; CHECK: OpStore %gl_FragColor [[ex2]] -%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -OpStore %19 %18 -%20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -%21 = OpLoad %v4float %20 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs_before + before, - true); -} - -TEST_F(LocalAccessChainConvertTest, - StructOfVecsOfFloatConvertedWithDecorationOnStore) { - // #version 140 - // - // in vec4 BaseColor; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // gl_FragColor = s0.v1; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %s0 RelaxedPrecision -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"( -; CHECK: OpDecorate -; CHECK: OpDecorate [[ld1:%\w+]] RelaxedPrecision -; CHECK: OpDecorate [[ins:%\w+]] RelaxedPrecision -; CHECK-NOT: OpDecorate -; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor -; CHECK: [[ld1]] = OpLoad %S_t %s0 -; CHECK: [[ins]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 -; CHECK: OpStore %s0 [[ins]] -; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 -; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 -; CHECK: OpStore %gl_FragColor [[ex2]] -%main = OpFunction %void None %8 -%17 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%18 = OpLoad %v4float %BaseColor -%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -OpStore %19 %18 -%20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -%21 = OpLoad %v4float %20 -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs_before + before, - true); -} - -TEST_F(LocalAccessChainConvertTest, DynamicallyIndexedVarNotConverted) { - // #version 140 - // - // in vec4 BaseColor; - // flat in int Idx; - // in float Bi; - // - // struct S_t { - // vec4 v0; - // vec4 v1; - // }; - // - // void main() - // { - // S_t s0; - // s0.v1 = BaseColor; - // s0.v1[Idx] = Bi; - // gl_FragColor = s0.v1; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Idx %Bi %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpName %s0 "s0" -OpName %BaseColor "BaseColor" -OpName %Idx "Idx" -OpName %Bi "Bi" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %Idx Flat -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%S_t = OpTypeStruct %v4float %v4float -%_ptr_Function_S_t = OpTypePointer Function %S_t -%int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_int = OpTypePointer Input %int -%Idx = OpVariable %_ptr_Input_int Input -%_ptr_Input_float = OpTypePointer Input %float -%Bi = OpVariable %_ptr_Input_float Input -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %10 -%22 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%23 = OpLoad %v4float %BaseColor -%24 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -OpStore %24 %23 -%25 = OpLoad %int %Idx -%26 = OpLoad %float %Bi -%27 = OpAccessChain %_ptr_Function_float %s0 %int_1 %25 -OpStore %27 %26 -%28 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 -%29 = OpLoad %v4float %28 -OpStore %gl_FragColor %29 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, false, - true); -} - -TEST_F(LocalAccessChainConvertTest, VariablePointersStorageBuffer) { - // A case with a storage buffer variable pointer. We should still convert - // the access chain on the function scope symbol. - const std::string test = - R"( -; CHECK: OpFunction -; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Function -; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[var]] -; CHECK: OpCompositeExtract {{%\w+}} [[ld]] 0 0 - OpCapability Shader - OpCapability VariablePointersStorageBuffer - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 1 1 - OpSource GLSL 450 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_struct_3 Block - OpDecorate %4 DescriptorSet 0 - OpDecorate %4 Binding 0 - OpDecorate %_ptr_StorageBuffer_int ArrayStride 4 - OpDecorate %_arr_int_int_128 ArrayStride 4 - %void = OpTypeVoid - %8 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %int_128 = OpConstant %int 128 -%_arr_int_int_128 = OpTypeArray %int %int_128 - %_struct_3 = OpTypeStruct %_arr_int_int_128 -%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3 -%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3 - %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer - %bool = OpTypeBool - %true = OpConstantTrue %bool - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 -%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int -%_ptr_Function_int = OpTypePointer Function %int - %2 = OpFunction %void None %8 - %18 = OpLabel - %19 = OpVariable %_ptr_Function__struct_3 Function - %20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0 - OpBranch %21 - %21 = OpLabel - %22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24 - OpLoopMerge %25 %24 None - OpBranchConditional %true %26 %25 - %26 = OpLabel - OpStore %22 %int_0 - OpBranch %24 - %24 = OpLabel - %23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1 - OpBranch %21 - %25 = OpLabel - %27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0 - %28 = OpLoad %int %27 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(test, true); -} - -TEST_F(LocalAccessChainConvertTest, VariablePointers) { - // A case with variable pointer capability. We should not convert - // the access chain on the function scope symbol because the variable pointer - // could the analysis to miss references to function scope symbols. - const std::string test = - R"(OpCapability Shader -OpCapability VariablePointers -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %2 "main" -OpExecutionMode %2 LocalSize 1 1 1 -OpSource GLSL 450 -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_struct_3 Block -OpDecorate %4 DescriptorSet 0 -OpDecorate %4 Binding 0 -OpDecorate %_ptr_StorageBuffer_int ArrayStride 4 -OpDecorate %_arr_int_int_128 ArrayStride 4 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%int_128 = OpConstant %int 128 -%_arr_int_int_128 = OpTypeArray %int %int_128 -%_struct_3 = OpTypeStruct %_arr_int_int_128 -%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3 -%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3 -%4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int -%_ptr_Function_int = OpTypePointer Function %int -%2 = OpFunction %void None %8 -%18 = OpLabel -%19 = OpVariable %_ptr_Function__struct_3 Function -%20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0 -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24 -OpLoopMerge %25 %24 None -OpBranchConditional %true %26 %25 -%26 = OpLabel -OpStore %22 %int_0 -OpBranch %24 -%24 = OpLabel -%23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1 -OpBranch %21 -%25 = OpLabel -%27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0 -%28 = OpLoad %int %27 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(test, test, false, true); -} - -TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingLoad) { - const std::string text = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "PSMain" - OpExecutionMode %4 OriginUpperLeft - OpDecorate %10 Location 47360 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %_struct_8 = OpTypeStruct %v4float -%_ptr_Function__struct_8 = OpTypePointer Function %_struct_8 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %4 = OpFunction %void None %3 - %5 = OpLabel - %10 = OpVariable %_ptr_Function__struct_8 Function - %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0 - %4194302 = OpLoad %v4float %4194301 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore1) { - const std::string text = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "PSMain" - OpExecutionMode %4 OriginUpperLeft - OpDecorate %10 Location 47360 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %_struct_7 = OpTypeStruct %v4float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %13 = OpConstantNull %v4float - %4 = OpFunction %void None %3 - %5 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %4194302 = OpAccessChain %_ptr_Function_v4float %10 %int_0 - OpStore %4194302 %13 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore2) { - const std::string text = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "PSMain" - OpExecutionMode %4 OriginUpperLeft - OpDecorate %10 Location 47360 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %_struct_7 = OpTypeStruct %v4float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %13 = OpConstantNull %v4float - %4 = OpFunction %void None %3 - %5 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0 - OpStore %4194301 %13 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// Assorted vector and matrix types -// Assorted struct array types -// Assorted scalar types -// Assorted non-target types -// OpInBoundsAccessChain -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/local_redundancy_elimination_test.cpp b/3rdparty/spirv-tools/test/opt/local_redundancy_elimination_test.cpp deleted file mode 100644 index bc4635e29..000000000 --- a/3rdparty/spirv-tools/test/opt/local_redundancy_elimination_test.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/value_number_table.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; -using LocalRedundancyEliminationTest = PassTest<::testing::Test>; - -// Remove an instruction when it was already computed. -TEST_F(LocalRedundancyEliminationTest, RemoveRedundantAdd) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 -; CHECK: OpFAdd -; CHECK-NOT: OpFAdd - %11 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -// Make sure we keep instruction that are different, but look similar. -TEST_F(LocalRedundancyEliminationTest, KeepDifferentAdd) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 -; CHECK: OpFAdd - OpStore %8 %10 - %11 = OpLoad %5 %8 -; CHECK: %11 = OpLoad - %12 = OpFAdd %5 %11 %11 -; CHECK: OpFAdd [[:%\w+]] %11 %11 - OpReturn - OpFunctionEnd - )"; - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(text, false); -} - -// This test is check that the values are being propagated properly, and that -// we are able to identify sequences of instruction that are not needed. -TEST_F(LocalRedundancyEliminationTest, RemoveMultipleInstructions) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Uniform %5 - %8 = OpVariable %6 Uniform - %2 = OpFunction %3 None %4 - %7 = OpLabel -; CHECK: [[r1:%\w+]] = OpLoad - %9 = OpLoad %5 %8 -; CHECK-NEXT: [[r2:%\w+]] = OpFAdd [[:%\w+]] [[r1]] [[r1]] - %10 = OpFAdd %5 %9 %9 -; CHECK-NEXT: [[r3:%\w+]] = OpFMul [[:%\w+]] [[r2]] [[r1]] - %11 = OpFMul %5 %10 %9 -; CHECK-NOT: OpLoad - %12 = OpLoad %5 %8 -; CHECK-NOT: OpFAdd [[:\w+]] %12 %12 - %13 = OpFAdd %5 %12 %12 -; CHECK-NOT: OpFMul - %14 = OpFMul %5 %13 %12 -; CHECK-NEXT: [[:%\w+]] = OpFAdd [[:%\w+]] [[r3]] [[r3]] - %15 = OpFAdd %5 %14 %11 - OpReturn - OpFunctionEnd - )"; - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(text, false); -} - -// Redundant instructions in different blocks should be kept. -TEST_F(LocalRedundancyEliminationTest, KeepInstructionsInDifferentBlocks) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %bb1 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 -; CHECK: OpFAdd - OpBranch %bb2 - %bb2 = OpLabel -; CHECK: OpFAdd - %11 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/local_single_block_elim.cpp b/3rdparty/spirv-tools/test/opt/local_single_block_elim.cpp deleted file mode 100644 index 402352d73..000000000 --- a/3rdparty/spirv-tools/test/opt/local_single_block_elim.cpp +++ /dev/null @@ -1,1130 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using LocalSingleBlockLoadStoreElimTest = PassTest<::testing::Test>; - -TEST_F(LocalSingleBlockLoadStoreElimTest, SimpleStoreLoadElim) { - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // gl_FragColor = v; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -%15 = OpLoad %v4float %v -OpStore %gl_FragColor %15 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpStore %gl_FragColor %14 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + before, predefs_before + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, SimpleLoadLoadElim) { - // #version 140 - // - // in vec4 BaseColor; - // in float fi; - // - // void main() - // { - // vec4 v = BaseColor; - // if (fi < 0) - // v = vec4(0.0); - // gl_FragData[0] = v; - // gl_FragData[1] = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragData -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %fi "fi" -OpName %gl_FragData "gl_FragData" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%16 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%uint = OpTypeInt 32 0 -%uint_32 = OpConstant %uint 32 -%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32 -%_ptr_Output__arr_v4float_uint_32 = OpTypePointer Output %_arr_v4float_uint_32 -%gl_FragData = OpVariable %_ptr_Output__arr_v4float_uint_32 Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%int_1 = OpConstant %int 1 -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%25 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%26 = OpLoad %v4float %BaseColor -OpStore %v %26 -%27 = OpLoad %float %fi -%28 = OpFOrdLessThan %bool %27 %float_0 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -OpStore %v %16 -OpBranch %29 -%29 = OpLabel -%31 = OpLoad %v4float %v -%32 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0 -OpStore %32 %31 -%33 = OpLoad %v4float %v -%34 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1 -OpStore %34 %33 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%25 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%26 = OpLoad %v4float %BaseColor -OpStore %v %26 -%27 = OpLoad %float %fi -%28 = OpFOrdLessThan %bool %27 %float_0 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -OpStore %v %16 -OpBranch %29 -%29 = OpLabel -%31 = OpLoad %v4float %v -%32 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0 -OpStore %32 %31 -%34 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1 -OpStore %34 %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before, predefs + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, StoreStoreElim) { - // - // Note first store to v is eliminated - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // vec4 v = BaseColor; - // v = v * 0.5; - // OutColor = v; - // } - - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %OutColor "OutColor" -OpDecorate %BaseColor Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%float_0_5 = OpConstant %float 0.5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%14 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%15 = OpLoad %v4float %BaseColor -OpStore %v %15 -%16 = OpLoad %v4float %v -%17 = OpVectorTimesScalar %v4float %16 %float_0_5 -OpStore %v %17 -%18 = OpLoad %v4float %v -OpStore %OutColor %18 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%14 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%15 = OpLoad %v4float %BaseColor -%17 = OpVectorTimesScalar %v4float %15 %float_0_5 -OpStore %v %17 -OpStore %OutColor %17 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs_before + before, predefs_before + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, - NoStoreElimIfInterveningAccessChainLoad) { - // - // Note the first Store to %v is not eliminated due to the following access - // chain reference. - // - // #version 450 - // - // layout(location = 0) in vec4 BaseColor0; - // layout(location = 1) in vec4 BaseColor1; - // layout(location = 2) flat in int Idx; - // layout(location = 0) out vec4 OutColor; - // - // void main() - // { - // vec4 v = BaseColor0; - // float f = v[Idx]; - // v = BaseColor1 + vec4(0.1); - // OutColor = v/f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor0 %Idx %BaseColor1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor0 "BaseColor0" -OpName %f "f" -OpName %Idx "Idx" -OpName %BaseColor1 "BaseColor1" -OpName %OutColor "OutColor" -OpDecorate %BaseColor0 Location 0 -OpDecorate %Idx Flat -OpDecorate %Idx Location 2 -OpDecorate %BaseColor1 Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%Idx = OpVariable %_ptr_Input_int Input -%BaseColor1 = OpVariable %_ptr_Input_v4float Input -%float_0_100000001 = OpConstant %float 0.100000001 -%19 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%22 = OpLoad %v4float %BaseColor0 -OpStore %v %22 -%23 = OpLoad %int %Idx -%24 = OpAccessChain %_ptr_Function_float %v %23 -%25 = OpLoad %float %24 -OpStore %f %25 -%26 = OpLoad %v4float %BaseColor1 -%27 = OpFAdd %v4float %26 %19 -OpStore %v %27 -%28 = OpLoad %v4float %v -%29 = OpLoad %float %f -%30 = OpCompositeConstruct %v4float %29 %29 %29 %29 -%31 = OpFDiv %v4float %28 %30 -OpStore %OutColor %31 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%22 = OpLoad %v4float %BaseColor0 -OpStore %v %22 -%23 = OpLoad %int %Idx -%24 = OpAccessChain %_ptr_Function_float %v %23 -%25 = OpLoad %float %24 -OpStore %f %25 -%26 = OpLoad %v4float %BaseColor1 -%27 = OpFAdd %v4float %26 %19 -OpStore %v %27 -%30 = OpCompositeConstruct %v4float %25 %25 %25 %25 -%31 = OpFDiv %v4float %27 %30 -OpStore %OutColor %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before, predefs + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, NoElimIfInterveningAccessChainStore) { - // #version 140 - // - // in vec4 BaseColor; - // flat in int Idx; - // - // void main() - // { - // vec4 v = BaseColor; - // v[Idx] = 0; - // gl_FragColor = v; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %Idx %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %Idx "Idx" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %Idx Flat -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%Idx = OpVariable %_ptr_Input_int Input -%float_0 = OpConstant %float 0 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %8 -%18 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%19 = OpLoad %v4float %BaseColor -OpStore %v %19 -%20 = OpLoad %int %Idx -%21 = OpAccessChain %_ptr_Function_float %v %20 -OpStore %21 %float_0 -%22 = OpLoad %v4float %v -OpStore %gl_FragColor %22 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, - false, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, NoElimIfInterveningFunctionCall) { - // #version 140 - // - // in vec4 BaseColor; - // - // void foo() { - // } - // - // void main() - // { - // vec4 v = BaseColor; - // foo(); - // gl_FragColor = v; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_ "foo(" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %8 -%14 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%15 = OpLoad %v4float %BaseColor -OpStore %v %15 -%16 = OpFunctionCall %void %foo_ -%17 = OpLoad %v4float %v -OpStore %gl_FragColor %17 -OpReturn -OpFunctionEnd -%foo_ = OpFunction %void None %8 -%18 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, - false, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, ElimIfCopyObjectInFunction) { - // Note: SPIR-V hand edited to insert CopyObject - // - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v1 = BaseColor; - // gl_FragData[0] = v1; - // vec4 v2 = BaseColor * 0.5; - // gl_FragData[1] = v2; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragData -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v1 "v1" -OpName %BaseColor "BaseColor" -OpName %gl_FragData "gl_FragData" -OpName %v2 "v2" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_32 = OpConstant %uint 32 -%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32 -%_ptr_Output__arr_v4float_uint_32 = OpTypePointer Output %_arr_v4float_uint_32 -%gl_FragData = OpVariable %_ptr_Output__arr_v4float_uint_32 Output -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%float_0_5 = OpConstant %float 0.5 -%int_1 = OpConstant %int 1 -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%v1 = OpVariable %_ptr_Function_v4float Function -%v2 = OpVariable %_ptr_Function_v4float Function -%23 = OpLoad %v4float %BaseColor -OpStore %v1 %23 -%24 = OpLoad %v4float %v1 -%25 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0 -OpStore %25 %24 -%26 = OpLoad %v4float %BaseColor -%27 = OpVectorTimesScalar %v4float %26 %float_0_5 -%28 = OpCopyObject %_ptr_Function_v4float %v2 -OpStore %28 %27 -%29 = OpLoad %v4float %28 -%30 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1 -OpStore %30 %29 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%v1 = OpVariable %_ptr_Function_v4float Function -%v2 = OpVariable %_ptr_Function_v4float Function -%23 = OpLoad %v4float %BaseColor -OpStore %v1 %23 -%25 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0 -OpStore %25 %23 -%26 = OpLoad %v4float %BaseColor -%27 = OpVectorTimesScalar %v4float %26 %float_0_5 -%28 = OpCopyObject %_ptr_Function_v4float %v2 -OpStore %28 %27 -%30 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1 -OpStore %30 %27 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before, predefs + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, ElimOpaque) { - // SPIR-V not representable in GLSL; not generatable from HLSL - // at the moment - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %outColor %texCoords -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %S_t "S_t" -OpMemberName %S_t 0 "v0" -OpMemberName %S_t 1 "v1" -OpMemberName %S_t 2 "smp" -OpName %outColor "outColor" -OpName %sampler15 "sampler15" -OpName %s0 "s0" -OpName %texCoords "texCoords" -OpName %param "param" -OpDecorate %sampler15 DescriptorSet 0 -%void = OpTypeVoid -%12 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%outColor = OpVariable %_ptr_Output_v4float Output -%17 = OpTypeImage %float 2D 0 0 0 1 Unknown -%18 = OpTypeSampledImage %17 -%S_t = OpTypeStruct %v2float %v2float %18 -%_ptr_Function_S_t = OpTypePointer Function %S_t -%20 = OpTypeFunction %void %_ptr_Function_S_t -%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 -%_ptr_Function_18 = OpTypePointer Function %18 -%sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%texCoords = OpVariable %_ptr_Input_v2float Input -)"; - - const std::string before = - R"(%main = OpFunction %void None %12 -%28 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%29 = OpLoad %v2float %texCoords -%30 = OpLoad %S_t %s0 -%31 = OpCompositeInsert %S_t %29 %30 0 -OpStore %s0 %31 -%32 = OpLoad %18 %sampler15 -%33 = OpLoad %S_t %s0 -%34 = OpCompositeInsert %S_t %32 %33 2 -OpStore %s0 %34 -%35 = OpLoad %S_t %s0 -OpStore %param %35 -%36 = OpLoad %S_t %param -%37 = OpCompositeExtract %18 %36 2 -%38 = OpLoad %S_t %param -%39 = OpCompositeExtract %v2float %38 0 -%40 = OpImageSampleImplicitLod %v4float %37 %39 -OpStore %outColor %40 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %12 -%28 = OpLabel -%s0 = OpVariable %_ptr_Function_S_t Function -%param = OpVariable %_ptr_Function_S_t Function -%29 = OpLoad %v2float %texCoords -%30 = OpLoad %S_t %s0 -%31 = OpCompositeInsert %S_t %29 %30 0 -%32 = OpLoad %18 %sampler15 -%34 = OpCompositeInsert %S_t %32 %31 2 -OpStore %s0 %34 -OpStore %param %34 -%37 = OpCompositeExtract %18 %34 2 -%39 = OpCompositeExtract %v2float %34 0 -%40 = OpImageSampleImplicitLod %v4float %37 %39 -OpStore %outColor %40 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - predefs + before, predefs + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, PositiveAndNegativeCallTree) { - // Note that the call tree function bar is optimized, but foo is not - // - // #version 140 - // - // in vec4 BaseColor; - // - // vec4 foo(vec4 v1) - // { - // vec4 t = v1; - // return t; - // } - // - // vec4 bar(vec4 v1) - // { - // vec4 t = v1; - // return t; - // } - // - // void main() - // { - // gl_FragColor = bar(BaseColor); - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %foo_vf4_ "foo(vf4;" -OpName %v1 "v1" -OpName %bar_vf4_ "bar(vf4;" -OpName %v1_0 "v1" -OpName %t "t" -OpName %t_0 "t" -OpName %gl_FragColor "gl_FragColor" -OpName %BaseColor "BaseColor" -OpName %param "param" -%void = OpTypeVoid -%13 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%17 = OpTypeFunction %v4float %_ptr_Function_v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %13 -%20 = OpLabel -%param = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %v4float %BaseColor -OpStore %param %21 -%22 = OpFunctionCall %v4float %bar_vf4_ %param -OpStore %gl_FragColor %22 -OpReturn -OpFunctionEnd -)"; - - const std::string before = - R"(%foo_vf4_ = OpFunction %v4float None %17 -%v1 = OpFunctionParameter %_ptr_Function_v4float -%23 = OpLabel -%t = OpVariable %_ptr_Function_v4float Function -%24 = OpLoad %v4float %v1 -OpStore %t %24 -%25 = OpLoad %v4float %t -OpReturnValue %25 -OpFunctionEnd -%bar_vf4_ = OpFunction %v4float None %17 -%v1_0 = OpFunctionParameter %_ptr_Function_v4float -%26 = OpLabel -%t_0 = OpVariable %_ptr_Function_v4float Function -%27 = OpLoad %v4float %v1_0 -OpStore %t_0 %27 -%28 = OpLoad %v4float %t_0 -OpReturnValue %28 -OpFunctionEnd -)"; - - const std::string after = - R"(%foo_vf4_ = OpFunction %v4float None %17 -%v1 = OpFunctionParameter %_ptr_Function_v4float -%23 = OpLabel -%t = OpVariable %_ptr_Function_v4float Function -%24 = OpLoad %v4float %v1 -OpStore %t %24 -%25 = OpLoad %v4float %t -OpReturnValue %25 -OpFunctionEnd -%bar_vf4_ = OpFunction %v4float None %17 -%v1_0 = OpFunctionParameter %_ptr_Function_v4float -%26 = OpLabel -%t_0 = OpVariable %_ptr_Function_v4float Function -%27 = OpLoad %v4float %v1_0 -OpStore %t_0 %27 -OpReturnValue %27 -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before, predefs + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, PointerVariable) { - // Test that checks if a pointer variable is removed. - - const std::string before = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%26 = OpLoad %_ptr_Uniform__struct_5 %24 -%27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - // Relax logical pointers to allow pointer allocations. - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ValidatorOptions()->relax_logical_pointer = true; - SinglePassRunAndCheck(before, after, true, - true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, RedundantStore) { - // Test that checks if a pointer variable is removed. - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpBranch %16 -%16 = OpLabel -%15 = OpLoad %v4float %v -OpStore %v %15 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpBranch %16 -%16 = OpLabel -%15 = OpLoad %v4float %v -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - predefs_before + before, predefs_before + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, RedundantStore2) { - // Test that checks if a pointer variable is removed. - const std::string predefs_before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpBranch %16 -%16 = OpLabel -%15 = OpLoad %v4float %v -OpStore %v %15 -%17 = OpLoad %v4float %v -OpStore %v %17 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %7 -%13 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%14 = OpLoad %v4float %BaseColor -OpStore %v %14 -OpBranch %16 -%16 = OpLabel -%15 = OpLoad %v4float %v -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - predefs_before + before, predefs_before + after, true, true); -} - -// Test that that an unused OpAccessChain between two store does does not -// hinders the removal of the first store. We need to check this because -// local-access-chain-convert does always remove the OpAccessChain instructions -// that become dead. - -TEST_F(LocalSingleBlockLoadStoreElimTest, - StoreElimIfInterveningUnusedAccessChain) { - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor0 %Idx %BaseColor1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %BaseColor0 "BaseColor0" -OpName %Idx "Idx" -OpName %BaseColor1 "BaseColor1" -OpName %OutColor "OutColor" -OpDecorate %BaseColor0 Location 0 -OpDecorate %Idx Flat -OpDecorate %Idx Location 2 -OpDecorate %BaseColor1 Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%Idx = OpVariable %_ptr_Input_int Input -%BaseColor1 = OpVariable %_ptr_Input_v4float Input -%float_0_100000001 = OpConstant %float 0.100000001 -%19 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %BaseColor0 -OpStore %v %22 -%23 = OpLoad %int %Idx -%24 = OpAccessChain %_ptr_Function_float %v %23 -%26 = OpLoad %v4float %BaseColor1 -%27 = OpFAdd %v4float %26 %19 -OpStore %v %27 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%22 = OpLoad %v4float %BaseColor0 -%23 = OpLoad %int %Idx -%24 = OpAccessChain %_ptr_Function_float %v %23 -%26 = OpLoad %v4float %BaseColor1 -%27 = OpFAdd %v4float %26 %19 -OpStore %v %27 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - predefs + before, predefs + after, true, true); -} - -TEST_F(LocalSingleBlockLoadStoreElimTest, VariablePointerTest) { - // Check that the load of the first variable is still used and that the load - // of the third variable is propagated. The first load has to remain because - // of the store to the variable pointer. - const std::string text = R"( -; CHECK: [[v1:%\w+]] = OpVariable -; CHECK: [[v2:%\w+]] = OpVariable -; CHECK: [[v3:%\w+]] = OpVariable -; CHECK: [[phi:%\w+]] = OpPhi -; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]] -; CHECK: OpIAdd %int [[ld1]] %int_0 - OpCapability Shader - OpCapability VariablePointers - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 1 1 - OpSource GLSL 450 - OpMemberDecorate %_struct_3 0 Offset 0 - OpMemberDecorate %_struct_3 1 Offset 4 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool - %_struct_3 = OpTypeStruct %int %int -%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3 -%_ptr_Function_int = OpTypePointer Function %int - %true = OpConstantTrue %bool - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %13 = OpConstantNull %_struct_3 - %2 = OpFunction %void None %5 - %14 = OpLabel - %15 = OpVariable %_ptr_Function_int Function - %16 = OpVariable %_ptr_Function_int Function - %17 = OpVariable %_ptr_Function_int Function - OpSelectionMerge %18 None - OpBranchConditional %true %19 %20 - %19 = OpLabel - OpBranch %18 - %20 = OpLabel - OpBranch %18 - %18 = OpLabel - %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20 - OpStore %15 %int_1 - OpStore %21 %int_0 - %22 = OpLoad %int %15 - OpStore %17 %int_0 - %23 = OpLoad %int %17 - %24 = OpIAdd %int %22 %23 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// Other target variable types -// InBounds Access Chains -// Check for correctness in the presence of function calls -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/local_single_store_elim_test.cpp b/3rdparty/spirv-tools/test/opt/local_single_store_elim_test.cpp deleted file mode 100644 index 5a1650b7f..000000000 --- a/3rdparty/spirv-tools/test/opt/local_single_store_elim_test.cpp +++ /dev/null @@ -1,912 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using LocalSingleStoreElimTest = PassTest<::testing::Test>; - -TEST_F(LocalSingleStoreElimTest, PositiveAndNegative) { - // Single store to v is optimized. Multiple store to - // f is not optimized. - // - // #version 140 - // - // in vec4 BaseColor; - // in float fi; - // - // void main() - // { - // vec4 v = BaseColor; - // float f = fi; - // if (f < 0) - // f = 0.0; - // gl_FragColor = v + f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %f "f" -OpName %fi "fi" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -OpStore %f %21 -%22 = OpLoad %float %f -%23 = OpFOrdLessThan %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %24 -%25 = OpLabel -OpStore %f %float_0 -OpBranch %24 -%24 = OpLabel -%26 = OpLoad %v4float %v -%27 = OpLoad %float %f -%28 = OpCompositeConstruct %v4float %27 %27 %27 %27 -%29 = OpFAdd %v4float %26 %28 -OpStore %gl_FragColor %29 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -OpStore %f %21 -%22 = OpLoad %float %f -%23 = OpFOrdLessThan %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %24 -%25 = OpLabel -OpStore %f %float_0 -OpBranch %24 -%24 = OpLabel -%27 = OpLoad %float %f -%28 = OpCompositeConstruct %v4float %27 %27 %27 %27 -%29 = OpFAdd %v4float %20 %28 -OpStore %gl_FragColor %29 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, - predefs + after, true, true); -} - -TEST_F(LocalSingleStoreElimTest, ThreeStores) { - // Three stores to multiple loads of v is not optimized. - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %fi "fi" -OpName %r "r" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%r = OpVariable %_ptr_Function_v4float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -%22 = OpFOrdLessThan %bool %21 %float_0 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %25 -%24 = OpLabel -%26 = OpLoad %v4float %v -OpStore %v %26 -OpStore %r %26 -OpBranch %23 -%25 = OpLabel -%27 = OpLoad %v4float %v -%28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1 -OpStore %v %28 -%29 = OpFSub %v4float %28 %27 -OpStore %r %29 -OpBranch %23 -%23 = OpLabel -%30 = OpLoad %v4float %r -OpStore %gl_FragColor %30 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, - predefs + before, true, true); -} - -TEST_F(LocalSingleStoreElimTest, MultipleLoads) { - // Single store to multiple loads of v is optimized. - // - // #version 140 - // - // in vec4 BaseColor; - // in float fi; - // - // void main() - // { - // vec4 v = BaseColor; - // float f = fi; - // if (f < 0) - // f = 0.0; - // gl_FragColor = v + f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %fi "fi" -OpName %r "r" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%r = OpVariable %_ptr_Function_v4float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -%22 = OpFOrdLessThan %bool %21 %float_0 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %25 -%24 = OpLabel -%26 = OpLoad %v4float %v -OpStore %r %26 -OpBranch %23 -%25 = OpLabel -%27 = OpLoad %v4float %v -%28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1 -%29 = OpFSub %v4float %28 %27 -OpStore %r %29 -OpBranch %23 -%23 = OpLabel -%30 = OpLoad %v4float %r -OpStore %gl_FragColor %30 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%r = OpVariable %_ptr_Function_v4float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -%22 = OpFOrdLessThan %bool %21 %float_0 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %25 -%24 = OpLabel -OpStore %r %20 -OpBranch %23 -%25 = OpLabel -%28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1 -%29 = OpFSub %v4float %28 %20 -OpStore %r %29 -OpBranch %23 -%23 = OpLabel -%30 = OpLoad %v4float %r -OpStore %gl_FragColor %30 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, - predefs + after, true, true); -} - -TEST_F(LocalSingleStoreElimTest, NoStoreElimWithInterveningAccessChainLoad) { - // Last load of v is eliminated, but access chain load and store of v isn't - // - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // float f = v[3]; - // gl_FragColor = v * f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %f "f" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%uint = OpTypeInt 32 0 -%uint_3 = OpConstant %uint 3 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -%19 = OpAccessChain %_ptr_Function_float %v %uint_3 -%20 = OpLoad %float %19 -OpStore %f %20 -%21 = OpLoad %v4float %v -%22 = OpLoad %float %f -%23 = OpVectorTimesScalar %v4float %21 %22 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -%19 = OpAccessChain %_ptr_Function_float %v %uint_3 -%20 = OpLoad %float %19 -OpStore %f %20 -%23 = OpVectorTimesScalar %v4float %18 %20 -OpStore %gl_FragColor %23 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, - predefs + after, true, true); -} - -TEST_F(LocalSingleStoreElimTest, NoReplaceOfDominatingPartialStore) { - // Note: SPIR-V hand edited to initialize v to vec4(0.0) - // - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v; - // float v[1] = 1.0; - // gl_FragColor = v; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %gl_FragColor "gl_FragColor" -OpName %BaseColor "BaseColor" -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%float_1 = OpConstant %float 1 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %7 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function %12 -%20 = OpAccessChain %_ptr_Function_float %v %uint_1 -OpStore %20 %float_1 -%21 = OpLoad %v4float %v -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, - true); -} - -TEST_F(LocalSingleStoreElimTest, ElimIfCopyObjectInFunction) { - // Note: hand edited to insert OpCopyObject - // - // #version 140 - // - // in vec4 BaseColor; - // in float fi; - // - // void main() - // { - // vec4 v = BaseColor; - // float f = fi; - // if (f < 0) - // f = 0.0; - // gl_FragColor = v + f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %f "f" -OpName %fi "fi" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -OpStore %f %21 -%22 = OpLoad %float %f -%23 = OpFOrdLessThan %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %24 -%25 = OpLabel -OpStore %f %float_0 -OpBranch %24 -%24 = OpLabel -%26 = OpCopyObject %_ptr_Function_v4float %v -%27 = OpLoad %v4float %26 -%28 = OpLoad %float %f -%29 = OpCompositeConstruct %v4float %28 %28 %28 %28 -%30 = OpFAdd %v4float %27 %29 -OpStore %gl_FragColor %30 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%19 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%f = OpVariable %_ptr_Function_float Function -%20 = OpLoad %v4float %BaseColor -OpStore %v %20 -%21 = OpLoad %float %fi -OpStore %f %21 -%22 = OpLoad %float %f -%23 = OpFOrdLessThan %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %24 -%25 = OpLabel -OpStore %f %float_0 -OpBranch %24 -%24 = OpLabel -%26 = OpCopyObject %_ptr_Function_v4float %v -%28 = OpLoad %float %f -%29 = OpCompositeConstruct %v4float %28 %28 %28 %28 -%30 = OpFAdd %v4float %20 %29 -OpStore %gl_FragColor %30 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, - predefs + after, true, true); -} - -TEST_F(LocalSingleStoreElimTest, NoOptIfStoreNotDominating) { - // Single store to f not optimized because it does not dominate - // the load. - // - // #version 140 - // - // in vec4 BaseColor; - // in float fi; - // - // void main() - // { - // float f; - // if (fi < 0) - // f = 0.5; - // if (fi < 0) - // gl_FragColor = BaseColor * f; - // else - // gl_FragColor = BaseColor; - // } - - const std::string assembly = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %fi %gl_FragColor %BaseColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %fi "fi" -OpName %f "f" -OpName %gl_FragColor "gl_FragColor" -OpName %BaseColor "BaseColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%_ptr_Function_float = OpTypePointer Function %float -%float_0_5 = OpConstant %float 0.5 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%main = OpFunction %void None %8 -%18 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%19 = OpLoad %float %fi -%20 = OpFOrdLessThan %bool %19 %float_0 -OpSelectionMerge %21 None -OpBranchConditional %20 %22 %21 -%22 = OpLabel -OpStore %f %float_0_5 -OpBranch %21 -%21 = OpLabel -%23 = OpLoad %float %fi -%24 = OpFOrdLessThan %bool %23 %float_0 -OpSelectionMerge %25 None -OpBranchConditional %24 %26 %27 -%26 = OpLabel -%28 = OpLoad %v4float %BaseColor -%29 = OpLoad %float %f -%30 = OpVectorTimesScalar %v4float %28 %29 -OpStore %gl_FragColor %30 -OpBranch %25 -%27 = OpLabel -%31 = OpLoad %v4float %BaseColor -OpStore %gl_FragColor %31 -OpBranch %25 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(assembly, assembly, true, - true); -} - -TEST_F(LocalSingleStoreElimTest, OptInitializedVariableLikeStore) { - // Initialized variable f is optimized like it was a store. - // Note: The SPIR-V was edited to turn the store to f to an - // an initialization. - // - // #version 140 - // - // void main() - // { - // float f = 0.0; - // gl_FragColor = vec4(f); - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %f "f" -OpName %gl_FragColor "gl_FragColor" -OpDecorate %gl_FragColor Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %6 -%12 = OpLabel -%f = OpVariable %_ptr_Function_float Function %float_0 -%13 = OpLoad %float %f -%14 = OpCompositeConstruct %v4float %13 %13 %13 %13 -OpStore %gl_FragColor %14 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %6 -%12 = OpLabel -%f = OpVariable %_ptr_Function_float Function %float_0 -%14 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_0 -OpStore %gl_FragColor %14 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, - predefs + after, true, true); -} - -TEST_F(LocalSingleStoreElimTest, PointerVariable) { - // Test that checks if a pointer variable is removed. - - const std::string before = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%26 = OpLoad %_ptr_Uniform__struct_5 %24 -%27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - // Relax logical pointers to allow pointer allocations. - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ValidatorOptions()->relax_logical_pointer = true; - SinglePassRunAndCheck(before, after, true, true); -} - -// Test that that an unused OpAccessChain between a store and a use does does -// not hinders the replacement of the use. We need to check this because -// local-access-chain-convert does always remove the OpAccessChain instructions -// that become dead. - -TEST_F(LocalSingleStoreElimTest, - StoreElimWithUnusedInterveningAccessChainLoad) { - // Last load of v is eliminated, but access chain load and store of v isn't - // - // #version 140 - // - // in vec4 BaseColor; - // - // void main() - // { - // vec4 v = BaseColor; - // float f = v[3]; - // gl_FragColor = v * f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Function_float = OpTypePointer Function %float -%uint = OpTypeInt 32 0 -%uint_3 = OpConstant %uint 3 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -%19 = OpAccessChain %_ptr_Function_float %v %uint_3 -%21 = OpLoad %v4float %v -OpStore %gl_FragColor %21 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%17 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%18 = OpLoad %v4float %BaseColor -OpStore %v %18 -%19 = OpAccessChain %_ptr_Function_float %v %uint_3 -OpStore %gl_FragColor %18 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(predefs + before, - predefs + after, true, true); -} - -TEST_F(LocalSingleStoreElimTest, VariablePointerTest) { - // Check that the load of the first variable is still used and that the load - // of the third variable is propagated. The first load has to remain because - // of the store to the variable pointer. - const std::string text = R"( -; CHECK: [[v1:%\w+]] = OpVariable -; CHECK: [[v2:%\w+]] = OpVariable -; CHECK: [[v3:%\w+]] = OpVariable -; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]] -; CHECK: OpIAdd %int [[ld1]] %int_0 - OpCapability Shader - OpCapability VariablePointers - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 1 1 - OpSource GLSL 450 - OpMemberDecorate %_struct_3 0 Offset 0 - OpMemberDecorate %_struct_3 1 Offset 4 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool - %_struct_3 = OpTypeStruct %int %int -%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3 -%_ptr_Function_int = OpTypePointer Function %int - %true = OpConstantTrue %bool - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %13 = OpConstantNull %_struct_3 - %2 = OpFunction %void None %5 - %14 = OpLabel - %15 = OpVariable %_ptr_Function_int Function - %16 = OpVariable %_ptr_Function_int Function - %17 = OpVariable %_ptr_Function_int Function - OpStore %15 %int_1 - OpStore %17 %int_0 - OpSelectionMerge %18 None - OpBranchConditional %true %19 %20 - %19 = OpLabel - OpBranch %18 - %20 = OpLabel - OpBranch %18 - %18 = OpLabel - %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20 - OpStore %21 %int_0 - %22 = OpLoad %int %15 - %23 = OpLoad %int %17 - %24 = OpIAdd %int %22 %23 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// Other types -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/local_ssa_elim_test.cpp b/3rdparty/spirv-tools/test/opt/local_ssa_elim_test.cpp deleted file mode 100644 index 7afbb4cf4..000000000 --- a/3rdparty/spirv-tools/test/opt/local_ssa_elim_test.cpp +++ /dev/null @@ -1,2012 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using LocalSSAElimTest = PassTest<::testing::Test>; - -TEST_F(LocalSSAElimTest, ForLoop) { - // #version 140 - // - // in vec4 BC; - // out float fo; - // - // void main() - // { - // float f = 0.0; - // for (int i=0; i<4; i++) { - // f = f + BC[i]; - // } - // fo = f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BC %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %f "f" -OpName %i "i" -OpName %BC "BC" -OpName %fo "fo" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_4 = OpConstant %int 4 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BC = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %23 -%23 = OpLabel -OpLoopMerge %24 %25 None -OpBranch %26 -%26 = OpLabel -%27 = OpLoad %int %i -%28 = OpSLessThan %bool %27 %int_4 -OpBranchConditional %28 %29 %24 -%29 = OpLabel -%30 = OpLoad %float %f -%31 = OpLoad %int %i -%32 = OpAccessChain %_ptr_Input_float %BC %31 -%33 = OpLoad %float %32 -%34 = OpFAdd %float %30 %33 -OpStore %f %34 -OpBranch %25 -%25 = OpLabel -%35 = OpLoad %int %i -%36 = OpIAdd %int %35 %int_1 -OpStore %i %36 -OpBranch %23 -%24 = OpLabel -%37 = OpLoad %float %f -OpStore %fo %37 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%22 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %23 -%23 = OpLabel -%39 = OpPhi %float %float_0 %22 %34 %25 -%38 = OpPhi %int %int_0 %22 %36 %25 -OpLoopMerge %24 %25 None -OpBranch %26 -%26 = OpLabel -%28 = OpSLessThan %bool %38 %int_4 -OpBranchConditional %28 %29 %24 -%29 = OpLabel -%32 = OpAccessChain %_ptr_Input_float %BC %38 -%33 = OpLoad %float %32 -%34 = OpFAdd %float %39 %33 -OpStore %f %34 -OpBranch %25 -%25 = OpLabel -%36 = OpIAdd %int %38 %int_1 -OpStore %i %36 -OpBranch %23 -%24 = OpLabel -OpStore %fo %39 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, NestedForLoop) { - // #version 450 - // - // layout (location=0) in mat4 BC; - // layout (location=0) out float fo; - // - // void main() - // { - // float f = 0.0; - // for (int i=0; i<4; i++) - // for (int j=0; j<4; j++) - // f = f + BC[i][j]; - // fo = f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BC %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %f "f" -OpName %i "i" -OpName %j "j" -OpName %BC "BC" -OpName %fo "fo" -OpDecorate %BC Location 0 -OpDecorate %fo Location 0 -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_4 = OpConstant %int 4 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%mat4v4float = OpTypeMatrix %v4float 4 -%_ptr_Input_mat4v4float = OpTypePointer Input %mat4v4float -%BC = OpVariable %_ptr_Input_mat4v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -)"; - - const std::string before = - R"( -; CHECK: = OpFunction -; CHECK-NEXT: [[entry:%\w+]] = OpLabel -; CHECK: [[outer_header:%\w+]] = OpLabel -; CHECK-NEXT: [[outer_f:%\w+]] = OpPhi %float %float_0 [[entry]] [[inner_f:%\w+]] [[outer_be:%\w+]] -; CHECK-NEXT: [[i:%\w+]] = OpPhi %int %int_0 [[entry]] [[i_next:%\w+]] [[outer_be]] -; CHECK-NEXT: OpSLessThan {{%\w+}} [[i]] -; CHECK: [[inner_pre_header:%\w+]] = OpLabel -; CHECK: [[inner_header:%\w+]] = OpLabel -; CHECK-NEXT: [[inner_f]] = OpPhi %float [[outer_f]] [[inner_pre_header]] [[f_next:%\w+]] [[inner_be:%\w+]] -; CHECK-NEXT: [[j:%\w+]] = OpPhi %int %int_0 [[inner_pre_header]] [[j_next:%\w+]] [[inner_be]] -; CHECK: [[inner_be]] = OpLabel -; CHECK: [[f_next]] = OpFAdd %float [[inner_f]] -; CHECK: [[j_next]] = OpIAdd %int [[j]] %int_1 -; CHECK: [[outer_be]] = OpLabel -; CHECK: [[i_next]] = OpIAdd -; CHECK: OpStore %fo [[outer_f]] -%main = OpFunction %void None %9 -%24 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%j = OpVariable %_ptr_Function_int Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %25 -%25 = OpLabel -%26 = OpLoad %int %i -%27 = OpSLessThan %bool %26 %int_4 -OpLoopMerge %28 %29 None -OpBranchConditional %27 %30 %28 -%30 = OpLabel -OpStore %j %int_0 -OpBranch %31 -%31 = OpLabel -%32 = OpLoad %int %j -%33 = OpSLessThan %bool %32 %int_4 -OpLoopMerge %50 %34 None -OpBranchConditional %33 %34 %50 -%34 = OpLabel -%35 = OpLoad %float %f -%36 = OpLoad %int %i -%37 = OpLoad %int %j -%38 = OpAccessChain %_ptr_Input_float %BC %36 %37 -%39 = OpLoad %float %38 -%40 = OpFAdd %float %35 %39 -OpStore %f %40 -%41 = OpLoad %int %j -%42 = OpIAdd %int %41 %int_1 -OpStore %j %42 -OpBranch %31 -%50 = OpLabel -OpBranch %29 -%29 = OpLabel -%43 = OpLoad %int %i -%44 = OpIAdd %int %43 %int_1 -OpStore %i %44 -OpBranch %25 -%28 = OpLabel -%45 = OpLoad %float %f -OpStore %fo %45 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(predefs + before, true); -} - -TEST_F(LocalSSAElimTest, ForLoopWithContinue) { - // #version 140 - // - // in vec4 BC; - // out float fo; - // - // void main() - // { - // float f = 0.0; - // for (int i=0; i<4; i++) { - // float t = BC[i]; - // if (t < 0.0) - // continue; - // f = f + t; - // } - // fo = f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BC %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -)"; - - const std::string names = - R"(OpName %main "main" -OpName %f "f" -OpName %i "i" -OpName %t "t" -OpName %BC "BC" -OpName %fo "fo" -)"; - - const std::string predefs2 = - R"(%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_4 = OpConstant %int 4 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BC = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%23 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %24 -%24 = OpLabel -OpLoopMerge %25 %26 None -OpBranch %27 -%27 = OpLabel -%28 = OpLoad %int %i -%29 = OpSLessThan %bool %28 %int_4 -OpBranchConditional %29 %30 %25 -%30 = OpLabel -%31 = OpLoad %int %i -%32 = OpAccessChain %_ptr_Input_float %BC %31 -%33 = OpLoad %float %32 -OpStore %t %33 -%34 = OpLoad %float %t -%35 = OpFOrdLessThan %bool %34 %float_0 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %36 -%37 = OpLabel -OpBranch %26 -%36 = OpLabel -%38 = OpLoad %float %f -%39 = OpLoad %float %t -%40 = OpFAdd %float %38 %39 -OpStore %f %40 -OpBranch %26 -%26 = OpLabel -%41 = OpLoad %int %i -%42 = OpIAdd %int %41 %int_1 -OpStore %i %42 -OpBranch %24 -%25 = OpLabel -%43 = OpLoad %float %f -OpStore %fo %43 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%23 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %24 -%24 = OpLabel -%45 = OpPhi %float %float_0 %23 %47 %26 -%44 = OpPhi %int %int_0 %23 %42 %26 -OpLoopMerge %25 %26 None -OpBranch %27 -%27 = OpLabel -%29 = OpSLessThan %bool %44 %int_4 -OpBranchConditional %29 %30 %25 -%30 = OpLabel -%32 = OpAccessChain %_ptr_Input_float %BC %44 -%33 = OpLoad %float %32 -OpStore %t %33 -%35 = OpFOrdLessThan %bool %33 %float_0 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %36 -%37 = OpLabel -OpBranch %26 -%36 = OpLabel -%40 = OpFAdd %float %45 %33 -OpStore %f %40 -OpBranch %26 -%26 = OpLabel -%47 = OpPhi %float %45 %37 %40 %36 -%42 = OpIAdd %int %44 %int_1 -OpStore %i %42 -OpBranch %24 -%25 = OpLabel -OpStore %fo %45 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + names + predefs2 + before, - predefs + names + predefs2 + after, - true, true); -} - -TEST_F(LocalSSAElimTest, ForLoopWithBreak) { - // #version 140 - // - // in vec4 BC; - // out float fo; - // - // void main() - // { - // float f = 0.0; - // for (int i=0; i<4; i++) { - // float t = f + BC[i]; - // if (t > 1.0) - // break; - // f = t; - // } - // fo = f; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BC %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %f "f" -OpName %i "i" -OpName %t "t" -OpName %BC "BC" -OpName %fo "fo" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_4 = OpConstant %int 4 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BC = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%24 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %25 -%25 = OpLabel -OpLoopMerge %26 %27 None -OpBranch %28 -%28 = OpLabel -%29 = OpLoad %int %i -%30 = OpSLessThan %bool %29 %int_4 -OpBranchConditional %30 %31 %26 -%31 = OpLabel -%32 = OpLoad %float %f -%33 = OpLoad %int %i -%34 = OpAccessChain %_ptr_Input_float %BC %33 -%35 = OpLoad %float %34 -%36 = OpFAdd %float %32 %35 -OpStore %t %36 -%37 = OpLoad %float %t -%38 = OpFOrdGreaterThan %bool %37 %float_1 -OpSelectionMerge %39 None -OpBranchConditional %38 %40 %39 -%40 = OpLabel -OpBranch %26 -%39 = OpLabel -%41 = OpLoad %float %t -OpStore %f %41 -OpBranch %27 -%27 = OpLabel -%42 = OpLoad %int %i -%43 = OpIAdd %int %42 %int_1 -OpStore %i %43 -OpBranch %25 -%26 = OpLabel -%44 = OpLoad %float %f -OpStore %fo %44 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%24 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %25 -%25 = OpLabel -%46 = OpPhi %float %float_0 %24 %36 %27 -%45 = OpPhi %int %int_0 %24 %43 %27 -OpLoopMerge %26 %27 None -OpBranch %28 -%28 = OpLabel -%30 = OpSLessThan %bool %45 %int_4 -OpBranchConditional %30 %31 %26 -%31 = OpLabel -%34 = OpAccessChain %_ptr_Input_float %BC %45 -%35 = OpLoad %float %34 -%36 = OpFAdd %float %46 %35 -OpStore %t %36 -%38 = OpFOrdGreaterThan %bool %36 %float_1 -OpSelectionMerge %39 None -OpBranchConditional %38 %40 %39 -%40 = OpLabel -OpBranch %26 -%39 = OpLabel -OpStore %f %36 -OpBranch %27 -%27 = OpLabel -%43 = OpIAdd %int %45 %int_1 -OpStore %i %43 -OpBranch %25 -%26 = OpLabel -OpStore %fo %46 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, SwapProblem) { - // #version 140 - // - // in float fe; - // out float fo; - // - // void main() - // { - // float f1 = 0.0; - // float f2 = 1.0; - // int ie = int(fe); - // for (int i=0; i(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, LostCopyProblem) { - // #version 140 - // - // in vec4 BC; - // out float fo; - // - // void main() - // { - // float f = 0.0; - // float t; - // for (int i=0; i<4; i++) { - // t = f; - // f = f + BC[i]; - // if (f > 1.0) - // break; - // } - // fo = t; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BC %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %f "f" -OpName %i "i" -OpName %t "t" -OpName %BC "BC" -OpName %fo "fo" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_4 = OpConstant %int 4 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BC = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%24 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %25 -%25 = OpLabel -OpLoopMerge %26 %27 None -OpBranch %28 -%28 = OpLabel -%29 = OpLoad %int %i -%30 = OpSLessThan %bool %29 %int_4 -OpBranchConditional %30 %31 %26 -%31 = OpLabel -%32 = OpLoad %float %f -OpStore %t %32 -%33 = OpLoad %float %f -%34 = OpLoad %int %i -%35 = OpAccessChain %_ptr_Input_float %BC %34 -%36 = OpLoad %float %35 -%37 = OpFAdd %float %33 %36 -OpStore %f %37 -%38 = OpLoad %float %f -%39 = OpFOrdGreaterThan %bool %38 %float_1 -OpSelectionMerge %40 None -OpBranchConditional %39 %41 %40 -%41 = OpLabel -OpBranch %26 -%40 = OpLabel -OpBranch %27 -%27 = OpLabel -%42 = OpLoad %int %i -%43 = OpIAdd %int %42 %int_1 -OpStore %i %43 -OpBranch %25 -%26 = OpLabel -%44 = OpLoad %float %t -OpStore %fo %44 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%49 = OpUndef %float -%main = OpFunction %void None %9 -%24 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -%t = OpVariable %_ptr_Function_float Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %25 -%25 = OpLabel -%46 = OpPhi %float %float_0 %24 %37 %27 -%45 = OpPhi %int %int_0 %24 %43 %27 -%48 = OpPhi %float %49 %24 %46 %27 -OpLoopMerge %26 %27 None -OpBranch %28 -%28 = OpLabel -%30 = OpSLessThan %bool %45 %int_4 -OpBranchConditional %30 %31 %26 -%31 = OpLabel -OpStore %t %46 -%35 = OpAccessChain %_ptr_Input_float %BC %45 -%36 = OpLoad %float %35 -%37 = OpFAdd %float %46 %36 -OpStore %f %37 -%39 = OpFOrdGreaterThan %bool %37 %float_1 -OpSelectionMerge %40 None -OpBranchConditional %39 %41 %40 -%41 = OpLabel -OpBranch %26 -%40 = OpLabel -OpBranch %27 -%27 = OpLabel -%43 = OpIAdd %int %45 %int_1 -OpStore %i %43 -OpBranch %25 -%26 = OpLabel -%47 = OpPhi %float %48 %28 %46 %41 -OpStore %fo %47 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, IfThenElse) { - // #version 140 - // - // in vec4 BaseColor; - // in float f; - // - // void main() - // { - // vec4 v; - // if (f >= 0) - // v = BaseColor * 0.5; - // else - // v = BaseColor + vec4(1.0,1.0,1.0,1.0); - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %f %BaseColor %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %f "f" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Input_float = OpTypePointer Input %float -%f = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%float_0_5 = OpConstant %float 0.5 -%float_1 = OpConstant %float 1 -%18 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%20 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %float %f -%22 = OpFOrdGreaterThanEqual %bool %21 %float_0 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %25 -%24 = OpLabel -%26 = OpLoad %v4float %BaseColor -%27 = OpVectorTimesScalar %v4float %26 %float_0_5 -OpStore %v %27 -OpBranch %23 -%25 = OpLabel -%28 = OpLoad %v4float %BaseColor -%29 = OpFAdd %v4float %28 %18 -OpStore %v %29 -OpBranch %23 -%23 = OpLabel -%30 = OpLoad %v4float %v -OpStore %gl_FragColor %30 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%20 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%21 = OpLoad %float %f -%22 = OpFOrdGreaterThanEqual %bool %21 %float_0 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %25 -%24 = OpLabel -%26 = OpLoad %v4float %BaseColor -%27 = OpVectorTimesScalar %v4float %26 %float_0_5 -OpStore %v %27 -OpBranch %23 -%25 = OpLabel -%28 = OpLoad %v4float %BaseColor -%29 = OpFAdd %v4float %28 %18 -OpStore %v %29 -OpBranch %23 -%23 = OpLabel -%31 = OpPhi %v4float %27 %24 %29 %25 -OpStore %gl_FragColor %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, IfThen) { - // #version 140 - // - // in vec4 BaseColor; - // in float f; - // - // void main() - // { - // vec4 v = BaseColor; - // if (f <= 0) - // v = v * 0.5; - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %f "f" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%f = OpVariable %_ptr_Input_float Input -%float_0 = OpConstant %float 0 -%bool = OpTypeBool -%float_0_5 = OpConstant %float 0.5 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %8 -%18 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%19 = OpLoad %v4float %BaseColor -OpStore %v %19 -%20 = OpLoad %float %f -%21 = OpFOrdLessThanEqual %bool %20 %float_0 -OpSelectionMerge %22 None -OpBranchConditional %21 %23 %22 -%23 = OpLabel -%24 = OpLoad %v4float %v -%25 = OpVectorTimesScalar %v4float %24 %float_0_5 -OpStore %v %25 -OpBranch %22 -%22 = OpLabel -%26 = OpLoad %v4float %v -OpStore %gl_FragColor %26 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %8 -%18 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%19 = OpLoad %v4float %BaseColor -OpStore %v %19 -%20 = OpLoad %float %f -%21 = OpFOrdLessThanEqual %bool %20 %float_0 -OpSelectionMerge %22 None -OpBranchConditional %21 %23 %22 -%23 = OpLabel -%25 = OpVectorTimesScalar %v4float %19 %float_0_5 -OpStore %v %25 -OpBranch %22 -%22 = OpLabel -%27 = OpPhi %v4float %19 %18 %25 %23 -OpStore %gl_FragColor %27 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, Switch) { - // #version 140 - // - // in vec4 BaseColor; - // in float f; - // - // void main() - // { - // vec4 v = BaseColor; - // int i = int(f); - // switch (i) { - // case 0: - // v = v * 0.25; - // break; - // case 1: - // v = v * 0.625; - // break; - // case 2: - // v = v * 0.75; - // break; - // default: - // break; - // } - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %i "i" -OpName %f "f" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_float = OpTypePointer Input %float -%f = OpVariable %_ptr_Input_float Input -%float_0_25 = OpConstant %float 0.25 -%float_0_625 = OpConstant %float 0.625 -%float_0_75 = OpConstant %float 0.75 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%i = OpVariable %_ptr_Function_int Function -%22 = OpLoad %v4float %BaseColor -OpStore %v %22 -%23 = OpLoad %float %f -%24 = OpConvertFToS %int %23 -OpStore %i %24 -%25 = OpLoad %int %i -OpSelectionMerge %26 None -OpSwitch %25 %27 0 %28 1 %29 2 %30 -%27 = OpLabel -OpBranch %26 -%28 = OpLabel -%31 = OpLoad %v4float %v -%32 = OpVectorTimesScalar %v4float %31 %float_0_25 -OpStore %v %32 -OpBranch %26 -%29 = OpLabel -%33 = OpLoad %v4float %v -%34 = OpVectorTimesScalar %v4float %33 %float_0_625 -OpStore %v %34 -OpBranch %26 -%30 = OpLabel -%35 = OpLoad %v4float %v -%36 = OpVectorTimesScalar %v4float %35 %float_0_75 -OpStore %v %36 -OpBranch %26 -%26 = OpLabel -%37 = OpLoad %v4float %v -OpStore %gl_FragColor %37 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%i = OpVariable %_ptr_Function_int Function -%22 = OpLoad %v4float %BaseColor -OpStore %v %22 -%23 = OpLoad %float %f -%24 = OpConvertFToS %int %23 -OpStore %i %24 -OpSelectionMerge %26 None -OpSwitch %24 %27 0 %28 1 %29 2 %30 -%27 = OpLabel -OpBranch %26 -%28 = OpLabel -%32 = OpVectorTimesScalar %v4float %22 %float_0_25 -OpStore %v %32 -OpBranch %26 -%29 = OpLabel -%34 = OpVectorTimesScalar %v4float %22 %float_0_625 -OpStore %v %34 -OpBranch %26 -%30 = OpLabel -%36 = OpVectorTimesScalar %v4float %22 %float_0_75 -OpStore %v %36 -OpBranch %26 -%26 = OpLabel -%38 = OpPhi %v4float %22 %27 %32 %28 %34 %29 %36 %30 -OpStore %gl_FragColor %38 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, SwitchWithFallThrough) { - // #version 140 - // - // in vec4 BaseColor; - // in float f; - // - // void main() - // { - // vec4 v = BaseColor; - // int i = int(f); - // switch (i) { - // case 0: - // v = v * 0.25; - // break; - // case 1: - // v = v + 0.25; - // case 2: - // v = v * 0.75; - // break; - // default: - // break; - // } - // gl_FragColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %v "v" -OpName %BaseColor "BaseColor" -OpName %i "i" -OpName %f "f" -OpName %gl_FragColor "gl_FragColor" -%void = OpTypeVoid -%9 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BaseColor = OpVariable %_ptr_Input_v4float Input -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_float = OpTypePointer Input %float -%f = OpVariable %_ptr_Input_float Input -%float_0_25 = OpConstant %float 0.25 -%float_0_75 = OpConstant %float 0.75 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%gl_FragColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string before = - R"(%main = OpFunction %void None %9 -%20 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%i = OpVariable %_ptr_Function_int Function -%21 = OpLoad %v4float %BaseColor -OpStore %v %21 -%22 = OpLoad %float %f -%23 = OpConvertFToS %int %22 -OpStore %i %23 -%24 = OpLoad %int %i -OpSelectionMerge %25 None -OpSwitch %24 %26 0 %27 1 %28 2 %29 -%26 = OpLabel -OpBranch %25 -%27 = OpLabel -%30 = OpLoad %v4float %v -%31 = OpVectorTimesScalar %v4float %30 %float_0_25 -OpStore %v %31 -OpBranch %25 -%28 = OpLabel -%32 = OpLoad %v4float %v -%33 = OpCompositeConstruct %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25 -%34 = OpFAdd %v4float %32 %33 -OpStore %v %34 -OpBranch %29 -%29 = OpLabel -%35 = OpLoad %v4float %v -%36 = OpVectorTimesScalar %v4float %35 %float_0_75 -OpStore %v %36 -OpBranch %25 -%25 = OpLabel -%37 = OpLoad %v4float %v -OpStore %gl_FragColor %37 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %9 -%20 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function -%i = OpVariable %_ptr_Function_int Function -%21 = OpLoad %v4float %BaseColor -OpStore %v %21 -%22 = OpLoad %float %f -%23 = OpConvertFToS %int %22 -OpStore %i %23 -OpSelectionMerge %25 None -OpSwitch %23 %26 0 %27 1 %28 2 %29 -%26 = OpLabel -OpBranch %25 -%27 = OpLabel -%31 = OpVectorTimesScalar %v4float %21 %float_0_25 -OpStore %v %31 -OpBranch %25 -%28 = OpLabel -%33 = OpCompositeConstruct %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25 -%34 = OpFAdd %v4float %21 %33 -OpStore %v %34 -OpBranch %29 -%29 = OpLabel -%38 = OpPhi %v4float %21 %20 %34 %28 -%36 = OpVectorTimesScalar %v4float %38 %float_0_75 -OpStore %v %36 -OpBranch %25 -%25 = OpLabel -%39 = OpPhi %v4float %21 %26 %31 %27 %36 %29 -OpStore %gl_FragColor %39 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, true, - true); -} - -TEST_F(LocalSSAElimTest, DontPatchPhiInLoopHeaderThatIsNotAVar) { - // From https://github.com/KhronosGroup/SPIRV-Tools/issues/826 - // Don't try patching the (%16 %7) value/predecessor pair in the OpPhi. - // That OpPhi is unrelated to this optimization: we did not set that up - // in the SSA initialization for the loop header block. - // The pass should be a no-op on this module. - - const std::string before = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%float_1 = OpConstant %float 1 -%1 = OpFunction %void None %3 -%6 = OpLabel -OpBranch %7 -%7 = OpLabel -%8 = OpPhi %float %float_1 %6 %9 %7 -%9 = OpFAdd %float %8 %float_1 -OpLoopMerge %10 %7 None -OpBranch %7 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, before, true, true); -} - -TEST_F(LocalSSAElimTest, OptInitializedVariableLikeStore) { - // Note: SPIR-V edited to change store to v into variable initialization - // - // #version 450 - // - // layout (location=0) in vec4 iColor; - // layout (location=1) in float fi; - // layout (location=0) out vec4 oColor; - // - // void main() - // { - // vec4 v = vec4(0.0); - // if (fi < 0.0) - // v.x = iColor.x; - // oColor = v; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %fi %iColor %oColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %v "v" -OpName %fi "fi" -OpName %iColor "iColor" -OpName %oColor "oColor" -OpDecorate %fi Location 1 -OpDecorate %iColor Location 0 -OpDecorate %oColor Location 0 -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%float_0 = OpConstant %float 0 -%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%_ptr_Input_float = OpTypePointer Input %float -%fi = OpVariable %_ptr_Input_float Input -%bool = OpTypeBool -%_ptr_Input_v4float = OpTypePointer Input %v4float -%iColor = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%oColor = OpVariable %_ptr_Output_v4float Output -)"; - - const std::string func_before = - R"(%main = OpFunction %void None %8 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function %13 -%22 = OpLoad %float %fi -%23 = OpFOrdLessThan %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %24 -%25 = OpLabel -%26 = OpAccessChain %_ptr_Input_float %iColor %uint_0 -%27 = OpLoad %float %26 -%28 = OpLoad %v4float %v -%29 = OpCompositeInsert %v4float %27 %28 0 -OpStore %v %29 -OpBranch %24 -%24 = OpLabel -%30 = OpLoad %v4float %v -OpStore %oColor %30 -OpReturn -OpFunctionEnd -)"; - - const std::string func_after = - R"(%main = OpFunction %void None %8 -%21 = OpLabel -%v = OpVariable %_ptr_Function_v4float Function %13 -%22 = OpLoad %float %fi -%23 = OpFOrdLessThan %bool %22 %float_0 -OpSelectionMerge %24 None -OpBranchConditional %23 %25 %24 -%25 = OpLabel -%26 = OpAccessChain %_ptr_Input_float %iColor %uint_0 -%27 = OpLoad %float %26 -%29 = OpCompositeInsert %v4float %27 %13 0 -OpStore %v %29 -OpBranch %24 -%24 = OpLabel -%31 = OpPhi %v4float %13 %21 %29 %25 -OpStore %oColor %31 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + func_before, - predefs + func_after, true, true); -} - -TEST_F(LocalSSAElimTest, PointerVariable) { - // Test that checks if a pointer variable is removed. - - const std::string before = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%26 = OpLoad %_ptr_Uniform__struct_5 %24 -%27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpMemberDecorate %_struct_3 0 Offset 0 -OpDecorate %_runtimearr__struct_3 ArrayStride 16 -OpMemberDecorate %_struct_5 0 Offset 0 -OpDecorate %_struct_5 BufferBlock -OpMemberDecorate %_struct_6 0 Offset 0 -OpDecorate %_struct_6 BufferBlock -OpDecorate %2 Location 0 -OpDecorate %7 DescriptorSet 0 -OpDecorate %7 Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%_struct_3 = OpTypeStruct %v4float -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 -%_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 -%_struct_6 = OpTypeStruct %int -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 -%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 -%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%2 = OpVariable %_ptr_Output_v4float Output -%7 = OpVariable %_ptr_Uniform__struct_5 Uniform -%1 = OpFunction %void None %10 -%23 = OpLabel -%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function -OpStore %24 %7 -%27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0 -%28 = OpLoad %v4float %27 -%29 = OpCopyObject %v4float %28 -OpStore %2 %28 -OpReturn -OpFunctionEnd -)"; - - // Relax logical pointers to allow pointer allocations. - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ValidatorOptions()->relax_logical_pointer = true; - SinglePassRunAndCheck(before, after, true, true); -} - -TEST_F(LocalSSAElimTest, VerifyInstToBlockMap) { - // #version 140 - // - // in vec4 BC; - // out float fo; - // - // void main() - // { - // float f = 0.0; - // for (int i=0; i<4; i++) { - // f = f + BC[i]; - // } - // fo = f; - // } - - const std::string text = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %BC %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 140 -OpName %main "main" -OpName %f "f" -OpName %i "i" -OpName %BC "BC" -OpName %fo "fo" -%void = OpTypeVoid -%8 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_4 = OpConstant %int 4 -%bool = OpTypeBool -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%BC = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%int_1 = OpConstant %int 1 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %8 -%22 = OpLabel -%f = OpVariable %_ptr_Function_float Function -%i = OpVariable %_ptr_Function_int Function -OpStore %f %float_0 -OpStore %i %int_0 -OpBranch %23 -%23 = OpLabel -OpLoopMerge %24 %25 None -OpBranch %26 -%26 = OpLabel -%27 = OpLoad %int %i -%28 = OpSLessThan %bool %27 %int_4 -OpBranchConditional %28 %29 %24 -%29 = OpLabel -%30 = OpLoad %float %f -%31 = OpLoad %int %i -%32 = OpAccessChain %_ptr_Input_float %BC %31 -%33 = OpLoad %float %32 -%34 = OpFAdd %float %30 %33 -OpStore %f %34 -OpBranch %25 -%25 = OpLabel -%35 = OpLoad %int %i -%36 = OpIAdd %int %35 %int_1 -OpStore %i %36 -OpBranch %23 -%24 = OpLabel -%37 = OpLoad %float %f -OpStore %fo %37 -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(nullptr, context); - - // Force the instruction to block mapping to get built. - context->get_instr_block(27u); - - auto pass = MakeUnique(); - pass->SetMessageConsumer(nullptr); - const auto status = pass->Run(context.get()); - EXPECT_TRUE(status == Pass::Status::SuccessWithChange); -} - -TEST_F(LocalSSAElimTest, CompositeExtractProblem) { - const std::string spv_asm = R"( - OpCapability Tessellation - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint TessellationControl %2 "main" %16 %17 %18 %20 %22 %26 %27 %30 %31 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 - %v3float = OpTypeVector %float 3 - %v2float = OpTypeVector %float 2 - %_struct_11 = OpTypeStruct %v4float %v4float %v4float %v3float %v3float %v2float %v2float -%_arr__struct_11_uint_3 = OpTypeArray %_struct_11 %uint_3 -%_ptr_Function__arr__struct_11_uint_3 = OpTypePointer Function %_arr__struct_11_uint_3 -%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3 -%_ptr_Input__arr_v4float_uint_3 = OpTypePointer Input %_arr_v4float_uint_3 - %16 = OpVariable %_ptr_Input__arr_v4float_uint_3 Input - %17 = OpVariable %_ptr_Input__arr_v4float_uint_3 Input - %18 = OpVariable %_ptr_Input__arr_v4float_uint_3 Input -%_ptr_Input_uint = OpTypePointer Input %uint - %20 = OpVariable %_ptr_Input_uint Input -%_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3 - %22 = OpVariable %_ptr_Output__arr_v4float_uint_3 Output -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_arr_v3float_uint_3 = OpTypeArray %v3float %uint_3 -%_ptr_Input__arr_v3float_uint_3 = OpTypePointer Input %_arr_v3float_uint_3 - %26 = OpVariable %_ptr_Input__arr_v3float_uint_3 Input - %27 = OpVariable %_ptr_Input__arr_v3float_uint_3 Input -%_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3 -%_ptr_Input__arr_v2float_uint_3 = OpTypePointer Input %_arr_v2float_uint_3 - %30 = OpVariable %_ptr_Input__arr_v2float_uint_3 Input - %31 = OpVariable %_ptr_Input__arr_v2float_uint_3 Input -%_ptr_Function__struct_11 = OpTypePointer Function %_struct_11 - %2 = OpFunction %void None %4 - %33 = OpLabel - %66 = OpVariable %_ptr_Function__arr__struct_11_uint_3 Function - %34 = OpLoad %_arr_v4float_uint_3 %16 - %35 = OpLoad %_arr_v4float_uint_3 %17 - %36 = OpLoad %_arr_v4float_uint_3 %18 - %37 = OpLoad %_arr_v3float_uint_3 %26 - %38 = OpLoad %_arr_v3float_uint_3 %27 - %39 = OpLoad %_arr_v2float_uint_3 %30 - %40 = OpLoad %_arr_v2float_uint_3 %31 - %41 = OpCompositeExtract %v4float %34 0 - %42 = OpCompositeExtract %v4float %35 0 - %43 = OpCompositeExtract %v4float %36 0 - %44 = OpCompositeExtract %v3float %37 0 - %45 = OpCompositeExtract %v3float %38 0 - %46 = OpCompositeExtract %v2float %39 0 - %47 = OpCompositeExtract %v2float %40 0 - %48 = OpCompositeConstruct %_struct_11 %41 %42 %43 %44 %45 %46 %47 - %49 = OpCompositeExtract %v4float %34 1 - %50 = OpCompositeExtract %v4float %35 1 - %51 = OpCompositeExtract %v4float %36 1 - %52 = OpCompositeExtract %v3float %37 1 - %53 = OpCompositeExtract %v3float %38 1 - %54 = OpCompositeExtract %v2float %39 1 - %55 = OpCompositeExtract %v2float %40 1 - %56 = OpCompositeConstruct %_struct_11 %49 %50 %51 %52 %53 %54 %55 - %57 = OpCompositeExtract %v4float %34 2 - %58 = OpCompositeExtract %v4float %35 2 - %59 = OpCompositeExtract %v4float %36 2 - %60 = OpCompositeExtract %v3float %37 2 - %61 = OpCompositeExtract %v3float %38 2 - %62 = OpCompositeExtract %v2float %39 2 - %63 = OpCompositeExtract %v2float %40 2 - %64 = OpCompositeConstruct %_struct_11 %57 %58 %59 %60 %61 %62 %63 - %65 = OpCompositeConstruct %_arr__struct_11_uint_3 %48 %56 %64 - %67 = OpLoad %uint %20 - -; CHECK OpStore {{%\d+}} [[store_source:%\d+]] - OpStore %66 %65 - %68 = OpAccessChain %_ptr_Function__struct_11 %66 %67 - -; This load was being removed, because %_ptr_Function__struct_11 was being -; wrongfully considered an SSA target. -; CHECK OpLoad %_struct_11 %68 - %69 = OpLoad %_struct_11 %68 - -; Similarly, %69 cannot be replaced with %65. -; CHECK-NOT: OpCompositeExtract %v4float [[store_source]] 0 - %70 = OpCompositeExtract %v4float %69 0 - - %71 = OpAccessChain %_ptr_Output_v4float %22 %67 - OpStore %71 %70 - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(spv_asm, true); -} - -// Test that the RelaxedPrecision decoration on the variable to added to the -// result of the OpPhi instruction. -TEST_F(LocalSSAElimTest, DecoratedVariable) { - const std::string spv_asm = R"( -; CHECK: OpDecorate [[var:%\w+]] RelaxedPrecision -; CHECK: OpDecorate [[phi_id:%\w+]] RelaxedPrecision -; CHECK: [[phi_id]] = OpPhi - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpDecorate %v RelaxedPrecision - %void = OpTypeVoid - %func_t = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %int = OpTypeInt 32 0 - %int_p = OpTypePointer Function %int - %int_1 = OpConstant %int 1 - %int_0 = OpConstant %int 0 - %2 = OpFunction %void None %func_t - %33 = OpLabel - %v = OpVariable %int_p Function - OpSelectionMerge %merge None - OpBranchConditional %true %l1 %l2 - %l1 = OpLabel - OpStore %v %int_1 - OpBranch %merge - %l2 = OpLabel - OpStore %v %int_0 - OpBranch %merge - %merge = OpLabel - %ld = OpLoad %int %v - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(spv_asm, true); -} - -// Test that the RelaxedPrecision decoration on the variable to added to the -// result of the OpPhi instruction. -TEST_F(LocalSSAElimTest, MultipleEdges) { - const std::string spv_asm = R"( - ; CHECK: OpSelectionMerge - ; CHECK: [[header_bb:%\w+]] = OpLabel - ; CHECK-NOT: OpLabel - ; CHECK: OpSwitch {{%\w+}} {{%\w+}} 76 [[bb1:%\w+]] 17 [[bb2:%\w+]] - ; CHECK-SAME: 4 [[bb2]] - ; CHECK: [[bb2]] = OpLabel - ; CHECK-NEXT: OpPhi [[type:%\w+]] [[val:%\w+]] [[header_bb]] %int_0 [[bb1]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %false = OpConstantFalse %bool - %int_1 = OpConstant %int 1 - %4 = OpFunction %void None %3 - %5 = OpLabel - %8 = OpVariable %_ptr_Function_int Function - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - OpBranchConditional %true %11 %12 - %11 = OpLabel - OpSelectionMerge %19 None - OpBranchConditional %false %18 %19 - %18 = OpLabel - OpSelectionMerge %22 None - OpSwitch %int_0 %22 76 %20 17 %21 4 %21 - %20 = OpLabel - %23 = OpLoad %int %8 - OpStore %8 %int_0 - OpBranch %21 - %21 = OpLabel - OpBranch %22 - %22 = OpLabel - OpBranch %19 - %19 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(spv_asm, true); -} - -TEST_F(LocalSSAElimTest, VariablePointerTest1) { - // Check that the load of the first variable is still used and that the load - // of the third variable is propagated. The first load has to remain because - // of the store to the variable pointer. - const std::string text = R"( -; CHECK: [[v1:%\w+]] = OpVariable -; CHECK: [[v2:%\w+]] = OpVariable -; CHECK: [[v3:%\w+]] = OpVariable -; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]] -; CHECK: OpIAdd %int [[ld1]] %int_0 - OpCapability Shader - OpCapability VariablePointers - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 1 1 - OpSource GLSL 450 - OpMemberDecorate %_struct_3 0 Offset 0 - OpMemberDecorate %_struct_3 1 Offset 4 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool - %_struct_3 = OpTypeStruct %int %int -%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3 -%_ptr_Function_int = OpTypePointer Function %int - %true = OpConstantTrue %bool - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %13 = OpConstantNull %_struct_3 - %2 = OpFunction %void None %5 - %14 = OpLabel - %15 = OpVariable %_ptr_Function_int Function - %16 = OpVariable %_ptr_Function_int Function - %17 = OpVariable %_ptr_Function_int Function - OpStore %15 %int_1 - OpStore %17 %int_0 - OpSelectionMerge %18 None - OpBranchConditional %true %19 %20 - %19 = OpLabel - OpBranch %18 - %20 = OpLabel - OpBranch %18 - %18 = OpLabel - %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20 - OpStore %21 %int_0 - %22 = OpLoad %int %15 - %23 = OpLoad %int %17 - %24 = OpIAdd %int %22 %23 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(LocalSSAElimTest, VariablePointerTest2) { - // Check that the load of the first variable is still used and that the load - // of the third variable is propagated. The first load has to remain because - // of the store to the variable pointer. - const std::string text = R"( -; CHECK: [[v1:%\w+]] = OpVariable -; CHECK: [[v2:%\w+]] = OpVariable -; CHECK: [[v3:%\w+]] = OpVariable -; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]] -; CHECK: OpIAdd %int [[ld1]] %int_0 - OpCapability Shader - OpCapability VariablePointers - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 1 1 - OpSource GLSL 450 - OpMemberDecorate %_struct_3 0 Offset 0 - OpMemberDecorate %_struct_3 1 Offset 4 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool - %_struct_3 = OpTypeStruct %int %int -%_ptr_Function__struct_3 = OpTypePointer Function %_struct_3 -%_ptr_Function_int = OpTypePointer Function %int - %true = OpConstantTrue %bool - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %13 = OpConstantNull %_struct_3 - %2 = OpFunction %void None %5 - %14 = OpLabel - %15 = OpVariable %_ptr_Function_int Function - %16 = OpVariable %_ptr_Function_int Function - %17 = OpVariable %_ptr_Function_int Function - OpStore %15 %int_1 - OpStore %17 %int_0 - OpSelectionMerge %18 None - OpBranchConditional %true %19 %20 - %19 = OpLabel - OpBranch %18 - %20 = OpLabel - OpBranch %18 - %18 = OpLabel - %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20 - OpStore %21 %int_0 - %22 = OpLoad %int %15 - %23 = OpLoad %int %17 - %24 = OpIAdd %int %22 %23 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(LocalSSAElimTest, ChainedTrivialPhis) { - // Check that the copy object get the undef value implicitly assigned in the - // entry block. - const std::string text = R"( -; CHECK: [[undef:%\w+]] = OpUndef %v4float -; CHECK: OpCopyObject %v4float [[undef]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 1 18 6 - OpSource ESSL 310 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %2 = OpFunction %void None %4 - %9 = OpLabel - %10 = OpVariable %_ptr_Function_v4float Function - OpBranch %11 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpUndef %bool - OpBranchConditional %15 %16 %12 - %16 = OpLabel - %17 = OpUndef %bool - OpSelectionMerge %18 None - OpBranchConditional %17 %19 %18 - %19 = OpLabel - %20 = OpUndef %bool - OpLoopMerge %21 %22 None - OpBranchConditional %20 %23 %21 - %23 = OpLabel - %24 = OpLoad %v4float %10 - %25 = OpCopyObject %v4float %24 - %26 = OpUndef %bool - OpBranch %22 - %22 = OpLabel - OpBranch %19 - %21 = OpLabel - OpBranch %12 - %18 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %11 - %12 = OpLabel - %27 = OpLoad %v4float %10 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(LocalSSAElimTest, Overflowtest1) { - // Check that the copy object get the undef value implicitly assigned in the - // entry block. - const std::string text = R"( -OpCapability Geometry -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "P2Mai" %12 %17 -OpExecutionMode %4 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeFloat 32 -%7 = OpTypeVector %6 4 -%11 = OpTypePointer Input %7 -%16 = OpTypePointer Output %7 -%23 = OpTypePointer Function %7 -%12 = OpVariable %11 Input -%17 = OpVariable %16 Output -%4 = OpFunction %2 None %3 -%2177 = OpLabel -%4194302 = OpVariable %23 Function -%4194301 = OpLoad %7 %4194302 -OpStore %17 %4194301 -OpReturn -OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// No optimization in the presence of -// access chains -// function calls -// OpCopyMemory? -// unsupported extensions -// Others? - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/CMakeLists.txt b/3rdparty/spirv-tools/test/opt/loop_optimizations/CMakeLists.txt deleted file mode 100644 index e3620787d..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2017 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. - - -add_spvtools_unittest(TARGET opt_loops - SRCS ../function_utils.h - dependence_analysis.cpp - dependence_analysis_helpers.cpp - fusion_compatibility.cpp - fusion_illegal.cpp - fusion_legal.cpp - fusion_pass.cpp - hoist_all_loop_types.cpp - hoist_double_nested_loops.cpp - hoist_from_independent_loops.cpp - hoist_simple_case.cpp - hoist_single_nested_loops.cpp - hoist_without_preheader.cpp - lcssa.cpp - loop_descriptions.cpp - loop_fission.cpp - nested_loops.cpp - peeling.cpp - peeling_pass.cpp - unroll_assumptions.cpp - unroll_simple.cpp - unswitch.cpp - LIBS SPIRV-Tools-opt - PCH_FILE pch_test_opt_loop -) diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/dependence_analysis.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/dependence_analysis.cpp deleted file mode 100644 index 8aeb20afc..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/dependence_analysis.cpp +++ /dev/null @@ -1,4205 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 - -#include "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_dependence.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/tree_iterator.h" -#include "test/opt//assembly_builder.h" -#include "test/opt//function_utils.h" -#include "test/opt//pass_fixture.h" -#include "test/opt//pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DependencyAnalysis = ::testing::Test; - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void main(){ - int[10] arr; - int[10] arr2; - int a = 2; - for (int i = 0; i < 10; i++) { - arr[a] = arr[3]; - arr[a*2] = arr[a+3]; - arr[6] = arr2[6]; - arr[a+5] = arr2[7]; - } -} -*/ -TEST(DependencyAnalysis, ZIV) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %25 "arr" - OpName %39 "arr2" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %11 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 10 - %23 = OpTypeArray %6 %22 - %24 = OpTypePointer Function %23 - %27 = OpConstant %6 3 - %38 = OpConstant %6 6 - %44 = OpConstant %6 5 - %46 = OpConstant %6 7 - %51 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %25 = OpVariable %24 Function - %39 = OpVariable %24 Function - OpBranch %12 - %12 = OpLabel - %53 = OpPhi %6 %11 %5 %52 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %53 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %28 = OpAccessChain %7 %25 %27 - %29 = OpLoad %6 %28 - %30 = OpAccessChain %7 %25 %9 - OpStore %30 %29 - %32 = OpIMul %6 %9 %9 - %34 = OpIAdd %6 %9 %27 - %35 = OpAccessChain %7 %25 %34 - %36 = OpLoad %6 %35 - %37 = OpAccessChain %7 %25 %32 - OpStore %37 %36 - %40 = OpAccessChain %7 %39 %38 - %41 = OpLoad %6 %40 - %42 = OpAccessChain %7 %25 %38 - OpStore %42 %41 - %45 = OpIAdd %6 %9 %44 - %47 = OpAccessChain %7 %39 %46 - %48 = OpLoad %6 %47 - %49 = OpAccessChain %7 %25 %45 - OpStore %49 %48 - OpBranch %15 - %15 = OpLabel - %52 = OpIAdd %6 %53 %51 - OpBranch %12 - %14 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 13)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // 29 -> 30 tests looking through constants. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(29), - store[0], &distance_vector)); - } - - // 36 -> 37 tests looking through additions. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(36), - store[1], &distance_vector)); - } - - // 41 -> 42 tests looking at same index across two different arrays. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(41), - store[2], &distance_vector)); - } - - // 48 -> 49 tests looking through additions for same index in two different - // arrays. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(48), - store[3], &distance_vector)); - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -layout(location = 0) in vec4 c; -void main(){ - int[10] arr; - int[10] arr2; - int[10] arr3; - int[10] arr4; - int[10] arr5; - int N = int(c.x); - for (int i = 0; i < N; i++) { - arr[2*N] = arr[N]; - arr2[2*N+1] = arr2[N]; - arr3[2*N] = arr3[N-1]; - arr4[N] = arr5[N]; - } -} -*/ -TEST(DependencyAnalysis, SymbolicZIV) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %12 "c" - OpName %33 "arr" - OpName %41 "arr2" - OpName %50 "arr3" - OpName %58 "arr4" - OpName %60 "arr5" - OpDecorate %12 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypeVector %9 4 - %11 = OpTypePointer Input %10 - %12 = OpVariable %11 Input - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Input %9 - %20 = OpConstant %6 0 - %28 = OpTypeBool - %30 = OpConstant %13 10 - %31 = OpTypeArray %6 %30 - %32 = OpTypePointer Function %31 - %34 = OpConstant %6 2 - %44 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %33 = OpVariable %32 Function - %41 = OpVariable %32 Function - %50 = OpVariable %32 Function - %58 = OpVariable %32 Function - %60 = OpVariable %32 Function - %16 = OpAccessChain %15 %12 %14 - %17 = OpLoad %9 %16 - %18 = OpConvertFToS %6 %17 - OpBranch %21 - %21 = OpLabel - %67 = OpPhi %6 %20 %5 %66 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %29 = OpSLessThan %28 %67 %18 - OpBranchConditional %29 %22 %23 - %22 = OpLabel - %36 = OpIMul %6 %34 %18 - %38 = OpAccessChain %7 %33 %18 - %39 = OpLoad %6 %38 - %40 = OpAccessChain %7 %33 %36 - OpStore %40 %39 - %43 = OpIMul %6 %34 %18 - %45 = OpIAdd %6 %43 %44 - %47 = OpAccessChain %7 %41 %18 - %48 = OpLoad %6 %47 - %49 = OpAccessChain %7 %41 %45 - OpStore %49 %48 - %52 = OpIMul %6 %34 %18 - %54 = OpISub %6 %18 %44 - %55 = OpAccessChain %7 %50 %54 - %56 = OpLoad %6 %55 - %57 = OpAccessChain %7 %50 %52 - OpStore %57 %56 - %62 = OpAccessChain %7 %60 %18 - %63 = OpLoad %6 %62 - %64 = OpAccessChain %7 %58 %18 - OpStore %64 %63 - OpBranch %24 - %24 = OpLabel - %66 = OpIAdd %6 %67 %44 - OpBranch %21 - %23 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 22)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // independent due to loop bounds (won't enter if N <= 0). - // 39 -> 40 tests looking through symbols and multiplicaiton. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(39), - store[0], &distance_vector)); - } - - // 48 -> 49 tests looking through symbols and multiplication + addition. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(48), - store[1], &distance_vector)); - } - - // 56 -> 57 tests looking through symbols and arithmetic on load and store. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(56), - store[2], &distance_vector)); - } - - // independent as different arrays - // 63 -> 64 tests looking through symbols and load/store from/to different - // arrays. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(63), - store[3], &distance_vector)); - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void a(){ - int[10] arr; - int[11] arr2; - int[20] arr3; - int[20] arr4; - int a = 2; - for (int i = 0; i < 10; i++) { - arr[i] = arr[i]; - arr2[i] = arr2[i+1]; - arr3[i] = arr3[i-1]; - arr4[2*i] = arr4[i]; - } -} -void b(){ - int[10] arr; - int[11] arr2; - int[20] arr3; - int[20] arr4; - int a = 2; - for (int i = 10; i > 0; i--) { - arr[i] = arr[i]; - arr2[i] = arr2[i+1]; - arr3[i] = arr3[i-1]; - arr4[2*i] = arr4[i]; - } -} - -void main() { - a(); - b(); -} -*/ -TEST(DependencyAnalysis, SIV) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %12 "a" - OpName %14 "i" - OpName %29 "arr" - OpName %38 "arr2" - OpName %49 "arr3" - OpName %56 "arr4" - OpName %65 "a" - OpName %66 "i" - OpName %74 "arr" - OpName %80 "arr2" - OpName %87 "arr3" - OpName %94 "arr4" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 2 - %15 = OpConstant %10 0 - %22 = OpConstant %10 10 - %23 = OpTypeBool - %25 = OpTypeInt 32 0 - %26 = OpConstant %25 10 - %27 = OpTypeArray %10 %26 - %28 = OpTypePointer Function %27 - %35 = OpConstant %25 11 - %36 = OpTypeArray %10 %35 - %37 = OpTypePointer Function %36 - %41 = OpConstant %10 1 - %46 = OpConstant %25 20 - %47 = OpTypeArray %10 %46 - %48 = OpTypePointer Function %47 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %103 = OpFunctionCall %2 %6 - %104 = OpFunctionCall %2 %8 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %12 = OpVariable %11 Function - %14 = OpVariable %11 Function - %29 = OpVariable %28 Function - %38 = OpVariable %37 Function - %49 = OpVariable %48 Function - %56 = OpVariable %48 Function - OpStore %12 %13 - OpStore %14 %15 - OpBranch %16 - %16 = OpLabel - %105 = OpPhi %10 %15 %7 %64 %19 - OpLoopMerge %18 %19 None - OpBranch %20 - %20 = OpLabel - %24 = OpSLessThan %23 %105 %22 - OpBranchConditional %24 %17 %18 - %17 = OpLabel - %32 = OpAccessChain %11 %29 %105 - %33 = OpLoad %10 %32 - %34 = OpAccessChain %11 %29 %105 - OpStore %34 %33 - %42 = OpIAdd %10 %105 %41 - %43 = OpAccessChain %11 %38 %42 - %44 = OpLoad %10 %43 - %45 = OpAccessChain %11 %38 %105 - OpStore %45 %44 - %52 = OpISub %10 %105 %41 - %53 = OpAccessChain %11 %49 %52 - %54 = OpLoad %10 %53 - %55 = OpAccessChain %11 %49 %105 - OpStore %55 %54 - %58 = OpIMul %10 %13 %105 - %60 = OpAccessChain %11 %56 %105 - %61 = OpLoad %10 %60 - %62 = OpAccessChain %11 %56 %58 - OpStore %62 %61 - OpBranch %19 - %19 = OpLabel - %64 = OpIAdd %10 %105 %41 - OpStore %14 %64 - OpBranch %16 - %18 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %65 = OpVariable %11 Function - %66 = OpVariable %11 Function - %74 = OpVariable %28 Function - %80 = OpVariable %37 Function - %87 = OpVariable %48 Function - %94 = OpVariable %48 Function - OpStore %65 %13 - OpStore %66 %22 - OpBranch %67 - %67 = OpLabel - %106 = OpPhi %10 %22 %9 %102 %70 - OpLoopMerge %69 %70 None - OpBranch %71 - %71 = OpLabel - %73 = OpSGreaterThan %23 %106 %15 - OpBranchConditional %73 %68 %69 - %68 = OpLabel - %77 = OpAccessChain %11 %74 %106 - %78 = OpLoad %10 %77 - %79 = OpAccessChain %11 %74 %106 - OpStore %79 %78 - %83 = OpIAdd %10 %106 %41 - %84 = OpAccessChain %11 %80 %83 - %85 = OpLoad %10 %84 - %86 = OpAccessChain %11 %80 %106 - OpStore %86 %85 - %90 = OpISub %10 %106 %41 - %91 = OpAccessChain %11 %87 %90 - %92 = OpLoad %10 %91 - %93 = OpAccessChain %11 %87 %106 - OpStore %93 %92 - %96 = OpIMul %10 %13 %106 - %98 = OpAccessChain %11 %94 %106 - %99 = OpLoad %10 %98 - %100 = OpAccessChain %11 %94 %96 - OpStore %100 %99 - OpBranch %70 - %70 = OpLabel - %102 = OpISub %10 %106 %41 - OpStore %66 %102 - OpBranch %67 - %69 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - // For the loop in function a. - { - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 17)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // = dependence - // 33 -> 34 tests looking at SIV in same array. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(33), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::EQ); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 0); - } - - // > -1 dependence - // 44 -> 45 tests looking at SIV in same array with addition. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(44), store[1], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::GT); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, -1); - } - - // < 1 dependence - // 54 -> 55 tests looking at SIV in same array with subtraction. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(54), store[2], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::LT); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 1); - } - - // <=> dependence - // 61 -> 62 tests looking at SIV in same array with multiplication. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(61), store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::UNKNOWN); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::ALL); - } - } - // For the loop in function b. - { - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 68)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // = dependence - // 78 -> 79 tests looking at SIV in same array. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(78), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::EQ); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 0); - } - - // < 1 dependence - // 85 -> 86 tests looking at SIV in same array with addition. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(85), store[1], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::LT); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 1); - } - - // > -1 dependence - // 92 -> 93 tests looking at SIV in same array with subtraction. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(92), store[2], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::GT); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, -1); - } - - // <=> dependence - // 99 -> 100 tests looking at SIV in same array with multiplication. - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(99), store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::UNKNOWN); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::ALL); - } - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -layout(location = 0) in vec4 c; -void a() { - int[13] arr; - int[15] arr2; - int[18] arr3; - int[18] arr4; - int N = int(c.x); - int C = 2; - int a = 2; - for (int i = 0; i < N; i++) { // Bounds are N - 1 - arr[i+2*N] = arr[i+N]; // |distance| = N - arr2[i+N] = arr2[i+2*N] + C; // |distance| = N - arr3[2*i+2*N+1] = arr3[2*i+N+1]; // |distance| = N - arr4[a*i+N+1] = arr4[a*i+2*N+1]; // |distance| = N - } -} -void b() { - int[13] arr; - int[15] arr2; - int[18] arr3; - int[18] arr4; - int N = int(c.x); - int C = 2; - int a = 2; - for (int i = N; i > 0; i--) { // Bounds are N - 1 - arr[i+2*N] = arr[i+N]; // |distance| = N - arr2[i+N] = arr2[i+2*N] + C; // |distance| = N - arr3[2*i+2*N+1] = arr3[2*i+N+1]; // |distance| = N - arr4[a*i+N+1] = arr4[a*i+2*N+1]; // |distance| = N - } -} -void main(){ - a(); - b(); -}*/ -TEST(DependencyAnalysis, SymbolicSIV) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %16 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %12 "N" - OpName %16 "c" - OpName %23 "C" - OpName %25 "a" - OpName %26 "i" - OpName %40 "arr" - OpName %54 "arr2" - OpName %70 "arr3" - OpName %86 "arr4" - OpName %105 "N" - OpName %109 "C" - OpName %110 "a" - OpName %111 "i" - OpName %120 "arr" - OpName %131 "arr2" - OpName %144 "arr3" - OpName %159 "arr4" - OpDecorate %16 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Input %14 - %16 = OpVariable %15 Input - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 0 - %19 = OpTypePointer Input %13 - %24 = OpConstant %10 2 - %27 = OpConstant %10 0 - %35 = OpTypeBool - %37 = OpConstant %17 13 - %38 = OpTypeArray %10 %37 - %39 = OpTypePointer Function %38 - %51 = OpConstant %17 15 - %52 = OpTypeArray %10 %51 - %53 = OpTypePointer Function %52 - %67 = OpConstant %17 18 - %68 = OpTypeArray %10 %67 - %69 = OpTypePointer Function %68 - %76 = OpConstant %10 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %178 = OpFunctionCall %2 %6 - %179 = OpFunctionCall %2 %8 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %12 = OpVariable %11 Function - %23 = OpVariable %11 Function - %25 = OpVariable %11 Function - %26 = OpVariable %11 Function - %40 = OpVariable %39 Function - %54 = OpVariable %53 Function - %70 = OpVariable %69 Function - %86 = OpVariable %69 Function - %20 = OpAccessChain %19 %16 %18 - %21 = OpLoad %13 %20 - %22 = OpConvertFToS %10 %21 - OpStore %12 %22 - OpStore %23 %24 - OpStore %25 %24 - OpStore %26 %27 - OpBranch %28 - %28 = OpLabel - %180 = OpPhi %10 %27 %7 %104 %31 - OpLoopMerge %30 %31 None - OpBranch %32 - %32 = OpLabel - %36 = OpSLessThan %35 %180 %22 - OpBranchConditional %36 %29 %30 - %29 = OpLabel - %43 = OpIMul %10 %24 %22 - %44 = OpIAdd %10 %180 %43 - %47 = OpIAdd %10 %180 %22 - %48 = OpAccessChain %11 %40 %47 - %49 = OpLoad %10 %48 - %50 = OpAccessChain %11 %40 %44 - OpStore %50 %49 - %57 = OpIAdd %10 %180 %22 - %60 = OpIMul %10 %24 %22 - %61 = OpIAdd %10 %180 %60 - %62 = OpAccessChain %11 %54 %61 - %63 = OpLoad %10 %62 - %65 = OpIAdd %10 %63 %24 - %66 = OpAccessChain %11 %54 %57 - OpStore %66 %65 - %72 = OpIMul %10 %24 %180 - %74 = OpIMul %10 %24 %22 - %75 = OpIAdd %10 %72 %74 - %77 = OpIAdd %10 %75 %76 - %79 = OpIMul %10 %24 %180 - %81 = OpIAdd %10 %79 %22 - %82 = OpIAdd %10 %81 %76 - %83 = OpAccessChain %11 %70 %82 - %84 = OpLoad %10 %83 - %85 = OpAccessChain %11 %70 %77 - OpStore %85 %84 - %89 = OpIMul %10 %24 %180 - %91 = OpIAdd %10 %89 %22 - %92 = OpIAdd %10 %91 %76 - %95 = OpIMul %10 %24 %180 - %97 = OpIMul %10 %24 %22 - %98 = OpIAdd %10 %95 %97 - %99 = OpIAdd %10 %98 %76 - %100 = OpAccessChain %11 %86 %99 - %101 = OpLoad %10 %100 - %102 = OpAccessChain %11 %86 %92 - OpStore %102 %101 - OpBranch %31 - %31 = OpLabel - %104 = OpIAdd %10 %180 %76 - OpStore %26 %104 - OpBranch %28 - %30 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %105 = OpVariable %11 Function - %109 = OpVariable %11 Function - %110 = OpVariable %11 Function - %111 = OpVariable %11 Function - %120 = OpVariable %39 Function - %131 = OpVariable %53 Function - %144 = OpVariable %69 Function - %159 = OpVariable %69 Function - %106 = OpAccessChain %19 %16 %18 - %107 = OpLoad %13 %106 - %108 = OpConvertFToS %10 %107 - OpStore %105 %108 - OpStore %109 %24 - OpStore %110 %24 - OpStore %111 %108 - OpBranch %113 - %113 = OpLabel - %181 = OpPhi %10 %108 %9 %177 %116 - OpLoopMerge %115 %116 None - OpBranch %117 - %117 = OpLabel - %119 = OpSGreaterThan %35 %181 %27 - OpBranchConditional %119 %114 %115 - %114 = OpLabel - %123 = OpIMul %10 %24 %108 - %124 = OpIAdd %10 %181 %123 - %127 = OpIAdd %10 %181 %108 - %128 = OpAccessChain %11 %120 %127 - %129 = OpLoad %10 %128 - %130 = OpAccessChain %11 %120 %124 - OpStore %130 %129 - %134 = OpIAdd %10 %181 %108 - %137 = OpIMul %10 %24 %108 - %138 = OpIAdd %10 %181 %137 - %139 = OpAccessChain %11 %131 %138 - %140 = OpLoad %10 %139 - %142 = OpIAdd %10 %140 %24 - %143 = OpAccessChain %11 %131 %134 - OpStore %143 %142 - %146 = OpIMul %10 %24 %181 - %148 = OpIMul %10 %24 %108 - %149 = OpIAdd %10 %146 %148 - %150 = OpIAdd %10 %149 %76 - %152 = OpIMul %10 %24 %181 - %154 = OpIAdd %10 %152 %108 - %155 = OpIAdd %10 %154 %76 - %156 = OpAccessChain %11 %144 %155 - %157 = OpLoad %10 %156 - %158 = OpAccessChain %11 %144 %150 - OpStore %158 %157 - %162 = OpIMul %10 %24 %181 - %164 = OpIAdd %10 %162 %108 - %165 = OpIAdd %10 %164 %76 - %168 = OpIMul %10 %24 %181 - %170 = OpIMul %10 %24 %108 - %171 = OpIAdd %10 %168 %170 - %172 = OpIAdd %10 %171 %76 - %173 = OpAccessChain %11 %159 %172 - %174 = OpLoad %10 %173 - %175 = OpAccessChain %11 %159 %165 - OpStore %175 %174 - OpBranch %116 - %116 = OpLabel - %177 = OpISub %10 %181 %76 - OpStore %111 %177 - OpBranch %113 - %115 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - // For the loop in function a. - { - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // independent due to loop bounds (won't enter when N <= 0) - // 49 -> 50 tests looking through SIV and symbols with multiplication - { - DistanceVector distance_vector{loops.size()}; - // Independent but not yet supported. - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(49), store[0], &distance_vector)); - } - - // 63 -> 66 tests looking through SIV and symbols with multiplication and + - // C - { - DistanceVector distance_vector{loops.size()}; - // Independent. - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(63), - store[1], &distance_vector)); - } - - // 84 -> 85 tests looking through arithmetic on SIV and symbols - { - DistanceVector distance_vector{loops.size()}; - // Independent but not yet supported. - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(84), store[2], &distance_vector)); - } - - // 101 -> 102 tests looking through symbol arithmetic on SIV and symbols - { - DistanceVector distance_vector{loops.size()}; - // Independent. - EXPECT_TRUE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(101), store[3], &distance_vector)); - } - } - // For the loop in function b. - { - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 114)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // independent due to loop bounds (won't enter when N <= 0). - // 129 -> 130 tests looking through SIV and symbols with multiplication. - { - DistanceVector distance_vector{loops.size()}; - // Independent but not yet supported. - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(129), store[0], &distance_vector)); - } - - // 140 -> 143 tests looking through SIV and symbols with multiplication and - // + C. - { - DistanceVector distance_vector{loops.size()}; - // Independent. - EXPECT_TRUE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(140), store[1], &distance_vector)); - } - - // 157 -> 158 tests looking through arithmetic on SIV and symbols. - { - DistanceVector distance_vector{loops.size()}; - // Independent but not yet supported. - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(157), store[2], &distance_vector)); - } - - // 174 -> 175 tests looking through symbol arithmetic on SIV and symbols. - { - DistanceVector distance_vector{loops.size()}; - // Independent. - EXPECT_TRUE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(174), store[3], &distance_vector)); - } - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void a() { - int[6] arr; - int N = 5; - for (int i = 1; i < N; i++) { - arr[i] = arr[N-i]; - } -} -void b() { - int[6] arr; - int N = 5; - for (int i = 1; i < N; i++) { - arr[N-i] = arr[i]; - } -} -void c() { - int[11] arr; - int N = 10; - for (int i = 1; i < N; i++) { - arr[i] = arr[N-i+1]; - } -} -void d() { - int[11] arr; - int N = 10; - for (int i = 1; i < N; i++) { - arr[N-i+1] = arr[i]; - } -} -void e() { - int[6] arr; - int N = 5; - for (int i = N; i > 0; i--) { - arr[i] = arr[N-i]; - } -} -void f() { - int[6] arr; - int N = 5; - for (int i = N; i > 0; i--) { - arr[N-i] = arr[i]; - } -} -void g() { - int[11] arr; - int N = 10; - for (int i = N; i > 0; i--) { - arr[i] = arr[N-i+1]; - } -} -void h() { - int[11] arr; - int N = 10; - for (int i = N; i > 0; i--) { - arr[N-i+1] = arr[i]; - } -} -void main(){ - a(); - b(); - c(); - d(); - e(); - f(); - g(); - h(); -} -*/ -TEST(DependencyAnalysis, Crossing) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %14 "e(" - OpName %16 "f(" - OpName %18 "g(" - OpName %20 "h(" - OpName %24 "N" - OpName %26 "i" - OpName %41 "arr" - OpName %51 "N" - OpName %52 "i" - OpName %61 "arr" - OpName %71 "N" - OpName %73 "i" - OpName %85 "arr" - OpName %96 "N" - OpName %97 "i" - OpName %106 "arr" - OpName %117 "N" - OpName %118 "i" - OpName %128 "arr" - OpName %138 "N" - OpName %139 "i" - OpName %148 "arr" - OpName %158 "N" - OpName %159 "i" - OpName %168 "arr" - OpName %179 "N" - OpName %180 "i" - OpName %189 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %22 = OpTypeInt 32 1 - %23 = OpTypePointer Function %22 - %25 = OpConstant %22 5 - %27 = OpConstant %22 1 - %35 = OpTypeBool - %37 = OpTypeInt 32 0 - %38 = OpConstant %37 6 - %39 = OpTypeArray %22 %38 - %40 = OpTypePointer Function %39 - %72 = OpConstant %22 10 - %82 = OpConstant %37 11 - %83 = OpTypeArray %22 %82 - %84 = OpTypePointer Function %83 - %126 = OpConstant %22 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %200 = OpFunctionCall %2 %6 - %201 = OpFunctionCall %2 %8 - %202 = OpFunctionCall %2 %10 - %203 = OpFunctionCall %2 %12 - %204 = OpFunctionCall %2 %14 - %205 = OpFunctionCall %2 %16 - %206 = OpFunctionCall %2 %18 - %207 = OpFunctionCall %2 %20 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %24 = OpVariable %23 Function - %26 = OpVariable %23 Function - %41 = OpVariable %40 Function - OpStore %24 %25 - OpStore %26 %27 - OpBranch %28 - %28 = OpLabel - %208 = OpPhi %22 %27 %7 %50 %31 - OpLoopMerge %30 %31 None - OpBranch %32 - %32 = OpLabel - %36 = OpSLessThan %35 %208 %25 - OpBranchConditional %36 %29 %30 - %29 = OpLabel - %45 = OpISub %22 %25 %208 - %46 = OpAccessChain %23 %41 %45 - %47 = OpLoad %22 %46 - %48 = OpAccessChain %23 %41 %208 - OpStore %48 %47 - OpBranch %31 - %31 = OpLabel - %50 = OpIAdd %22 %208 %27 - OpStore %26 %50 - OpBranch %28 - %30 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %51 = OpVariable %23 Function - %52 = OpVariable %23 Function - %61 = OpVariable %40 Function - OpStore %51 %25 - OpStore %52 %27 - OpBranch %53 - %53 = OpLabel - %209 = OpPhi %22 %27 %9 %70 %56 - OpLoopMerge %55 %56 None - OpBranch %57 - %57 = OpLabel - %60 = OpSLessThan %35 %209 %25 - OpBranchConditional %60 %54 %55 - %54 = OpLabel - %64 = OpISub %22 %25 %209 - %66 = OpAccessChain %23 %61 %209 - %67 = OpLoad %22 %66 - %68 = OpAccessChain %23 %61 %64 - OpStore %68 %67 - OpBranch %56 - %56 = OpLabel - %70 = OpIAdd %22 %209 %27 - OpStore %52 %70 - OpBranch %53 - %55 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %71 = OpVariable %23 Function - %73 = OpVariable %23 Function - %85 = OpVariable %84 Function - OpStore %71 %72 - OpStore %73 %27 - OpBranch %74 - %74 = OpLabel - %210 = OpPhi %22 %27 %11 %95 %77 - OpLoopMerge %76 %77 None - OpBranch %78 - %78 = OpLabel - %81 = OpSLessThan %35 %210 %72 - OpBranchConditional %81 %75 %76 - %75 = OpLabel - %89 = OpISub %22 %72 %210 - %90 = OpIAdd %22 %89 %27 - %91 = OpAccessChain %23 %85 %90 - %92 = OpLoad %22 %91 - %93 = OpAccessChain %23 %85 %210 - OpStore %93 %92 - OpBranch %77 - %77 = OpLabel - %95 = OpIAdd %22 %210 %27 - OpStore %73 %95 - OpBranch %74 - %76 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %96 = OpVariable %23 Function - %97 = OpVariable %23 Function - %106 = OpVariable %84 Function - OpStore %96 %72 - OpStore %97 %27 - OpBranch %98 - %98 = OpLabel - %211 = OpPhi %22 %27 %13 %116 %101 - OpLoopMerge %100 %101 None - OpBranch %102 - %102 = OpLabel - %105 = OpSLessThan %35 %211 %72 - OpBranchConditional %105 %99 %100 - %99 = OpLabel - %109 = OpISub %22 %72 %211 - %110 = OpIAdd %22 %109 %27 - %112 = OpAccessChain %23 %106 %211 - %113 = OpLoad %22 %112 - %114 = OpAccessChain %23 %106 %110 - OpStore %114 %113 - OpBranch %101 - %101 = OpLabel - %116 = OpIAdd %22 %211 %27 - OpStore %97 %116 - OpBranch %98 - %100 = OpLabel - OpReturn - OpFunctionEnd - %14 = OpFunction %2 None %3 - %15 = OpLabel - %117 = OpVariable %23 Function - %118 = OpVariable %23 Function - %128 = OpVariable %40 Function - OpStore %117 %25 - OpStore %118 %25 - OpBranch %120 - %120 = OpLabel - %212 = OpPhi %22 %25 %15 %137 %123 - OpLoopMerge %122 %123 None - OpBranch %124 - %124 = OpLabel - %127 = OpSGreaterThan %35 %212 %126 - OpBranchConditional %127 %121 %122 - %121 = OpLabel - %132 = OpISub %22 %25 %212 - %133 = OpAccessChain %23 %128 %132 - %134 = OpLoad %22 %133 - %135 = OpAccessChain %23 %128 %212 - OpStore %135 %134 - OpBranch %123 - %123 = OpLabel - %137 = OpISub %22 %212 %27 - OpStore %118 %137 - OpBranch %120 - %122 = OpLabel - OpReturn - OpFunctionEnd - %16 = OpFunction %2 None %3 - %17 = OpLabel - %138 = OpVariable %23 Function - %139 = OpVariable %23 Function - %148 = OpVariable %40 Function - OpStore %138 %25 - OpStore %139 %25 - OpBranch %141 - %141 = OpLabel - %213 = OpPhi %22 %25 %17 %157 %144 - OpLoopMerge %143 %144 None - OpBranch %145 - %145 = OpLabel - %147 = OpSGreaterThan %35 %213 %126 - OpBranchConditional %147 %142 %143 - %142 = OpLabel - %151 = OpISub %22 %25 %213 - %153 = OpAccessChain %23 %148 %213 - %154 = OpLoad %22 %153 - %155 = OpAccessChain %23 %148 %151 - OpStore %155 %154 - OpBranch %144 - %144 = OpLabel - %157 = OpISub %22 %213 %27 - OpStore %139 %157 - OpBranch %141 - %143 = OpLabel - OpReturn - OpFunctionEnd - %18 = OpFunction %2 None %3 - %19 = OpLabel - %158 = OpVariable %23 Function - %159 = OpVariable %23 Function - %168 = OpVariable %84 Function - OpStore %158 %72 - OpStore %159 %72 - OpBranch %161 - %161 = OpLabel - %214 = OpPhi %22 %72 %19 %178 %164 - OpLoopMerge %163 %164 None - OpBranch %165 - %165 = OpLabel - %167 = OpSGreaterThan %35 %214 %126 - OpBranchConditional %167 %162 %163 - %162 = OpLabel - %172 = OpISub %22 %72 %214 - %173 = OpIAdd %22 %172 %27 - %174 = OpAccessChain %23 %168 %173 - %175 = OpLoad %22 %174 - %176 = OpAccessChain %23 %168 %214 - OpStore %176 %175 - OpBranch %164 - %164 = OpLabel - %178 = OpISub %22 %214 %27 - OpStore %159 %178 - OpBranch %161 - %163 = OpLabel - OpReturn - OpFunctionEnd - %20 = OpFunction %2 None %3 - %21 = OpLabel - %179 = OpVariable %23 Function - %180 = OpVariable %23 Function - %189 = OpVariable %84 Function - OpStore %179 %72 - OpStore %180 %72 - OpBranch %182 - %182 = OpLabel - %215 = OpPhi %22 %72 %21 %199 %185 - OpLoopMerge %184 %185 None - OpBranch %186 - %186 = OpLabel - %188 = OpSGreaterThan %35 %215 %126 - OpBranchConditional %188 %183 %184 - %183 = OpLabel - %192 = OpISub %22 %72 %215 - %193 = OpIAdd %22 %192 %27 - %195 = OpAccessChain %23 %189 %215 - %196 = OpLoad %22 %195 - %197 = OpAccessChain %23 %189 %193 - OpStore %197 %196 - OpBranch %185 - %185 = OpLabel - %199 = OpISub %22 %215 %27 - OpStore %180 %199 - OpBranch %182 - %184 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - // First two tests can be split into two loops. - // Tests even crossing subscripts from low to high indexes. - // 47 -> 48 - { - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(47), - store, &distance_vector)); - } - - // Tests even crossing subscripts from high to low indexes. - // 67 -> 68 - { - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 54)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(67), - store, &distance_vector)); - } - - // Next two tests can have an end peeled, then be split. - // Tests uneven crossing subscripts from low to high indexes. - // 92 -> 93 - { - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 75)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(92), - store, &distance_vector)); - } - - // Tests uneven crossing subscripts from high to low indexes. - // 113 -> 114 - { - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 99)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(113), - store, &distance_vector)); - } - - // First two tests can be split into two loops. - // Tests even crossing subscripts from low to high indexes. - // 134 -> 135 - { - const Function* f = spvtest::GetFunction(module, 14); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 121)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(134), - store, &distance_vector)); - } - - // Tests even crossing subscripts from high to low indexes. - // 154 -> 155 - { - const Function* f = spvtest::GetFunction(module, 16); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 142)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(154), - store, &distance_vector)); - } - - // Next two tests can have an end peeled, then be split. - // Tests uneven crossing subscripts from low to high indexes. - // 175 -> 176 - { - const Function* f = spvtest::GetFunction(module, 18); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 162)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(175), - store, &distance_vector)); - } - - // Tests uneven crossing subscripts from high to low indexes. - // 196 -> 197 - { - const Function* f = spvtest::GetFunction(module, 20); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 183)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - } - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(196), - store, &distance_vector)); - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void a() { - int[10] arr; - for (int i = 0; i < 10; i++) { - arr[0] = arr[i]; // peel first - arr[i] = arr[0]; // peel first - arr[9] = arr[i]; // peel last - arr[i] = arr[9]; // peel last - } -} -void b() { - int[11] arr; - for (int i = 0; i <= 10; i++) { - arr[0] = arr[i]; // peel first - arr[i] = arr[0]; // peel first - arr[10] = arr[i]; // peel last - arr[i] = arr[10]; // peel last - - } -} -void c() { - int[11] arr; - for (int i = 10; i > 0; i--) { - arr[10] = arr[i]; // peel first - arr[i] = arr[10]; // peel first - arr[1] = arr[i]; // peel last - arr[i] = arr[1]; // peel last - - } -} -void d() { - int[11] arr; - for (int i = 10; i >= 0; i--) { - arr[10] = arr[i]; // peel first - arr[i] = arr[10]; // peel first - arr[0] = arr[i]; // peel last - arr[i] = arr[0]; // peel last - - } -} -void main(){ - a(); - b(); - c(); - d(); -} -*/ -TEST(DependencyAnalysis, WeakZeroSIV) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %16 "i" - OpName %31 "arr" - OpName %52 "i" - OpName %63 "arr" - OpName %82 "i" - OpName %90 "arr" - OpName %109 "i" - OpName %117 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %14 = OpTypeInt 32 1 - %15 = OpTypePointer Function %14 - %17 = OpConstant %14 0 - %24 = OpConstant %14 10 - %25 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %14 %28 - %30 = OpTypePointer Function %29 - %40 = OpConstant %14 9 - %50 = OpConstant %14 1 - %60 = OpConstant %27 11 - %61 = OpTypeArray %14 %60 - %62 = OpTypePointer Function %61 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %136 = OpFunctionCall %2 %6 - %137 = OpFunctionCall %2 %8 - %138 = OpFunctionCall %2 %10 - %139 = OpFunctionCall %2 %12 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %16 = OpVariable %15 Function - %31 = OpVariable %30 Function - OpStore %16 %17 - OpBranch %18 - %18 = OpLabel - %140 = OpPhi %14 %17 %7 %51 %21 - OpLoopMerge %20 %21 None - OpBranch %22 - %22 = OpLabel - %26 = OpSLessThan %25 %140 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %33 = OpAccessChain %15 %31 %140 - %34 = OpLoad %14 %33 - %35 = OpAccessChain %15 %31 %17 - OpStore %35 %34 - %37 = OpAccessChain %15 %31 %17 - %38 = OpLoad %14 %37 - %39 = OpAccessChain %15 %31 %140 - OpStore %39 %38 - %42 = OpAccessChain %15 %31 %140 - %43 = OpLoad %14 %42 - %44 = OpAccessChain %15 %31 %40 - OpStore %44 %43 - %46 = OpAccessChain %15 %31 %40 - %47 = OpLoad %14 %46 - %48 = OpAccessChain %15 %31 %140 - OpStore %48 %47 - OpBranch %21 - %21 = OpLabel - %51 = OpIAdd %14 %140 %50 - OpStore %16 %51 - OpBranch %18 - %20 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %52 = OpVariable %15 Function - %63 = OpVariable %62 Function - OpStore %52 %17 - OpBranch %53 - %53 = OpLabel - %141 = OpPhi %14 %17 %9 %81 %56 - OpLoopMerge %55 %56 None - OpBranch %57 - %57 = OpLabel - %59 = OpSLessThanEqual %25 %141 %24 - OpBranchConditional %59 %54 %55 - %54 = OpLabel - %65 = OpAccessChain %15 %63 %141 - %66 = OpLoad %14 %65 - %67 = OpAccessChain %15 %63 %17 - OpStore %67 %66 - %69 = OpAccessChain %15 %63 %17 - %70 = OpLoad %14 %69 - %71 = OpAccessChain %15 %63 %141 - OpStore %71 %70 - %73 = OpAccessChain %15 %63 %141 - %74 = OpLoad %14 %73 - %75 = OpAccessChain %15 %63 %24 - OpStore %75 %74 - %77 = OpAccessChain %15 %63 %24 - %78 = OpLoad %14 %77 - %79 = OpAccessChain %15 %63 %141 - OpStore %79 %78 - OpBranch %56 - %56 = OpLabel - %81 = OpIAdd %14 %141 %50 - OpStore %52 %81 - OpBranch %53 - %55 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %82 = OpVariable %15 Function - %90 = OpVariable %62 Function - OpStore %82 %24 - OpBranch %83 - %83 = OpLabel - %142 = OpPhi %14 %24 %11 %108 %86 - OpLoopMerge %85 %86 None - OpBranch %87 - %87 = OpLabel - %89 = OpSGreaterThan %25 %142 %17 - OpBranchConditional %89 %84 %85 - %84 = OpLabel - %92 = OpAccessChain %15 %90 %142 - %93 = OpLoad %14 %92 - %94 = OpAccessChain %15 %90 %24 - OpStore %94 %93 - %96 = OpAccessChain %15 %90 %24 - %97 = OpLoad %14 %96 - %98 = OpAccessChain %15 %90 %142 - OpStore %98 %97 - %100 = OpAccessChain %15 %90 %142 - %101 = OpLoad %14 %100 - %102 = OpAccessChain %15 %90 %50 - OpStore %102 %101 - %104 = OpAccessChain %15 %90 %50 - %105 = OpLoad %14 %104 - %106 = OpAccessChain %15 %90 %142 - OpStore %106 %105 - OpBranch %86 - %86 = OpLabel - %108 = OpISub %14 %142 %50 - OpStore %82 %108 - OpBranch %83 - %85 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %109 = OpVariable %15 Function - %117 = OpVariable %62 Function - OpStore %109 %24 - OpBranch %110 - %110 = OpLabel - %143 = OpPhi %14 %24 %13 %135 %113 - OpLoopMerge %112 %113 None - OpBranch %114 - %114 = OpLabel - %116 = OpSGreaterThanEqual %25 %143 %17 - OpBranchConditional %116 %111 %112 - %111 = OpLabel - %119 = OpAccessChain %15 %117 %143 - %120 = OpLoad %14 %119 - %121 = OpAccessChain %15 %117 %24 - OpStore %121 %120 - %123 = OpAccessChain %15 %117 %24 - %124 = OpLoad %14 %123 - %125 = OpAccessChain %15 %117 %143 - OpStore %125 %124 - %127 = OpAccessChain %15 %117 %143 - %128 = OpLoad %14 %127 - %129 = OpAccessChain %15 %117 %17 - OpStore %129 %128 - %131 = OpAccessChain %15 %117 %17 - %132 = OpLoad %14 %131 - %133 = OpAccessChain %15 %117 %143 - OpStore %133 %132 - OpBranch %113 - %113 = OpLabel - %135 = OpISub %14 %143 %50 - OpStore %109 %135 - OpBranch %110 - %112 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - // For the loop in function a - { - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 19)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 34 -> 35 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(34), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 38 -> 39 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(38), store[1], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 43 -> 44 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(43), store[2], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 47 -> 48 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(47), store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - } - // For the loop in function b - { - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 54)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 66 -> 67 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(66), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 70 -> 71 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(70), store[1], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 74 -> 75 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(74), store[2], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 78 -> 79 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(78), store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - } - // For the loop in function c - { - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 84)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 93 -> 94 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(93), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 97 -> 98 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(97), store[1], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 101 -> 102 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(101), store[2], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 105 -> 106 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(105), store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - } - // For the loop in function d - { - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[4]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 111)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(store[i]); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 120 -> 121 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(120), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 124 -> 125 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(124), store[1], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_first); - } - - // Tests identifying peel first with weak zero with destination as zero - // index. - // 128 -> 129 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(128), store[2], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - - // Tests identifying peel first with weak zero with source as zero index. - // 132 -> 133 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(132), store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::PEEL); - EXPECT_TRUE(distance_vector.GetEntries()[0].peel_last); - } - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void main(){ - int[10][10] arr; - for (int i = 0; i < 10; i++) { - arr[i][i] = arr[i][i]; - arr[0][i] = arr[1][i]; - arr[1][i] = arr[0][i]; - arr[i][0] = arr[i][1]; - arr[i][1] = arr[i][0]; - arr[0][1] = arr[1][0]; - } -} -*/ -TEST(DependencyAnalysis, MultipleSubscriptZIVSIV) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %24 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypeArray %21 %20 - %23 = OpTypePointer Function %22 - %33 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %24 = OpVariable %23 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %58 = OpPhi %6 %9 %5 %57 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %58 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %29 = OpAccessChain %7 %24 %58 %58 - %30 = OpLoad %6 %29 - %31 = OpAccessChain %7 %24 %58 %58 - OpStore %31 %30 - %35 = OpAccessChain %7 %24 %33 %58 - %36 = OpLoad %6 %35 - %37 = OpAccessChain %7 %24 %9 %58 - OpStore %37 %36 - %40 = OpAccessChain %7 %24 %9 %58 - %41 = OpLoad %6 %40 - %42 = OpAccessChain %7 %24 %33 %58 - OpStore %42 %41 - %45 = OpAccessChain %7 %24 %58 %33 - %46 = OpLoad %6 %45 - %47 = OpAccessChain %7 %24 %58 %9 - OpStore %47 %46 - %50 = OpAccessChain %7 %24 %58 %9 - %51 = OpLoad %6 %50 - %52 = OpAccessChain %7 %24 %58 %33 - OpStore %52 %51 - %53 = OpAccessChain %7 %24 %33 %9 - %54 = OpLoad %6 %53 - %55 = OpAccessChain %7 %24 %9 %33 - OpStore %55 %54 - OpBranch %13 - %13 = OpLabel - %57 = OpIAdd %6 %58 %33 - OpStore %8 %57 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[6]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 11)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 6; ++i) { - EXPECT_TRUE(store[i]); - } - - // 30 -> 31 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(30), - store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::EQ); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 0); - } - - // 36 -> 37 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(36), - store[1], &distance_vector)); - } - - // 41 -> 42 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(41), - store[2], &distance_vector)); - } - - // 46 -> 47 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(46), - store[3], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::EQ); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 0); - } - - // 51 -> 52 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(51), - store[4], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::EQ); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 0); - } - - // 54 -> 55 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_TRUE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(54), - store[5], &distance_vector)); - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void a(){ - int[10] arr; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - arr[j] = arr[j]; - } - } -} -void b(){ - int[10] arr; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - arr[i] = arr[i]; - } - } -} -void main() { - a(); - b(); -} -*/ -TEST(DependencyAnalysis, IrrelevantSubscripts) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %12 "i" - OpName %23 "j" - OpName %35 "arr" - OpName %46 "i" - OpName %54 "j" - OpName %62 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 0 - %20 = OpConstant %10 10 - %21 = OpTypeBool - %31 = OpTypeInt 32 0 - %32 = OpConstant %31 10 - %33 = OpTypeArray %10 %32 - %34 = OpTypePointer Function %33 - %42 = OpConstant %10 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %72 = OpFunctionCall %2 %6 - %73 = OpFunctionCall %2 %8 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %12 = OpVariable %11 Function - %23 = OpVariable %11 Function - %35 = OpVariable %34 Function - OpStore %12 %13 - OpBranch %14 - %14 = OpLabel - %74 = OpPhi %10 %13 %7 %45 %17 - OpLoopMerge %16 %17 None - OpBranch %18 - %18 = OpLabel - %22 = OpSLessThan %21 %74 %20 - OpBranchConditional %22 %15 %16 - %15 = OpLabel - OpStore %23 %13 - OpBranch %24 - %24 = OpLabel - %75 = OpPhi %10 %13 %15 %43 %27 - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %30 = OpSLessThan %21 %75 %20 - OpBranchConditional %30 %25 %26 - %25 = OpLabel - %38 = OpAccessChain %11 %35 %75 - %39 = OpLoad %10 %38 - %40 = OpAccessChain %11 %35 %75 - OpStore %40 %39 - OpBranch %27 - %27 = OpLabel - %43 = OpIAdd %10 %75 %42 - OpStore %23 %43 - OpBranch %24 - %26 = OpLabel - OpBranch %17 - %17 = OpLabel - %45 = OpIAdd %10 %74 %42 - OpStore %12 %45 - OpBranch %14 - %16 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %46 = OpVariable %11 Function - %54 = OpVariable %11 Function - %62 = OpVariable %34 Function - OpStore %46 %13 - OpBranch %47 - %47 = OpLabel - %77 = OpPhi %10 %13 %9 %71 %50 - OpLoopMerge %49 %50 None - OpBranch %51 - %51 = OpLabel - %53 = OpSLessThan %21 %77 %20 - OpBranchConditional %53 %48 %49 - %48 = OpLabel - OpStore %54 %13 - OpBranch %55 - %55 = OpLabel - %78 = OpPhi %10 %13 %48 %69 %58 - OpLoopMerge %57 %58 None - OpBranch %59 - %59 = OpLabel - %61 = OpSLessThan %21 %78 %20 - OpBranchConditional %61 %56 %57 - %56 = OpLabel - %65 = OpAccessChain %11 %62 %77 - %66 = OpLoad %10 %65 - %67 = OpAccessChain %11 %62 %77 - OpStore %67 %66 - OpBranch %58 - %58 = OpLabel - %69 = OpIAdd %10 %78 %42 - OpStore %54 %69 - OpBranch %55 - %57 = OpLabel - OpBranch %50 - %50 = OpLabel - %71 = OpIAdd %10 %77 %42 - OpStore %46 %71 - OpBranch %47 - %49 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - // For the loop in function a - { - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - std::vector loops{&ld.GetLoopByIndex(1), - &ld.GetLoopByIndex(0)}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[1]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 25)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 1; ++i) { - EXPECT_TRUE(store[i]); - } - - // 39 -> 40 - { - DistanceVector distance_vector{loops.size()}; - analysis.SetDebugStream(std::cout); - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(39), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::IRRELEVANT); - EXPECT_EQ(distance_vector.GetEntries()[1].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[1].distance, 0); - } - } - - // For the loop in function b - { - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - std::vector loops{&ld.GetLoopByIndex(1), - &ld.GetLoopByIndex(0)}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[1]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 56)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 1; ++i) { - EXPECT_TRUE(store[i]); - } - - // 66 -> 67 - { - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.GetDependence( - context->get_def_use_mgr()->GetDef(66), store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::DISTANCE); - EXPECT_EQ(distance_vector.GetEntries()[0].distance, 0); - EXPECT_EQ(distance_vector.GetEntries()[1].dependence_information, - DistanceEntry::DependenceInformation::IRRELEVANT); - } - } -} - -void CheckDependenceAndDirection(const Instruction* source, - const Instruction* destination, - bool expected_dependence, - DistanceVector expected_distance, - LoopDependenceAnalysis* analysis) { - DistanceVector dv_entry(2); - EXPECT_EQ(expected_dependence, - analysis->GetDependence(source, destination, &dv_entry)); - EXPECT_EQ(expected_distance, dv_entry); -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -layout(location = 0) in vec4 c; -void main(){ - int[10] arr; - int a = 2; - int b = 3; - int N = int(c.x); - for (int i = 0; i < 10; i++) { - for (int j = 2; j < 10; j++) { - arr[i] = arr[j]; // 0 - arr[j] = arr[i]; // 1 - arr[j-2] = arr[i+3]; // 2 - arr[j-a] = arr[i+b]; // 3 - arr[2*i] = arr[4*j+3]; // 4, independent - arr[2*i] = arr[4*j]; // 5 - arr[i+j] = arr[i+j]; // 6 - arr[10*i+j] = arr[10*i+j]; // 7 - arr[10*i+10*j] = arr[10*i+10*j+3]; // 8, independent - arr[10*i+10*j] = arr[10*i+N*j+3]; // 9, bail out because of N coefficient - arr[10*i+10*j] = arr[10*i+10*j+N]; // 10, bail out because of N constant - // term - arr[10*i+N*j] = arr[10*i+10*j+3]; // 11, bail out because of N coefficient - arr[10*i+10*j+N] = arr[10*i+10*j]; // 12, bail out because of N constant - // term - arr[10*i] = arr[5*j]; // 13, independent - arr[5*i] = arr[10*j]; // 14, independent - arr[9*i] = arr[3*j]; // 15, independent - arr[3*i] = arr[9*j]; // 16, independent - } - } -} -*/ -TEST(DependencyAnalysis, MIV) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %16 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "a" - OpName %10 "b" - OpName %12 "N" - OpName %16 "c" - OpName %23 "i" - OpName %34 "j" - OpName %45 "arr" - OpDecorate %16 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %11 = OpConstant %6 3 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Input %14 - %16 = OpVariable %15 Input - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 0 - %19 = OpTypePointer Input %13 - %24 = OpConstant %6 0 - %31 = OpConstant %6 10 - %32 = OpTypeBool - %42 = OpConstant %17 10 - %43 = OpTypeArray %6 %42 - %44 = OpTypePointer Function %43 - %74 = OpConstant %6 4 - %184 = OpConstant %6 5 - %197 = OpConstant %6 9 - %213 = OpConstant %6 1 - %218 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %12 = OpVariable %7 Function - %23 = OpVariable %7 Function - %34 = OpVariable %7 Function - %45 = OpVariable %44 Function - OpStore %8 %9 - OpStore %10 %11 - %20 = OpAccessChain %19 %16 %18 - %21 = OpLoad %13 %20 - %22 = OpConvertFToS %6 %21 - OpStore %12 %22 - OpStore %23 %24 - OpBranch %25 - %25 = OpLabel - %217 = OpPhi %6 %24 %5 %216 %28 - %219 = OpPhi %6 %218 %5 %220 %28 - OpLoopMerge %27 %28 None - OpBranch %29 - %29 = OpLabel - %33 = OpSLessThan %32 %217 %31 - OpBranchConditional %33 %26 %27 - %26 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %220 = OpPhi %6 %9 %26 %214 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %32 %220 %31 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %48 = OpAccessChain %7 %45 %220 - %49 = OpLoad %6 %48 - %50 = OpAccessChain %7 %45 %217 - OpStore %50 %49 - %53 = OpAccessChain %7 %45 %217 - %54 = OpLoad %6 %53 - %55 = OpAccessChain %7 %45 %220 - OpStore %55 %54 - %57 = OpISub %6 %220 %9 - %59 = OpIAdd %6 %217 %11 - %60 = OpAccessChain %7 %45 %59 - %61 = OpLoad %6 %60 - %62 = OpAccessChain %7 %45 %57 - OpStore %62 %61 - %65 = OpISub %6 %220 %9 - %68 = OpIAdd %6 %217 %11 - %69 = OpAccessChain %7 %45 %68 - %70 = OpLoad %6 %69 - %71 = OpAccessChain %7 %45 %65 - OpStore %71 %70 - %73 = OpIMul %6 %9 %217 - %76 = OpIMul %6 %74 %220 - %77 = OpIAdd %6 %76 %11 - %78 = OpAccessChain %7 %45 %77 - %79 = OpLoad %6 %78 - %80 = OpAccessChain %7 %45 %73 - OpStore %80 %79 - %82 = OpIMul %6 %9 %217 - %84 = OpIMul %6 %74 %220 - %85 = OpAccessChain %7 %45 %84 - %86 = OpLoad %6 %85 - %87 = OpAccessChain %7 %45 %82 - OpStore %87 %86 - %90 = OpIAdd %6 %217 %220 - %93 = OpIAdd %6 %217 %220 - %94 = OpAccessChain %7 %45 %93 - %95 = OpLoad %6 %94 - %96 = OpAccessChain %7 %45 %90 - OpStore %96 %95 - %98 = OpIMul %6 %31 %217 - %100 = OpIAdd %6 %98 %220 - %102 = OpIMul %6 %31 %217 - %104 = OpIAdd %6 %102 %220 - %105 = OpAccessChain %7 %45 %104 - %106 = OpLoad %6 %105 - %107 = OpAccessChain %7 %45 %100 - OpStore %107 %106 - %109 = OpIMul %6 %31 %217 - %111 = OpIMul %6 %31 %220 - %112 = OpIAdd %6 %109 %111 - %114 = OpIMul %6 %31 %217 - %116 = OpIMul %6 %31 %220 - %117 = OpIAdd %6 %114 %116 - %118 = OpIAdd %6 %117 %11 - %119 = OpAccessChain %7 %45 %118 - %120 = OpLoad %6 %119 - %121 = OpAccessChain %7 %45 %112 - OpStore %121 %120 - %123 = OpIMul %6 %31 %217 - %125 = OpIMul %6 %31 %220 - %126 = OpIAdd %6 %123 %125 - %128 = OpIMul %6 %31 %217 - %131 = OpIMul %6 %22 %220 - %132 = OpIAdd %6 %128 %131 - %133 = OpIAdd %6 %132 %11 - %134 = OpAccessChain %7 %45 %133 - %135 = OpLoad %6 %134 - %136 = OpAccessChain %7 %45 %126 - OpStore %136 %135 - %138 = OpIMul %6 %31 %217 - %140 = OpIMul %6 %31 %220 - %141 = OpIAdd %6 %138 %140 - %143 = OpIMul %6 %31 %217 - %145 = OpIMul %6 %31 %220 - %146 = OpIAdd %6 %143 %145 - %148 = OpIAdd %6 %146 %22 - %149 = OpAccessChain %7 %45 %148 - %150 = OpLoad %6 %149 - %151 = OpAccessChain %7 %45 %141 - OpStore %151 %150 - %153 = OpIMul %6 %31 %217 - %156 = OpIMul %6 %22 %220 - %157 = OpIAdd %6 %153 %156 - %159 = OpIMul %6 %31 %217 - %161 = OpIMul %6 %31 %220 - %162 = OpIAdd %6 %159 %161 - %163 = OpIAdd %6 %162 %11 - %164 = OpAccessChain %7 %45 %163 - %165 = OpLoad %6 %164 - %166 = OpAccessChain %7 %45 %157 - OpStore %166 %165 - %168 = OpIMul %6 %31 %217 - %170 = OpIMul %6 %31 %220 - %171 = OpIAdd %6 %168 %170 - %173 = OpIAdd %6 %171 %22 - %175 = OpIMul %6 %31 %217 - %177 = OpIMul %6 %31 %220 - %178 = OpIAdd %6 %175 %177 - %179 = OpAccessChain %7 %45 %178 - %180 = OpLoad %6 %179 - %181 = OpAccessChain %7 %45 %173 - OpStore %181 %180 - %183 = OpIMul %6 %31 %217 - %186 = OpIMul %6 %184 %220 - %187 = OpAccessChain %7 %45 %186 - %188 = OpLoad %6 %187 - %189 = OpAccessChain %7 %45 %183 - OpStore %189 %188 - %191 = OpIMul %6 %184 %217 - %193 = OpIMul %6 %31 %220 - %194 = OpAccessChain %7 %45 %193 - %195 = OpLoad %6 %194 - %196 = OpAccessChain %7 %45 %191 - OpStore %196 %195 - %199 = OpIMul %6 %197 %217 - %201 = OpIMul %6 %11 %220 - %202 = OpAccessChain %7 %45 %201 - %203 = OpLoad %6 %202 - %204 = OpAccessChain %7 %45 %199 - OpStore %204 %203 - %206 = OpIMul %6 %11 %217 - %208 = OpIMul %6 %197 %220 - %209 = OpAccessChain %7 %45 %208 - %210 = OpLoad %6 %209 - %211 = OpAccessChain %7 %45 %206 - OpStore %211 %210 - OpBranch %38 - %38 = OpLabel - %214 = OpIAdd %6 %220 %213 - OpStore %34 %214 - OpBranch %35 - %37 = OpLabel - OpBranch %28 - %28 = OpLabel - %216 = OpIAdd %6 %217 %213 - OpStore %23 %216 - OpBranch %25 - %27 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - std::vector loops{&ld.GetLoopByIndex(0), &ld.GetLoopByIndex(1)}; - - LoopDependenceAnalysis analysis{context.get(), loops}; - - const int instructions_expected = 17; - const Instruction* store[instructions_expected]; - const Instruction* load[instructions_expected]; - int stores_found = 0; - int loads_found = 0; - - int block_id = 36; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load[loads_found] = &inst; - ++loads_found; - } - } - - EXPECT_EQ(instructions_expected, stores_found); - EXPECT_EQ(instructions_expected, loads_found); - - auto directions_all = DistanceEntry(DistanceEntry::Directions::ALL); - auto directions_none = DistanceEntry(DistanceEntry::Directions::NONE); - - auto dependent = DistanceVector({directions_all, directions_all}); - auto independent = DistanceVector({directions_none, directions_none}); - - CheckDependenceAndDirection(load[0], store[0], false, dependent, &analysis); - CheckDependenceAndDirection(load[1], store[1], false, dependent, &analysis); - CheckDependenceAndDirection(load[2], store[2], false, dependent, &analysis); - CheckDependenceAndDirection(load[3], store[3], false, dependent, &analysis); - CheckDependenceAndDirection(load[4], store[4], true, independent, &analysis); - CheckDependenceAndDirection(load[5], store[5], false, dependent, &analysis); - CheckDependenceAndDirection(load[6], store[6], false, dependent, &analysis); - CheckDependenceAndDirection(load[7], store[7], false, dependent, &analysis); - CheckDependenceAndDirection(load[8], store[8], true, independent, &analysis); - CheckDependenceAndDirection(load[9], store[9], false, dependent, &analysis); - CheckDependenceAndDirection(load[10], store[10], false, dependent, &analysis); - CheckDependenceAndDirection(load[11], store[11], false, dependent, &analysis); - CheckDependenceAndDirection(load[12], store[12], false, dependent, &analysis); - CheckDependenceAndDirection(load[13], store[13], true, independent, - &analysis); - CheckDependenceAndDirection(load[14], store[14], true, independent, - &analysis); - CheckDependenceAndDirection(load[15], store[15], true, independent, - &analysis); - CheckDependenceAndDirection(load[16], store[16], true, independent, - &analysis); -} - -void PartitionSubscripts(const Instruction* instruction_0, - const Instruction* instruction_1, - LoopDependenceAnalysis* analysis, - std::vector> expected_ids) { - auto subscripts_0 = analysis->GetSubscripts(instruction_0); - auto subscripts_1 = analysis->GetSubscripts(instruction_1); - - std::vector>> - expected_partition{}; - - for (const auto& partition : expected_ids) { - expected_partition.push_back( - std::set>{}); - for (auto id : partition) { - expected_partition.back().insert({subscripts_0[id], subscripts_1[id]}); - } - } - - EXPECT_EQ(expected_partition, - analysis->PartitionSubscripts(subscripts_0, subscripts_1)); -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void main(){ - int[10][10][10][10] arr; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - for (int k = 0; k < 10; k++) { - for (int l = 0; l < 10; l++) { - arr[i][j][k][l] = arr[i][j][k][l]; // 0, all independent - arr[i][j][k][l] = arr[i][j][l][0]; // 1, last 2 coupled - arr[i][j][k][l] = arr[j][i][k][l]; // 2, first 2 coupled - arr[i][j][k][l] = arr[l][j][k][i]; // 3, first & last coupled - arr[i][j][k][l] = arr[i][k][j][l]; // 4, middle 2 coupled - arr[i+j][j][k][l] = arr[i][j][k][l]; // 5, first 2 coupled - arr[i+j+k][j][k][l] = arr[i][j][k][l]; // 6, first 3 coupled - arr[i+j+k+l][j][k][l] = arr[i][j][k][l]; // 7, all 4 coupled - arr[i][j][k][l] = arr[i][l][j][k]; // 8, last 3 coupled - arr[i][j-k][k][l] = arr[i][j][l][k]; // 9, last 3 coupled - arr[i][j][k][l] = arr[l][i][j][k]; // 10, all 4 coupled - arr[i][j][k][l] = arr[j][i][l][k]; // 11, 2 coupled partitions (i,j) & -(l&k) - arr[i][j][k][l] = arr[k][l][i][j]; // 12, 2 coupled partitions (i,k) & -(j&l) - } - } - } - } -} -*/ -TEST(DependencyAnalysis, SubscriptPartitioning) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %27 "k" - OpName %35 "l" - OpName %50 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %43 = OpTypeInt 32 0 - %44 = OpConstant %43 10 - %45 = OpTypeArray %6 %44 - %46 = OpTypeArray %45 %44 - %47 = OpTypeArray %46 %44 - %48 = OpTypeArray %47 %44 - %49 = OpTypePointer Function %48 - %208 = OpConstant %6 1 - %217 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %27 = OpVariable %7 Function - %35 = OpVariable %7 Function - %50 = OpVariable %49 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %216 = OpPhi %6 %9 %5 %215 %13 - %218 = OpPhi %6 %217 %5 %221 %13 - %219 = OpPhi %6 %217 %5 %222 %13 - %220 = OpPhi %6 %217 %5 %223 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %216 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %221 = OpPhi %6 %9 %11 %213 %23 - %222 = OpPhi %6 %219 %11 %224 %23 - %223 = OpPhi %6 %220 %11 %225 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %221 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - OpStore %27 %9 - OpBranch %28 - %28 = OpLabel - %224 = OpPhi %6 %9 %21 %211 %31 - %225 = OpPhi %6 %223 %21 %226 %31 - OpLoopMerge %30 %31 None - OpBranch %32 - %32 = OpLabel - %34 = OpSLessThan %17 %224 %16 - OpBranchConditional %34 %29 %30 - %29 = OpLabel - OpStore %35 %9 - OpBranch %36 - %36 = OpLabel - %226 = OpPhi %6 %9 %29 %209 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %17 %226 %16 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %59 = OpAccessChain %7 %50 %216 %221 %224 %226 - %60 = OpLoad %6 %59 - %61 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %61 %60 - %69 = OpAccessChain %7 %50 %216 %221 %226 %9 - %70 = OpLoad %6 %69 - %71 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %71 %70 - %80 = OpAccessChain %7 %50 %221 %216 %224 %226 - %81 = OpLoad %6 %80 - %82 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %82 %81 - %91 = OpAccessChain %7 %50 %226 %221 %224 %216 - %92 = OpLoad %6 %91 - %93 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %93 %92 - %102 = OpAccessChain %7 %50 %216 %224 %221 %226 - %103 = OpLoad %6 %102 - %104 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %104 %103 - %107 = OpIAdd %6 %216 %221 - %115 = OpAccessChain %7 %50 %216 %221 %224 %226 - %116 = OpLoad %6 %115 - %117 = OpAccessChain %7 %50 %107 %221 %224 %226 - OpStore %117 %116 - %120 = OpIAdd %6 %216 %221 - %122 = OpIAdd %6 %120 %224 - %130 = OpAccessChain %7 %50 %216 %221 %224 %226 - %131 = OpLoad %6 %130 - %132 = OpAccessChain %7 %50 %122 %221 %224 %226 - OpStore %132 %131 - %135 = OpIAdd %6 %216 %221 - %137 = OpIAdd %6 %135 %224 - %139 = OpIAdd %6 %137 %226 - %147 = OpAccessChain %7 %50 %216 %221 %224 %226 - %148 = OpLoad %6 %147 - %149 = OpAccessChain %7 %50 %139 %221 %224 %226 - OpStore %149 %148 - %158 = OpAccessChain %7 %50 %216 %226 %221 %224 - %159 = OpLoad %6 %158 - %160 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %160 %159 - %164 = OpISub %6 %221 %224 - %171 = OpAccessChain %7 %50 %216 %221 %226 %224 - %172 = OpLoad %6 %171 - %173 = OpAccessChain %7 %50 %216 %164 %224 %226 - OpStore %173 %172 - %182 = OpAccessChain %7 %50 %226 %216 %221 %224 - %183 = OpLoad %6 %182 - %184 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %184 %183 - %193 = OpAccessChain %7 %50 %221 %216 %226 %224 - %194 = OpLoad %6 %193 - %195 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %195 %194 - %204 = OpAccessChain %7 %50 %224 %226 %216 %221 - %205 = OpLoad %6 %204 - %206 = OpAccessChain %7 %50 %216 %221 %224 %226 - OpStore %206 %205 - OpBranch %39 - %39 = OpLabel - %209 = OpIAdd %6 %226 %208 - OpStore %35 %209 - OpBranch %36 - %38 = OpLabel - OpBranch %31 - %31 = OpLabel - %211 = OpIAdd %6 %224 %208 - OpStore %27 %211 - OpBranch %28 - %30 = OpLabel - OpBranch %23 - %23 = OpLabel - %213 = OpIAdd %6 %221 %208 - OpStore %19 %213 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %215 = OpIAdd %6 %216 %208 - OpStore %8 %215 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - std::vector loop_nest{ - &ld.GetLoopByIndex(0), &ld.GetLoopByIndex(1), &ld.GetLoopByIndex(2), - &ld.GetLoopByIndex(3)}; - LoopDependenceAnalysis analysis{context.get(), loop_nest}; - - const int instructions_expected = 13; - const Instruction* store[instructions_expected]; - const Instruction* load[instructions_expected]; - int stores_found = 0; - int loads_found = 0; - - int block_id = 37; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load[loads_found] = &inst; - ++loads_found; - } - } - - EXPECT_EQ(instructions_expected, stores_found); - EXPECT_EQ(instructions_expected, loads_found); - - PartitionSubscripts(load[0], store[0], &analysis, {{0}, {1}, {2}, {3}}); - PartitionSubscripts(load[1], store[1], &analysis, {{0}, {1}, {2, 3}}); - PartitionSubscripts(load[2], store[2], &analysis, {{0, 1}, {2}, {3}}); - PartitionSubscripts(load[3], store[3], &analysis, {{0, 3}, {1}, {2}}); - PartitionSubscripts(load[4], store[4], &analysis, {{0}, {1, 2}, {3}}); - PartitionSubscripts(load[5], store[5], &analysis, {{0, 1}, {2}, {3}}); - PartitionSubscripts(load[6], store[6], &analysis, {{0, 1, 2}, {3}}); - PartitionSubscripts(load[7], store[7], &analysis, {{0, 1, 2, 3}}); - PartitionSubscripts(load[8], store[8], &analysis, {{0}, {1, 2, 3}}); - PartitionSubscripts(load[9], store[9], &analysis, {{0}, {1, 2, 3}}); - PartitionSubscripts(load[10], store[10], &analysis, {{0, 1, 2, 3}}); - PartitionSubscripts(load[11], store[11], &analysis, {{0, 1}, {2, 3}}); - PartitionSubscripts(load[12], store[12], &analysis, {{0, 2}, {1, 3}}); -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store - -#version 440 core -void a() { - int[10][10] arr; - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 10; ++j) { - // Dependent, distance vector (1, -1) - arr[i+1][i+j] = arr[i][i+j]; - } - } -} - -void b() { - int[10][10] arr; - for (int i = 0; i < 10; ++i) { - // Independent - arr[i+1][i+2] = arr[i][i] + 2; - } -} - -void c() { - int[10][10] arr; - for (int i = 0; i < 10; ++i) { - // Dependence point (1,2) - arr[i][i] = arr[1][i-1] + 2; - } -} - -void d() { - int[10][10][10] arr; - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 10; ++j) { - for (int k = 0; k < 10; ++k) { - // Dependent, distance vector (1,1,-1) - arr[j-i][i+1][j+k] = arr[j-i][i][j+k]; - } - } - } -} - -void e() { - int[10][10] arr; - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 10; ++j) { - // Independent with GCD after propagation - arr[i][2*j+i] = arr[i][2*j-i+5]; - } - } -} - -void main(){ - a(); - b(); - c(); - d(); - e(); -} -*/ -TEST(DependencyAnalysis, Delta) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %14 "e(" - OpName %18 "i" - OpName %29 "j" - OpName %42 "arr" - OpName %60 "i" - OpName %68 "arr" - OpName %82 "i" - OpName %90 "arr" - OpName %101 "i" - OpName %109 "j" - OpName %117 "k" - OpName %127 "arr" - OpName %152 "i" - OpName %160 "j" - OpName %168 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %16 = OpTypeInt 32 1 - %17 = OpTypePointer Function %16 - %19 = OpConstant %16 0 - %26 = OpConstant %16 10 - %27 = OpTypeBool - %37 = OpTypeInt 32 0 - %38 = OpConstant %37 10 - %39 = OpTypeArray %16 %38 - %40 = OpTypeArray %39 %38 - %41 = OpTypePointer Function %40 - %44 = OpConstant %16 1 - %72 = OpConstant %16 2 - %125 = OpTypeArray %40 %38 - %126 = OpTypePointer Function %125 - %179 = OpConstant %16 5 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %188 = OpFunctionCall %2 %6 - %189 = OpFunctionCall %2 %8 - %190 = OpFunctionCall %2 %10 - %191 = OpFunctionCall %2 %12 - %192 = OpFunctionCall %2 %14 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %18 = OpVariable %17 Function - %29 = OpVariable %17 Function - %42 = OpVariable %41 Function - OpStore %18 %19 - OpBranch %20 - %20 = OpLabel - %193 = OpPhi %16 %19 %7 %59 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %28 = OpSLessThan %27 %193 %26 - OpBranchConditional %28 %21 %22 - %21 = OpLabel - OpStore %29 %19 - OpBranch %30 - %30 = OpLabel - %194 = OpPhi %16 %19 %21 %57 %33 - OpLoopMerge %32 %33 None - OpBranch %34 - %34 = OpLabel - %36 = OpSLessThan %27 %194 %26 - OpBranchConditional %36 %31 %32 - %31 = OpLabel - %45 = OpIAdd %16 %193 %44 - %48 = OpIAdd %16 %193 %194 - %52 = OpIAdd %16 %193 %194 - %53 = OpAccessChain %17 %42 %193 %52 - %54 = OpLoad %16 %53 - %55 = OpAccessChain %17 %42 %45 %48 - OpStore %55 %54 - OpBranch %33 - %33 = OpLabel - %57 = OpIAdd %16 %194 %44 - OpStore %29 %57 - OpBranch %30 - %32 = OpLabel - OpBranch %23 - %23 = OpLabel - %59 = OpIAdd %16 %193 %44 - OpStore %18 %59 - OpBranch %20 - %22 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %60 = OpVariable %17 Function - %68 = OpVariable %41 Function - OpStore %60 %19 - OpBranch %61 - %61 = OpLabel - %196 = OpPhi %16 %19 %9 %81 %64 - OpLoopMerge %63 %64 None - OpBranch %65 - %65 = OpLabel - %67 = OpSLessThan %27 %196 %26 - OpBranchConditional %67 %62 %63 - %62 = OpLabel - %70 = OpIAdd %16 %196 %44 - %73 = OpIAdd %16 %196 %72 - %76 = OpAccessChain %17 %68 %196 %196 - %77 = OpLoad %16 %76 - %78 = OpIAdd %16 %77 %72 - %79 = OpAccessChain %17 %68 %70 %73 - OpStore %79 %78 - OpBranch %64 - %64 = OpLabel - %81 = OpIAdd %16 %196 %44 - OpStore %60 %81 - OpBranch %61 - %63 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %82 = OpVariable %17 Function - %90 = OpVariable %41 Function - OpStore %82 %19 - OpBranch %83 - %83 = OpLabel - %197 = OpPhi %16 %19 %11 %100 %86 - OpLoopMerge %85 %86 None - OpBranch %87 - %87 = OpLabel - %89 = OpSLessThan %27 %197 %26 - OpBranchConditional %89 %84 %85 - %84 = OpLabel - %94 = OpISub %16 %197 %44 - %95 = OpAccessChain %17 %90 %44 %94 - %96 = OpLoad %16 %95 - %97 = OpIAdd %16 %96 %72 - %98 = OpAccessChain %17 %90 %197 %197 - OpStore %98 %97 - OpBranch %86 - %86 = OpLabel - %100 = OpIAdd %16 %197 %44 - OpStore %82 %100 - OpBranch %83 - %85 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %101 = OpVariable %17 Function - %109 = OpVariable %17 Function - %117 = OpVariable %17 Function - %127 = OpVariable %126 Function - OpStore %101 %19 - OpBranch %102 - %102 = OpLabel - %198 = OpPhi %16 %19 %13 %151 %105 - OpLoopMerge %104 %105 None - OpBranch %106 - %106 = OpLabel - %108 = OpSLessThan %27 %198 %26 - OpBranchConditional %108 %103 %104 - %103 = OpLabel - OpStore %109 %19 - OpBranch %110 - %110 = OpLabel - %199 = OpPhi %16 %19 %103 %149 %113 - OpLoopMerge %112 %113 None - OpBranch %114 - %114 = OpLabel - %116 = OpSLessThan %27 %199 %26 - OpBranchConditional %116 %111 %112 - %111 = OpLabel - OpStore %117 %19 - OpBranch %118 - %118 = OpLabel - %201 = OpPhi %16 %19 %111 %147 %121 - OpLoopMerge %120 %121 None - OpBranch %122 - %122 = OpLabel - %124 = OpSLessThan %27 %201 %26 - OpBranchConditional %124 %119 %120 - %119 = OpLabel - %130 = OpISub %16 %199 %198 - %132 = OpIAdd %16 %198 %44 - %135 = OpIAdd %16 %199 %201 - %138 = OpISub %16 %199 %198 - %142 = OpIAdd %16 %199 %201 - %143 = OpAccessChain %17 %127 %138 %198 %142 - %144 = OpLoad %16 %143 - %145 = OpAccessChain %17 %127 %130 %132 %135 - OpStore %145 %144 - OpBranch %121 - %121 = OpLabel - %147 = OpIAdd %16 %201 %44 - OpStore %117 %147 - OpBranch %118 - %120 = OpLabel - OpBranch %113 - %113 = OpLabel - %149 = OpIAdd %16 %199 %44 - OpStore %109 %149 - OpBranch %110 - %112 = OpLabel - OpBranch %105 - %105 = OpLabel - %151 = OpIAdd %16 %198 %44 - OpStore %101 %151 - OpBranch %102 - %104 = OpLabel - OpReturn - OpFunctionEnd - %14 = OpFunction %2 None %3 - %15 = OpLabel - %152 = OpVariable %17 Function - %160 = OpVariable %17 Function - %168 = OpVariable %41 Function - OpStore %152 %19 - OpBranch %153 - %153 = OpLabel - %204 = OpPhi %16 %19 %15 %187 %156 - OpLoopMerge %155 %156 None - OpBranch %157 - %157 = OpLabel - %159 = OpSLessThan %27 %204 %26 - OpBranchConditional %159 %154 %155 - %154 = OpLabel - OpStore %160 %19 - OpBranch %161 - %161 = OpLabel - %205 = OpPhi %16 %19 %154 %185 %164 - OpLoopMerge %163 %164 None - OpBranch %165 - %165 = OpLabel - %167 = OpSLessThan %27 %205 %26 - OpBranchConditional %167 %162 %163 - %162 = OpLabel - %171 = OpIMul %16 %72 %205 - %173 = OpIAdd %16 %171 %204 - %176 = OpIMul %16 %72 %205 - %178 = OpISub %16 %176 %204 - %180 = OpIAdd %16 %178 %179 - %181 = OpAccessChain %17 %168 %204 %180 - %182 = OpLoad %16 %181 - %183 = OpAccessChain %17 %168 %204 %173 - OpStore %183 %182 - OpBranch %164 - %164 = OpLabel - %185 = OpIAdd %16 %205 %44 - OpStore %160 %185 - OpBranch %161 - %163 = OpLabel - OpBranch %156 - %156 = OpLabel - %187 = OpIAdd %16 %204 %44 - OpStore %152 %187 - OpBranch %153 - %155 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - ASSERT_NE(nullptr, context); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - { - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - const Instruction* store = nullptr; - const Instruction* load = nullptr; - - int block_id = 31; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(nullptr, store); - EXPECT_NE(nullptr, load); - - std::vector loop_nest{&ld.GetLoopByIndex(0), - &ld.GetLoopByIndex(1)}; - LoopDependenceAnalysis analysis{context.get(), loop_nest}; - - DistanceVector dv_entry(loop_nest.size()); - - std::vector expected_entries{ - DistanceEntry(DistanceEntry::Directions::LT, 1), - DistanceEntry(DistanceEntry::Directions::LT, 1)}; - - DistanceVector expected_distance_vector(expected_entries); - - auto is_independent = analysis.GetDependence(load, store, &dv_entry); - - EXPECT_FALSE(is_independent); - EXPECT_EQ(expected_distance_vector, dv_entry); - } - - { - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - const Instruction* store = nullptr; - const Instruction* load = nullptr; - - int block_id = 62; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(nullptr, store); - EXPECT_NE(nullptr, load); - - std::vector loop_nest{&ld.GetLoopByIndex(0)}; - LoopDependenceAnalysis analysis{context.get(), loop_nest}; - - DistanceVector dv_entry(loop_nest.size()); - auto is_independent = analysis.GetDependence(load, store, &dv_entry); - - EXPECT_TRUE(is_independent); - } - - { - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - const Instruction* store = nullptr; - const Instruction* load = nullptr; - - int block_id = 84; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(nullptr, store); - EXPECT_NE(nullptr, load); - - std::vector loop_nest{&ld.GetLoopByIndex(0)}; - LoopDependenceAnalysis analysis{context.get(), loop_nest}; - - DistanceVector dv_entry(loop_nest.size()); - auto is_independent = analysis.GetDependence(load, store, &dv_entry); - - DistanceVector expected_distance_vector({DistanceEntry(1, 2)}); - - EXPECT_FALSE(is_independent); - EXPECT_EQ(expected_distance_vector, dv_entry); - } - - { - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - const Instruction* store = nullptr; - const Instruction* load = nullptr; - - int block_id = 119; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(nullptr, store); - EXPECT_NE(nullptr, load); - - std::vector loop_nest{ - &ld.GetLoopByIndex(0), &ld.GetLoopByIndex(1), &ld.GetLoopByIndex(2)}; - LoopDependenceAnalysis analysis{context.get(), loop_nest}; - - DistanceVector dv_entry(loop_nest.size()); - - std::vector expected_entries{ - DistanceEntry(DistanceEntry::Directions::LT, 1), - DistanceEntry(DistanceEntry::Directions::LT, 1), - DistanceEntry(DistanceEntry::Directions::GT, -1)}; - - DistanceVector expected_distance_vector(expected_entries); - - auto is_independent = analysis.GetDependence(store, load, &dv_entry); - - EXPECT_FALSE(is_independent); - EXPECT_EQ(expected_distance_vector, dv_entry); - } - - { - const Function* f = spvtest::GetFunction(module, 14); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - const Instruction* store = nullptr; - const Instruction* load = nullptr; - - int block_id = 162; - ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id)); - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(nullptr, store); - EXPECT_NE(nullptr, load); - - std::vector loop_nest{&ld.GetLoopByIndex(0), - &ld.GetLoopByIndex(1)}; - LoopDependenceAnalysis analysis{context.get(), loop_nest}; - - DistanceVector dv_entry(loop_nest.size()); - auto is_independent = analysis.GetDependence(load, store, &dv_entry); - - EXPECT_TRUE(is_independent); - } -} - -TEST(DependencyAnalysis, ConstraintIntersection) { - LoopDependenceAnalysis analysis{nullptr, std::vector{}}; - auto scalar_evolution = analysis.GetScalarEvolution(); - { - // One is none. Other should be returned - auto none = analysis.make_constraint(); - auto x = scalar_evolution->CreateConstant(1); - auto y = scalar_evolution->CreateConstant(10); - auto point = analysis.make_constraint(x, y, nullptr); - - auto ret_0 = analysis.IntersectConstraints(none, point, nullptr, nullptr); - - auto ret_point_0 = ret_0->AsDependencePoint(); - ASSERT_NE(nullptr, ret_point_0); - EXPECT_EQ(*x, *ret_point_0->GetSource()); - EXPECT_EQ(*y, *ret_point_0->GetDestination()); - - auto ret_1 = analysis.IntersectConstraints(point, none, nullptr, nullptr); - - auto ret_point_1 = ret_1->AsDependencePoint(); - ASSERT_NE(nullptr, ret_point_1); - EXPECT_EQ(*x, *ret_point_1->GetSource()); - EXPECT_EQ(*y, *ret_point_1->GetDestination()); - } - - { - // Both distances - auto x = scalar_evolution->CreateConstant(1); - auto y = scalar_evolution->CreateConstant(10); - - auto distance_0 = analysis.make_constraint(x, nullptr); - auto distance_1 = analysis.make_constraint(y, nullptr); - - // Equal distances - auto ret_0 = - analysis.IntersectConstraints(distance_1, distance_1, nullptr, nullptr); - - auto ret_distance = ret_0->AsDependenceDistance(); - ASSERT_NE(nullptr, ret_distance); - EXPECT_EQ(*y, *ret_distance->GetDistance()); - - // Non-equal distances - auto ret_1 = - analysis.IntersectConstraints(distance_0, distance_1, nullptr, nullptr); - EXPECT_NE(nullptr, ret_1->AsDependenceEmpty()); - } - - { - // Both points - auto x = scalar_evolution->CreateConstant(1); - auto y = scalar_evolution->CreateConstant(10); - - auto point_0 = analysis.make_constraint(x, y, nullptr); - auto point_1 = analysis.make_constraint(x, y, nullptr); - auto point_2 = analysis.make_constraint(y, y, nullptr); - - // Equal points - auto ret_0 = - analysis.IntersectConstraints(point_0, point_1, nullptr, nullptr); - auto ret_point_0 = ret_0->AsDependencePoint(); - ASSERT_NE(nullptr, ret_point_0); - EXPECT_EQ(*x, *ret_point_0->GetSource()); - EXPECT_EQ(*y, *ret_point_0->GetDestination()); - - // Non-equal points - auto ret_1 = - analysis.IntersectConstraints(point_0, point_2, nullptr, nullptr); - EXPECT_NE(nullptr, ret_1->AsDependenceEmpty()); - } - - { - // Both lines, parallel - auto a0 = scalar_evolution->CreateConstant(3); - auto b0 = scalar_evolution->CreateConstant(6); - auto c0 = scalar_evolution->CreateConstant(9); - - auto a1 = scalar_evolution->CreateConstant(6); - auto b1 = scalar_evolution->CreateConstant(12); - auto c1 = scalar_evolution->CreateConstant(18); - - auto line_0 = analysis.make_constraint(a0, b0, c0, nullptr); - auto line_1 = analysis.make_constraint(a1, b1, c1, nullptr); - - // Same line, both ways - auto ret_0 = - analysis.IntersectConstraints(line_0, line_1, nullptr, nullptr); - auto ret_1 = - analysis.IntersectConstraints(line_1, line_0, nullptr, nullptr); - - auto ret_line_0 = ret_0->AsDependenceLine(); - auto ret_line_1 = ret_1->AsDependenceLine(); - - EXPECT_NE(nullptr, ret_line_0); - EXPECT_NE(nullptr, ret_line_1); - - // Non-intersecting parallel lines - auto c2 = scalar_evolution->CreateConstant(12); - auto line_2 = analysis.make_constraint(a1, b1, c2, nullptr); - - auto ret_2 = - analysis.IntersectConstraints(line_0, line_2, nullptr, nullptr); - auto ret_3 = - analysis.IntersectConstraints(line_2, line_0, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_2->AsDependenceEmpty()); - EXPECT_NE(nullptr, ret_3->AsDependenceEmpty()); - - auto c3 = scalar_evolution->CreateConstant(20); - auto line_3 = analysis.make_constraint(a1, b1, c3, nullptr); - - auto ret_4 = - analysis.IntersectConstraints(line_0, line_3, nullptr, nullptr); - auto ret_5 = - analysis.IntersectConstraints(line_3, line_0, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_4->AsDependenceEmpty()); - EXPECT_NE(nullptr, ret_5->AsDependenceEmpty()); - } - - { - // Non-constant line - auto unknown = scalar_evolution->CreateCantComputeNode(); - auto constant = scalar_evolution->CreateConstant(10); - - auto line_0 = analysis.make_constraint(constant, constant, - constant, nullptr); - auto line_1 = analysis.make_constraint(unknown, unknown, - unknown, nullptr); - - auto ret_0 = - analysis.IntersectConstraints(line_0, line_1, nullptr, nullptr); - auto ret_1 = - analysis.IntersectConstraints(line_1, line_0, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_0->AsDependenceNone()); - EXPECT_NE(nullptr, ret_1->AsDependenceNone()); - } - - { - auto bound_0 = scalar_evolution->CreateConstant(0); - auto bound_1 = scalar_evolution->CreateConstant(20); - - auto a0 = scalar_evolution->CreateConstant(1); - auto b0 = scalar_evolution->CreateConstant(2); - auto c0 = scalar_evolution->CreateConstant(6); - - auto a1 = scalar_evolution->CreateConstant(-1); - auto b1 = scalar_evolution->CreateConstant(2); - auto c1 = scalar_evolution->CreateConstant(2); - - auto line_0 = analysis.make_constraint(a0, b0, c0, nullptr); - auto line_1 = analysis.make_constraint(a1, b1, c1, nullptr); - - // Intersecting lines, has integer solution, in bounds - auto ret_0 = - analysis.IntersectConstraints(line_0, line_1, bound_0, bound_1); - auto ret_1 = - analysis.IntersectConstraints(line_1, line_0, bound_0, bound_1); - - auto ret_point_0 = ret_0->AsDependencePoint(); - auto ret_point_1 = ret_1->AsDependencePoint(); - - EXPECT_NE(nullptr, ret_point_0); - EXPECT_NE(nullptr, ret_point_1); - - auto const_2 = scalar_evolution->CreateConstant(2); - - EXPECT_EQ(*const_2, *ret_point_0->GetSource()); - EXPECT_EQ(*const_2, *ret_point_0->GetDestination()); - - EXPECT_EQ(*const_2, *ret_point_1->GetSource()); - EXPECT_EQ(*const_2, *ret_point_1->GetDestination()); - - // Intersecting lines, has integer solution, out of bounds - auto ret_2 = - analysis.IntersectConstraints(line_0, line_1, bound_0, bound_0); - auto ret_3 = - analysis.IntersectConstraints(line_1, line_0, bound_0, bound_0); - - EXPECT_NE(nullptr, ret_2->AsDependenceEmpty()); - EXPECT_NE(nullptr, ret_3->AsDependenceEmpty()); - - auto a2 = scalar_evolution->CreateConstant(-4); - auto b2 = scalar_evolution->CreateConstant(1); - auto c2 = scalar_evolution->CreateConstant(0); - - auto a3 = scalar_evolution->CreateConstant(4); - auto b3 = scalar_evolution->CreateConstant(1); - auto c3 = scalar_evolution->CreateConstant(4); - - auto line_2 = analysis.make_constraint(a2, b2, c2, nullptr); - auto line_3 = analysis.make_constraint(a3, b3, c3, nullptr); - - // Intersecting, no integer solution - auto ret_4 = - analysis.IntersectConstraints(line_2, line_3, bound_0, bound_1); - auto ret_5 = - analysis.IntersectConstraints(line_3, line_2, bound_0, bound_1); - - EXPECT_NE(nullptr, ret_4->AsDependenceEmpty()); - EXPECT_NE(nullptr, ret_5->AsDependenceEmpty()); - - auto unknown = scalar_evolution->CreateCantComputeNode(); - - // Non-constant bound - auto ret_6 = - analysis.IntersectConstraints(line_0, line_1, unknown, bound_1); - auto ret_7 = - analysis.IntersectConstraints(line_1, line_0, bound_0, unknown); - - EXPECT_NE(nullptr, ret_6->AsDependenceNone()); - EXPECT_NE(nullptr, ret_7->AsDependenceNone()); - } - - { - auto constant_0 = scalar_evolution->CreateConstant(0); - auto constant_1 = scalar_evolution->CreateConstant(1); - auto constant_neg_1 = scalar_evolution->CreateConstant(-1); - auto constant_2 = scalar_evolution->CreateConstant(2); - auto constant_neg_2 = scalar_evolution->CreateConstant(-2); - - auto point_0_0 = analysis.make_constraint( - constant_0, constant_0, nullptr); - auto point_0_1 = analysis.make_constraint( - constant_0, constant_1, nullptr); - auto point_1_0 = analysis.make_constraint( - constant_1, constant_0, nullptr); - auto point_1_1 = analysis.make_constraint( - constant_1, constant_1, nullptr); - auto point_1_2 = analysis.make_constraint( - constant_1, constant_2, nullptr); - auto point_1_neg_1 = analysis.make_constraint( - constant_1, constant_neg_1, nullptr); - auto point_neg_1_1 = analysis.make_constraint( - constant_neg_1, constant_1, nullptr); - - auto line_y_0 = analysis.make_constraint( - constant_0, constant_1, constant_0, nullptr); - auto line_y_1 = analysis.make_constraint( - constant_0, constant_1, constant_1, nullptr); - auto line_y_2 = analysis.make_constraint( - constant_0, constant_1, constant_2, nullptr); - - // Parallel horizontal lines, y = 0 & y = 1, should return no intersection - auto ret = - analysis.IntersectConstraints(line_y_0, line_y_1, nullptr, nullptr); - - EXPECT_NE(nullptr, ret->AsDependenceEmpty()); - - // Parallel horizontal lines, y = 1 & y = 2, should return no intersection - auto ret_y_12 = - analysis.IntersectConstraints(line_y_1, line_y_2, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_y_12->AsDependenceEmpty()); - - // Same horizontal lines, y = 0 & y = 0, should return the line - auto ret_y_same_0 = - analysis.IntersectConstraints(line_y_0, line_y_0, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_y_same_0->AsDependenceLine()); - - // Same horizontal lines, y = 1 & y = 1, should return the line - auto ret_y_same_1 = - analysis.IntersectConstraints(line_y_1, line_y_1, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_y_same_1->AsDependenceLine()); - - auto line_x_0 = analysis.make_constraint( - constant_1, constant_0, constant_0, nullptr); - auto line_x_1 = analysis.make_constraint( - constant_1, constant_0, constant_1, nullptr); - auto line_x_2 = analysis.make_constraint( - constant_1, constant_0, constant_2, nullptr); - auto line_2x_1 = analysis.make_constraint( - constant_2, constant_0, constant_1, nullptr); - auto line_2x_2 = analysis.make_constraint( - constant_2, constant_0, constant_2, nullptr); - - // Parallel vertical lines, x = 0 & x = 1, should return no intersection - auto ret_x = - analysis.IntersectConstraints(line_x_0, line_x_1, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_x->AsDependenceEmpty()); - - // Parallel vertical lines, x = 1 & x = 2, should return no intersection - auto ret_x_12 = - analysis.IntersectConstraints(line_x_1, line_x_2, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_x_12->AsDependenceEmpty()); - - // Parallel vertical lines, 2x = 1 & 2x = 2, should return no intersection - auto ret_2x_2_2x_1 = - analysis.IntersectConstraints(line_2x_2, line_2x_1, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_2x_2_2x_1->AsDependenceEmpty()); - - // same line, 2x=2 & x = 1 - auto ret_2x_2_x_1 = - analysis.IntersectConstraints(line_2x_2, line_x_1, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_2x_2_x_1->AsDependenceLine()); - - // Same vertical lines, x = 0 & x = 0, should return the line - auto ret_x_same_0 = - analysis.IntersectConstraints(line_x_0, line_x_0, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_x_same_0->AsDependenceLine()); - // EXPECT_EQ(*line_x_0, *ret_x_same_0->AsDependenceLine()); - - // Same vertical lines, x = 1 & x = 1, should return the line - auto ret_x_same_1 = - analysis.IntersectConstraints(line_x_1, line_x_1, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_x_same_1->AsDependenceLine()); - EXPECT_EQ(*line_x_1, *ret_x_same_1->AsDependenceLine()); - - // x=1 & y = 0, intersect at (1, 0) - auto ret_1_0 = analysis.IntersectConstraints(line_x_1, line_y_0, - constant_neg_1, constant_2); - - auto ret_point_1_0 = ret_1_0->AsDependencePoint(); - EXPECT_NE(nullptr, ret_point_1_0); - EXPECT_EQ(*point_1_0, *ret_point_1_0); - - // x=1 & y = 1, intersect at (1, 1) - auto ret_1_1 = analysis.IntersectConstraints(line_x_1, line_y_1, - constant_neg_1, constant_2); - - auto ret_point_1_1 = ret_1_1->AsDependencePoint(); - EXPECT_NE(nullptr, ret_point_1_1); - EXPECT_EQ(*point_1_1, *ret_point_1_1); - - // x=0 & y = 0, intersect at (0, 0) - auto ret_0_0 = analysis.IntersectConstraints(line_x_0, line_y_0, - constant_neg_1, constant_2); - - auto ret_point_0_0 = ret_0_0->AsDependencePoint(); - EXPECT_NE(nullptr, ret_point_0_0); - EXPECT_EQ(*point_0_0, *ret_point_0_0); - - // x=0 & y = 1, intersect at (0, 1) - auto ret_0_1 = analysis.IntersectConstraints(line_x_0, line_y_1, - constant_neg_1, constant_2); - auto ret_point_0_1 = ret_0_1->AsDependencePoint(); - EXPECT_NE(nullptr, ret_point_0_1); - EXPECT_EQ(*point_0_1, *ret_point_0_1); - - // x = 1 & y = 2 - auto ret_1_2 = analysis.IntersectConstraints(line_x_1, line_y_2, - constant_neg_1, constant_2); - auto ret_point_1_2 = ret_1_2->AsDependencePoint(); - EXPECT_NE(nullptr, ret_point_1_2); - EXPECT_EQ(*point_1_2, *ret_point_1_2); - - auto line_x_y_0 = analysis.make_constraint( - constant_1, constant_1, constant_0, nullptr); - auto line_x_y_1 = analysis.make_constraint( - constant_1, constant_1, constant_1, nullptr); - - // x+y=0 & x=0, intersect (0, 0) - auto ret_xy_0_x_0 = analysis.IntersectConstraints( - line_x_y_0, line_x_0, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_xy_0_x_0->AsDependencePoint()); - EXPECT_EQ(*point_0_0, *ret_xy_0_x_0); - - // x+y=0 & y=0, intersect (0, 0) - auto ret_xy_0_y_0 = analysis.IntersectConstraints( - line_x_y_0, line_y_0, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_xy_0_y_0->AsDependencePoint()); - EXPECT_EQ(*point_0_0, *ret_xy_0_y_0); - - // x+y=0 & x=1, intersect (1, -1) - auto ret_xy_0_x_1 = analysis.IntersectConstraints( - line_x_y_0, line_x_1, constant_neg_2, constant_2); - - EXPECT_NE(nullptr, ret_xy_0_x_1->AsDependencePoint()); - EXPECT_EQ(*point_1_neg_1, *ret_xy_0_x_1); - - // x+y=0 & y=1, intersect (-1, 1) - auto ret_xy_0_y_1 = analysis.IntersectConstraints( - line_x_y_0, line_y_1, constant_neg_2, constant_2); - - EXPECT_NE(nullptr, ret_xy_0_y_1->AsDependencePoint()); - EXPECT_EQ(*point_neg_1_1, *ret_xy_0_y_1); - - // x=0 & x+y=0, intersect (0, 0) - auto ret_x_0_xy_0 = analysis.IntersectConstraints( - line_x_0, line_x_y_0, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_x_0_xy_0->AsDependencePoint()); - EXPECT_EQ(*point_0_0, *ret_x_0_xy_0); - - // y=0 & x+y=0, intersect (0, 0) - auto ret_y_0_xy_0 = analysis.IntersectConstraints( - line_y_0, line_x_y_0, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_y_0_xy_0->AsDependencePoint()); - EXPECT_EQ(*point_0_0, *ret_y_0_xy_0); - - // x=1 & x+y=0, intersect (1, -1) - auto ret_x_1_xy_0 = analysis.IntersectConstraints( - line_x_1, line_x_y_0, constant_neg_2, constant_2); - - EXPECT_NE(nullptr, ret_x_1_xy_0->AsDependencePoint()); - EXPECT_EQ(*point_1_neg_1, *ret_x_1_xy_0); - - // y=1 & x+y=0, intersect (-1, 1) - auto ret_y_1_xy_0 = analysis.IntersectConstraints( - line_y_1, line_x_y_0, constant_neg_2, constant_2); - - EXPECT_NE(nullptr, ret_y_1_xy_0->AsDependencePoint()); - EXPECT_EQ(*point_neg_1_1, *ret_y_1_xy_0); - - // x+y=1 & x=0, intersect (0, 1) - auto ret_xy_1_x_0 = analysis.IntersectConstraints( - line_x_y_1, line_x_0, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_xy_1_x_0->AsDependencePoint()); - EXPECT_EQ(*point_0_1, *ret_xy_1_x_0); - - // x+y=1 & y=0, intersect (1, 0) - auto ret_xy_1_y_0 = analysis.IntersectConstraints( - line_x_y_1, line_y_0, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_xy_1_y_0->AsDependencePoint()); - EXPECT_EQ(*point_1_0, *ret_xy_1_y_0); - - // x+y=1 & x=1, intersect (1, 0) - auto ret_xy_1_x_1 = analysis.IntersectConstraints( - line_x_y_1, line_x_1, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_xy_1_x_1->AsDependencePoint()); - EXPECT_EQ(*point_1_0, *ret_xy_1_x_1); - - // x+y=1 & y=1, intersect (0, 1) - auto ret_xy_1_y_1 = analysis.IntersectConstraints( - line_x_y_1, line_y_1, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_xy_1_y_1->AsDependencePoint()); - EXPECT_EQ(*point_0_1, *ret_xy_1_y_1); - - // x=0 & x+y=1, intersect (0, 1) - auto ret_x_0_xy_1 = analysis.IntersectConstraints( - line_x_0, line_x_y_1, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_x_0_xy_1->AsDependencePoint()); - EXPECT_EQ(*point_0_1, *ret_x_0_xy_1); - - // y=0 & x+y=1, intersect (1, 0) - auto ret_y_0_xy_1 = analysis.IntersectConstraints( - line_y_0, line_x_y_1, constant_neg_1, constant_2); - - EXPECT_NE(nullptr, ret_y_0_xy_1->AsDependencePoint()); - EXPECT_EQ(*point_1_0, *ret_y_0_xy_1); - - // x=1 & x+y=1, intersect (1, 0) - auto ret_x_1_xy_1 = analysis.IntersectConstraints( - line_x_1, line_x_y_1, constant_neg_2, constant_2); - - EXPECT_NE(nullptr, ret_x_1_xy_1->AsDependencePoint()); - EXPECT_EQ(*point_1_0, *ret_x_1_xy_1); - - // y=1 & x+y=1, intersect (0, 1) - auto ret_y_1_xy_1 = analysis.IntersectConstraints( - line_y_1, line_x_y_1, constant_neg_2, constant_2); - - EXPECT_NE(nullptr, ret_y_1_xy_1->AsDependencePoint()); - EXPECT_EQ(*point_0_1, *ret_y_1_xy_1); - } - - { - // Line and point - auto a = scalar_evolution->CreateConstant(3); - auto b = scalar_evolution->CreateConstant(10); - auto c = scalar_evolution->CreateConstant(16); - - auto line = analysis.make_constraint(a, b, c, nullptr); - - // Point on line - auto x = scalar_evolution->CreateConstant(2); - auto y = scalar_evolution->CreateConstant(1); - auto point_0 = analysis.make_constraint(x, y, nullptr); - - auto ret_0 = analysis.IntersectConstraints(line, point_0, nullptr, nullptr); - auto ret_1 = analysis.IntersectConstraints(point_0, line, nullptr, nullptr); - - auto ret_point_0 = ret_0->AsDependencePoint(); - auto ret_point_1 = ret_1->AsDependencePoint(); - ASSERT_NE(nullptr, ret_point_0); - ASSERT_NE(nullptr, ret_point_1); - - EXPECT_EQ(*x, *ret_point_0->GetSource()); - EXPECT_EQ(*y, *ret_point_0->GetDestination()); - - EXPECT_EQ(*x, *ret_point_1->GetSource()); - EXPECT_EQ(*y, *ret_point_1->GetDestination()); - - // Point not on line - auto point_1 = analysis.make_constraint(a, a, nullptr); - - auto ret_2 = analysis.IntersectConstraints(line, point_1, nullptr, nullptr); - auto ret_3 = analysis.IntersectConstraints(point_1, line, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_2->AsDependenceEmpty()); - EXPECT_NE(nullptr, ret_3->AsDependenceEmpty()); - - // Non-constant - auto unknown = scalar_evolution->CreateCantComputeNode(); - - auto point_2 = - analysis.make_constraint(unknown, x, nullptr); - - auto ret_4 = analysis.IntersectConstraints(line, point_2, nullptr, nullptr); - auto ret_5 = analysis.IntersectConstraints(point_2, line, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_4->AsDependenceNone()); - EXPECT_NE(nullptr, ret_5->AsDependenceNone()); - } - - { - // Distance and point - auto d = scalar_evolution->CreateConstant(5); - auto distance = analysis.make_constraint(d, nullptr); - - // Point on line - auto x = scalar_evolution->CreateConstant(10); - auto point_0 = analysis.make_constraint(d, x, nullptr); - - auto ret_0 = - analysis.IntersectConstraints(distance, point_0, nullptr, nullptr); - auto ret_1 = - analysis.IntersectConstraints(point_0, distance, nullptr, nullptr); - - auto ret_point_0 = ret_0->AsDependencePoint(); - auto ret_point_1 = ret_1->AsDependencePoint(); - ASSERT_NE(nullptr, ret_point_0); - ASSERT_NE(nullptr, ret_point_1); - - // Point not on line - auto point_1 = analysis.make_constraint(x, x, nullptr); - - auto ret_2 = - analysis.IntersectConstraints(distance, point_1, nullptr, nullptr); - auto ret_3 = - analysis.IntersectConstraints(point_1, distance, nullptr, nullptr); - - EXPECT_NE(nullptr, ret_2->AsDependenceEmpty()); - EXPECT_NE(nullptr, ret_3->AsDependenceEmpty()); - - // Non-constant - auto unknown = scalar_evolution->CreateCantComputeNode(); - auto unknown_distance = - analysis.make_constraint(unknown, nullptr); - - auto ret_4 = analysis.IntersectConstraints(unknown_distance, point_1, - nullptr, nullptr); - auto ret_5 = analysis.IntersectConstraints(point_1, unknown_distance, - nullptr, nullptr); - - EXPECT_NE(nullptr, ret_4->AsDependenceNone()); - EXPECT_NE(nullptr, ret_5->AsDependenceNone()); - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp deleted file mode 100644 index 715cf541d..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp +++ /dev/null @@ -1,3017 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_dependence.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/scalar_analysis.h" -#include "source/opt/tree_iterator.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using DependencyAnalysisHelpers = ::testing::Test; - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void a() { - int[10][10] arr; - int i = 0; - int j = 0; - for (; i < 10 && j < 10; i++, j++) { - arr[i][j] = arr[i][j]; - } -} -void b() { - int[10] arr; - for (int i = 0; i < 10; i+=2) { - arr[i] = arr[i]; - } -} -void main(){ - a(); - b(); -} -*/ -TEST(DependencyAnalysisHelpers, UnsupportedLoops) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %12 "i" - OpName %14 "j" - OpName %32 "arr" - OpName %45 "i" - OpName %54 "arr" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %13 = OpConstant %10 0 - %21 = OpConstant %10 10 - %22 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %10 %28 - %30 = OpTypeArray %29 %28 - %31 = OpTypePointer Function %30 - %41 = OpConstant %10 1 - %53 = OpTypePointer Function %29 - %60 = OpConstant %10 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %63 = OpFunctionCall %2 %6 - %64 = OpFunctionCall %2 %8 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %12 = OpVariable %11 Function - %14 = OpVariable %11 Function - %32 = OpVariable %31 Function - OpStore %12 %13 - OpStore %14 %13 - OpBranch %15 - %15 = OpLabel - %65 = OpPhi %10 %13 %7 %42 %18 - %66 = OpPhi %10 %13 %7 %44 %18 - OpLoopMerge %17 %18 None - OpBranch %19 - %19 = OpLabel - %23 = OpSLessThan %22 %65 %21 - %25 = OpSLessThan %22 %66 %21 - %26 = OpLogicalAnd %22 %23 %25 - OpBranchConditional %26 %16 %17 - %16 = OpLabel - %37 = OpAccessChain %11 %32 %65 %66 - %38 = OpLoad %10 %37 - %39 = OpAccessChain %11 %32 %65 %66 - OpStore %39 %38 - OpBranch %18 - %18 = OpLabel - %42 = OpIAdd %10 %65 %41 - OpStore %12 %42 - %44 = OpIAdd %10 %66 %41 - OpStore %14 %44 - OpBranch %15 - %17 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %45 = OpVariable %11 Function - %54 = OpVariable %53 Function - OpStore %45 %13 - OpBranch %46 - %46 = OpLabel - %67 = OpPhi %10 %13 %9 %62 %49 - OpLoopMerge %48 %49 None - OpBranch %50 - %50 = OpLabel - %52 = OpSLessThan %22 %67 %21 - OpBranchConditional %52 %47 %48 - %47 = OpLabel - %57 = OpAccessChain %11 %54 %67 - %58 = OpLoad %10 %57 - %59 = OpAccessChain %11 %54 %67 - OpStore %59 %58 - OpBranch %49 - %49 = OpLabel - %62 = OpIAdd %10 %67 %60 - OpStore %45 %62 - OpBranch %46 - %48 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - { - // Function a - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[1] = {nullptr}; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 16)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - // 38 -> 39 - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.IsSupportedLoop(loops[0])); - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(38), - store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::UNKNOWN); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::ALL); - } - { - // Function b - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* store[1] = {nullptr}; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 47)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store[stores_found] = &inst; - ++stores_found; - } - } - // 58 -> 59 - DistanceVector distance_vector{loops.size()}; - EXPECT_FALSE(analysis.IsSupportedLoop(loops[0])); - EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(58), - store[0], &distance_vector)); - EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information, - DistanceEntry::DependenceInformation::UNKNOWN); - EXPECT_EQ(distance_vector.GetEntries()[0].direction, - DistanceEntry::Directions::ALL); - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void a() { - for (int i = -10; i < 0; i++) { - - } -} -void b() { - for (int i = -5; i < 5; i++) { - - } -} -void c() { - for (int i = 0; i < 10; i++) { - - } -} -void d() { - for (int i = 5; i < 15; i++) { - - } -} -void e() { - for (int i = -10; i <= 0; i++) { - - } -} -void f() { - for (int i = -5; i <= 5; i++) { - - } -} -void g() { - for (int i = 0; i <= 10; i++) { - - } -} -void h() { - for (int i = 5; i <= 15; i++) { - - } -} -void i() { - for (int i = 0; i > -10; i--) { - - } -} -void j() { - for (int i = 5; i > -5; i--) { - - } -} -void k() { - for (int i = 10; i > 0; i--) { - - } -} -void l() { - for (int i = 15; i > 5; i--) { - - } -} -void m() { - for (int i = 0; i >= -10; i--) { - - } -} -void n() { - for (int i = 5; i >= -5; i--) { - - } -} -void o() { - for (int i = 10; i >= 0; i--) { - - } -} -void p() { - for (int i = 15; i >= 5; i--) { - - } -} -void main(){ - a(); - b(); - c(); - d(); - e(); - f(); - g(); - h(); - i(); - j(); - k(); - l(); - m(); - n(); - o(); - p(); -} -*/ -TEST(DependencyAnalysisHelpers, loop_information) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %14 "e(" - OpName %16 "f(" - OpName %18 "g(" - OpName %20 "h(" - OpName %22 "i(" - OpName %24 "j(" - OpName %26 "k(" - OpName %28 "l(" - OpName %30 "m(" - OpName %32 "n(" - OpName %34 "o(" - OpName %36 "p(" - OpName %40 "i" - OpName %54 "i" - OpName %66 "i" - OpName %77 "i" - OpName %88 "i" - OpName %98 "i" - OpName %108 "i" - OpName %118 "i" - OpName %128 "i" - OpName %138 "i" - OpName %148 "i" - OpName %158 "i" - OpName %168 "i" - OpName %178 "i" - OpName %188 "i" - OpName %198 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %38 = OpTypeInt 32 1 - %39 = OpTypePointer Function %38 - %41 = OpConstant %38 -10 - %48 = OpConstant %38 0 - %49 = OpTypeBool - %52 = OpConstant %38 1 - %55 = OpConstant %38 -5 - %62 = OpConstant %38 5 - %73 = OpConstant %38 10 - %84 = OpConstant %38 15 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %208 = OpFunctionCall %2 %6 - %209 = OpFunctionCall %2 %8 - %210 = OpFunctionCall %2 %10 - %211 = OpFunctionCall %2 %12 - %212 = OpFunctionCall %2 %14 - %213 = OpFunctionCall %2 %16 - %214 = OpFunctionCall %2 %18 - %215 = OpFunctionCall %2 %20 - %216 = OpFunctionCall %2 %22 - %217 = OpFunctionCall %2 %24 - %218 = OpFunctionCall %2 %26 - %219 = OpFunctionCall %2 %28 - %220 = OpFunctionCall %2 %30 - %221 = OpFunctionCall %2 %32 - %222 = OpFunctionCall %2 %34 - %223 = OpFunctionCall %2 %36 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %40 = OpVariable %39 Function - OpStore %40 %41 - OpBranch %42 - %42 = OpLabel - %224 = OpPhi %38 %41 %7 %53 %45 - OpLoopMerge %44 %45 None - OpBranch %46 - %46 = OpLabel - %50 = OpSLessThan %49 %224 %48 - OpBranchConditional %50 %43 %44 - %43 = OpLabel - OpBranch %45 - %45 = OpLabel - %53 = OpIAdd %38 %224 %52 - OpStore %40 %53 - OpBranch %42 - %44 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %54 = OpVariable %39 Function - OpStore %54 %55 - OpBranch %56 - %56 = OpLabel - %225 = OpPhi %38 %55 %9 %65 %59 - OpLoopMerge %58 %59 None - OpBranch %60 - %60 = OpLabel - %63 = OpSLessThan %49 %225 %62 - OpBranchConditional %63 %57 %58 - %57 = OpLabel - OpBranch %59 - %59 = OpLabel - %65 = OpIAdd %38 %225 %52 - OpStore %54 %65 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %66 = OpVariable %39 Function - OpStore %66 %48 - OpBranch %67 - %67 = OpLabel - %226 = OpPhi %38 %48 %11 %76 %70 - OpLoopMerge %69 %70 None - OpBranch %71 - %71 = OpLabel - %74 = OpSLessThan %49 %226 %73 - OpBranchConditional %74 %68 %69 - %68 = OpLabel - OpBranch %70 - %70 = OpLabel - %76 = OpIAdd %38 %226 %52 - OpStore %66 %76 - OpBranch %67 - %69 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %77 = OpVariable %39 Function - OpStore %77 %62 - OpBranch %78 - %78 = OpLabel - %227 = OpPhi %38 %62 %13 %87 %81 - OpLoopMerge %80 %81 None - OpBranch %82 - %82 = OpLabel - %85 = OpSLessThan %49 %227 %84 - OpBranchConditional %85 %79 %80 - %79 = OpLabel - OpBranch %81 - %81 = OpLabel - %87 = OpIAdd %38 %227 %52 - OpStore %77 %87 - OpBranch %78 - %80 = OpLabel - OpReturn - OpFunctionEnd - %14 = OpFunction %2 None %3 - %15 = OpLabel - %88 = OpVariable %39 Function - OpStore %88 %41 - OpBranch %89 - %89 = OpLabel - %228 = OpPhi %38 %41 %15 %97 %92 - OpLoopMerge %91 %92 None - OpBranch %93 - %93 = OpLabel - %95 = OpSLessThanEqual %49 %228 %48 - OpBranchConditional %95 %90 %91 - %90 = OpLabel - OpBranch %92 - %92 = OpLabel - %97 = OpIAdd %38 %228 %52 - OpStore %88 %97 - OpBranch %89 - %91 = OpLabel - OpReturn - OpFunctionEnd - %16 = OpFunction %2 None %3 - %17 = OpLabel - %98 = OpVariable %39 Function - OpStore %98 %55 - OpBranch %99 - %99 = OpLabel - %229 = OpPhi %38 %55 %17 %107 %102 - OpLoopMerge %101 %102 None - OpBranch %103 - %103 = OpLabel - %105 = OpSLessThanEqual %49 %229 %62 - OpBranchConditional %105 %100 %101 - %100 = OpLabel - OpBranch %102 - %102 = OpLabel - %107 = OpIAdd %38 %229 %52 - OpStore %98 %107 - OpBranch %99 - %101 = OpLabel - OpReturn - OpFunctionEnd - %18 = OpFunction %2 None %3 - %19 = OpLabel - %108 = OpVariable %39 Function - OpStore %108 %48 - OpBranch %109 - %109 = OpLabel - %230 = OpPhi %38 %48 %19 %117 %112 - OpLoopMerge %111 %112 None - OpBranch %113 - %113 = OpLabel - %115 = OpSLessThanEqual %49 %230 %73 - OpBranchConditional %115 %110 %111 - %110 = OpLabel - OpBranch %112 - %112 = OpLabel - %117 = OpIAdd %38 %230 %52 - OpStore %108 %117 - OpBranch %109 - %111 = OpLabel - OpReturn - OpFunctionEnd - %20 = OpFunction %2 None %3 - %21 = OpLabel - %118 = OpVariable %39 Function - OpStore %118 %62 - OpBranch %119 - %119 = OpLabel - %231 = OpPhi %38 %62 %21 %127 %122 - OpLoopMerge %121 %122 None - OpBranch %123 - %123 = OpLabel - %125 = OpSLessThanEqual %49 %231 %84 - OpBranchConditional %125 %120 %121 - %120 = OpLabel - OpBranch %122 - %122 = OpLabel - %127 = OpIAdd %38 %231 %52 - OpStore %118 %127 - OpBranch %119 - %121 = OpLabel - OpReturn - OpFunctionEnd - %22 = OpFunction %2 None %3 - %23 = OpLabel - %128 = OpVariable %39 Function - OpStore %128 %48 - OpBranch %129 - %129 = OpLabel - %232 = OpPhi %38 %48 %23 %137 %132 - OpLoopMerge %131 %132 None - OpBranch %133 - %133 = OpLabel - %135 = OpSGreaterThan %49 %232 %41 - OpBranchConditional %135 %130 %131 - %130 = OpLabel - OpBranch %132 - %132 = OpLabel - %137 = OpISub %38 %232 %52 - OpStore %128 %137 - OpBranch %129 - %131 = OpLabel - OpReturn - OpFunctionEnd - %24 = OpFunction %2 None %3 - %25 = OpLabel - %138 = OpVariable %39 Function - OpStore %138 %62 - OpBranch %139 - %139 = OpLabel - %233 = OpPhi %38 %62 %25 %147 %142 - OpLoopMerge %141 %142 None - OpBranch %143 - %143 = OpLabel - %145 = OpSGreaterThan %49 %233 %55 - OpBranchConditional %145 %140 %141 - %140 = OpLabel - OpBranch %142 - %142 = OpLabel - %147 = OpISub %38 %233 %52 - OpStore %138 %147 - OpBranch %139 - %141 = OpLabel - OpReturn - OpFunctionEnd - %26 = OpFunction %2 None %3 - %27 = OpLabel - %148 = OpVariable %39 Function - OpStore %148 %73 - OpBranch %149 - %149 = OpLabel - %234 = OpPhi %38 %73 %27 %157 %152 - OpLoopMerge %151 %152 None - OpBranch %153 - %153 = OpLabel - %155 = OpSGreaterThan %49 %234 %48 - OpBranchConditional %155 %150 %151 - %150 = OpLabel - OpBranch %152 - %152 = OpLabel - %157 = OpISub %38 %234 %52 - OpStore %148 %157 - OpBranch %149 - %151 = OpLabel - OpReturn - OpFunctionEnd - %28 = OpFunction %2 None %3 - %29 = OpLabel - %158 = OpVariable %39 Function - OpStore %158 %84 - OpBranch %159 - %159 = OpLabel - %235 = OpPhi %38 %84 %29 %167 %162 - OpLoopMerge %161 %162 None - OpBranch %163 - %163 = OpLabel - %165 = OpSGreaterThan %49 %235 %62 - OpBranchConditional %165 %160 %161 - %160 = OpLabel - OpBranch %162 - %162 = OpLabel - %167 = OpISub %38 %235 %52 - OpStore %158 %167 - OpBranch %159 - %161 = OpLabel - OpReturn - OpFunctionEnd - %30 = OpFunction %2 None %3 - %31 = OpLabel - %168 = OpVariable %39 Function - OpStore %168 %48 - OpBranch %169 - %169 = OpLabel - %236 = OpPhi %38 %48 %31 %177 %172 - OpLoopMerge %171 %172 None - OpBranch %173 - %173 = OpLabel - %175 = OpSGreaterThanEqual %49 %236 %41 - OpBranchConditional %175 %170 %171 - %170 = OpLabel - OpBranch %172 - %172 = OpLabel - %177 = OpISub %38 %236 %52 - OpStore %168 %177 - OpBranch %169 - %171 = OpLabel - OpReturn - OpFunctionEnd - %32 = OpFunction %2 None %3 - %33 = OpLabel - %178 = OpVariable %39 Function - OpStore %178 %62 - OpBranch %179 - %179 = OpLabel - %237 = OpPhi %38 %62 %33 %187 %182 - OpLoopMerge %181 %182 None - OpBranch %183 - %183 = OpLabel - %185 = OpSGreaterThanEqual %49 %237 %55 - OpBranchConditional %185 %180 %181 - %180 = OpLabel - OpBranch %182 - %182 = OpLabel - %187 = OpISub %38 %237 %52 - OpStore %178 %187 - OpBranch %179 - %181 = OpLabel - OpReturn - OpFunctionEnd - %34 = OpFunction %2 None %3 - %35 = OpLabel - %188 = OpVariable %39 Function - OpStore %188 %73 - OpBranch %189 - %189 = OpLabel - %238 = OpPhi %38 %73 %35 %197 %192 - OpLoopMerge %191 %192 None - OpBranch %193 - %193 = OpLabel - %195 = OpSGreaterThanEqual %49 %238 %48 - OpBranchConditional %195 %190 %191 - %190 = OpLabel - OpBranch %192 - %192 = OpLabel - %197 = OpISub %38 %238 %52 - OpStore %188 %197 - OpBranch %189 - %191 = OpLabel - OpReturn - OpFunctionEnd - %36 = OpFunction %2 None %3 - %37 = OpLabel - %198 = OpVariable %39 Function - OpStore %198 %84 - OpBranch %199 - %199 = OpLabel - %239 = OpPhi %38 %84 %37 %207 %202 - OpLoopMerge %201 %202 None - OpBranch %203 - %203 = OpLabel - %205 = OpSGreaterThanEqual %49 %239 %62 - OpBranchConditional %205 %200 %201 - %200 = OpLabel - OpBranch %202 - %202 = OpLabel - %207 = OpISub %38 %239 %52 - OpStore %198 %207 - OpBranch %199 - %201 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - { - // Function a - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -10); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -1); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(-10)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(-1)); - } - { - // Function b - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -5); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 4); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(-5)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(4)); - } - { - // Function c - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 0); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 9); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(0)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(9)); - } - { - // Function d - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 5); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 14); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(5)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(14)); - } - { - // Function e - const Function* f = spvtest::GetFunction(module, 14); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -10); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 0); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(-10)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(0)); - } - { - // Function f - const Function* f = spvtest::GetFunction(module, 16); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -5); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 5); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(-5)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(5)); - } - { - // Function g - const Function* f = spvtest::GetFunction(module, 18); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 0); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(0)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(10)); - } - { - // Function h - const Function* f = spvtest::GetFunction(module, 20); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 5); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 15); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(5)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(1)), - analysis.GetScalarEvolution()->CreateConstant(15)); - } - { - // Function i - const Function* f = spvtest::GetFunction(module, 22); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 0); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -9); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(0)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(-9)); - } - { - // Function j - const Function* f = spvtest::GetFunction(module, 24); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 5); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -4); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(5)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(-4)); - } - { - // Function k - const Function* f = spvtest::GetFunction(module, 26); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 1); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(10)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(1)); - } - { - // Function l - const Function* f = spvtest::GetFunction(module, 28); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 15); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 6); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(15)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(6)); - } - { - // Function m - const Function* f = spvtest::GetFunction(module, 30); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 0); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -10); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(0)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(-10)); - } - { - // Function n - const Function* f = spvtest::GetFunction(module, 32); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 5); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - -5); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(5)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(-5)); - } - { - // Function o - const Function* f = spvtest::GetFunction(module, 34); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 10); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 0); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(10)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(0)); - } - { - // Function p - const Function* f = spvtest::GetFunction(module, 36); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_EQ( - analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 15); - EXPECT_EQ( - analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(), - 5); - - EXPECT_EQ( - analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(), - 11); - - EXPECT_EQ(analysis.GetFirstTripInductionNode(loop), - analysis.GetScalarEvolution()->CreateConstant(15)); - - EXPECT_EQ(analysis.GetFinalTripInductionNode( - loop, analysis.GetScalarEvolution()->CreateConstant(-1)), - analysis.GetScalarEvolution()->CreateConstant(5)); - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -void main(){ - for (int i = 0; i < 10; i++) { - - } -} -*/ -TEST(DependencyAnalysisHelpers, bounds_checks) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %22 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %22 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %22 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - // We need a shader that includes a loop for this test so we can build a - // LoopDependenceAnalaysis - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - EXPECT_TRUE(analysis.IsWithinBounds(0, 0, 0)); - EXPECT_TRUE(analysis.IsWithinBounds(0, -1, 0)); - EXPECT_TRUE(analysis.IsWithinBounds(0, 0, 1)); - EXPECT_TRUE(analysis.IsWithinBounds(0, -1, 1)); - EXPECT_TRUE(analysis.IsWithinBounds(-2, -2, -2)); - EXPECT_TRUE(analysis.IsWithinBounds(-2, -3, 0)); - EXPECT_TRUE(analysis.IsWithinBounds(-2, 0, -3)); - EXPECT_TRUE(analysis.IsWithinBounds(2, 2, 2)); - EXPECT_TRUE(analysis.IsWithinBounds(2, 3, 0)); - - EXPECT_FALSE(analysis.IsWithinBounds(2, 3, 3)); - EXPECT_FALSE(analysis.IsWithinBounds(0, 1, 5)); - EXPECT_FALSE(analysis.IsWithinBounds(0, -1, -4)); - EXPECT_FALSE(analysis.IsWithinBounds(-2, -4, -3)); -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -layout(location = 0) in vec4 in_vec; -// Loop iterates from constant to symbolic -void a() { - int N = int(in_vec.x); - int arr[10]; - for (int i = 0; i < N; i++) { // Bounds are N - 0 - 1 - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void b() { - int N = int(in_vec.x); - int arr[10]; - for (int i = 0; i <= N; i++) { // Bounds are N - 0 - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void c() { - int N = int(in_vec.x); - int arr[10]; - for (int i = 9; i > N; i--) { // Bounds are 9 - N - 1 - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void d() { - int N = int(in_vec.x); - int arr[10]; - for (int i = 9; i >= N; i--) { // Bounds are 9 - N - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void main(){ - a(); - b(); - c(); - d(); -} -*/ -TEST(DependencyAnalysisHelpers, const_to_symbolic) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %20 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %16 "N" - OpName %20 "in_vec" - OpName %27 "i" - OpName %41 "arr" - OpName %59 "N" - OpName %63 "i" - OpName %72 "arr" - OpName %89 "N" - OpName %93 "i" - OpName %103 "arr" - OpName %120 "N" - OpName %124 "i" - OpName %133 "arr" - OpDecorate %20 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %14 = OpTypeInt 32 1 - %15 = OpTypePointer Function %14 - %17 = OpTypeFloat 32 - %18 = OpTypeVector %17 4 - %19 = OpTypePointer Input %18 - %20 = OpVariable %19 Input - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 0 - %23 = OpTypePointer Input %17 - %28 = OpConstant %14 0 - %36 = OpTypeBool - %38 = OpConstant %21 10 - %39 = OpTypeArray %14 %38 - %40 = OpTypePointer Function %39 - %57 = OpConstant %14 1 - %94 = OpConstant %14 9 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %150 = OpFunctionCall %2 %6 - %151 = OpFunctionCall %2 %8 - %152 = OpFunctionCall %2 %10 - %153 = OpFunctionCall %2 %12 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %16 = OpVariable %15 Function - %27 = OpVariable %15 Function - %41 = OpVariable %40 Function - %24 = OpAccessChain %23 %20 %22 - %25 = OpLoad %17 %24 - %26 = OpConvertFToS %14 %25 - OpStore %16 %26 - OpStore %27 %28 - OpBranch %29 - %29 = OpLabel - %154 = OpPhi %14 %28 %7 %58 %32 - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %37 = OpSLessThan %36 %154 %26 - OpBranchConditional %37 %30 %31 - %30 = OpLabel - %45 = OpIAdd %14 %154 %26 - %46 = OpAccessChain %15 %41 %45 - %47 = OpLoad %14 %46 - %48 = OpAccessChain %15 %41 %154 - OpStore %48 %47 - %51 = OpIAdd %14 %154 %26 - %53 = OpAccessChain %15 %41 %154 - %54 = OpLoad %14 %53 - %55 = OpAccessChain %15 %41 %51 - OpStore %55 %54 - OpBranch %32 - %32 = OpLabel - %58 = OpIAdd %14 %154 %57 - OpStore %27 %58 - OpBranch %29 - %31 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %59 = OpVariable %15 Function - %63 = OpVariable %15 Function - %72 = OpVariable %40 Function - %60 = OpAccessChain %23 %20 %22 - %61 = OpLoad %17 %60 - %62 = OpConvertFToS %14 %61 - OpStore %59 %62 - OpStore %63 %28 - OpBranch %64 - %64 = OpLabel - %155 = OpPhi %14 %28 %9 %88 %67 - OpLoopMerge %66 %67 None - OpBranch %68 - %68 = OpLabel - %71 = OpSLessThanEqual %36 %155 %62 - OpBranchConditional %71 %65 %66 - %65 = OpLabel - %76 = OpIAdd %14 %155 %62 - %77 = OpAccessChain %15 %72 %76 - %78 = OpLoad %14 %77 - %79 = OpAccessChain %15 %72 %155 - OpStore %79 %78 - %82 = OpIAdd %14 %155 %62 - %84 = OpAccessChain %15 %72 %155 - %85 = OpLoad %14 %84 - %86 = OpAccessChain %15 %72 %82 - OpStore %86 %85 - OpBranch %67 - %67 = OpLabel - %88 = OpIAdd %14 %155 %57 - OpStore %63 %88 - OpBranch %64 - %66 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %89 = OpVariable %15 Function - %93 = OpVariable %15 Function - %103 = OpVariable %40 Function - %90 = OpAccessChain %23 %20 %22 - %91 = OpLoad %17 %90 - %92 = OpConvertFToS %14 %91 - OpStore %89 %92 - OpStore %93 %94 - OpBranch %95 - %95 = OpLabel - %156 = OpPhi %14 %94 %11 %119 %98 - OpLoopMerge %97 %98 None - OpBranch %99 - %99 = OpLabel - %102 = OpSGreaterThan %36 %156 %92 - OpBranchConditional %102 %96 %97 - %96 = OpLabel - %107 = OpIAdd %14 %156 %92 - %108 = OpAccessChain %15 %103 %107 - %109 = OpLoad %14 %108 - %110 = OpAccessChain %15 %103 %156 - OpStore %110 %109 - %113 = OpIAdd %14 %156 %92 - %115 = OpAccessChain %15 %103 %156 - %116 = OpLoad %14 %115 - %117 = OpAccessChain %15 %103 %113 - OpStore %117 %116 - OpBranch %98 - %98 = OpLabel - %119 = OpISub %14 %156 %57 - OpStore %93 %119 - OpBranch %95 - %97 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %120 = OpVariable %15 Function - %124 = OpVariable %15 Function - %133 = OpVariable %40 Function - %121 = OpAccessChain %23 %20 %22 - %122 = OpLoad %17 %121 - %123 = OpConvertFToS %14 %122 - OpStore %120 %123 - OpStore %124 %94 - OpBranch %125 - %125 = OpLabel - %157 = OpPhi %14 %94 %13 %149 %128 - OpLoopMerge %127 %128 None - OpBranch %129 - %129 = OpLabel - %132 = OpSGreaterThanEqual %36 %157 %123 - OpBranchConditional %132 %126 %127 - %126 = OpLabel - %137 = OpIAdd %14 %157 %123 - %138 = OpAccessChain %15 %133 %137 - %139 = OpLoad %14 %138 - %140 = OpAccessChain %15 %133 %157 - OpStore %140 %139 - %143 = OpIAdd %14 %157 %123 - %145 = OpAccessChain %15 %133 %157 - %146 = OpLoad %14 %145 - %147 = OpAccessChain %15 %133 %143 - OpStore %147 %146 - OpBranch %128 - %128 = OpLabel - %149 = OpISub %14 %157 %57 - OpStore %124 %149 - OpBranch %125 - %127 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - { - // Function a - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 47 -> 48 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(47) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent and supported. - EXPECT_TRUE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 54 -> 55 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(54) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent but not supported. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function b - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 65)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 78 -> 79 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(78) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 85 -> 86 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(85) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function c - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 109 -> 110 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(109) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent but not supported. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 116 -> 117 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(116) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent but not supported. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function d - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 126)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 139 -> 140 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(139) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 146 -> 147 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(146) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -layout(location = 0) in vec4 in_vec; -// Loop iterates from symbolic to constant -void a() { - int N = int(in_vec.x); - int arr[10]; - for (int i = N; i < 9; i++) { // Bounds are 9 - N - 1 - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void b() { - int N = int(in_vec.x); - int arr[10]; - for (int i = N; i <= 9; i++) { // Bounds are 9 - N - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void c() { - int N = int(in_vec.x); - int arr[10]; - for (int i = N; i > 0; i--) { // Bounds are N - 0 - 1 - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void d() { - int N = int(in_vec.x); - int arr[10]; - for (int i = N; i >= 0; i--) { // Bounds are N - 0 - arr[i] = arr[i+N]; // |distance| = N - arr[i+N] = arr[i]; // |distance| = N - } -} -void main(){ - a(); - b(); - c(); - d(); -} -*/ -TEST(DependencyAnalysisHelpers, symbolic_to_const) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %20 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %16 "N" - OpName %20 "in_vec" - OpName %27 "i" - OpName %41 "arr" - OpName %59 "N" - OpName %63 "i" - OpName %72 "arr" - OpName %89 "N" - OpName %93 "i" - OpName %103 "arr" - OpName %120 "N" - OpName %124 "i" - OpName %133 "arr" - OpDecorate %20 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %14 = OpTypeInt 32 1 - %15 = OpTypePointer Function %14 - %17 = OpTypeFloat 32 - %18 = OpTypeVector %17 4 - %19 = OpTypePointer Input %18 - %20 = OpVariable %19 Input - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 0 - %23 = OpTypePointer Input %17 - %35 = OpConstant %14 9 - %36 = OpTypeBool - %38 = OpConstant %21 10 - %39 = OpTypeArray %14 %38 - %40 = OpTypePointer Function %39 - %57 = OpConstant %14 1 - %101 = OpConstant %14 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %150 = OpFunctionCall %2 %6 - %151 = OpFunctionCall %2 %8 - %152 = OpFunctionCall %2 %10 - %153 = OpFunctionCall %2 %12 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %16 = OpVariable %15 Function - %27 = OpVariable %15 Function - %41 = OpVariable %40 Function - %24 = OpAccessChain %23 %20 %22 - %25 = OpLoad %17 %24 - %26 = OpConvertFToS %14 %25 - OpStore %16 %26 - OpStore %27 %26 - OpBranch %29 - %29 = OpLabel - %154 = OpPhi %14 %26 %7 %58 %32 - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %37 = OpSLessThan %36 %154 %35 - OpBranchConditional %37 %30 %31 - %30 = OpLabel - %45 = OpIAdd %14 %154 %26 - %46 = OpAccessChain %15 %41 %45 - %47 = OpLoad %14 %46 - %48 = OpAccessChain %15 %41 %154 - OpStore %48 %47 - %51 = OpIAdd %14 %154 %26 - %53 = OpAccessChain %15 %41 %154 - %54 = OpLoad %14 %53 - %55 = OpAccessChain %15 %41 %51 - OpStore %55 %54 - OpBranch %32 - %32 = OpLabel - %58 = OpIAdd %14 %154 %57 - OpStore %27 %58 - OpBranch %29 - %31 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %59 = OpVariable %15 Function - %63 = OpVariable %15 Function - %72 = OpVariable %40 Function - %60 = OpAccessChain %23 %20 %22 - %61 = OpLoad %17 %60 - %62 = OpConvertFToS %14 %61 - OpStore %59 %62 - OpStore %63 %62 - OpBranch %65 - %65 = OpLabel - %155 = OpPhi %14 %62 %9 %88 %68 - OpLoopMerge %67 %68 None - OpBranch %69 - %69 = OpLabel - %71 = OpSLessThanEqual %36 %155 %35 - OpBranchConditional %71 %66 %67 - %66 = OpLabel - %76 = OpIAdd %14 %155 %62 - %77 = OpAccessChain %15 %72 %76 - %78 = OpLoad %14 %77 - %79 = OpAccessChain %15 %72 %155 - OpStore %79 %78 - %82 = OpIAdd %14 %155 %62 - %84 = OpAccessChain %15 %72 %155 - %85 = OpLoad %14 %84 - %86 = OpAccessChain %15 %72 %82 - OpStore %86 %85 - OpBranch %68 - %68 = OpLabel - %88 = OpIAdd %14 %155 %57 - OpStore %63 %88 - OpBranch %65 - %67 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %89 = OpVariable %15 Function - %93 = OpVariable %15 Function - %103 = OpVariable %40 Function - %90 = OpAccessChain %23 %20 %22 - %91 = OpLoad %17 %90 - %92 = OpConvertFToS %14 %91 - OpStore %89 %92 - OpStore %93 %92 - OpBranch %95 - %95 = OpLabel - %156 = OpPhi %14 %92 %11 %119 %98 - OpLoopMerge %97 %98 None - OpBranch %99 - %99 = OpLabel - %102 = OpSGreaterThan %36 %156 %101 - OpBranchConditional %102 %96 %97 - %96 = OpLabel - %107 = OpIAdd %14 %156 %92 - %108 = OpAccessChain %15 %103 %107 - %109 = OpLoad %14 %108 - %110 = OpAccessChain %15 %103 %156 - OpStore %110 %109 - %113 = OpIAdd %14 %156 %92 - %115 = OpAccessChain %15 %103 %156 - %116 = OpLoad %14 %115 - %117 = OpAccessChain %15 %103 %113 - OpStore %117 %116 - OpBranch %98 - %98 = OpLabel - %119 = OpISub %14 %156 %57 - OpStore %93 %119 - OpBranch %95 - %97 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %120 = OpVariable %15 Function - %124 = OpVariable %15 Function - %133 = OpVariable %40 Function - %121 = OpAccessChain %23 %20 %22 - %122 = OpLoad %17 %121 - %123 = OpConvertFToS %14 %122 - OpStore %120 %123 - OpStore %124 %123 - OpBranch %126 - %126 = OpLabel - %157 = OpPhi %14 %123 %13 %149 %129 - OpLoopMerge %128 %129 None - OpBranch %130 - %130 = OpLabel - %132 = OpSGreaterThanEqual %36 %157 %101 - OpBranchConditional %132 %127 %128 - %127 = OpLabel - %137 = OpIAdd %14 %157 %123 - %138 = OpAccessChain %15 %133 %137 - %139 = OpLoad %14 %138 - %140 = OpAccessChain %15 %133 %157 - OpStore %140 %139 - %143 = OpIAdd %14 %157 %123 - %145 = OpAccessChain %15 %133 %157 - %146 = OpLoad %14 %145 - %147 = OpAccessChain %15 %133 %143 - OpStore %147 %146 - OpBranch %129 - %129 = OpLabel - %149 = OpISub %14 %157 %57 - OpStore %124 %149 - OpBranch %126 - %128 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - { - // Function a - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 47 -> 48 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(47) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent but not supported. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 54 -> 55 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(54) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent but not supported. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function b - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 66)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 78 -> 79 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(78) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 85 -> 86 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(85) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function c - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 109 -> 110 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(109) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent and supported. - EXPECT_TRUE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 116 -> 117 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(116) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Independent but not supported. - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function d - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 127)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 139 -> 140 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(139) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 146 -> 147 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(146) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - // Dependent - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } -} - -/* - Generated from the following GLSL fragment shader - with --eliminate-local-multi-store -#version 440 core -layout(location = 0) in vec4 in_vec; -// Loop iterates from symbolic to symbolic -void a() { - int M = int(in_vec.x); - int N = int(in_vec.y); - int arr[10]; - for (int i = M; i < N; i++) { // Bounds are N - M - 1 - arr[i+M+N] = arr[i+M+2*N]; // |distance| = N - arr[i+M+2*N] = arr[i+M+N]; // |distance| = N - } -} -void b() { - int M = int(in_vec.x); - int N = int(in_vec.y); - int arr[10]; - for (int i = M; i <= N; i++) { // Bounds are N - M - arr[i+M+N] = arr[i+M+2*N]; // |distance| = N - arr[i+M+2*N] = arr[i+M+N]; // |distance| = N - } -} -void c() { - int M = int(in_vec.x); - int N = int(in_vec.y); - int arr[10]; - for (int i = M; i > N; i--) { // Bounds are M - N - 1 - arr[i+M+N] = arr[i+M+2*N]; // |distance| = N - arr[i+M+2*N] = arr[i+M+N]; // |distance| = N - } -} -void d() { - int M = int(in_vec.x); - int N = int(in_vec.y); - int arr[10]; - for (int i = M; i >= N; i--) { // Bounds are M - N - arr[i+M+N] = arr[i+M+2*N]; // |distance| = N - arr[i+M+2*N] = arr[i+M+N]; // |distance| = N - } -} -void main(){ - a(); - b(); - c(); - d(); -} -*/ -TEST(DependencyAnalysisHelpers, symbolic_to_symbolic) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %20 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %6 "a(" - OpName %8 "b(" - OpName %10 "c(" - OpName %12 "d(" - OpName %16 "M" - OpName %20 "in_vec" - OpName %27 "N" - OpName %32 "i" - OpName %46 "arr" - OpName %79 "M" - OpName %83 "N" - OpName %87 "i" - OpName %97 "arr" - OpName %128 "M" - OpName %132 "N" - OpName %136 "i" - OpName %146 "arr" - OpName %177 "M" - OpName %181 "N" - OpName %185 "i" - OpName %195 "arr" - OpDecorate %20 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %14 = OpTypeInt 32 1 - %15 = OpTypePointer Function %14 - %17 = OpTypeFloat 32 - %18 = OpTypeVector %17 4 - %19 = OpTypePointer Input %18 - %20 = OpVariable %19 Input - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 0 - %23 = OpTypePointer Input %17 - %28 = OpConstant %21 1 - %41 = OpTypeBool - %43 = OpConstant %21 10 - %44 = OpTypeArray %14 %43 - %45 = OpTypePointer Function %44 - %55 = OpConstant %14 2 - %77 = OpConstant %14 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %226 = OpFunctionCall %2 %6 - %227 = OpFunctionCall %2 %8 - %228 = OpFunctionCall %2 %10 - %229 = OpFunctionCall %2 %12 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - %16 = OpVariable %15 Function - %27 = OpVariable %15 Function - %32 = OpVariable %15 Function - %46 = OpVariable %45 Function - %24 = OpAccessChain %23 %20 %22 - %25 = OpLoad %17 %24 - %26 = OpConvertFToS %14 %25 - OpStore %16 %26 - %29 = OpAccessChain %23 %20 %28 - %30 = OpLoad %17 %29 - %31 = OpConvertFToS %14 %30 - OpStore %27 %31 - OpStore %32 %26 - OpBranch %34 - %34 = OpLabel - %230 = OpPhi %14 %26 %7 %78 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %42 = OpSLessThan %41 %230 %31 - OpBranchConditional %42 %35 %36 - %35 = OpLabel - %49 = OpIAdd %14 %230 %26 - %51 = OpIAdd %14 %49 %31 - %54 = OpIAdd %14 %230 %26 - %57 = OpIMul %14 %55 %31 - %58 = OpIAdd %14 %54 %57 - %59 = OpAccessChain %15 %46 %58 - %60 = OpLoad %14 %59 - %61 = OpAccessChain %15 %46 %51 - OpStore %61 %60 - %64 = OpIAdd %14 %230 %26 - %66 = OpIMul %14 %55 %31 - %67 = OpIAdd %14 %64 %66 - %70 = OpIAdd %14 %230 %26 - %72 = OpIAdd %14 %70 %31 - %73 = OpAccessChain %15 %46 %72 - %74 = OpLoad %14 %73 - %75 = OpAccessChain %15 %46 %67 - OpStore %75 %74 - OpBranch %37 - %37 = OpLabel - %78 = OpIAdd %14 %230 %77 - OpStore %32 %78 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %79 = OpVariable %15 Function - %83 = OpVariable %15 Function - %87 = OpVariable %15 Function - %97 = OpVariable %45 Function - %80 = OpAccessChain %23 %20 %22 - %81 = OpLoad %17 %80 - %82 = OpConvertFToS %14 %81 - OpStore %79 %82 - %84 = OpAccessChain %23 %20 %28 - %85 = OpLoad %17 %84 - %86 = OpConvertFToS %14 %85 - OpStore %83 %86 - OpStore %87 %82 - OpBranch %89 - %89 = OpLabel - %231 = OpPhi %14 %82 %9 %127 %92 - OpLoopMerge %91 %92 None - OpBranch %93 - %93 = OpLabel - %96 = OpSLessThanEqual %41 %231 %86 - OpBranchConditional %96 %90 %91 - %90 = OpLabel - %100 = OpIAdd %14 %231 %82 - %102 = OpIAdd %14 %100 %86 - %105 = OpIAdd %14 %231 %82 - %107 = OpIMul %14 %55 %86 - %108 = OpIAdd %14 %105 %107 - %109 = OpAccessChain %15 %97 %108 - %110 = OpLoad %14 %109 - %111 = OpAccessChain %15 %97 %102 - OpStore %111 %110 - %114 = OpIAdd %14 %231 %82 - %116 = OpIMul %14 %55 %86 - %117 = OpIAdd %14 %114 %116 - %120 = OpIAdd %14 %231 %82 - %122 = OpIAdd %14 %120 %86 - %123 = OpAccessChain %15 %97 %122 - %124 = OpLoad %14 %123 - %125 = OpAccessChain %15 %97 %117 - OpStore %125 %124 - OpBranch %92 - %92 = OpLabel - %127 = OpIAdd %14 %231 %77 - OpStore %87 %127 - OpBranch %89 - %91 = OpLabel - OpReturn - OpFunctionEnd - %10 = OpFunction %2 None %3 - %11 = OpLabel - %128 = OpVariable %15 Function - %132 = OpVariable %15 Function - %136 = OpVariable %15 Function - %146 = OpVariable %45 Function - %129 = OpAccessChain %23 %20 %22 - %130 = OpLoad %17 %129 - %131 = OpConvertFToS %14 %130 - OpStore %128 %131 - %133 = OpAccessChain %23 %20 %28 - %134 = OpLoad %17 %133 - %135 = OpConvertFToS %14 %134 - OpStore %132 %135 - OpStore %136 %131 - OpBranch %138 - %138 = OpLabel - %232 = OpPhi %14 %131 %11 %176 %141 - OpLoopMerge %140 %141 None - OpBranch %142 - %142 = OpLabel - %145 = OpSGreaterThan %41 %232 %135 - OpBranchConditional %145 %139 %140 - %139 = OpLabel - %149 = OpIAdd %14 %232 %131 - %151 = OpIAdd %14 %149 %135 - %154 = OpIAdd %14 %232 %131 - %156 = OpIMul %14 %55 %135 - %157 = OpIAdd %14 %154 %156 - %158 = OpAccessChain %15 %146 %157 - %159 = OpLoad %14 %158 - %160 = OpAccessChain %15 %146 %151 - OpStore %160 %159 - %163 = OpIAdd %14 %232 %131 - %165 = OpIMul %14 %55 %135 - %166 = OpIAdd %14 %163 %165 - %169 = OpIAdd %14 %232 %131 - %171 = OpIAdd %14 %169 %135 - %172 = OpAccessChain %15 %146 %171 - %173 = OpLoad %14 %172 - %174 = OpAccessChain %15 %146 %166 - OpStore %174 %173 - OpBranch %141 - %141 = OpLabel - %176 = OpISub %14 %232 %77 - OpStore %136 %176 - OpBranch %138 - %140 = OpLabel - OpReturn - OpFunctionEnd - %12 = OpFunction %2 None %3 - %13 = OpLabel - %177 = OpVariable %15 Function - %181 = OpVariable %15 Function - %185 = OpVariable %15 Function - %195 = OpVariable %45 Function - %178 = OpAccessChain %23 %20 %22 - %179 = OpLoad %17 %178 - %180 = OpConvertFToS %14 %179 - OpStore %177 %180 - %182 = OpAccessChain %23 %20 %28 - %183 = OpLoad %17 %182 - %184 = OpConvertFToS %14 %183 - OpStore %181 %184 - OpStore %185 %180 - OpBranch %187 - %187 = OpLabel - %233 = OpPhi %14 %180 %13 %225 %190 - OpLoopMerge %189 %190 None - OpBranch %191 - %191 = OpLabel - %194 = OpSGreaterThanEqual %41 %233 %184 - OpBranchConditional %194 %188 %189 - %188 = OpLabel - %198 = OpIAdd %14 %233 %180 - %200 = OpIAdd %14 %198 %184 - %203 = OpIAdd %14 %233 %180 - %205 = OpIMul %14 %55 %184 - %206 = OpIAdd %14 %203 %205 - %207 = OpAccessChain %15 %195 %206 - %208 = OpLoad %14 %207 - %209 = OpAccessChain %15 %195 %200 - OpStore %209 %208 - %212 = OpIAdd %14 %233 %180 - %214 = OpIMul %14 %55 %184 - %215 = OpIAdd %14 %212 %214 - %218 = OpIAdd %14 %233 %180 - %220 = OpIAdd %14 %218 %184 - %221 = OpAccessChain %15 %195 %220 - %222 = OpLoad %14 %221 - %223 = OpAccessChain %15 %195 %215 - OpStore %223 %222 - OpBranch %190 - %190 = OpLabel - %225 = OpISub %14 %233 %77 - OpStore %185 %225 - OpBranch %187 - %189 = OpLabel - OpReturn - OpFunctionEnd -)"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - { - // Function a - const Function* f = spvtest::GetFunction(module, 6); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 35)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 60 -> 61 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(60) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 74 -> 75 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(74) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function b - const Function* f = spvtest::GetFunction(module, 8); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 90)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 110 -> 111 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(110) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 124 -> 125 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(124) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function c - const Function* f = spvtest::GetFunction(module, 10); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 139)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 159 -> 160 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(159) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 173 -> 174 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(173) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } - { - // Function d - const Function* f = spvtest::GetFunction(module, 12); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - Loop* loop = &ld.GetLoopByIndex(0); - std::vector loops{loop}; - LoopDependenceAnalysis analysis{context.get(), loops}; - - const Instruction* stores[2]; - int stores_found = 0; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 188)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[stores_found] = &inst; - ++stores_found; - } - } - - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(stores[i]); - } - - // 208 -> 209 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(208) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[0]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - - // 222 -> 223 - { - // Analyse and simplify the instruction behind the access chain of this - // load. - Instruction* load_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(context->get_def_use_mgr() - ->GetDef(222) - ->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* load = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(load_var)); - - // Analyse and simplify the instruction behind the access chain of this - // store. - Instruction* store_var = context->get_def_use_mgr()->GetDef( - context->get_def_use_mgr() - ->GetDef(stores[1]->GetSingleWordInOperand(0)) - ->GetSingleWordInOperand(1)); - SENode* store = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->AnalyzeInstruction(store_var)); - - SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression( - analysis.GetScalarEvolution()->CreateSubtraction(load, store)); - - EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds( - loop, delta, store->AsSERecurrentNode()->GetCoefficient())); - } - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_compatibility.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_compatibility.cpp deleted file mode 100644 index cda8576c5..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_compatibility.cpp +++ /dev/null @@ -1,1785 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/loop_fusion.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using FusionCompatibilityTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int i = 0; // Can't fuse, i=0 in first & i=10 in second - for (; i < 10; i++) {} - for (; i < 10; i++) {} -} -*/ -TEST_F(FusionCompatibilityTest, SameInductionVariableDifferentBounds) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %31 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %31 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %31 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpBranch %22 - %22 = OpLabel - %32 = OpPhi %6 %31 %12 %30 %25 - OpLoopMerge %24 %25 None - OpBranch %26 - %26 = OpLabel - %28 = OpSLessThan %17 %32 %16 - OpBranchConditional %28 %23 %24 - %23 = OpLabel - OpBranch %25 - %25 = OpLabel - %30 = OpIAdd %6 %32 %20 - OpStore %8 %30 - OpBranch %22 - %24 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 1 -#version 440 core -void main() { - for (int i = 0; i < 10; i++) {} - for (int i = 0; i < 10; i++) {} -} -*/ -TEST_F(FusionCompatibilityTest, Compatible) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %32 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %32 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %32 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %33 = OpPhi %6 %9 %12 %31 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %33 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %31 = OpIAdd %6 %33 %20 - OpStore %22 %31 - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 2 -#version 440 core -void main() { - for (int i = 0; i < 10; i++) {} - for (int j = 0; j < 10; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, DifferentName) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %32 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %32 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %32 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %33 = OpPhi %6 %9 %12 %31 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %33 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %31 = OpIAdd %6 %33 %20 - OpStore %22 %31 - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - // Can't fuse, different step - for (int i = 0; i < 10; i++) {} - for (int j = 0; j < 10; j=j+2) {} -} - -*/ -TEST_F(FusionCompatibilityTest, SameBoundsDifferentStep) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %31 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %33 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %33 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %33 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %34 = OpPhi %6 %9 %12 %32 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %34 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %32 = OpIAdd %6 %34 %31 - OpStore %22 %32 - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 4 -#version 440 core -void main() { - // Can't fuse, different upper bound - for (int i = 0; i < 10; i++) {} - for (int j = 0; j < 20; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, DifferentUpperBound) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %29 = OpConstant %6 20 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %33 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %33 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %33 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %34 = OpPhi %6 %9 %12 %32 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %30 = OpSLessThan %17 %34 %29 - OpBranchConditional %30 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %32 = OpIAdd %6 %34 %20 - OpStore %22 %32 - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 5 -#version 440 core -void main() { - // Can't fuse, different lower bound - for (int i = 5; i < 10; i++) {} - for (int j = 0; j < 10; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, DifferentLowerBound) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 5 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %23 = OpConstant %6 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %33 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %33 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %33 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %23 - OpBranch %24 - %24 = OpLabel - %34 = OpPhi %6 %23 %12 %32 %27 - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %30 = OpSLessThan %17 %34 %16 - OpBranchConditional %30 %25 %26 - %25 = OpLabel - OpBranch %27 - %27 = OpLabel - %32 = OpIAdd %6 %34 %20 - OpStore %22 %32 - OpBranch %24 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 6 -#version 440 core -void main() { - // Can't fuse, break in first loop - for (int i = 0; i < 10; i++) { - if (i == 5) { - break; - } - } - for (int j = 0; j < 10; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, Break) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %28 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 5 - %26 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %28 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %38 = OpPhi %6 %9 %5 %27 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %38 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %21 = OpIEqual %17 %38 %20 - OpSelectionMerge %23 None - OpBranchConditional %21 %22 %23 - %22 = OpLabel - OpBranch %12 - %23 = OpLabel - OpBranch %13 - %13 = OpLabel - %27 = OpIAdd %6 %38 %26 - OpStore %8 %27 - OpBranch %10 - %12 = OpLabel - OpStore %28 %9 - OpBranch %29 - %29 = OpLabel - %39 = OpPhi %6 %9 %12 %37 %32 - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %35 = OpSLessThan %17 %39 %16 - OpBranchConditional %35 %30 %31 - %30 = OpLabel - OpBranch %32 - %32 = OpLabel - %37 = OpIAdd %6 %39 %26 - OpStore %28 %37 - OpBranch %29 - %31 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -layout(location = 0) in vec4 c; -void main() { - int N = int(c.x); - for (int i = 0; i < N; i++) {} - for (int j = 0; j < N; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, UnknownButSameUpperBound) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "N" - OpName %12 "c" - OpName %19 "i" - OpName %33 "j" - OpDecorate %12 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypeVector %9 4 - %11 = OpTypePointer Input %10 - %12 = OpVariable %11 Input - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Input %9 - %20 = OpConstant %6 0 - %28 = OpTypeBool - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %33 = OpVariable %7 Function - %16 = OpAccessChain %15 %12 %14 - %17 = OpLoad %9 %16 - %18 = OpConvertFToS %6 %17 - OpStore %8 %18 - OpStore %19 %20 - OpBranch %21 - %21 = OpLabel - %44 = OpPhi %6 %20 %5 %32 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %29 = OpSLessThan %28 %44 %18 - OpBranchConditional %29 %22 %23 - %22 = OpLabel - OpBranch %24 - %24 = OpLabel - %32 = OpIAdd %6 %44 %31 - OpStore %19 %32 - OpBranch %21 - %23 = OpLabel - OpStore %33 %20 - OpBranch %34 - %34 = OpLabel - %46 = OpPhi %6 %20 %23 %43 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %41 = OpSLessThan %28 %46 %18 - OpBranchConditional %41 %35 %36 - %35 = OpLabel - OpBranch %37 - %37 = OpLabel - %43 = OpIAdd %6 %46 %31 - OpStore %33 %43 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -layout(location = 0) in vec4 c; -void main() { - int N = int(c.x); - for (int i = 0; N > j; i++) {} - for (int j = 0; N > j; j++) {} -} -*/ -TEST_F(FusionCompatibilityTest, UnknownButSameUpperBoundReverseCondition) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "N" - OpName %12 "c" - OpName %19 "i" - OpName %33 "j" - OpDecorate %12 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypeVector %9 4 - %11 = OpTypePointer Input %10 - %12 = OpVariable %11 Input - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Input %9 - %20 = OpConstant %6 0 - %28 = OpTypeBool - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %33 = OpVariable %7 Function - %16 = OpAccessChain %15 %12 %14 - %17 = OpLoad %9 %16 - %18 = OpConvertFToS %6 %17 - OpStore %8 %18 - OpStore %19 %20 - OpBranch %21 - %21 = OpLabel - %45 = OpPhi %6 %20 %5 %32 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %29 = OpSGreaterThan %28 %18 %45 - OpBranchConditional %29 %22 %23 - %22 = OpLabel - OpBranch %24 - %24 = OpLabel - %32 = OpIAdd %6 %45 %31 - OpStore %19 %32 - OpBranch %21 - %23 = OpLabel - OpStore %33 %20 - OpBranch %34 - %34 = OpLabel - %47 = OpPhi %6 %20 %23 %43 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %41 = OpSGreaterThan %28 %18 %47 - OpBranchConditional %41 %35 %36 - %35 = OpLabel - OpBranch %37 - %37 = OpLabel - %43 = OpIAdd %6 %47 %31 - OpStore %33 %43 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -layout(location = 0) in vec4 c; -void main() { - // Can't fuse different bound - int N = int(c.x); - for (int i = 0; i < N; i++) {} - for (int j = 0; j < N+1; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, UnknownUpperBoundAddition) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "N" - OpName %12 "c" - OpName %19 "i" - OpName %33 "j" - OpDecorate %12 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypeVector %9 4 - %11 = OpTypePointer Input %10 - %12 = OpVariable %11 Input - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Input %9 - %20 = OpConstant %6 0 - %28 = OpTypeBool - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %33 = OpVariable %7 Function - %16 = OpAccessChain %15 %12 %14 - %17 = OpLoad %9 %16 - %18 = OpConvertFToS %6 %17 - OpStore %8 %18 - OpStore %19 %20 - OpBranch %21 - %21 = OpLabel - %45 = OpPhi %6 %20 %5 %32 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %29 = OpSLessThan %28 %45 %18 - OpBranchConditional %29 %22 %23 - %22 = OpLabel - OpBranch %24 - %24 = OpLabel - %32 = OpIAdd %6 %45 %31 - OpStore %19 %32 - OpBranch %21 - %23 = OpLabel - OpStore %33 %20 - OpBranch %34 - %34 = OpLabel - %47 = OpPhi %6 %20 %23 %44 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %41 = OpIAdd %6 %18 %31 - %42 = OpSLessThan %28 %47 %41 - OpBranchConditional %42 %35 %36 - %35 = OpLabel - OpBranch %37 - %37 = OpLabel - %44 = OpIAdd %6 %47 %31 - OpStore %33 %44 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 10 -#version 440 core -void main() { - for (int i = 0; i < 10; i++) {} - for (int j = 0; j < 10; j++) {} - for (int k = 0; k < 10; k++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, SeveralAdjacentLoops) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "j" - OpName %32 "k" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - %32 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %42 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %42 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %42 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %43 = OpPhi %6 %9 %12 %31 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %43 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %31 = OpIAdd %6 %43 %20 - OpStore %22 %31 - OpBranch %23 - %25 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - %44 = OpPhi %6 %9 %25 %41 %36 - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %39 = OpSLessThan %17 %44 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpBranch %36 - %36 = OpLabel - %41 = OpIAdd %6 %44 %20 - OpStore %32 %41 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_0).AreCompatible()); - EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_2).AreCompatible()); - EXPECT_FALSE(LoopFusion(context.get(), loop_1, loop_0).AreCompatible()); - EXPECT_TRUE(LoopFusion(context.get(), loop_0, loop_1).AreCompatible()); - EXPECT_TRUE(LoopFusion(context.get(), loop_1, loop_2).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - // Can't fuse, not adjacent - int x = 0; - for (int i = 0; i < 10; i++) { - if (i > 10) { - x++; - } - } - x++; - for (int j = 0; j < 10; j++) {} - for (int k = 0; k < 10; k++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, NonAdjacentLoops) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "x" - OpName %10 "i" - OpName %31 "j" - OpName %41 "k" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %25 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %31 = OpVariable %7 Function - %41 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %52 = OpPhi %6 %9 %5 %56 %14 - %51 = OpPhi %6 %9 %5 %28 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %51 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %21 = OpSGreaterThan %18 %52 %17 - OpSelectionMerge %23 None - OpBranchConditional %21 %22 %23 - %22 = OpLabel - %26 = OpIAdd %6 %52 %25 - OpStore %8 %26 - OpBranch %23 - %23 = OpLabel - %56 = OpPhi %6 %52 %12 %26 %22 - OpBranch %14 - %14 = OpLabel - %28 = OpIAdd %6 %51 %25 - OpStore %10 %28 - OpBranch %11 - %13 = OpLabel - %30 = OpIAdd %6 %52 %25 - OpStore %8 %30 - OpStore %31 %9 - OpBranch %32 - %32 = OpLabel - %53 = OpPhi %6 %9 %13 %40 %35 - OpLoopMerge %34 %35 None - OpBranch %36 - %36 = OpLabel - %38 = OpSLessThan %18 %53 %17 - OpBranchConditional %38 %33 %34 - %33 = OpLabel - OpBranch %35 - %35 = OpLabel - %40 = OpIAdd %6 %53 %25 - OpStore %31 %40 - OpBranch %32 - %34 = OpLabel - OpStore %41 %9 - OpBranch %42 - %42 = OpLabel - %54 = OpPhi %6 %9 %34 %50 %45 - OpLoopMerge %44 %45 None - OpBranch %46 - %46 = OpLabel - %48 = OpSLessThan %18 %54 %17 - OpBranchConditional %48 %43 %44 - %43 = OpLabel - OpBranch %45 - %45 = OpLabel - %50 = OpIAdd %6 %54 %25 - OpStore %41 %50 - OpBranch %42 - %44 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_0).AreCompatible()); - EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_2).AreCompatible()); - EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_1).AreCompatible()); - EXPECT_TRUE(LoopFusion(context.get(), loop_1, loop_2).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 12 -#version 440 core -void main() { - int j = 0; - int i = 0; - for (; i < 10; i++) {} - for (; j < 10; j++) {} -} - -*/ -TEST_F(FusionCompatibilityTest, CompatibleInitDeclaredBeforeLoops) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "j" - OpName %10 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %21 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %32 = OpPhi %6 %9 %5 %22 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %32 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - OpBranch %14 - %14 = OpLabel - %22 = OpIAdd %6 %32 %21 - OpStore %10 %22 - OpBranch %11 - %13 = OpLabel - OpBranch %23 - %23 = OpLabel - %33 = OpPhi %6 %9 %13 %31 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %18 %33 %17 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %31 = OpIAdd %6 %33 %21 - OpStore %8 %31 - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - EXPECT_TRUE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 13 regenerate! -#version 440 core -void main() { - int[10] a; - int[10] b; - // Can't fuse, several induction variables - for (int j = 0; j < 10; j++) { - b[i] = a[i]; - } - for (int i = 0, j = 0; i < 10; i++, j = j+2) { - } -} - -*/ -TEST_F(FusionCompatibilityTest, SeveralInductionVariables) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "j" - OpName %23 "b" - OpName %25 "a" - OpName %33 "i" - OpName %34 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %31 = OpConstant %6 1 - %48 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %33 = OpVariable %7 Function - %34 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %50 = OpPhi %6 %9 %5 %32 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %50 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %50 - %28 = OpLoad %6 %27 - %29 = OpAccessChain %7 %23 %50 - OpStore %29 %28 - OpBranch %13 - %13 = OpLabel - %32 = OpIAdd %6 %50 %31 - OpStore %8 %32 - OpBranch %10 - %12 = OpLabel - OpStore %33 %9 - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %52 = OpPhi %6 %9 %12 %49 %38 - %51 = OpPhi %6 %9 %12 %46 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %51 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %44 = OpAccessChain %7 %25 %52 - OpStore %44 %51 - OpBranch %38 - %38 = OpLabel - %46 = OpIAdd %6 %51 %31 - OpStore %33 %46 - %49 = OpIAdd %6 %52 %48 - OpStore %34 %49 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - EXPECT_FALSE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 14 -#version 440 core -void main() { - // Fine - for (int i = 0; i < 10; i = i + 2) {} - for (int j = 0; j < 10; j = j + 2) {} -} - -*/ -TEST_F(FusionCompatibilityTest, CompatibleNonIncrementStep) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "j" - OpName %10 "i" - OpName %11 "i" - OpName %24 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %22 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %11 = OpVariable %7 Function - %24 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpStore %11 %9 - OpBranch %12 - %12 = OpLabel - %34 = OpPhi %6 %9 %5 %23 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %34 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - OpBranch %15 - %15 = OpLabel - %23 = OpIAdd %6 %34 %22 - OpStore %11 %23 - OpBranch %12 - %14 = OpLabel - OpStore %24 %9 - OpBranch %25 - %25 = OpLabel - %35 = OpPhi %6 %9 %14 %33 %28 - OpLoopMerge %27 %28 None - OpBranch %29 - %29 = OpLabel - %31 = OpSLessThan %19 %35 %18 - OpBranchConditional %31 %26 %27 - %26 = OpLabel - OpBranch %28 - %28 = OpLabel - %33 = OpIAdd %6 %35 %22 - OpStore %24 %33 - OpBranch %25 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - EXPECT_TRUE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 15 -#version 440 core - -int j = 0; - -void main() { - // Not compatible, unknown init for second. - for (int i = 0; i < 10; i = i + 2) {} - for (; j < 10; j = j + 2) {} -} - -*/ -TEST_F(FusionCompatibilityTest, UnknonInitForSecondLoop) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "j" - OpName %11 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Private %6 - %8 = OpVariable %7 Private - %9 = OpConstant %6 0 - %10 = OpTypePointer Function %6 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %22 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpVariable %10 Function - OpStore %8 %9 - OpStore %11 %9 - OpBranch %12 - %12 = OpLabel - %33 = OpPhi %6 %9 %5 %23 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %33 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - OpBranch %15 - %15 = OpLabel - %23 = OpIAdd %6 %33 %22 - OpStore %11 %23 - OpBranch %12 - %14 = OpLabel - OpBranch %24 - %24 = OpLabel - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %29 = OpLoad %6 %8 - %30 = OpSLessThan %19 %29 %18 - OpBranchConditional %30 %25 %26 - %25 = OpLabel - OpBranch %27 - %27 = OpLabel - %31 = OpLoad %6 %8 - %32 = OpIAdd %6 %31 %22 - OpStore %8 %32 - OpBranch %24 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - EXPECT_FALSE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 16 -#version 440 core -void main() { - // Not compatible, continue in loop 0 - for (int i = 0; i < 10; ++i) { - if (i % 2 == 1) { - continue; - } - } - for (int j = 0; j < 10; ++j) {} -} - -*/ -TEST_F(FusionCompatibilityTest, Continue) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %29 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 2 - %22 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %29 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %39 = OpPhi %6 %9 %5 %28 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %39 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %21 = OpSMod %6 %39 %20 - %23 = OpIEqual %17 %21 %22 - OpSelectionMerge %25 None - OpBranchConditional %23 %24 %25 - %24 = OpLabel - OpBranch %13 - %25 = OpLabel - OpBranch %13 - %13 = OpLabel - %28 = OpIAdd %6 %39 %22 - OpStore %8 %28 - OpBranch %10 - %12 = OpLabel - OpStore %29 %9 - OpBranch %30 - %30 = OpLabel - %40 = OpPhi %6 %9 %12 %38 %33 - OpLoopMerge %32 %33 None - OpBranch %34 - %34 = OpLabel - %36 = OpSLessThan %17 %40 %16 - OpBranchConditional %36 %31 %32 - %31 = OpLabel - OpBranch %33 - %33 = OpLabel - %38 = OpIAdd %6 %40 %22 - OpStore %29 %38 - OpBranch %30 - %32 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - EXPECT_FALSE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - // Compatible - for (int i = 0; i < 10; ++i) { - if (i % 2 == 1) { - } else { - a[i] = i; - } - } - for (int j = 0; j < 10; ++j) {} -} - -*/ -TEST_F(FusionCompatibilityTest, IfElseInLoop) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %31 "a" - OpName %37 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 2 - %22 = OpConstant %6 1 - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypePointer Function %29 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %31 = OpVariable %30 Function - %37 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %47 = OpPhi %6 %9 %5 %36 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %47 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %21 = OpSMod %6 %47 %20 - %23 = OpIEqual %17 %21 %22 - OpSelectionMerge %25 None - OpBranchConditional %23 %24 %26 - %24 = OpLabel - OpBranch %25 - %26 = OpLabel - %34 = OpAccessChain %7 %31 %47 - OpStore %34 %47 - OpBranch %25 - %25 = OpLabel - OpBranch %13 - %13 = OpLabel - %36 = OpIAdd %6 %47 %22 - OpStore %8 %36 - OpBranch %10 - %12 = OpLabel - OpStore %37 %9 - OpBranch %38 - %38 = OpLabel - %48 = OpPhi %6 %9 %12 %46 %41 - OpLoopMerge %40 %41 None - OpBranch %42 - %42 = OpLabel - %44 = OpSLessThan %17 %48 %16 - OpBranchConditional %44 %39 %40 - %39 = OpLabel - OpBranch %41 - %41 = OpLabel - %46 = OpIAdd %6 %48 %22 - OpStore %37 %46 - OpBranch %38 - %40 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - EXPECT_TRUE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_illegal.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_illegal.cpp deleted file mode 100644 index 26d54457d..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_illegal.cpp +++ /dev/null @@ -1,1592 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/loop_fusion.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using FusionIllegalTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Illegal, loop-independent dependence will become a - // backward loop-carried antidependence - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i+1] + 2; - } -} - -*/ -TEST_F(FusionIllegalTest, PositiveDistanceCreatedRAW) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %42 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %48 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %53 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %53 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %53 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %53 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %53 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %54 = OpPhi %6 %9 %12 %52 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %54 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpIAdd %6 %54 %29 - %46 = OpAccessChain %7 %23 %45 - %47 = OpLoad %6 %46 - %49 = OpIAdd %6 %47 %48 - %50 = OpAccessChain %7 %42 %54 - OpStore %50 %49 - OpBranch %38 - %38 = OpLabel - %52 = OpIAdd %6 %54 %29 - OpStore %34 %52 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core - -int func() { - return 10; -} - -void main() { - int[10] a; - int[10] b; - // Illegal, function call - for (int i = 0; i < 10; i++) { - a[i] = func(); - } - for (int i = 0; i < 10; i++) { - b[i] = a[i]; - } -} -*/ -TEST_F(FusionIllegalTest, FunctionCall) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "func(" - OpName %14 "i" - OpName %28 "a" - OpName %35 "i" - OpName %43 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFunction %6 - %10 = OpConstant %6 10 - %13 = OpTypePointer Function %6 - %15 = OpConstant %6 0 - %22 = OpTypeBool - %24 = OpTypeInt 32 0 - %25 = OpConstant %24 10 - %26 = OpTypeArray %6 %25 - %27 = OpTypePointer Function %26 - %33 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %14 = OpVariable %13 Function - %28 = OpVariable %27 Function - %35 = OpVariable %13 Function - %43 = OpVariable %27 Function - OpStore %14 %15 - OpBranch %16 - %16 = OpLabel - %51 = OpPhi %6 %15 %5 %34 %19 - OpLoopMerge %18 %19 None - OpBranch %20 - %20 = OpLabel - %23 = OpSLessThan %22 %51 %10 - OpBranchConditional %23 %17 %18 - %17 = OpLabel - %30 = OpFunctionCall %6 %8 - %31 = OpAccessChain %13 %28 %51 - OpStore %31 %30 - OpBranch %19 - %19 = OpLabel - %34 = OpIAdd %6 %51 %33 - OpStore %14 %34 - OpBranch %16 - %18 = OpLabel - OpStore %35 %15 - OpBranch %36 - %36 = OpLabel - %52 = OpPhi %6 %15 %18 %50 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %22 %52 %10 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %46 = OpAccessChain %13 %28 %52 - %47 = OpLoad %6 %46 - %48 = OpAccessChain %13 %43 %52 - OpStore %48 %47 - OpBranch %39 - %39 = OpLabel - %50 = OpIAdd %6 %52 %33 - OpStore %35 %50 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %6 None %7 - %9 = OpLabel - OpReturnValue %10 - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 16 -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Illegal outer. - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - c[i][j] = a[i][j] + 2; - } - } - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - b[i][j] = c[i+1][j] + 10; - } - } -} - -*/ -TEST_F(FusionIllegalTest, PositiveDistanceCreatedRAWOuterLoop) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %32 "c" - OpName %35 "a" - OpName %48 "i" - OpName %56 "j" - OpName %64 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypeArray %29 %28 - %31 = OpTypePointer Function %30 - %40 = OpConstant %6 2 - %44 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %31 Function - %35 = OpVariable %31 Function - %48 = OpVariable %7 Function - %56 = OpVariable %7 Function - %64 = OpVariable %31 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %78 = OpPhi %6 %9 %5 %47 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %78 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %82 = OpPhi %6 %9 %11 %45 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %82 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %38 = OpAccessChain %7 %35 %78 %82 - %39 = OpLoad %6 %38 - %41 = OpIAdd %6 %39 %40 - %42 = OpAccessChain %7 %32 %78 %82 - OpStore %42 %41 - OpBranch %23 - %23 = OpLabel - %45 = OpIAdd %6 %82 %44 - OpStore %19 %45 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %47 = OpIAdd %6 %78 %44 - OpStore %8 %47 - OpBranch %10 - %12 = OpLabel - OpStore %48 %9 - OpBranch %49 - %49 = OpLabel - %79 = OpPhi %6 %9 %12 %77 %52 - OpLoopMerge %51 %52 None - OpBranch %53 - %53 = OpLabel - %55 = OpSLessThan %17 %79 %16 - OpBranchConditional %55 %50 %51 - %50 = OpLabel - OpStore %56 %9 - OpBranch %57 - %57 = OpLabel - %80 = OpPhi %6 %9 %50 %75 %60 - OpLoopMerge %59 %60 None - OpBranch %61 - %61 = OpLabel - %63 = OpSLessThan %17 %80 %16 - OpBranchConditional %63 %58 %59 - %58 = OpLabel - %68 = OpIAdd %6 %79 %44 - %70 = OpAccessChain %7 %32 %68 %80 - %71 = OpLoad %6 %70 - %72 = OpIAdd %6 %71 %16 - %73 = OpAccessChain %7 %64 %79 %80 - OpStore %73 %72 - OpBranch %60 - %60 = OpLabel - %75 = OpIAdd %6 %80 %44 - OpStore %56 %75 - OpBranch %57 - %59 = OpLabel - OpBranch %52 - %52 = OpLabel - %77 = OpIAdd %6 %79 %44 - OpStore %48 %77 - OpBranch %49 - %51 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 4u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - auto loop_3 = loops[3]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_2, loop_3); - EXPECT_FALSE(fusion.AreCompatible()); - } - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 19 -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Illegal, would create a backward loop-carried anti-dependence. - for (int i = 0; i < 10; i++) { - c[i] = a[i] + 1; - } - for (int i = 0; i < 10; i++) { - a[i+1] = c[i] + 2; - } -} - -*/ -TEST_F(FusionIllegalTest, PositiveDistanceCreatedWAR) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "c" - OpName %25 "a" - OpName %34 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %47 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %52 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %52 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %52 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %52 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %52 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %53 = OpPhi %6 %9 %12 %51 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %53 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %43 = OpIAdd %6 %53 %29 - %45 = OpAccessChain %7 %23 %53 - %46 = OpLoad %6 %45 - %48 = OpIAdd %6 %46 %47 - %49 = OpAccessChain %7 %25 %43 - OpStore %49 %48 - OpBranch %38 - %38 = OpLabel - %51 = OpIAdd %6 %53 %29 - OpStore %34 %51 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 21 -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Illegal, would create a backward loop-carried anti-dependence. - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - a[i+1] = c[i+1] + 2; - } -} - -*/ -TEST_F(FusionIllegalTest, PositiveDistanceCreatedWAW) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %44 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %49 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %44 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %54 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %54 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %54 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %54 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %54 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %55 = OpPhi %6 %9 %12 %53 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %55 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %43 = OpIAdd %6 %55 %29 - %46 = OpIAdd %6 %55 %29 - %47 = OpAccessChain %7 %44 %46 - %48 = OpLoad %6 %47 - %50 = OpIAdd %6 %48 %49 - %51 = OpAccessChain %7 %23 %43 - OpStore %51 %50 - OpBranch %38 - %38 = OpLabel - %53 = OpIAdd %6 %55 %29 - OpStore %34 %53 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 28 -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum_0 = 0; - - // Illegal - for (int i = 0; i < 10; i++) { - sum_0 += a[i]; - } - for (int j = 0; j < 10; j++) { - sum_0 += b[j]; - } -} - -*/ -TEST_F(FusionIllegalTest, SameReductionVariable) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum_0" - OpName %10 "i" - OpName %24 "a" - OpName %33 "j" - OpName %41 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 10 - %22 = OpTypeArray %6 %21 - %23 = OpTypePointer Function %22 - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %24 = OpVariable %23 Function - %33 = OpVariable %7 Function - %41 = OpVariable %23 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %52 = OpPhi %6 %9 %5 %29 %14 - %49 = OpPhi %6 %9 %5 %32 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %49 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %26 = OpAccessChain %7 %24 %49 - %27 = OpLoad %6 %26 - %29 = OpIAdd %6 %52 %27 - OpStore %8 %29 - OpBranch %14 - %14 = OpLabel - %32 = OpIAdd %6 %49 %31 - OpStore %10 %32 - OpBranch %11 - %13 = OpLabel - OpStore %33 %9 - OpBranch %34 - %34 = OpLabel - %51 = OpPhi %6 %52 %13 %46 %37 - %50 = OpPhi %6 %9 %13 %48 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %40 = OpSLessThan %18 %50 %17 - OpBranchConditional %40 %35 %36 - %35 = OpLabel - %43 = OpAccessChain %7 %41 %50 - %44 = OpLoad %6 %43 - %46 = OpIAdd %6 %51 %44 - OpStore %8 %46 - OpBranch %37 - %37 = OpLabel - %48 = OpIAdd %6 %50 %31 - OpStore %33 %48 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 28 -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum_0 = 0; - - // Illegal - for (int i = 0; i < 10; i++) { - sum_0 += a[i]; - } - for (int j = 0; j < 10; j++) { - sum_0 += b[j]; - } -} - -*/ -TEST_F(FusionIllegalTest, SameReductionVariableLCSSA) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum_0" - OpName %10 "i" - OpName %24 "a" - OpName %33 "j" - OpName %41 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 10 - %22 = OpTypeArray %6 %21 - %23 = OpTypePointer Function %22 - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %24 = OpVariable %23 Function - %33 = OpVariable %7 Function - %41 = OpVariable %23 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %52 = OpPhi %6 %9 %5 %29 %14 - %49 = OpPhi %6 %9 %5 %32 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %49 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %26 = OpAccessChain %7 %24 %49 - %27 = OpLoad %6 %26 - %29 = OpIAdd %6 %52 %27 - OpStore %8 %29 - OpBranch %14 - %14 = OpLabel - %32 = OpIAdd %6 %49 %31 - OpStore %10 %32 - OpBranch %11 - %13 = OpLabel - OpStore %33 %9 - OpBranch %34 - %34 = OpLabel - %51 = OpPhi %6 %52 %13 %46 %37 - %50 = OpPhi %6 %9 %13 %48 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %40 = OpSLessThan %18 %50 %17 - OpBranchConditional %40 %35 %36 - %35 = OpLabel - %43 = OpAccessChain %7 %41 %50 - %44 = OpLoad %6 %43 - %46 = OpIAdd %6 %51 %44 - OpStore %8 %46 - OpBranch %37 - %37 = OpLabel - %48 = OpIAdd %6 %50 %31 - OpStore %33 %48 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopUtils utils_0(context.get(), loops[0]); - utils_0.MakeLoopClosedSSA(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 30 -#version 440 core -int x; -void main() { - int[10] a; - int[10] b; - - // Illegal, x is unknown. - for (int i = 0; i < 10; i++) { - a[x] = a[i]; - } - for (int j = 0; j < 10; j++) { - a[j] = b[j]; - } -} - -*/ -TEST_F(FusionIllegalTest, UnknownIndexVariable) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "x" - OpName %34 "j" - OpName %43 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %24 = OpTypePointer Private %6 - %25 = OpVariable %24 Private - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %34 = OpVariable %7 Function - %43 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %50 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %50 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpLoad %6 %25 - %28 = OpAccessChain %7 %23 %50 - %29 = OpLoad %6 %28 - %30 = OpAccessChain %7 %23 %26 - OpStore %30 %29 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %50 %32 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %51 = OpPhi %6 %9 %12 %49 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %51 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %43 %51 - %46 = OpLoad %6 %45 - %47 = OpAccessChain %7 %23 %51 - OpStore %47 %46 - OpBranch %38 - %38 = OpLabel - %49 = OpIAdd %6 %51 %32 - OpStore %34 %49 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum = 0; - - // Illegal, accumulator used for indexing. - for (int i = 0; i < 10; i++) { - sum += a[i]; - b[sum] = a[i]; - } - for (int j = 0; j < 10; j++) { - b[j] = b[j]+1; - } -} - -*/ -TEST_F(FusionIllegalTest, AccumulatorIndexing) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum" - OpName %10 "i" - OpName %24 "a" - OpName %30 "b" - OpName %39 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 10 - %22 = OpTypeArray %6 %21 - %23 = OpTypePointer Function %22 - %37 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %24 = OpVariable %23 Function - %30 = OpVariable %23 Function - %39 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %57 = OpPhi %6 %9 %5 %29 %14 - %55 = OpPhi %6 %9 %5 %38 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %55 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %26 = OpAccessChain %7 %24 %55 - %27 = OpLoad %6 %26 - %29 = OpIAdd %6 %57 %27 - OpStore %8 %29 - %33 = OpAccessChain %7 %24 %55 - %34 = OpLoad %6 %33 - %35 = OpAccessChain %7 %30 %29 - OpStore %35 %34 - OpBranch %14 - %14 = OpLabel - %38 = OpIAdd %6 %55 %37 - OpStore %10 %38 - OpBranch %11 - %13 = OpLabel - OpStore %39 %9 - OpBranch %40 - %40 = OpLabel - %56 = OpPhi %6 %9 %13 %54 %43 - OpLoopMerge %42 %43 None - OpBranch %44 - %44 = OpLabel - %46 = OpSLessThan %18 %56 %17 - OpBranchConditional %46 %41 %42 - %41 = OpLabel - %49 = OpAccessChain %7 %30 %56 - %50 = OpLoad %6 %49 - %51 = OpIAdd %6 %50 %37 - %52 = OpAccessChain %7 %30 %56 - OpStore %52 %51 - OpBranch %43 - %43 = OpLabel - %54 = OpIAdd %6 %56 %37 - OpStore %39 %54 - OpBranch %40 - %42 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 33 -#version 440 core -void main() { - int[10] a; - int[10] b; - - // Illegal, barrier. - for (int i = 0; i < 10; i++) { - a[i] = a[i] * 2; - memoryBarrier(); - } - for (int j = 0; j < 10; j++) { - b[j] = b[j] + 1; - } -} - -*/ -TEST_F(FusionIllegalTest, Barrier) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %36 "j" - OpName %44 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %28 = OpConstant %6 2 - %31 = OpConstant %19 1 - %32 = OpConstant %19 3400 - %34 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %36 = OpVariable %7 Function - %44 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %53 = OpPhi %6 %9 %5 %35 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %53 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpAccessChain %7 %23 %53 - %27 = OpLoad %6 %26 - %29 = OpIMul %6 %27 %28 - %30 = OpAccessChain %7 %23 %53 - OpStore %30 %29 - OpMemoryBarrier %31 %32 - OpBranch %13 - %13 = OpLabel - %35 = OpIAdd %6 %53 %34 - OpStore %8 %35 - OpBranch %10 - %12 = OpLabel - OpStore %36 %9 - OpBranch %37 - %37 = OpLabel - %54 = OpPhi %6 %9 %12 %52 %40 - OpLoopMerge %39 %40 None - OpBranch %41 - %41 = OpLabel - %43 = OpSLessThan %17 %54 %16 - OpBranchConditional %43 %38 %39 - %38 = OpLabel - %47 = OpAccessChain %7 %44 %54 - %48 = OpLoad %6 %47 - %49 = OpIAdd %6 %48 %34 - %50 = OpAccessChain %7 %44 %54 - OpStore %50 %49 - OpBranch %40 - %40 = OpLabel - %52 = OpIAdd %6 %54 %34 - OpStore %36 %52 - OpBranch %37 - %39 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -struct TestStruct { - int[10] a; - int b; -}; - -void main() { - TestStruct test_0; - TestStruct test_1; - - for (int i = 0; i < 10; i++) { - test_0.a[i] = i; - } - for (int j = 0; j < 10; j++) { - test_0 = test_1; - } -} - -*/ -TEST_F(FusionIllegalTest, ArrayInStruct) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "TestStruct" - OpMemberName %22 0 "a" - OpMemberName %22 1 "b" - OpName %24 "test_0" - OpName %31 "j" - OpName %39 "test_1" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypeStruct %21 %6 - %23 = OpTypePointer Function %22 - %29 = OpConstant %6 1 - %47 = OpUndef %22 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %24 = OpVariable %23 Function - %31 = OpVariable %7 Function - %39 = OpVariable %23 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %43 = OpPhi %6 %9 %5 %30 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %43 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %24 %9 %43 - OpStore %27 %43 - OpBranch %13 - %13 = OpLabel - %30 = OpIAdd %6 %43 %29 - OpStore %8 %30 - OpBranch %10 - %12 = OpLabel - OpStore %31 %9 - OpBranch %32 - %32 = OpLabel - %44 = OpPhi %6 %9 %12 %42 %35 - OpLoopMerge %34 %35 None - OpBranch %36 - %36 = OpLabel - %38 = OpSLessThan %17 %44 %16 - OpBranchConditional %38 %33 %34 - %33 = OpLabel - OpStore %24 %47 - OpBranch %35 - %35 = OpLabel - %42 = OpIAdd %6 %44 %29 - OpStore %31 %42 - OpBranch %32 - %34 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 450 - -struct P {float x,y,z;}; -uniform G { int a; P b[2]; int c; } g; -layout(location = 0) out float o; - -void main() -{ - P p[2]; - for (int i = 0; i < 2; ++i) { - p = g.b; - } - for (int j = 0; j < 2; ++j) { - o = p[g.a].x; - } -} - -*/ -TEST_F(FusionIllegalTest, NestedAccessChain) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %64 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 450 - OpName %4 "main" - OpName %8 "i" - OpName %20 "P" - OpMemberName %20 0 "x" - OpMemberName %20 1 "y" - OpMemberName %20 2 "z" - OpName %25 "p" - OpName %26 "P" - OpMemberName %26 0 "x" - OpMemberName %26 1 "y" - OpMemberName %26 2 "z" - OpName %28 "G" - OpMemberName %28 0 "a" - OpMemberName %28 1 "b" - OpMemberName %28 2 "c" - OpName %30 "g" - OpName %55 "j" - OpName %64 "o" - OpMemberDecorate %26 0 Offset 0 - OpMemberDecorate %26 1 Offset 4 - OpMemberDecorate %26 2 Offset 8 - OpDecorate %27 ArrayStride 16 - OpMemberDecorate %28 0 Offset 0 - OpMemberDecorate %28 1 Offset 16 - OpMemberDecorate %28 2 Offset 48 - OpDecorate %28 Block - OpDecorate %30 DescriptorSet 0 - OpDecorate %64 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 2 - %17 = OpTypeBool - %19 = OpTypeFloat 32 - %20 = OpTypeStruct %19 %19 %19 - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 2 - %23 = OpTypeArray %20 %22 - %24 = OpTypePointer Function %23 - %26 = OpTypeStruct %19 %19 %19 - %27 = OpTypeArray %26 %22 - %28 = OpTypeStruct %6 %27 %6 - %29 = OpTypePointer Uniform %28 - %30 = OpVariable %29 Uniform - %31 = OpConstant %6 1 - %32 = OpTypePointer Uniform %27 - %36 = OpTypePointer Function %20 - %39 = OpTypePointer Function %19 - %63 = OpTypePointer Output %19 - %64 = OpVariable %63 Output - %65 = OpTypePointer Uniform %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %25 = OpVariable %24 Function - %55 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %72 = OpPhi %6 %9 %5 %54 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %72 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %33 = OpAccessChain %32 %30 %31 - %34 = OpLoad %27 %33 - %35 = OpCompositeExtract %26 %34 0 - %37 = OpAccessChain %36 %25 %9 - %38 = OpCompositeExtract %19 %35 0 - %40 = OpAccessChain %39 %37 %9 - OpStore %40 %38 - %41 = OpCompositeExtract %19 %35 1 - %42 = OpAccessChain %39 %37 %31 - OpStore %42 %41 - %43 = OpCompositeExtract %19 %35 2 - %44 = OpAccessChain %39 %37 %16 - OpStore %44 %43 - %45 = OpCompositeExtract %26 %34 1 - %46 = OpAccessChain %36 %25 %31 - %47 = OpCompositeExtract %19 %45 0 - %48 = OpAccessChain %39 %46 %9 - OpStore %48 %47 - %49 = OpCompositeExtract %19 %45 1 - %50 = OpAccessChain %39 %46 %31 - OpStore %50 %49 - %51 = OpCompositeExtract %19 %45 2 - %52 = OpAccessChain %39 %46 %16 - OpStore %52 %51 - OpBranch %13 - %13 = OpLabel - %54 = OpIAdd %6 %72 %31 - OpStore %8 %54 - OpBranch %10 - %12 = OpLabel - OpStore %55 %9 - OpBranch %56 - %56 = OpLabel - %73 = OpPhi %6 %9 %12 %71 %59 - OpLoopMerge %58 %59 None - OpBranch %60 - %60 = OpLabel - %62 = OpSLessThan %17 %73 %16 - OpBranchConditional %62 %57 %58 - %57 = OpLabel - %66 = OpAccessChain %65 %30 %9 - %67 = OpLoad %6 %66 - %68 = OpAccessChain %39 %25 %67 %9 - %69 = OpLoad %19 %68 - OpStore %64 %69 - OpBranch %59 - %59 = OpLabel - %71 = OpIAdd %6 %73 %31 - OpStore %55 %71 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_FALSE(fusion.IsLegal()); - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_legal.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_legal.cpp deleted file mode 100644 index 56b0b76f4..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_legal.cpp +++ /dev/null @@ -1,4580 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "source/opt/loop_descriptor.h" -#include "source/opt/loop_fusion.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using FusionLegalTest = PassTest<::testing::Test>; - -bool Validate(const std::vector& bin) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - spv_context spvContext = spvContextCreate(target_env); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {bin.data(), bin.size()}; - spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - return error == 0; -} - -void Match(const std::string& checks, IRContext* context) { - // Silence unused warnings with !defined(SPIRV_EFFCE) - (void)checks; - - std::vector bin; - context->module()->ToBinary(&bin, true); - EXPECT_TRUE(Validate(bin)); - std::string assembly; - SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); - EXPECT_TRUE( - tools.Disassemble(bin, &assembly, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) - << "Disassembling failed for shader:\n" - << assembly << std::endl; - auto match_result = effcee::Match(assembly, checks); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking result:\n" - << assembly; -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - // No dependence, legal - for (int i = 0; i < 10; i++) { - a[i] = a[i]*2; - } - for (int i = 0; i < 10; i++) { - b[i] = b[i]+2; - } -} - -*/ -TEST_F(FusionLegalTest, DifferentArraysInLoops) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %34 "i" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %28 = OpConstant %6 2 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpAccessChain %7 %23 %51 - %27 = OpLoad %6 %26 - %29 = OpIMul %6 %27 %28 - %30 = OpAccessChain %7 %23 %51 - OpStore %30 %29 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %51 %32 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %52 = OpPhi %6 %9 %12 %50 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %52 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %42 %52 - %46 = OpLoad %6 %45 - %47 = OpIAdd %6 %46 %28 - %48 = OpAccessChain %7 %42 %52 - OpStore %48 %47 - OpBranch %38 - %38 = OpLabel - %50 = OpIAdd %6 %52 %32 - OpStore %34 %50 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Only loads to the same array, legal - for (int i = 0; i < 10; i++) { - b[i] = a[i]*2; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i]+2; - } -} - -*/ -TEST_F(FusionLegalTest, OnlyLoadsToSameArray) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "b" - OpName %25 "a" - OpName %35 "i" - OpName %43 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 2 - %33 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %35 = OpVariable %7 Function - %43 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %52 = OpPhi %6 %9 %5 %34 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %52 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %52 - %28 = OpLoad %6 %27 - %30 = OpIMul %6 %28 %29 - %31 = OpAccessChain %7 %23 %52 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %34 = OpIAdd %6 %52 %33 - OpStore %8 %34 - OpBranch %10 - %12 = OpLabel - OpStore %35 %9 - OpBranch %36 - %36 = OpLabel - %53 = OpPhi %6 %9 %12 %51 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %17 %53 %16 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %46 = OpAccessChain %7 %25 %53 - %47 = OpLoad %6 %46 - %48 = OpIAdd %6 %47 %29 - %49 = OpAccessChain %7 %43 %53 - OpStore %49 %48 - OpBranch %39 - %39 = OpLabel - %51 = OpIAdd %6 %53 %33 - OpStore %35 %51 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - // No loop-carried dependences, legal - for (int i = 0; i < 10; i++) { - a[i] = a[i]*2; - } - for (int i = 0; i < 10; i++) { - b[i] = a[i]+2; - } -} - -*/ -TEST_F(FusionLegalTest, NoLoopCarriedDependences) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %34 "i" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %28 = OpConstant %6 2 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpAccessChain %7 %23 %51 - %27 = OpLoad %6 %26 - %29 = OpIMul %6 %27 %28 - %30 = OpAccessChain %7 %23 %51 - OpStore %30 %29 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %51 %32 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %52 = OpPhi %6 %9 %12 %50 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %52 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %23 %52 - %46 = OpLoad %6 %45 - %47 = OpIAdd %6 %46 %28 - %48 = OpAccessChain %7 %42 %52 - OpStore %48 %47 - OpBranch %38 - %38 = OpLabel - %50 = OpIAdd %6 %52 %32 - OpStore %34 %50 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Parallelism inhibiting, but legal. - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i] + c[i-1]; - } -} - -*/ -TEST_F(FusionLegalTest, ExistingLoopCarriedDependence) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %42 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %55 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %55 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %55 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %55 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %55 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %56 = OpPhi %6 %9 %12 %54 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %56 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %23 %56 - %46 = OpLoad %6 %45 - %48 = OpISub %6 %56 %29 - %49 = OpAccessChain %7 %42 %48 - %50 = OpLoad %6 %49 - %51 = OpIAdd %6 %46 %50 - %52 = OpAccessChain %7 %42 %56 - OpStore %52 %51 - OpBranch %38 - %38 = OpLabel - %54 = OpIAdd %6 %56 %29 - OpStore %34 %54 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[I_1:%\w+]] = OpISub {{%\w+}} [[PHI]] {{%\w+}} -CHECK-NEXT: [[LOAD_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_2]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Creates a loop-carried dependence, but negative, so legal - for (int i = 0; i < 10; i++) { - a[i+1] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, NegativeDistanceCreatedRAW) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %27 "b" - OpName %35 "i" - OpName %43 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %25 = OpConstant %6 1 - %48 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %27 = OpVariable %22 Function - %35 = OpVariable %7 Function - %43 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %53 = OpPhi %6 %9 %5 %34 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %53 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpIAdd %6 %53 %25 - %29 = OpAccessChain %7 %27 %53 - %30 = OpLoad %6 %29 - %31 = OpIAdd %6 %30 %25 - %32 = OpAccessChain %7 %23 %26 - OpStore %32 %31 - OpBranch %13 - %13 = OpLabel - %34 = OpIAdd %6 %53 %25 - OpStore %8 %34 - OpBranch %10 - %12 = OpLabel - OpStore %35 %9 - OpBranch %36 - %36 = OpLabel - %54 = OpPhi %6 %9 %12 %52 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %17 %54 %16 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %46 = OpAccessChain %7 %23 %54 - %47 = OpLoad %6 %46 - %49 = OpIAdd %6 %47 %48 - %50 = OpAccessChain %7 %43 %54 - OpStore %50 %49 - OpBranch %39 - %39 = OpLabel - %52 = OpIAdd %6 %54 %25 - OpStore %35 %52 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - auto& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal - for (int i = 0; i < 10; i++) { - a[i+1] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i+1] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, NoLoopCarriedDependencesAdjustedIndex) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %27 "b" - OpName %35 "i" - OpName %43 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %25 = OpConstant %6 1 - %49 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %27 = OpVariable %22 Function - %35 = OpVariable %7 Function - %43 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %54 = OpPhi %6 %9 %5 %34 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %54 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpIAdd %6 %54 %25 - %29 = OpAccessChain %7 %27 %54 - %30 = OpLoad %6 %29 - %31 = OpIAdd %6 %30 %25 - %32 = OpAccessChain %7 %23 %26 - OpStore %32 %31 - OpBranch %13 - %13 = OpLabel - %34 = OpIAdd %6 %54 %25 - OpStore %8 %34 - OpBranch %10 - %12 = OpLabel - OpStore %35 %9 - OpBranch %36 - %36 = OpLabel - %55 = OpPhi %6 %9 %12 %53 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %17 %55 %16 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %46 = OpIAdd %6 %55 %25 - %47 = OpAccessChain %7 %23 %46 - %48 = OpLoad %6 %47 - %50 = OpIAdd %6 %48 %49 - %51 = OpAccessChain %7 %43 %55 - OpStore %51 %50 - OpBranch %39 - %39 = OpLabel - %53 = OpIAdd %6 %55 %25 - OpStore %35 %53 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK-NEXT: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal, independent locations in |a|, SIV - for (int i = 0; i < 10; i++) { - a[2*i+1] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[2*i] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, IndependentSIV) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %29 "b" - OpName %37 "i" - OpName %45 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %24 = OpConstant %6 2 - %27 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %29 = OpVariable %22 Function - %37 = OpVariable %7 Function - %45 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %55 = OpPhi %6 %9 %5 %36 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %55 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpIMul %6 %24 %55 - %28 = OpIAdd %6 %26 %27 - %31 = OpAccessChain %7 %29 %55 - %32 = OpLoad %6 %31 - %33 = OpIAdd %6 %32 %27 - %34 = OpAccessChain %7 %23 %28 - OpStore %34 %33 - OpBranch %13 - %13 = OpLabel - %36 = OpIAdd %6 %55 %27 - OpStore %8 %36 - OpBranch %10 - %12 = OpLabel - OpStore %37 %9 - OpBranch %38 - %38 = OpLabel - %56 = OpPhi %6 %9 %12 %54 %41 - OpLoopMerge %40 %41 None - OpBranch %42 - %42 = OpLabel - %44 = OpSLessThan %17 %56 %16 - OpBranchConditional %44 %39 %40 - %39 = OpLabel - %48 = OpIMul %6 %24 %56 - %49 = OpAccessChain %7 %23 %48 - %50 = OpLoad %6 %49 - %51 = OpIAdd %6 %50 %24 - %52 = OpAccessChain %7 %45 %56 - OpStore %52 %51 - OpBranch %41 - %41 = OpLabel - %54 = OpIAdd %6 %56 %27 - OpStore %37 %54 - OpBranch %38 - %40 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[I_2:%\w+]] = OpIMul {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[I_2_1:%\w+]] = OpIAdd {{%\w+}} [[I_2]] {{%\w+}} -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_2_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[I_2:%\w+]] = OpIMul {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_2]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal, independent locations in |a|, ZIV - for (int i = 0; i < 10; i++) { - a[1] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[9] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, IndependentZIV) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %33 "i" - OpName %41 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %24 = OpConstant %6 1 - %43 = OpConstant %6 9 - %46 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %33 = OpVariable %7 Function - %41 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %32 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %51 - %28 = OpLoad %6 %27 - %29 = OpIAdd %6 %28 %24 - %30 = OpAccessChain %7 %23 %24 - OpStore %30 %29 - OpBranch %13 - %13 = OpLabel - %32 = OpIAdd %6 %51 %24 - OpStore %8 %32 - OpBranch %10 - %12 = OpLabel - OpStore %33 %9 - OpBranch %34 - %34 = OpLabel - %52 = OpPhi %6 %9 %12 %50 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %40 = OpSLessThan %17 %52 %16 - OpBranchConditional %40 %35 %36 - %35 = OpLabel - %44 = OpAccessChain %7 %23 %43 - %45 = OpLoad %6 %44 - %47 = OpIAdd %6 %45 %46 - %48 = OpAccessChain %7 %41 %52 - OpStore %48 %47 - OpBranch %37 - %37 = OpLabel - %50 = OpIAdd %6 %52 %24 - OpStore %33 %50 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK-NOT: OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK: OpStore -CHECK-NOT: OpPhi -CHECK-NOT: OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK: OpLoad -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[20] a; - int[10] b; - int[10] c; - // Legal, non-overlapping sections in |a| - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i+10] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, NonOverlappingAccesses) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %28 "b" - OpName %37 "i" - OpName %45 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 20 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %25 = OpConstant %19 10 - %26 = OpTypeArray %6 %25 - %27 = OpTypePointer Function %26 - %32 = OpConstant %6 1 - %51 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %28 = OpVariable %27 Function - %37 = OpVariable %7 Function - %45 = OpVariable %27 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %56 = OpPhi %6 %9 %5 %36 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %56 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %30 = OpAccessChain %7 %28 %56 - %31 = OpLoad %6 %30 - %33 = OpIAdd %6 %31 %32 - %34 = OpAccessChain %7 %23 %56 - OpStore %34 %33 - OpBranch %13 - %13 = OpLabel - %36 = OpIAdd %6 %56 %32 - OpStore %8 %36 - OpBranch %10 - %12 = OpLabel - OpStore %37 %9 - OpBranch %38 - %38 = OpLabel - %57 = OpPhi %6 %9 %12 %55 %41 - OpLoopMerge %40 %41 None - OpBranch %42 - %42 = OpLabel - %44 = OpSLessThan %17 %57 %16 - OpBranchConditional %44 %39 %40 - %39 = OpLabel - %48 = OpIAdd %6 %57 %16 - %49 = OpAccessChain %7 %23 %48 - %50 = OpLoad %6 %49 - %52 = OpIAdd %6 %50 %51 - %53 = OpAccessChain %7 %45 %57 - OpStore %53 %52 - OpBranch %41 - %41 = OpLabel - %55 = OpIAdd %6 %57 %32 - OpStore %37 %55 - OpBranch %38 - %40 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NOT: OpPhi -CHECK: [[I_10:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK-NEXT: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_10]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -)"; - - Match(checks, context.get()); - - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal, 3 adjacent loops - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i] + 2; - } - for (int i = 0; i < 10; i++) { - b[i] = c[i] + 10; - } -} - -*/ -TEST_F(FusionLegalTest, AdjacentLoops) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %42 "c" - OpName %52 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %47 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - %52 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %68 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %68 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %68 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %68 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %68 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %69 = OpPhi %6 %9 %12 %51 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %69 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %23 %69 - %46 = OpLoad %6 %45 - %48 = OpIAdd %6 %46 %47 - %49 = OpAccessChain %7 %42 %69 - OpStore %49 %48 - OpBranch %38 - %38 = OpLabel - %51 = OpIAdd %6 %69 %29 - OpStore %34 %51 - OpBranch %35 - %37 = OpLabel - OpStore %52 %9 - OpBranch %53 - %53 = OpLabel - %70 = OpPhi %6 %9 %37 %67 %56 - OpLoopMerge %55 %56 None - OpBranch %57 - %57 = OpLabel - %59 = OpSLessThan %17 %70 %16 - OpBranchConditional %59 %54 %55 - %54 = OpLabel - %62 = OpAccessChain %7 %42 %70 - %63 = OpLoad %6 %62 - %64 = OpIAdd %6 %63 %16 - %65 = OpAccessChain %7 %25 %70 - OpStore %65 %64 - OpBranch %56 - %56 = OpLabel - %67 = OpIAdd %6 %70 %29 - OpStore %52 %67 - OpBranch %53 - %55 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[1], loops[2]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_1]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_2]] -CHECK: [[STORE_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_2]] - )"; - - Match(checks, context.get()); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - std::string checks_ = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_2]] -CHECK: [[STORE_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_2]] - )"; - - Match(checks_, context.get()); - - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Legal inner loop fusion - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - c[i][j] = a[i][j] + 2; - } - for (int j = 0; j < 10; j++) { - b[i][j] = c[i][j] + 10; - } - } -} - -*/ -TEST_F(FusionLegalTest, InnerLoopFusion) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %32 "c" - OpName %35 "a" - OpName %46 "j" - OpName %54 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypeArray %29 %28 - %31 = OpTypePointer Function %30 - %40 = OpConstant %6 2 - %44 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %31 Function - %35 = OpVariable %31 Function - %46 = OpVariable %7 Function - %54 = OpVariable %31 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %67 = OpPhi %6 %9 %5 %66 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %67 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %68 = OpPhi %6 %9 %11 %45 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %68 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %38 = OpAccessChain %7 %35 %67 %68 - %39 = OpLoad %6 %38 - %41 = OpIAdd %6 %39 %40 - %42 = OpAccessChain %7 %32 %67 %68 - OpStore %42 %41 - OpBranch %23 - %23 = OpLabel - %45 = OpIAdd %6 %68 %44 - OpStore %19 %45 - OpBranch %20 - %22 = OpLabel - OpStore %46 %9 - OpBranch %47 - %47 = OpLabel - %69 = OpPhi %6 %9 %22 %64 %50 - OpLoopMerge %49 %50 None - OpBranch %51 - %51 = OpLabel - %53 = OpSLessThan %17 %69 %16 - OpBranchConditional %53 %48 %49 - %48 = OpLabel - %59 = OpAccessChain %7 %32 %67 %69 - %60 = OpLoad %6 %59 - %61 = OpIAdd %6 %60 %16 - %62 = OpAccessChain %7 %54 %67 %69 - OpStore %62 %61 - OpBranch %50 - %50 = OpLabel - %64 = OpIAdd %6 %69 %44 - OpStore %46 %64 - OpBranch %47 - %49 = OpLabel - OpBranch %13 - %13 = OpLabel - %66 = OpIAdd %6 %67 %44 - OpStore %8 %66 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - - auto& ld_final = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld_final.NumLoops(), 2u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// 12 -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Legal both - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - c[i][j] = a[i][j] + 2; - } - } - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - b[i][j] = c[i][j] + 10; - } - } -} - -*/ -TEST_F(FusionLegalTest, OuterAndInnerLoop) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %32 "c" - OpName %35 "a" - OpName %48 "i" - OpName %56 "j" - OpName %64 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypeArray %29 %28 - %31 = OpTypePointer Function %30 - %40 = OpConstant %6 2 - %44 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %31 Function - %35 = OpVariable %31 Function - %48 = OpVariable %7 Function - %56 = OpVariable %7 Function - %64 = OpVariable %31 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %77 = OpPhi %6 %9 %5 %47 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %77 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %81 = OpPhi %6 %9 %11 %45 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %81 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %38 = OpAccessChain %7 %35 %77 %81 - %39 = OpLoad %6 %38 - %41 = OpIAdd %6 %39 %40 - %42 = OpAccessChain %7 %32 %77 %81 - OpStore %42 %41 - OpBranch %23 - %23 = OpLabel - %45 = OpIAdd %6 %81 %44 - OpStore %19 %45 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %47 = OpIAdd %6 %77 %44 - OpStore %8 %47 - OpBranch %10 - %12 = OpLabel - OpStore %48 %9 - OpBranch %49 - %49 = OpLabel - %78 = OpPhi %6 %9 %12 %76 %52 - OpLoopMerge %51 %52 None - OpBranch %53 - %53 = OpLabel - %55 = OpSLessThan %17 %78 %16 - OpBranchConditional %55 %50 %51 - %50 = OpLabel - OpStore %56 %9 - OpBranch %57 - %57 = OpLabel - %79 = OpPhi %6 %9 %50 %74 %60 - OpLoopMerge %59 %60 None - OpBranch %61 - %61 = OpLabel - %63 = OpSLessThan %17 %79 %16 - OpBranchConditional %63 %58 %59 - %58 = OpLabel - %69 = OpAccessChain %7 %32 %78 %79 - %70 = OpLoad %6 %69 - %71 = OpIAdd %6 %70 %16 - %72 = OpAccessChain %7 %64 %78 %79 - OpStore %72 %71 - OpBranch %60 - %60 = OpLabel - %74 = OpIAdd %6 %79 %44 - OpStore %56 %74 - OpBranch %57 - %59 = OpLabel - OpBranch %52 - %52 = OpLabel - %76 = OpIAdd %6 %78 %44 - OpStore %48 %76 - OpBranch %49 - %51 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 4u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - auto loop_3 = loops[3]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_2, loop_3); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_3); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK: [[PHI_2:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_2]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_2]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - auto& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - auto& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Legal both, more complex - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - if (i % 2 == 0 && j % 2 == 0) { - c[i][j] = a[i][j] + 2; - } - } - } - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - b[i][j] = c[i][j] + 10; - } - } -} - -*/ -TEST_F(FusionLegalTest, OuterAndInnerLoopMoreComplex) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %44 "c" - OpName %47 "a" - OpName %59 "i" - OpName %67 "j" - OpName %75 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %28 = OpConstant %6 2 - %39 = OpTypeInt 32 0 - %40 = OpConstant %39 10 - %41 = OpTypeArray %6 %40 - %42 = OpTypeArray %41 %40 - %43 = OpTypePointer Function %42 - %55 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %44 = OpVariable %43 Function - %47 = OpVariable %43 Function - %59 = OpVariable %7 Function - %67 = OpVariable %7 Function - %75 = OpVariable %43 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %88 = OpPhi %6 %9 %5 %58 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %88 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %92 = OpPhi %6 %9 %11 %56 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %92 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %29 = OpSMod %6 %88 %28 - %30 = OpIEqual %17 %29 %9 - OpSelectionMerge %32 None - OpBranchConditional %30 %31 %32 - %31 = OpLabel - %34 = OpSMod %6 %92 %28 - %35 = OpIEqual %17 %34 %9 - OpBranch %32 - %32 = OpLabel - %36 = OpPhi %17 %30 %21 %35 %31 - OpSelectionMerge %38 None - OpBranchConditional %36 %37 %38 - %37 = OpLabel - %50 = OpAccessChain %7 %47 %88 %92 - %51 = OpLoad %6 %50 - %52 = OpIAdd %6 %51 %28 - %53 = OpAccessChain %7 %44 %88 %92 - OpStore %53 %52 - OpBranch %38 - %38 = OpLabel - OpBranch %23 - %23 = OpLabel - %56 = OpIAdd %6 %92 %55 - OpStore %19 %56 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %58 = OpIAdd %6 %88 %55 - OpStore %8 %58 - OpBranch %10 - %12 = OpLabel - OpStore %59 %9 - OpBranch %60 - %60 = OpLabel - %89 = OpPhi %6 %9 %12 %87 %63 - OpLoopMerge %62 %63 None - OpBranch %64 - %64 = OpLabel - %66 = OpSLessThan %17 %89 %16 - OpBranchConditional %66 %61 %62 - %61 = OpLabel - OpStore %67 %9 - OpBranch %68 - %68 = OpLabel - %90 = OpPhi %6 %9 %61 %85 %71 - OpLoopMerge %70 %71 None - OpBranch %72 - %72 = OpLabel - %74 = OpSLessThan %17 %90 %16 - OpBranchConditional %74 %69 %70 - %69 = OpLabel - %80 = OpAccessChain %7 %44 %89 %90 - %81 = OpLoad %6 %80 - %82 = OpIAdd %6 %81 %16 - %83 = OpAccessChain %7 %75 %89 %90 - OpStore %83 %82 - OpBranch %71 - %71 = OpLabel - %85 = OpIAdd %6 %90 %55 - OpStore %67 %85 - OpBranch %68 - %70 = OpLabel - OpBranch %63 - %63 = OpLabel - %87 = OpIAdd %6 %89 %55 - OpStore %59 %87 - OpBranch %60 - %62 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 4u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - auto loop_3 = loops[3]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_2, loop_3); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_3); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: OpPhi -CHECK-NEXT: OpSelectionMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK: [[PHI_2:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_2]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_2]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: OpPhi -CHECK-NEXT: OpSelectionMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Outer would have been illegal to fuse, but since written - // like this, inner loop fusion is legal. - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - c[i][j] = a[i][j] + 2; - } - for (int j = 0; j < 10; j++) { - b[i][j] = c[i+1][j] + 10; - } - } -} - -*/ -TEST_F(FusionLegalTest, InnerWithExistingDependenceOnOuter) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %32 "c" - OpName %35 "a" - OpName %46 "j" - OpName %54 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypeArray %29 %28 - %31 = OpTypePointer Function %30 - %40 = OpConstant %6 2 - %44 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %31 Function - %35 = OpVariable %31 Function - %46 = OpVariable %7 Function - %54 = OpVariable %31 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %68 = OpPhi %6 %9 %5 %67 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %68 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %69 = OpPhi %6 %9 %11 %45 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %69 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %38 = OpAccessChain %7 %35 %68 %69 - %39 = OpLoad %6 %38 - %41 = OpIAdd %6 %39 %40 - %42 = OpAccessChain %7 %32 %68 %69 - OpStore %42 %41 - OpBranch %23 - %23 = OpLabel - %45 = OpIAdd %6 %69 %44 - OpStore %19 %45 - OpBranch %20 - %22 = OpLabel - OpStore %46 %9 - OpBranch %47 - %47 = OpLabel - %70 = OpPhi %6 %9 %22 %65 %50 - OpLoopMerge %49 %50 None - OpBranch %51 - %51 = OpLabel - %53 = OpSLessThan %17 %70 %16 - OpBranchConditional %53 %48 %49 - %48 = OpLabel - %58 = OpIAdd %6 %68 %44 - %60 = OpAccessChain %7 %32 %58 %70 - %61 = OpLoad %6 %60 - %62 = OpIAdd %6 %61 %16 - %63 = OpAccessChain %7 %54 %68 %70 - OpStore %63 %62 - OpBranch %50 - %50 = OpLabel - %65 = OpIAdd %6 %70 %44 - OpStore %46 %65 - OpBranch %47 - %49 = OpLabel - OpBranch %13 - %13 = OpLabel - %67 = OpIAdd %6 %68 %44 - OpStore %8 %67 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI_0]] {{%\w+}} -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // One dimensional arrays. Legal, outer dist 0, inner independent. - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - c[i] = a[j] + 2; - } - } - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - b[j] = c[i] + 10; - } - } -} - -*/ -TEST_F(FusionLegalTest, OuterAndInnerLoopOneDimArrays) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %31 "c" - OpName %33 "a" - OpName %45 "i" - OpName %53 "j" - OpName %61 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypePointer Function %29 - %37 = OpConstant %6 2 - %41 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %31 = OpVariable %30 Function - %33 = OpVariable %30 Function - %45 = OpVariable %7 Function - %53 = OpVariable %7 Function - %61 = OpVariable %30 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %72 = OpPhi %6 %9 %5 %44 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %72 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %76 = OpPhi %6 %9 %11 %42 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %76 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %35 = OpAccessChain %7 %33 %76 - %36 = OpLoad %6 %35 - %38 = OpIAdd %6 %36 %37 - %39 = OpAccessChain %7 %31 %72 - OpStore %39 %38 - OpBranch %23 - %23 = OpLabel - %42 = OpIAdd %6 %76 %41 - OpStore %19 %42 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %44 = OpIAdd %6 %72 %41 - OpStore %8 %44 - OpBranch %10 - %12 = OpLabel - OpStore %45 %9 - OpBranch %46 - %46 = OpLabel - %73 = OpPhi %6 %9 %12 %71 %49 - OpLoopMerge %48 %49 None - OpBranch %50 - %50 = OpLabel - %52 = OpSLessThan %17 %73 %16 - OpBranchConditional %52 %47 %48 - %47 = OpLabel - OpStore %53 %9 - OpBranch %54 - %54 = OpLabel - %74 = OpPhi %6 %9 %47 %69 %57 - OpLoopMerge %56 %57 None - OpBranch %58 - %58 = OpLabel - %60 = OpSLessThan %17 %74 %16 - OpBranchConditional %60 %55 %56 - %55 = OpLabel - %64 = OpAccessChain %7 %31 %73 - %65 = OpLoad %6 %64 - %66 = OpIAdd %6 %65 %16 - %67 = OpAccessChain %7 %61 %74 - OpStore %67 %66 - OpBranch %57 - %57 = OpLabel - %69 = OpIAdd %6 %74 %41 - OpStore %53 %69 - OpBranch %54 - %56 = OpLabel - OpBranch %49 - %49 = OpLabel - %71 = OpIAdd %6 %73 %41 - OpStore %45 %71 - OpBranch %46 - %48 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 4u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - auto loop_3 = loops[3]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_2, loop_3); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK: [[PHI_2:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_2]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - auto loop_0 = loops[0]; - auto loop_1 = loops[1]; - auto loop_2 = loops[2]; - - { - LoopFusion fusion(context.get(), loop_0, loop_1); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_0, loop_2); - EXPECT_FALSE(fusion.AreCompatible()); - } - - { - LoopFusion fusion(context.get(), loop_1, loop_2); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal, creates a loop-carried dependence, but has negative distance - for (int i = 0; i < 10; i++) { - c[i] = a[i+1] + 1; - } - for (int i = 0; i < 10; i++) { - a[i] = c[i] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, NegativeDistanceCreatedWAR) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "c" - OpName %25 "a" - OpName %35 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %27 = OpConstant %6 1 - %47 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %35 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %52 = OpPhi %6 %9 %5 %34 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %52 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %28 = OpIAdd %6 %52 %27 - %29 = OpAccessChain %7 %25 %28 - %30 = OpLoad %6 %29 - %31 = OpIAdd %6 %30 %27 - %32 = OpAccessChain %7 %23 %52 - OpStore %32 %31 - OpBranch %13 - %13 = OpLabel - %34 = OpIAdd %6 %52 %27 - OpStore %8 %34 - OpBranch %10 - %12 = OpLabel - OpStore %35 %9 - OpBranch %36 - %36 = OpLabel - %53 = OpPhi %6 %9 %12 %51 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %17 %53 %16 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %45 = OpAccessChain %7 %23 %53 - %46 = OpLoad %6 %45 - %48 = OpIAdd %6 %46 %47 - %49 = OpAccessChain %7 %25 %53 - OpStore %49 %48 - OpBranch %39 - %39 = OpLabel - %51 = OpIAdd %6 %53 %27 - OpStore %35 %51 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK-NEXT: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } - - { - auto& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal, creates a loop-carried dependence, but has negative distance - for (int i = 0; i < 10; i++) { - a[i+1] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - a[i] = c[i+1] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, NegativeDistanceCreatedWAW) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %27 "b" - OpName %35 "i" - OpName %44 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %25 = OpConstant %6 1 - %49 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %27 = OpVariable %22 Function - %35 = OpVariable %7 Function - %44 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %54 = OpPhi %6 %9 %5 %34 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %54 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpIAdd %6 %54 %25 - %29 = OpAccessChain %7 %27 %54 - %30 = OpLoad %6 %29 - %31 = OpIAdd %6 %30 %25 - %32 = OpAccessChain %7 %23 %26 - OpStore %32 %31 - OpBranch %13 - %13 = OpLabel - %34 = OpIAdd %6 %54 %25 - OpStore %8 %34 - OpBranch %10 - %12 = OpLabel - OpStore %35 %9 - OpBranch %36 - %36 = OpLabel - %55 = OpPhi %6 %9 %12 %53 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %17 %55 %16 - OpBranchConditional %42 %37 %38 - %37 = OpLabel - %46 = OpIAdd %6 %55 %25 - %47 = OpAccessChain %7 %44 %46 - %48 = OpLoad %6 %47 - %50 = OpIAdd %6 %48 %49 - %51 = OpAccessChain %7 %23 %55 - OpStore %51 %50 - OpBranch %39 - %39 = OpLabel - %53 = OpIAdd %6 %55 %25 - OpStore %35 %53 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpStore -CHECK-NOT: OpPhi -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK-NEXT: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Legal, no loop-carried dependence - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - a[i] = c[i+1] + 2; - } -} - -*/ -TEST_F(FusionLegalTest, NoLoopCarriedDependencesWAW) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %43 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %48 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %43 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %53 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %53 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %53 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %53 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %53 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %54 = OpPhi %6 %9 %12 %52 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %54 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpIAdd %6 %54 %29 - %46 = OpAccessChain %7 %43 %45 - %47 = OpLoad %6 %46 - %49 = OpIAdd %6 %47 %48 - %50 = OpAccessChain %7 %23 %54 - OpStore %50 %49 - OpBranch %38 - %38 = OpLabel - %52 = OpIAdd %6 %54 %29 - OpStore %34 %52 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[I_1:%\w+]] = OpIAdd {{%\w+}} [[PHI]] {{%\w+}} -CHECK-NEXT: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[I_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Legal outer. Continue and break are fine if nested in inner loops - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - if (j % 2 == 0) { - c[i][j] = a[i][j] + 2; - } else { - continue; - } - } - } - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - if (j % 2 == 0) { - b[i][j] = c[i][j] + 10; - } else { - break; - } - } - } -} - -*/ -TEST_F(FusionLegalTest, OuterloopWithBreakContinueInInner) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %38 "c" - OpName %41 "a" - OpName %55 "i" - OpName %63 "j" - OpName %76 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %28 = OpConstant %6 2 - %33 = OpTypeInt 32 0 - %34 = OpConstant %33 10 - %35 = OpTypeArray %6 %34 - %36 = OpTypeArray %35 %34 - %37 = OpTypePointer Function %36 - %51 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %38 = OpVariable %37 Function - %41 = OpVariable %37 Function - %55 = OpVariable %7 Function - %63 = OpVariable %7 Function - %76 = OpVariable %37 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %91 = OpPhi %6 %9 %5 %54 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %91 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %96 = OpPhi %6 %9 %11 %52 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %96 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %29 = OpSMod %6 %96 %28 - %30 = OpIEqual %17 %29 %9 - OpSelectionMerge %sel_merge None - OpBranchConditional %30 %31 %48 - %31 = OpLabel - %44 = OpAccessChain %7 %41 %91 %96 - %45 = OpLoad %6 %44 - %46 = OpIAdd %6 %45 %28 - %47 = OpAccessChain %7 %38 %91 %96 - OpStore %47 %46 - OpBranch %32 - %48 = OpLabel - OpBranch %sel_merge - %32 = OpLabel - OpBranch %sel_merge - %sel_merge = OpLabel - OpBranch %23 - %23 = OpLabel - %52 = OpIAdd %6 %96 %51 - OpStore %19 %52 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %54 = OpIAdd %6 %91 %51 - OpStore %8 %54 - OpBranch %10 - %12 = OpLabel - OpStore %55 %9 - OpBranch %56 - %56 = OpLabel - %92 = OpPhi %6 %9 %12 %90 %59 - OpLoopMerge %58 %59 None - OpBranch %60 - %60 = OpLabel - %62 = OpSLessThan %17 %92 %16 - OpBranchConditional %62 %57 %58 - %57 = OpLabel - OpStore %63 %9 - OpBranch %64 - %64 = OpLabel - %93 = OpPhi %6 %9 %57 %88 %67 - OpLoopMerge %66 %67 None - OpBranch %68 - %68 = OpLabel - %70 = OpSLessThan %17 %93 %16 - OpBranchConditional %70 %65 %66 - %65 = OpLabel - %72 = OpSMod %6 %93 %28 - %73 = OpIEqual %17 %72 %9 - OpSelectionMerge %75 None - OpBranchConditional %73 %74 %66 - %74 = OpLabel - %81 = OpAccessChain %7 %38 %92 %93 - %82 = OpLoad %6 %81 - %83 = OpIAdd %6 %82 %16 - %84 = OpAccessChain %7 %76 %92 %93 - OpStore %84 %83 - OpBranch %75 - %75 = OpLabel - OpBranch %67 - %67 = OpLabel - %88 = OpIAdd %6 %93 %51 - OpStore %63 %88 - OpBranch %64 - %66 = OpLabel - OpBranch %59 - %59 = OpLabel - %90 = OpIAdd %6 %92 %51 - OpStore %55 %90 - OpBranch %56 - %58 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 4u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[2]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[1], loops[2]); - EXPECT_FALSE(fusion.AreCompatible()); - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK: [[PHI_2:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_2]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] [[PHI_2]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// j loop preheader removed manually -#version 440 core -void main() { - int[10] a; - int[10] b; - int i = 0; - int j = 0; - // No loop-carried dependences, legal - for (; i < 10; i++) { - a[i] = a[i]*2; - } - for (; j < 10; j++) { - b[j] = a[j]+2; - } -} - -*/ -TEST_F(FusionLegalTest, DifferentArraysInLoopsNoPreheader) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %10 "j" - OpName %24 "a" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 10 - %22 = OpTypeArray %6 %21 - %23 = OpTypePointer Function %22 - %29 = OpConstant %6 2 - %33 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %24 = OpVariable %23 Function - %42 = OpVariable %23 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %51 = OpPhi %6 %9 %5 %34 %14 - OpLoopMerge %35 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %51 %17 - OpBranchConditional %19 %12 %35 - %12 = OpLabel - %27 = OpAccessChain %7 %24 %51 - %28 = OpLoad %6 %27 - %30 = OpIMul %6 %28 %29 - %31 = OpAccessChain %7 %24 %51 - OpStore %31 %30 - OpBranch %14 - %14 = OpLabel - %34 = OpIAdd %6 %51 %33 - OpStore %8 %34 - OpBranch %11 - %35 = OpLabel - %52 = OpPhi %6 %9 %15 %50 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %18 %52 %17 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %24 %52 - %46 = OpLoad %6 %45 - %47 = OpIAdd %6 %46 %29 - %48 = OpAccessChain %7 %42 %52 - OpStore %48 %47 - OpBranch %38 - %38 = OpLabel - %50 = OpIAdd %6 %52 %33 - OpStore %10 %50 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - { - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); - } - - ld.CreatePreHeaderBlocksIfMissing(); - - { - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -// j & k loop preheaders removed manually -#version 440 core -void main() { - int[10] a; - int[10] b; - int i = 0; - int j = 0; - int k = 0; - // No loop-carried dependences, legal - for (; i < 10; i++) { - a[i] = a[i]*2; - } - for (; j < 10; j++) { - b[j] = a[j]+2; - } - for (; k < 10; k++) { - a[k] = a[k]*2; - } -} - -*/ -TEST_F(FusionLegalTest, AdjacentLoopsNoPreheaders) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %10 "j" - OpName %11 "k" - OpName %25 "a" - OpName %43 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 10 - %23 = OpTypeArray %6 %22 - %24 = OpTypePointer Function %23 - %30 = OpConstant %6 2 - %34 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %11 = OpVariable %7 Function - %25 = OpVariable %24 Function - %43 = OpVariable %24 Function - OpStore %8 %9 - OpStore %10 %9 - OpStore %11 %9 - OpBranch %12 - %12 = OpLabel - %67 = OpPhi %6 %9 %5 %35 %15 - OpLoopMerge %36 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %67 %18 - OpBranchConditional %20 %13 %36 - %13 = OpLabel - %28 = OpAccessChain %7 %25 %67 - %29 = OpLoad %6 %28 - %31 = OpIMul %6 %29 %30 - %32 = OpAccessChain %7 %25 %67 - OpStore %32 %31 - OpBranch %15 - %15 = OpLabel - %35 = OpIAdd %6 %67 %34 - OpStore %8 %35 - OpBranch %12 - %36 = OpLabel - %68 = OpPhi %6 %9 %16 %51 %39 - OpLoopMerge %52 %39 None - OpBranch %40 - %40 = OpLabel - %42 = OpSLessThan %19 %68 %18 - OpBranchConditional %42 %37 %52 - %37 = OpLabel - %46 = OpAccessChain %7 %25 %68 - %47 = OpLoad %6 %46 - %48 = OpIAdd %6 %47 %30 - %49 = OpAccessChain %7 %43 %68 - OpStore %49 %48 - OpBranch %39 - %39 = OpLabel - %51 = OpIAdd %6 %68 %34 - OpStore %10 %51 - OpBranch %36 - %52 = OpLabel - %70 = OpPhi %6 %9 %40 %66 %55 - OpLoopMerge %54 %55 None - OpBranch %56 - %56 = OpLabel - %58 = OpSLessThan %19 %70 %18 - OpBranchConditional %58 %53 %54 - %53 = OpLabel - %61 = OpAccessChain %7 %25 %70 - %62 = OpLoad %6 %61 - %63 = OpIMul %6 %62 %30 - %64 = OpAccessChain %7 %25 %70 - OpStore %64 %63 - OpBranch %55 - %55 = OpLabel - %66 = OpIAdd %6 %70 %34 - OpStore %11 %66 - OpBranch %52 - %54 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 3u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - { - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_FALSE(fusion.AreCompatible()); - } - - ld.CreatePreHeaderBlocksIfMissing(); - - { - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - std::string checks = R"( -CHECK: [[PHI_0:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_0]] -CHECK-NEXT: OpStore [[STORE_1]] -CHECK: [[PHI_1:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_2]] -CHECK: [[STORE_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI_1]] -CHECK-NEXT: OpStore [[STORE_2]] - )"; - - Match(checks, context.get()); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_0]] -CHECK: [[STORE_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpLoad {{%\w+}} [[LOAD_2]] -CHECK: [[STORE_2:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_2]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum_0 = 0; - int sum_1 = 0; - - // No loop-carried dependences, legal - for (int i = 0; i < 10; i++) { - sum_0 += a[i]; - } - for (int j = 0; j < 10; j++) { - sum_1 += b[j]; - } - - int total = sum_0 + sum_1; -} - -*/ -TEST_F(FusionLegalTest, IndependentReductions) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum_0" - OpName %10 "sum_1" - OpName %11 "i" - OpName %25 "a" - OpName %34 "j" - OpName %42 "b" - OpName %50 "total" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 10 - %23 = OpTypeArray %6 %22 - %24 = OpTypePointer Function %23 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %11 = OpVariable %7 Function - %25 = OpVariable %24 Function - %34 = OpVariable %7 Function - %42 = OpVariable %24 Function - %50 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpStore %11 %9 - OpBranch %12 - %12 = OpLabel - %57 = OpPhi %6 %9 %5 %30 %15 - %54 = OpPhi %6 %9 %5 %33 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %54 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %27 = OpAccessChain %7 %25 %54 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %57 %28 - OpStore %8 %30 - OpBranch %15 - %15 = OpLabel - %33 = OpIAdd %6 %54 %32 - OpStore %11 %33 - OpBranch %12 - %14 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %58 = OpPhi %6 %9 %14 %47 %38 - %55 = OpPhi %6 %9 %14 %49 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %19 %55 %18 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %44 = OpAccessChain %7 %42 %55 - %45 = OpLoad %6 %44 - %47 = OpIAdd %6 %58 %45 - OpStore %10 %47 - OpBranch %38 - %38 = OpLabel - %49 = OpIAdd %6 %55 %32 - OpStore %34 %49 - OpBranch %35 - %37 = OpLabel - %53 = OpIAdd %6 %57 %58 - OpStore %50 %53 - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[SUM_0:%\w+]] = OpPhi -CHECK-NEXT: [[SUM_1:%\w+]] = OpPhi -CHECK-NEXT: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_0:%\w+]] = OpLoad {{%\w+}} [[LOAD_0]] -CHECK-NEXT: [[ADD_RES_0:%\w+]] = OpIAdd {{%\w+}} [[SUM_0]] [[LOAD_RES_0]] -CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_1:%\w+]] = OpLoad {{%\w+}} [[LOAD_1]] -CHECK-NEXT: [[ADD_RES_1:%\w+]] = OpIAdd {{%\w+}} [[SUM_1]] [[LOAD_RES_1]] -CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum_0 = 0; - int sum_1 = 0; - - // No loop-carried dependences, legal - for (int i = 0; i < 10; i++) { - sum_0 += a[i]; - } - for (int j = 0; j < 10; j++) { - sum_1 += b[j]; - } - - int total = sum_0 + sum_1; -} - -*/ -TEST_F(FusionLegalTest, IndependentReductionsOneLCSSA) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum_0" - OpName %10 "sum_1" - OpName %11 "i" - OpName %25 "a" - OpName %34 "j" - OpName %42 "b" - OpName %50 "total" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 10 - %23 = OpTypeArray %6 %22 - %24 = OpTypePointer Function %23 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %11 = OpVariable %7 Function - %25 = OpVariable %24 Function - %34 = OpVariable %7 Function - %42 = OpVariable %24 Function - %50 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpStore %11 %9 - OpBranch %12 - %12 = OpLabel - %57 = OpPhi %6 %9 %5 %30 %15 - %54 = OpPhi %6 %9 %5 %33 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %54 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %27 = OpAccessChain %7 %25 %54 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %57 %28 - OpStore %8 %30 - OpBranch %15 - %15 = OpLabel - %33 = OpIAdd %6 %54 %32 - OpStore %11 %33 - OpBranch %12 - %14 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %58 = OpPhi %6 %9 %14 %47 %38 - %55 = OpPhi %6 %9 %14 %49 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %19 %55 %18 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %44 = OpAccessChain %7 %42 %55 - %45 = OpLoad %6 %44 - %47 = OpIAdd %6 %58 %45 - OpStore %10 %47 - OpBranch %38 - %38 = OpLabel - %49 = OpIAdd %6 %55 %32 - OpStore %34 %49 - OpBranch %35 - %37 = OpLabel - %53 = OpIAdd %6 %57 %58 - OpStore %50 %53 - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopUtils utils_0(context.get(), loops[0]); - utils_0.MakeLoopClosedSSA(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[SUM_0:%\w+]] = OpPhi -CHECK-NEXT: [[SUM_1:%\w+]] = OpPhi -CHECK-NEXT: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_0:%\w+]] = OpLoad {{%\w+}} [[LOAD_0]] -CHECK-NEXT: [[ADD_RES_0:%\w+]] = OpIAdd {{%\w+}} [[SUM_0]] [[LOAD_RES_0]] -CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_1:%\w+]] = OpLoad {{%\w+}} [[LOAD_1]] -CHECK-NEXT: [[ADD_RES_1:%\w+]] = OpIAdd {{%\w+}} [[SUM_1]] [[LOAD_RES_1]] -CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum_0 = 0; - int sum_1 = 0; - - // No loop-carried dependences, legal - for (int i = 0; i < 10; i++) { - sum_0 += a[i]; - } - for (int j = 0; j < 10; j++) { - sum_1 += b[j]; - } - - int total = sum_0 + sum_1; -} - -*/ -TEST_F(FusionLegalTest, IndependentReductionsBothLCSSA) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum_0" - OpName %10 "sum_1" - OpName %11 "i" - OpName %25 "a" - OpName %34 "j" - OpName %42 "b" - OpName %50 "total" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 10 - %23 = OpTypeArray %6 %22 - %24 = OpTypePointer Function %23 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %11 = OpVariable %7 Function - %25 = OpVariable %24 Function - %34 = OpVariable %7 Function - %42 = OpVariable %24 Function - %50 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %9 - OpStore %11 %9 - OpBranch %12 - %12 = OpLabel - %57 = OpPhi %6 %9 %5 %30 %15 - %54 = OpPhi %6 %9 %5 %33 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %19 %54 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %27 = OpAccessChain %7 %25 %54 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %57 %28 - OpStore %8 %30 - OpBranch %15 - %15 = OpLabel - %33 = OpIAdd %6 %54 %32 - OpStore %11 %33 - OpBranch %12 - %14 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %58 = OpPhi %6 %9 %14 %47 %38 - %55 = OpPhi %6 %9 %14 %49 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %19 %55 %18 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %44 = OpAccessChain %7 %42 %55 - %45 = OpLoad %6 %44 - %47 = OpIAdd %6 %58 %45 - OpStore %10 %47 - OpBranch %38 - %38 = OpLabel - %49 = OpIAdd %6 %55 %32 - OpStore %34 %49 - OpBranch %35 - %37 = OpLabel - %53 = OpIAdd %6 %57 %58 - OpStore %50 %53 - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopUtils utils_0(context.get(), loops[0]); - utils_0.MakeLoopClosedSSA(); - LoopUtils utils_1(context.get(), loops[1]); - utils_1.MakeLoopClosedSSA(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: [[SUM_0:%\w+]] = OpPhi -CHECK-NEXT: [[SUM_1:%\w+]] = OpPhi -CHECK-NEXT: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_0:%\w+]] = OpLoad {{%\w+}} [[LOAD_0]] -CHECK-NEXT: [[ADD_RES_0:%\w+]] = OpIAdd {{%\w+}} [[SUM_0]] [[LOAD_RES_0]] -CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_1:%\w+]] = OpLoad {{%\w+}} [[LOAD_1]] -CHECK-NEXT: [[ADD_RES_1:%\w+]] = OpIAdd {{%\w+}} [[SUM_1]] [[LOAD_RES_1]] -CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - - int sum_0 = 0; - - // No loop-carried dependences, legal - for (int i = 0; i < 10; i++) { - sum_0 += a[i]; - } - for (int j = 0; j < 10; j++) { - a[j] = b[j]; - } -} - -*/ -TEST_F(FusionLegalTest, LoadStoreReductionAndNonLoopCarriedDependence) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "sum_0" - OpName %10 "i" - OpName %24 "a" - OpName %33 "j" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 10 - %18 = OpTypeBool - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 10 - %22 = OpTypeArray %6 %21 - %23 = OpTypePointer Function %22 - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %24 = OpVariable %23 Function - %33 = OpVariable %7 Function - %42 = OpVariable %23 Function - OpStore %8 %9 - OpStore %10 %9 - OpBranch %11 - %11 = OpLabel - %51 = OpPhi %6 %9 %5 %29 %14 - %49 = OpPhi %6 %9 %5 %32 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %18 %49 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %26 = OpAccessChain %7 %24 %49 - %27 = OpLoad %6 %26 - %29 = OpIAdd %6 %51 %27 - OpStore %8 %29 - OpBranch %14 - %14 = OpLabel - %32 = OpIAdd %6 %49 %31 - OpStore %10 %32 - OpBranch %11 - %13 = OpLabel - OpStore %33 %9 - OpBranch %34 - %34 = OpLabel - %50 = OpPhi %6 %9 %13 %48 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %40 = OpSLessThan %18 %50 %17 - OpBranchConditional %40 %35 %36 - %35 = OpLabel - %44 = OpAccessChain %7 %42 %50 - %45 = OpLoad %6 %44 - %46 = OpAccessChain %7 %24 %50 - OpStore %46 %45 - OpBranch %37 - %37 = OpLabel - %48 = OpIAdd %6 %50 %31 - OpStore %33 %48 - OpBranch %34 - %36 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - // TODO: Loop descriptor doesn't return induction variables but all OpPhi - // in the header and LoopDependenceAnalysis falls over. - // EXPECT_TRUE(fusion.IsLegal()); - - // fusion.Fuse(); - } - - { - // LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - // EXPECT_EQ(ld.NumLoops(), 1u); - - // std::string checks = R"( - // CHECK: [[SUM_0:%\w+]] = OpPhi - // CHECK-NEXT: [[PHI:%\w+]] = OpPhi - // CHECK-NEXT: OpLoopMerge - // CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] - // CHECK-NEXT: [[LOAD_RES_0:%\w+]] = OpLoad {{%\w+}} [[LOAD_0]] - // CHECK-NEXT: [[ADD_RES_0:%\w+]] = OpIAdd {{%\w+}} [[SUM_0]] [[LOAD_RES_0]] - // CHECK-NEXT: OpStore {{%\w+}} [[ADD_RES_0]] - // CHECK-NOT: OpPhi - // CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] - // CHECK-NEXT: [[LOAD_RES_1:%\w+]] = OpLoad {{%\w+}} [[LOAD_1]] - // CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] - // CHECK-NEXT: OpStore [[STORE_1]] [[LOAD_RES_1]] - // )"; - - // Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -int x; -void main() { - int[10] a; - int[10] b; - - // Legal. - for (int i = 0; i < 10; i++) { - x += a[i]; - } - for (int j = 0; j < 10; j++) { - b[j] = b[j]+1; - } -} - -*/ -TEST_F(FusionLegalTest, ReductionAndNonLoopCarriedDependence) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %20 "x" - OpName %25 "a" - OpName %34 "j" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypePointer Private %6 - %20 = OpVariable %19 Private - %21 = OpTypeInt 32 0 - %22 = OpConstant %21 10 - %23 = OpTypeArray %6 %22 - %24 = OpTypePointer Function %23 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %25 = OpVariable %24 Function - %34 = OpVariable %7 Function - %42 = OpVariable %24 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %51 - %28 = OpLoad %6 %27 - %29 = OpLoad %6 %20 - %30 = OpIAdd %6 %29 %28 - OpStore %20 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %51 %32 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %52 = OpPhi %6 %9 %12 %50 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %52 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %42 %52 - %46 = OpLoad %6 %45 - %47 = OpIAdd %6 %46 %32 - %48 = OpAccessChain %7 %42 %52 - OpStore %48 %47 - OpBranch %38 - %38 = OpLabel - %50 = OpIAdd %6 %52 %32 - OpStore %34 %50 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - std::string checks = R"( -CHECK: OpName [[X:%\w+]] "x" -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[LOAD_0:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: [[LOAD_RES_0:%\w+]] = OpLoad {{%\w+}} [[LOAD_0]] -CHECK-NEXT: [[X_LOAD:%\w+]] = OpLoad {{%\w+}} [[X]] -CHECK-NEXT: [[ADD_RES_0:%\w+]] = OpIAdd {{%\w+}} [[X_LOAD]] [[LOAD_RES_0]] -CHECK-NEXT: OpStore [[X]] [[ADD_RES_0]] -CHECK-NOT: OpPhi -CHECK: [[LOAD_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: {{%\w+}} = OpLoad {{%\w+}} [[LOAD_1]] -CHECK: [[STORE_1:%\w+]] = OpAccessChain {{%\w+}} {{%\w+}} [[PHI]] -CHECK-NEXT: OpStore [[STORE_1]] - )"; - - Match(checks, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -struct TestStruct { - int[10] a; - int b; -}; - -void main() { - TestStruct test_0; - TestStruct test_1; - TestStruct test_2; - - test_1.b = 2; - - for (int i = 0; i < 10; i++) { - test_0.a[i] = i; - } - for (int j = 0; j < 10; j++) { - test_2 = test_1; - } -} - -*/ -TEST_F(FusionLegalTest, ArrayInStruct) { - std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %10 "TestStruct" - OpMemberName %10 0 "a" - OpMemberName %10 1 "b" - OpName %12 "test_1" - OpName %17 "i" - OpName %28 "test_0" - OpName %34 "j" - OpName %42 "test_2" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeInt 32 0 - %8 = OpConstant %7 10 - %9 = OpTypeArray %6 %8 - %10 = OpTypeStruct %9 %6 - %11 = OpTypePointer Function %10 - %13 = OpConstant %6 1 - %14 = OpConstant %6 2 - %15 = OpTypePointer Function %6 - %18 = OpConstant %6 0 - %25 = OpConstant %6 10 - %26 = OpTypeBool - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpVariable %11 Function - %17 = OpVariable %15 Function - %28 = OpVariable %11 Function - %34 = OpVariable %15 Function - %42 = OpVariable %11 Function - %16 = OpAccessChain %15 %12 %13 - OpStore %16 %14 - OpStore %17 %18 - OpBranch %19 - %19 = OpLabel - %46 = OpPhi %6 %18 %5 %33 %22 - OpLoopMerge %21 %22 None - OpBranch %23 - %23 = OpLabel - %27 = OpSLessThan %26 %46 %25 - OpBranchConditional %27 %20 %21 - %20 = OpLabel - %31 = OpAccessChain %15 %28 %18 %46 - OpStore %31 %46 - OpBranch %22 - %22 = OpLabel - %33 = OpIAdd %6 %46 %13 - OpStore %17 %33 - OpBranch %19 - %21 = OpLabel - OpStore %34 %18 - OpBranch %35 - %35 = OpLabel - %47 = OpPhi %6 %18 %21 %45 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %26 %47 %25 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %43 = OpLoad %10 %12 - OpStore %42 %43 - OpBranch %38 - %38 = OpLabel - %45 = OpIAdd %6 %47 %13 - OpStore %34 %45 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 2u); - - auto loops = ld.GetLoopsInBinaryLayoutOrder(); - - LoopFusion fusion(context.get(), loops[0], loops[1]); - EXPECT_TRUE(fusion.AreCompatible()); - EXPECT_TRUE(fusion.IsLegal()); - - fusion.Fuse(); - } - - { - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), 1u); - - // clang-format off - std::string checks = R"( -CHECK: OpName [[TEST_1:%\w+]] "test_1" -CHECK: OpName [[TEST_0:%\w+]] "test_0" -CHECK: OpName [[TEST_2:%\w+]] "test_2" -CHECK: [[PHI:%\w+]] = OpPhi -CHECK-NEXT: OpLoopMerge -CHECK: [[TEST_0_STORE:%\w+]] = OpAccessChain {{%\w+}} [[TEST_0]] {{%\w+}} {{%\w+}} -CHECK-NEXT: OpStore [[TEST_0_STORE]] [[PHI]] -CHECK-NOT: OpPhi -CHECK: [[TEST_1_LOAD:%\w+]] = OpLoad {{%\w+}} [[TEST_1]] -CHECK: OpStore [[TEST_2]] [[TEST_1_LOAD]] - )"; - // clang-format on - - Match(checks, context.get()); - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_pass.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_pass.cpp deleted file mode 100644 index 949392375..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/fusion_pass.cpp +++ /dev/null @@ -1,717 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "effcee/effcee.h" -#include "gmock/gmock.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using FusionPassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - for (int i = 0; i < 10; i++) { - a[i] = a[i]*2; - } - for (int i = 0; i < 10; i++) { - b[i] = a[i]+2; - } -} - -*/ -TEST_F(FusionPassTest, SimpleFusion) { - const std::string text = R"( -; CHECK: OpPhi -; CHECK: OpLoad -; CHECK: OpStore -; CHECK-NOT: OpPhi -; CHECK: OpLoad -; CHECK: OpStore - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %34 "i" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %28 = OpConstant %6 2 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpAccessChain %7 %23 %51 - %27 = OpLoad %6 %26 - %29 = OpIMul %6 %27 %28 - %30 = OpAccessChain %7 %23 %51 - OpStore %30 %29 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %51 %32 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %52 = OpPhi %6 %9 %12 %50 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %52 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %23 %52 - %46 = OpLoad %6 %45 - %47 = OpIAdd %6 %46 %28 - %48 = OpAccessChain %7 %42 %52 - OpStore %48 %47 - OpBranch %38 - %38 = OpLabel - %50 = OpIAdd %6 %52 %32 - OpStore %34 %50 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true, 20); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i] + 2; - } - for (int i = 0; i < 10; i++) { - b[i] = c[i] + 10; - } -} - -*/ -TEST_F(FusionPassTest, ThreeLoopsFused) { - const std::string text = R"( -; CHECK: OpPhi -; CHECK: OpLoad -; CHECK: OpStore -; CHECK-NOT: OpPhi -; CHECK: OpLoad -; CHECK: OpStore -; CHECK-NOT: OpPhi -; CHECK: OpLoad -; CHECK: OpStore - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %42 "c" - OpName %52 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %47 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - %52 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %68 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %68 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %68 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %68 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %68 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %69 = OpPhi %6 %9 %12 %51 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %69 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %23 %69 - %46 = OpLoad %6 %45 - %48 = OpIAdd %6 %46 %47 - %49 = OpAccessChain %7 %42 %69 - OpStore %49 %48 - OpBranch %38 - %38 = OpLabel - %51 = OpIAdd %6 %69 %29 - OpStore %34 %51 - OpBranch %35 - %37 = OpLabel - OpStore %52 %9 - OpBranch %53 - %53 = OpLabel - %70 = OpPhi %6 %9 %37 %67 %56 - OpLoopMerge %55 %56 None - OpBranch %57 - %57 = OpLabel - %59 = OpSLessThan %17 %70 %16 - OpBranchConditional %59 %54 %55 - %54 = OpLabel - %62 = OpAccessChain %7 %42 %70 - %63 = OpLoad %6 %62 - %64 = OpIAdd %6 %63 %16 - %65 = OpAccessChain %7 %25 %70 - OpStore %65 %64 - OpBranch %56 - %56 = OpLabel - %67 = OpIAdd %6 %70 %29 - OpStore %52 %67 - OpBranch %53 - %55 = OpLabel - OpReturn - OpFunctionEnd - - )"; - - SinglePassRunAndMatch(text, true, 20); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10][10] a; - int[10][10] b; - int[10][10] c; - // Legal both - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - c[i][j] = a[i][j] + 2; - } - } - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - b[i][j] = c[i][j] + 10; - } - } -} - -*/ -TEST_F(FusionPassTest, NestedLoopsFused) { - const std::string text = R"( -; CHECK: OpPhi -; CHECK: OpPhi -; CHECK: OpLoad -; CHECK: OpStore -; CHECK-NOT: OpPhi -; CHECK: OpLoad -; CHECK: OpStore - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %19 "j" - OpName %32 "c" - OpName %35 "a" - OpName %48 "i" - OpName %56 "j" - OpName %64 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %27 = OpTypeInt 32 0 - %28 = OpConstant %27 10 - %29 = OpTypeArray %6 %28 - %30 = OpTypeArray %29 %28 - %31 = OpTypePointer Function %30 - %40 = OpConstant %6 2 - %44 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %31 Function - %35 = OpVariable %31 Function - %48 = OpVariable %7 Function - %56 = OpVariable %7 Function - %64 = OpVariable %31 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %77 = OpPhi %6 %9 %5 %47 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %77 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - %81 = OpPhi %6 %9 %11 %45 %23 - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %26 = OpSLessThan %17 %81 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - %38 = OpAccessChain %7 %35 %77 %81 - %39 = OpLoad %6 %38 - %41 = OpIAdd %6 %39 %40 - %42 = OpAccessChain %7 %32 %77 %81 - OpStore %42 %41 - OpBranch %23 - %23 = OpLabel - %45 = OpIAdd %6 %81 %44 - OpStore %19 %45 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %47 = OpIAdd %6 %77 %44 - OpStore %8 %47 - OpBranch %10 - %12 = OpLabel - OpStore %48 %9 - OpBranch %49 - %49 = OpLabel - %78 = OpPhi %6 %9 %12 %76 %52 - OpLoopMerge %51 %52 None - OpBranch %53 - %53 = OpLabel - %55 = OpSLessThan %17 %78 %16 - OpBranchConditional %55 %50 %51 - %50 = OpLabel - OpStore %56 %9 - OpBranch %57 - %57 = OpLabel - %79 = OpPhi %6 %9 %50 %74 %60 - OpLoopMerge %59 %60 None - OpBranch %61 - %61 = OpLabel - %63 = OpSLessThan %17 %79 %16 - OpBranchConditional %63 %58 %59 - %58 = OpLabel - %69 = OpAccessChain %7 %32 %78 %79 - %70 = OpLoad %6 %69 - %71 = OpIAdd %6 %70 %16 - %72 = OpAccessChain %7 %64 %78 %79 - OpStore %72 %71 - OpBranch %60 - %60 = OpLabel - %74 = OpIAdd %6 %79 %44 - OpStore %56 %74 - OpBranch %57 - %59 = OpLabel - OpBranch %52 - %52 = OpLabel - %76 = OpIAdd %6 %78 %44 - OpStore %48 %76 - OpBranch %49 - %51 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true, 20); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - // Can't fuse, different step - for (int i = 0; i < 10; i++) {} - for (int j = 0; j < 10; j=j+2) {} -} - -*/ -TEST_F(FusionPassTest, Incompatible) { - const std::string text = R"( -; CHECK: OpPhi -; CHECK-NEXT: OpLoopMerge -; CHECK: OpPhi -; CHECK-NEXT: OpLoopMerge - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %22 "j" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %31 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %22 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %33 = OpPhi %6 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %33 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %6 %33 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpStore %22 %9 - OpBranch %23 - %23 = OpLabel - %34 = OpPhi %6 %9 %12 %32 %26 - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %17 %34 %16 - OpBranchConditional %29 %24 %25 - %24 = OpLabel - OpBranch %26 - %26 = OpLabel - %32 = OpIAdd %6 %34 %31 - OpStore %22 %32 - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true, 20); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - int[10] c; - // Illegal, loop-independent dependence will become a - // backward loop-carried antidependence - for (int i = 0; i < 10; i++) { - a[i] = b[i] + 1; - } - for (int i = 0; i < 10; i++) { - c[i] = a[i+1] + 2; - } -} - -*/ -TEST_F(FusionPassTest, Illegal) { - std::string text = R"( -; CHECK: OpPhi -; CHECK-NEXT: OpLoopMerge -; CHECK: OpLoad -; CHECK: OpStore -; CHECK: OpPhi -; CHECK-NEXT: OpLoopMerge -; CHECK: OpLoad -; CHECK: OpStore - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %25 "b" - OpName %34 "i" - OpName %42 "c" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %29 = OpConstant %6 1 - %48 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %25 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %53 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %53 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpAccessChain %7 %25 %53 - %28 = OpLoad %6 %27 - %30 = OpIAdd %6 %28 %29 - %31 = OpAccessChain %7 %23 %53 - OpStore %31 %30 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %53 %29 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %54 = OpPhi %6 %9 %12 %52 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %54 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpIAdd %6 %54 %29 - %46 = OpAccessChain %7 %23 %45 - %47 = OpLoad %6 %46 - %49 = OpIAdd %6 %47 %48 - %50 = OpAccessChain %7 %42 %54 - OpStore %50 %49 - OpBranch %38 - %38 = OpLabel - %52 = OpIAdd %6 %54 %29 - OpStore %34 %52 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true, 20); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -void main() { - int[10] a; - int[10] b; - for (int i = 0; i < 10; i++) { - a[i] = a[i]*2; - } - for (int i = 0; i < 10; i++) { - b[i] = a[i]+2; - } -} - -*/ -TEST_F(FusionPassTest, TooManyRegisters) { - const std::string text = R"( -; CHECK: OpPhi -; CHECK-NEXT: OpLoopMerge -; CHECK: OpLoad -; CHECK: OpStore -; CHECK: OpPhi -; CHECK-NEXT: OpLoopMerge -; CHECK: OpLoad -; CHECK: OpStore - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - OpName %8 "i" - OpName %23 "a" - OpName %34 "i" - OpName %42 "b" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 10 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %28 = OpConstant %6 2 - %32 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %23 = OpVariable %22 Function - %34 = OpVariable %7 Function - %42 = OpVariable %22 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %33 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpAccessChain %7 %23 %51 - %27 = OpLoad %6 %26 - %29 = OpIMul %6 %27 %28 - %30 = OpAccessChain %7 %23 %51 - OpStore %30 %29 - OpBranch %13 - %13 = OpLabel - %33 = OpIAdd %6 %51 %32 - OpStore %8 %33 - OpBranch %10 - %12 = OpLabel - OpStore %34 %9 - OpBranch %35 - %35 = OpLabel - %52 = OpPhi %6 %9 %12 %50 %38 - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %41 = OpSLessThan %17 %52 %16 - OpBranchConditional %41 %36 %37 - %36 = OpLabel - %45 = OpAccessChain %7 %23 %52 - %46 = OpLoad %6 %45 - %47 = OpIAdd %6 %46 %28 - %48 = OpAccessChain %7 %42 %52 - OpStore %48 %47 - OpBranch %38 - %38 = OpLabel - %50 = OpIAdd %6 %52 %32 - OpStore %34 %50 - OpBranch %35 - %37 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true, 5); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_all_loop_types.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_all_loop_types.cpp deleted file mode 100644 index 27e0a0d91..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_all_loop_types.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/licm_pass.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Tests that all loop types are handled appropriately by the LICM pass. - - Generated from the following GLSL fragment shader ---eliminate-local-multi-store has also been run on the spv binary -#version 440 core -void main(){ - int i_1 = 0; - for (i_1 = 0; i_1 < 10; i_1++) { - } - int i_2 = 0; - while (i_2 < 10) { - i_2++; - } - int i_3 = 0; - do { - i_3++; - } while (i_3 < 10); - int hoist = 0; - int i_4 = 0; - int i_5 = 0; - int i_6 = 0; - for (i_4 = 0; i_4 < 10; i_4++) { - while (i_5 < 10) { - do { - hoist = i_1 + i_2 + i_3; - i_6++; - } while (i_6 < 10); - i_5++; - } - } -} -*/ -TEST_F(PassClassTest, AllLoopTypes) { - const std::string before_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_1 = OpConstant %int 1 -%main = OpFunction %void None %4 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -%13 = OpPhi %int %int_0 %11 %14 %15 -OpLoopMerge %16 %15 None -OpBranch %17 -%17 = OpLabel -%18 = OpSLessThan %bool %13 %int_10 -OpBranchConditional %18 %19 %16 -%19 = OpLabel -OpBranch %15 -%15 = OpLabel -%14 = OpIAdd %int %13 %int_1 -OpBranch %12 -%16 = OpLabel -OpBranch %20 -%20 = OpLabel -%21 = OpPhi %int %int_0 %16 %22 %23 -OpLoopMerge %24 %23 None -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%22 = OpIAdd %int %21 %int_1 -OpBranch %23 -%23 = OpLabel -OpBranch %20 -%24 = OpLabel -OpBranch %28 -%28 = OpLabel -%29 = OpPhi %int %int_0 %24 %30 %31 -OpLoopMerge %32 %31 None -OpBranch %33 -%33 = OpLabel -%30 = OpIAdd %int %29 %int_1 -OpBranch %31 -%31 = OpLabel -%34 = OpSLessThan %bool %30 %int_10 -OpBranchConditional %34 %28 %32 -%32 = OpLabel -OpBranch %35 -%35 = OpLabel -%36 = OpPhi %int %int_0 %32 %37 %38 -%39 = OpPhi %int %int_0 %32 %40 %38 -%41 = OpPhi %int %int_0 %32 %42 %38 -%43 = OpPhi %int %int_0 %32 %44 %38 -OpLoopMerge %45 %38 None -OpBranch %46 -%46 = OpLabel -%47 = OpSLessThan %bool %39 %int_10 -OpBranchConditional %47 %48 %45 -%48 = OpLabel -OpBranch %49 -%49 = OpLabel -%37 = OpPhi %int %36 %48 %50 %51 -%42 = OpPhi %int %41 %48 %52 %51 -%44 = OpPhi %int %43 %48 %53 %51 -OpLoopMerge %54 %51 None -OpBranch %55 -%55 = OpLabel -%56 = OpSLessThan %bool %42 %int_10 -OpBranchConditional %56 %57 %54 -%57 = OpLabel -OpBranch %58 -%58 = OpLabel -%59 = OpPhi %int %37 %57 %50 %60 -%61 = OpPhi %int %44 %57 %53 %60 -OpLoopMerge %62 %60 None -OpBranch %63 -%63 = OpLabel -%64 = OpIAdd %int %13 %21 -%50 = OpIAdd %int %64 %30 -%53 = OpIAdd %int %61 %int_1 -OpBranch %60 -%60 = OpLabel -%65 = OpSLessThan %bool %53 %int_10 -OpBranchConditional %65 %58 %62 -%62 = OpLabel -%52 = OpIAdd %int %42 %int_1 -OpBranch %51 -%51 = OpLabel -OpBranch %49 -%54 = OpLabel -OpBranch %38 -%38 = OpLabel -%40 = OpIAdd %int %39 %int_1 -OpBranch %35 -%45 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_1 = OpConstant %int 1 -%main = OpFunction %void None %4 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -%13 = OpPhi %int %int_0 %11 %14 %15 -OpLoopMerge %16 %15 None -OpBranch %17 -%17 = OpLabel -%18 = OpSLessThan %bool %13 %int_10 -OpBranchConditional %18 %19 %16 -%19 = OpLabel -OpBranch %15 -%15 = OpLabel -%14 = OpIAdd %int %13 %int_1 -OpBranch %12 -%16 = OpLabel -OpBranch %20 -%20 = OpLabel -%21 = OpPhi %int %int_0 %16 %22 %23 -OpLoopMerge %24 %23 None -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%22 = OpIAdd %int %21 %int_1 -OpBranch %23 -%23 = OpLabel -OpBranch %20 -%24 = OpLabel -OpBranch %28 -%28 = OpLabel -%29 = OpPhi %int %int_0 %24 %30 %31 -OpLoopMerge %32 %31 None -OpBranch %33 -%33 = OpLabel -%30 = OpIAdd %int %29 %int_1 -OpBranch %31 -%31 = OpLabel -%34 = OpSLessThan %bool %30 %int_10 -OpBranchConditional %34 %28 %32 -%32 = OpLabel -%64 = OpIAdd %int %13 %21 -%50 = OpIAdd %int %64 %30 -OpBranch %35 -%35 = OpLabel -%36 = OpPhi %int %int_0 %32 %37 %38 -%39 = OpPhi %int %int_0 %32 %40 %38 -%41 = OpPhi %int %int_0 %32 %42 %38 -%43 = OpPhi %int %int_0 %32 %44 %38 -OpLoopMerge %45 %38 None -OpBranch %46 -%46 = OpLabel -%47 = OpSLessThan %bool %39 %int_10 -OpBranchConditional %47 %48 %45 -%48 = OpLabel -OpBranch %49 -%49 = OpLabel -%37 = OpPhi %int %36 %48 %50 %51 -%42 = OpPhi %int %41 %48 %52 %51 -%44 = OpPhi %int %43 %48 %53 %51 -OpLoopMerge %54 %51 None -OpBranch %55 -%55 = OpLabel -%56 = OpSLessThan %bool %42 %int_10 -OpBranchConditional %56 %57 %54 -%57 = OpLabel -OpBranch %58 -%58 = OpLabel -%59 = OpPhi %int %37 %57 %50 %60 -%61 = OpPhi %int %44 %57 %53 %60 -OpLoopMerge %62 %60 None -OpBranch %63 -%63 = OpLabel -%53 = OpIAdd %int %61 %int_1 -OpBranch %60 -%60 = OpLabel -%65 = OpSLessThan %bool %53 %int_10 -OpBranchConditional %65 %58 %62 -%62 = OpLabel -%52 = OpIAdd %int %42 %int_1 -OpBranch %51 -%51 = OpLabel -OpBranch %49 -%54 = OpLabel -OpBranch %38 -%38 = OpLabel -%40 = OpIAdd %int %39 %int_1 -OpBranch %35 -%45 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_hoist, after_hoist, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_double_nested_loops.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_double_nested_loops.cpp deleted file mode 100644 index ea1949658..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_double_nested_loops.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/licm_pass.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Tests that the LICM pass will move invariants through multiple loops - - Generated from the following GLSL fragment shader ---eliminate-local-multi-store has also been run on the spv binary -#version 440 core -void main(){ - int a = 2; - int b = 1; - int hoist = 0; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - // hoist 'hoist = a - b' out of both loops - hoist = a - b; - } - } -} -*/ -TEST_F(PassClassTest, NestedDoubleHoist) { - const std::string before_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_2 = OpConstant %int 2 -%int_1 = OpConstant %int 1 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%12 = OpUndef %int -%main = OpFunction %void None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %int %int_0 %13 %16 %17 -%18 = OpPhi %int %int_0 %13 %19 %17 -%20 = OpPhi %int %12 %13 %21 %17 -OpLoopMerge %22 %17 None -OpBranch %23 -%23 = OpLabel -%24 = OpSLessThan %bool %18 %int_10 -OpBranchConditional %24 %25 %22 -%25 = OpLabel -OpBranch %26 -%26 = OpLabel -%16 = OpPhi %int %15 %25 %27 %28 -%21 = OpPhi %int %int_0 %25 %29 %28 -OpLoopMerge %30 %28 None -OpBranch %31 -%31 = OpLabel -%32 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %32 %33 %30 -%33 = OpLabel -%27 = OpISub %int %int_2 %int_1 -OpBranch %28 -%28 = OpLabel -%29 = OpIAdd %int %21 %int_1 -OpBranch %26 -%30 = OpLabel -OpBranch %17 -%17 = OpLabel -%19 = OpIAdd %int %18 %int_1 -OpBranch %14 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_2 = OpConstant %int 2 -%int_1 = OpConstant %int 1 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%12 = OpUndef %int -%main = OpFunction %void None %4 -%13 = OpLabel -%27 = OpISub %int %int_2 %int_1 -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %int %int_0 %13 %16 %17 -%18 = OpPhi %int %int_0 %13 %19 %17 -%20 = OpPhi %int %12 %13 %21 %17 -OpLoopMerge %22 %17 None -OpBranch %23 -%23 = OpLabel -%24 = OpSLessThan %bool %18 %int_10 -OpBranchConditional %24 %25 %22 -%25 = OpLabel -OpBranch %26 -%26 = OpLabel -%16 = OpPhi %int %15 %25 %27 %28 -%21 = OpPhi %int %int_0 %25 %29 %28 -OpLoopMerge %30 %28 None -OpBranch %31 -%31 = OpLabel -%32 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %32 %33 %30 -%33 = OpLabel -OpBranch %28 -%28 = OpLabel -%29 = OpIAdd %int %21 %int_1 -OpBranch %26 -%30 = OpLabel -OpBranch %17 -%17 = OpLabel -%19 = OpIAdd %int %18 %int_1 -OpBranch %14 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_hoist, after_hoist, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_from_independent_loops.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_from_independent_loops.cpp deleted file mode 100644 index abc79e37c..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_from_independent_loops.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/licm_pass.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Tests that the LICM pass will analyse multiple independent loops in a function - - Generated from the following GLSL fragment shader ---eliminate-local-multi-store has also been run on the spv binary -#version 440 core -void main(){ - int a = 1; - int b = 2; - int hoist = 0; - for (int i = 0; i < 10; i++) { - // invariant - hoist = a + b; - } - for (int i = 0; i < 10; i++) { - // invariant - hoist = a + b; - } - int c = 1; - int d = 2; - int hoist2 = 0; - for (int i = 0; i < 10; i++) { - // invariant - hoist2 = c + d; - } -} -*/ -TEST_F(PassClassTest, HoistFromIndependentLoops) { - const std::string before_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%main = OpFunction %void None %4 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%14 = OpPhi %int %int_0 %12 %15 %16 -%17 = OpPhi %int %int_0 %12 %18 %16 -OpLoopMerge %19 %16 None -OpBranch %20 -%20 = OpLabel -%21 = OpSLessThan %bool %17 %int_10 -OpBranchConditional %21 %22 %19 -%22 = OpLabel -%15 = OpIAdd %int %int_1 %int_2 -OpBranch %16 -%16 = OpLabel -%18 = OpIAdd %int %17 %int_1 -OpBranch %13 -%19 = OpLabel -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %int %14 %19 %25 %26 -%27 = OpPhi %int %int_0 %19 %28 %26 -OpLoopMerge %29 %26 None -OpBranch %30 -%30 = OpLabel -%31 = OpSLessThan %bool %27 %int_10 -OpBranchConditional %31 %32 %29 -%32 = OpLabel -%25 = OpIAdd %int %int_1 %int_2 -OpBranch %26 -%26 = OpLabel -%28 = OpIAdd %int %27 %int_1 -OpBranch %23 -%29 = OpLabel -OpBranch %33 -%33 = OpLabel -%34 = OpPhi %int %int_0 %29 %35 %36 -%37 = OpPhi %int %int_0 %29 %38 %36 -OpLoopMerge %39 %36 None -OpBranch %40 -%40 = OpLabel -%41 = OpSLessThan %bool %37 %int_10 -OpBranchConditional %41 %42 %39 -%42 = OpLabel -%35 = OpIAdd %int %int_1 %int_2 -OpBranch %36 -%36 = OpLabel -%38 = OpIAdd %int %37 %int_1 -OpBranch %33 -%39 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%main = OpFunction %void None %4 -%12 = OpLabel -%15 = OpIAdd %int %int_1 %int_2 -OpBranch %13 -%13 = OpLabel -%14 = OpPhi %int %int_0 %12 %15 %16 -%17 = OpPhi %int %int_0 %12 %18 %16 -OpLoopMerge %19 %16 None -OpBranch %20 -%20 = OpLabel -%21 = OpSLessThan %bool %17 %int_10 -OpBranchConditional %21 %22 %19 -%22 = OpLabel -OpBranch %16 -%16 = OpLabel -%18 = OpIAdd %int %17 %int_1 -OpBranch %13 -%19 = OpLabel -%25 = OpIAdd %int %int_1 %int_2 -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %int %14 %19 %25 %26 -%27 = OpPhi %int %int_0 %19 %28 %26 -OpLoopMerge %29 %26 None -OpBranch %30 -%30 = OpLabel -%31 = OpSLessThan %bool %27 %int_10 -OpBranchConditional %31 %32 %29 -%32 = OpLabel -OpBranch %26 -%26 = OpLabel -%28 = OpIAdd %int %27 %int_1 -OpBranch %23 -%29 = OpLabel -%35 = OpIAdd %int %int_1 %int_2 -OpBranch %33 -%33 = OpLabel -%34 = OpPhi %int %int_0 %29 %35 %36 -%37 = OpPhi %int %int_0 %29 %38 %36 -OpLoopMerge %39 %36 None -OpBranch %40 -%40 = OpLabel -%41 = OpSLessThan %bool %37 %int_10 -OpBranchConditional %41 %42 %39 -%42 = OpLabel -OpBranch %36 -%36 = OpLabel -%38 = OpIAdd %int %37 %int_1 -OpBranch %33 -%39 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_hoist, after_hoist, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_simple_case.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_simple_case.cpp deleted file mode 100644 index e973d9d29..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_simple_case.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/licm_pass.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - A simple test for the LICM pass - - Generated from the following GLSL fragment shader ---eliminate-local-multi-store has also been run on the spv binary -#version 440 core -void main(){ - int a = 1; - int b = 2; - int hoist = 0; - for (int i = 0; i < 10; i++) { - // invariant - hoist = a + b; - } -} -*/ -TEST_F(PassClassTest, SimpleHoist) { - const std::string before_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%main = OpFunction %void None %4 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%14 = OpPhi %int %int_0 %12 %15 %16 -%17 = OpPhi %int %int_0 %12 %18 %16 -OpLoopMerge %19 %16 None -OpBranch %20 -%20 = OpLabel -%21 = OpSLessThan %bool %17 %int_10 -OpBranchConditional %21 %22 %19 -%22 = OpLabel -%15 = OpIAdd %int %int_1 %int_2 -OpBranch %16 -%16 = OpLabel -%18 = OpIAdd %int %17 %int_1 -OpBranch %13 -%19 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%main = OpFunction %void None %4 -%12 = OpLabel -%15 = OpIAdd %int %int_1 %int_2 -OpBranch %13 -%13 = OpLabel -%14 = OpPhi %int %int_0 %12 %15 %16 -%17 = OpPhi %int %int_0 %12 %18 %16 -OpLoopMerge %19 %16 None -OpBranch %20 -%20 = OpLabel -%21 = OpSLessThan %bool %17 %int_10 -OpBranchConditional %21 %22 %19 -%22 = OpLabel -OpBranch %16 -%16 = OpLabel -%18 = OpIAdd %int %17 %int_1 -OpBranch %13 -%19 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_hoist, after_hoist, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_single_nested_loops.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_single_nested_loops.cpp deleted file mode 100644 index 056f3f025..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_single_nested_loops.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/licm_pass.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; - -using PassClassTest = PassTest<::testing::Test>; - -/* - Tests that the LICM pass will detect an move an invariant from a nested loop, - but not it's parent loop - - Generated from the following GLSL fragment shader ---eliminate-local-multi-store has also been run on the spv binary -#version 440 core -void main(){ - int a = 2; - int hoist = 0; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - // hoist 'hoist = a - i' out of j loop, but not i loop - hoist = a - i; - } - } -} -*/ -TEST_F(PassClassTest, NestedSingleHoist) { - const std::string before_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_1 = OpConstant %int 1 -%12 = OpUndef %int -%main = OpFunction %void None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %int %int_0 %13 %16 %17 -%18 = OpPhi %int %int_0 %13 %19 %17 -%20 = OpPhi %int %12 %13 %21 %17 -OpLoopMerge %22 %17 None -OpBranch %23 -%23 = OpLabel -%24 = OpSLessThan %bool %18 %int_10 -OpBranchConditional %24 %25 %22 -%25 = OpLabel -OpBranch %26 -%26 = OpLabel -%16 = OpPhi %int %15 %25 %27 %28 -%21 = OpPhi %int %int_0 %25 %29 %28 -OpLoopMerge %30 %28 None -OpBranch %31 -%31 = OpLabel -%32 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %32 %33 %30 -%33 = OpLabel -%27 = OpISub %int %int_2 %18 -OpBranch %28 -%28 = OpLabel -%29 = OpIAdd %int %21 %int_1 -OpBranch %26 -%30 = OpLabel -OpBranch %17 -%17 = OpLabel -%19 = OpIAdd %int %18 %int_1 -OpBranch %14 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after_hoist = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_1 = OpConstant %int 1 -%12 = OpUndef %int -%main = OpFunction %void None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %int %int_0 %13 %16 %17 -%18 = OpPhi %int %int_0 %13 %19 %17 -%20 = OpPhi %int %12 %13 %21 %17 -OpLoopMerge %22 %17 None -OpBranch %23 -%23 = OpLabel -%24 = OpSLessThan %bool %18 %int_10 -OpBranchConditional %24 %25 %22 -%25 = OpLabel -%27 = OpISub %int %int_2 %18 -OpBranch %26 -%26 = OpLabel -%16 = OpPhi %int %15 %25 %27 %28 -%21 = OpPhi %int %int_0 %25 %29 %28 -OpLoopMerge %30 %28 None -OpBranch %31 -%31 = OpLabel -%32 = OpSLessThan %bool %21 %int_10 -OpBranchConditional %32 %33 %30 -%33 = OpLabel -OpBranch %28 -%28 = OpLabel -%29 = OpIAdd %int %21 %int_1 -OpBranch %26 -%30 = OpLabel -OpBranch %17 -%17 = OpLabel -%19 = OpIAdd %int %18 %int_1 -OpBranch %14 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_hoist, after_hoist, true); -} - -TEST_F(PassClassTest, PreHeaderIsAlsoHeader) { - // Move OpSLessThan out of the inner loop. The preheader for the inner loop - // is the header of the outer loop. The loop merge should not be separated - // from the branch in that block. - const std::string text = R"( - ; CHECK: OpFunction - ; CHECK-NEXT: OpLabel - ; CHECK-NEXT: OpBranch [[header:%\w+]] - ; CHECK: [[header]] = OpLabel - ; CHECK-NEXT: OpSLessThan %bool %int_1 %int_1 - ; CHECK-NEXT: OpLoopMerge - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %int_1 = OpConstant %int 1 - %bool = OpTypeBool - %2 = OpFunction %void None %4 - %18 = OpLabel - OpBranch %21 - %21 = OpLabel - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %25 = OpSLessThan %bool %int_1 %int_1 - OpLoopMerge %26 %27 None - OpBranchConditional %25 %27 %26 - %27 = OpLabel - OpBranch %24 - %26 = OpLabel - OpBranch %22 - %23 = OpLabel - OpBranch %21 - %22 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_without_preheader.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_without_preheader.cpp deleted file mode 100644 index 2e34b0142..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/hoist_without_preheader.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/licm_pass.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* - Tests that the LICM pass will generate a preheader when one is not present - - Generated from the following GLSL fragment shader ---eliminate-local-multi-store has also been run on the spv binary -#version 440 core -void main(){ - int a = 1; - int b = 2; - int hoist = 0; - for (int i = 0; i < 10; i++) { - if (i == 5) { - break; - } - } - for (int i = 0; i < 10; i++) { - hoist = a + b; - } -} -*/ -TEST_F(PassClassTest, HoistWithoutPreheader) { - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_5 = OpConstant %int 5 -%main = OpFunction %void None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %int %int_0 %13 %16 %17 -; CHECK: OpLoopMerge [[preheader:%\w+]] -OpLoopMerge %25 %17 None -OpBranch %19 -%19 = OpLabel -%20 = OpSLessThan %bool %15 %int_10 -OpBranchConditional %20 %21 %25 -%21 = OpLabel -%22 = OpIEqual %bool %15 %int_5 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %23 -%24 = OpLabel -OpBranch %25 -%23 = OpLabel -OpBranch %17 -%17 = OpLabel -%16 = OpIAdd %int %15 %int_1 -OpBranch %14 -; Check that we hoisted the code to the preheader -; CHECK: [[preheader]] = OpLabel -; CHECK-NEXT: OpPhi -; CHECK-NEXT: OpPhi -; CHECK-NEXT: OpIAdd -; CHECK-NEXT: OpBranch [[header:%\w+]] -; CHECK: [[header]] = OpLabel -; CHECK-NEXT: OpPhi -; CHECK-NEXT: OpPhi -; CHECK: OpLoopMerge -%25 = OpLabel -%26 = OpPhi %int %int_0 %24 %int_0 %19 %27 %28 -%29 = OpPhi %int %int_0 %24 %int_0 %19 %30 %28 -OpLoopMerge %31 %28 None -OpBranch %32 -%32 = OpLabel -%33 = OpSLessThan %bool %29 %int_10 -OpBranchConditional %33 %34 %31 -%34 = OpLabel -%27 = OpIAdd %int %int_1 %int_2 -OpBranch %28 -%28 = OpLabel -%30 = OpIAdd %int %29 %int_1 -OpBranch %25 -%31 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(PassClassTest, HoistWithoutPreheaderAtIdBound) { - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 440 -OpName %main "main" -%void = OpTypeVoid -%4 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_0 = OpConstant %int 0 -%int_10 = OpConstant %int 10 -%bool = OpTypeBool -%int_5 = OpConstant %int 5 -%main = OpFunction %void None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %int %int_0 %13 %16 %17 -OpLoopMerge %25 %17 None -OpBranch %19 -%19 = OpLabel -%20 = OpSLessThan %bool %15 %int_10 -OpBranchConditional %20 %21 %25 -%21 = OpLabel -%22 = OpIEqual %bool %15 %int_5 -OpSelectionMerge %23 None -OpBranchConditional %22 %24 %23 -%24 = OpLabel -OpBranch %25 -%23 = OpLabel -OpBranch %17 -%17 = OpLabel -%16 = OpIAdd %int %15 %int_1 -OpBranch %14 -%25 = OpLabel -%26 = OpPhi %int %int_0 %24 %int_0 %19 %27 %28 -%29 = OpPhi %int %int_0 %24 %int_0 %19 %30 %28 -OpLoopMerge %31 %28 None -OpBranch %32 -%32 = OpLabel -%33 = OpSLessThan %bool %29 %int_10 -OpBranchConditional %33 %34 %31 -%34 = OpLabel -%27 = OpIAdd %int %int_1 %int_2 -OpBranch %28 -%28 = OpLabel -%30 = OpIAdd %int %29 %int_1 -OpBranch %25 -%31 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound); - - auto pass = MakeUnique(); - auto result = pass->Run(context.get()); - EXPECT_EQ(result, Pass::Status::Failure); - - std::vector binary; - context->module()->ToBinary(&binary, false); - std::string optimized_asm; - SpirvTools tools_(SPV_ENV_UNIVERSAL_1_1); - tools_.Disassemble(binary, &optimized_asm); - std::cout << optimized_asm << std::endl; -} -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/lcssa.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/lcssa.cpp deleted file mode 100644 index ace6ce196..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/lcssa.cpp +++ /dev/null @@ -1,607 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "effcee/effcee.h" -#include "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/loop_utils.h" -#include "source/opt/pass.h" -#include "test/opt//assembly_builder.h" -#include "test/opt/function_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -bool Validate(const std::vector& bin) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - spv_context spvContext = spvContextCreate(target_env); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {bin.data(), bin.size()}; - spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - return error == 0; -} - -void Match(const std::string& original, IRContext* context, - bool do_validation = true) { - std::vector bin; - context->module()->ToBinary(&bin, true); - if (do_validation) { - EXPECT_TRUE(Validate(bin)); - } - std::string assembly; - SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); - EXPECT_TRUE( - tools.Disassemble(bin, &assembly, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) - << "Disassembling failed for shader:\n" - << assembly << std::endl; - auto match_result = effcee::Match(assembly, original); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking result:\n" - << assembly; -} - -using LCSSATest = ::testing::Test; - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - for (; i < 10; i++) { - } - if (i != 0) { - i = 1; - } -} -*/ -TEST_F(LCSSATest, SimpleLCSSA) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] %19 None -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} %30 %20 -; CHECK-NEXT: %27 = OpINotEqual {{%\w+}} [[phi]] %9 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %3 "c" - OpDecorate %3 Location 0 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeInt 32 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %10 = OpConstant %7 10 - %11 = OpTypeBool - %12 = OpConstant %7 1 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Output %14 - %3 = OpVariable %15 Output - %2 = OpFunction %5 None %6 - %16 = OpLabel - OpBranch %17 - %17 = OpLabel - %30 = OpPhi %7 %9 %16 %25 %19 - OpLoopMerge %18 %19 None - OpBranch %20 - %20 = OpLabel - %22 = OpSLessThan %11 %30 %10 - OpBranchConditional %22 %23 %18 - %23 = OpLabel - OpBranch %19 - %19 = OpLabel - %25 = OpIAdd %7 %30 %12 - OpBranch %17 - %18 = OpLabel - %27 = OpINotEqual %11 %30 %9 - OpSelectionMerge %28 None - OpBranchConditional %27 %29 %28 - %29 = OpLabel - OpBranch %28 - %28 = OpLabel - %31 = OpPhi %7 %30 %18 %12 %29 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - Loop* loop = ld[17]; - EXPECT_FALSE(loop->IsLCSSA()); - LoopUtils Util(context.get(), loop); - Util.MakeLoopClosedSSA(); - EXPECT_TRUE(loop->IsLCSSA()); - Match(text, context.get()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - for (; i < 10; i++) { - } - if (i != 0) { - i = 1; - } -} -*/ -// Same test as above, but should reuse an existing phi. -TEST_F(LCSSATest, PhiReuseLCSSA) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] %19 None -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} %30 %20 -; CHECK-NEXT: %27 = OpINotEqual {{%\w+}} [[phi]] %9 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %3 "c" - OpDecorate %3 Location 0 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeInt 32 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %10 = OpConstant %7 10 - %11 = OpTypeBool - %12 = OpConstant %7 1 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Output %14 - %3 = OpVariable %15 Output - %2 = OpFunction %5 None %6 - %16 = OpLabel - OpBranch %17 - %17 = OpLabel - %30 = OpPhi %7 %9 %16 %25 %19 - OpLoopMerge %18 %19 None - OpBranch %20 - %20 = OpLabel - %22 = OpSLessThan %11 %30 %10 - OpBranchConditional %22 %23 %18 - %23 = OpLabel - OpBranch %19 - %19 = OpLabel - %25 = OpIAdd %7 %30 %12 - OpBranch %17 - %18 = OpLabel - %32 = OpPhi %7 %30 %20 - %27 = OpINotEqual %11 %30 %9 - OpSelectionMerge %28 None - OpBranchConditional %27 %29 %28 - %29 = OpLabel - OpBranch %28 - %28 = OpLabel - %31 = OpPhi %7 %30 %18 %12 %29 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - Loop* loop = ld[17]; - EXPECT_FALSE(loop->IsLCSSA()); - LoopUtils Util(context.get(), loop); - Util.MakeLoopClosedSSA(); - EXPECT_TRUE(loop->IsLCSSA()); - Match(text, context.get()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - int j = 0; - for (; i < 10; i++) {} - for (; j < 10; j++) {} - if (j != 0) { - i = 1; - } -} -*/ -TEST_F(LCSSATest, DualLoopLCSSA) { - const std::string text = R"( -; CHECK: %20 = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi %6 %17 %21 -; CHECK: %33 = OpLabel -; CHECK-NEXT: {{%\w+}} = OpPhi {{%\w+}} [[phi]] %28 %11 %34 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %3 "c" - OpDecorate %3 Location 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpConstant %6 0 - %9 = OpConstant %6 10 - %10 = OpTypeBool - %11 = OpConstant %6 1 - %12 = OpTypeFloat 32 - %13 = OpTypeVector %12 4 - %14 = OpTypePointer Output %13 - %3 = OpVariable %14 Output - %2 = OpFunction %4 None %5 - %15 = OpLabel - OpBranch %16 - %16 = OpLabel - %17 = OpPhi %6 %8 %15 %18 %19 - OpLoopMerge %20 %19 None - OpBranch %21 - %21 = OpLabel - %22 = OpSLessThan %10 %17 %9 - OpBranchConditional %22 %23 %20 - %23 = OpLabel - OpBranch %19 - %19 = OpLabel - %18 = OpIAdd %6 %17 %11 - OpBranch %16 - %20 = OpLabel - OpBranch %24 - %24 = OpLabel - %25 = OpPhi %6 %8 %20 %26 %27 - OpLoopMerge %28 %27 None - OpBranch %29 - %29 = OpLabel - %30 = OpSLessThan %10 %25 %9 - OpBranchConditional %30 %31 %28 - %31 = OpLabel - OpBranch %27 - %27 = OpLabel - %26 = OpIAdd %6 %25 %11 - OpBranch %24 - %28 = OpLabel - %32 = OpINotEqual %10 %25 %8 - OpSelectionMerge %33 None - OpBranchConditional %32 %34 %33 - %34 = OpLabel - OpBranch %33 - %33 = OpLabel - %35 = OpPhi %6 %17 %28 %11 %34 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - Loop* loop = ld[16]; - EXPECT_FALSE(loop->IsLCSSA()); - LoopUtils Util(context.get(), loop); - Util.MakeLoopClosedSSA(); - EXPECT_TRUE(loop->IsLCSSA()); - Match(text, context.get()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - if (i != 0) { - for (; i < 10; i++) {} - } - if (i != 0) { - i = 1; - } -} -*/ -TEST_F(LCSSATest, PhiUserLCSSA) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] %22 None -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} %20 %24 -; CHECK: %17 = OpLabel -; CHECK-NEXT: {{%\w+}} = OpPhi {{%\w+}} %8 %15 [[phi]] %23 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %3 "c" - OpDecorate %3 Location 0 - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpConstant %6 0 - %9 = OpTypeBool - %10 = OpConstant %6 10 - %11 = OpConstant %6 1 - %12 = OpTypeFloat 32 - %13 = OpTypeVector %12 4 - %14 = OpTypePointer Output %13 - %3 = OpVariable %14 Output - %2 = OpFunction %4 None %5 - %15 = OpLabel - %16 = OpINotEqual %9 %8 %8 - OpSelectionMerge %17 None - OpBranchConditional %16 %18 %17 - %18 = OpLabel - OpBranch %19 - %19 = OpLabel - %20 = OpPhi %6 %8 %18 %21 %22 - OpLoopMerge %23 %22 None - OpBranch %24 - %24 = OpLabel - %25 = OpSLessThan %9 %20 %10 - OpBranchConditional %25 %26 %23 - %26 = OpLabel - OpBranch %22 - %22 = OpLabel - %21 = OpIAdd %6 %20 %11 - OpBranch %19 - %23 = OpLabel - OpBranch %17 - %17 = OpLabel - %27 = OpPhi %6 %8 %15 %20 %23 - %28 = OpINotEqual %9 %27 %8 - OpSelectionMerge %29 None - OpBranchConditional %28 %30 %29 - %30 = OpLabel - OpBranch %29 - %29 = OpLabel - %31 = OpPhi %6 %27 %17 %11 %30 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - Loop* loop = ld[19]; - EXPECT_FALSE(loop->IsLCSSA()); - LoopUtils Util(context.get(), loop); - Util.MakeLoopClosedSSA(); - EXPECT_TRUE(loop->IsLCSSA()); - Match(text, context.get()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -void main() { - int i = 0; - if (i != 0) { - for (; i < 10; i++) { - if (i > 5) break; - } - } - if (i != 0) { - i = 1; - } -} -*/ -TEST_F(LCSSATest, LCSSAWithBreak) { - const std::string text = R"( -; CHECK: OpLoopMerge [[merge:%\w+]] %19 None -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} %17 %21 %17 %26 -; CHECK: %14 = OpLabel -; CHECK-NEXT: {{%\w+}} = OpPhi {{%\w+}} %7 %12 [[phi]] [[merge]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpConstant %5 0 - %8 = OpTypeBool - %9 = OpConstant %5 10 - %10 = OpConstant %5 5 - %11 = OpConstant %5 1 - %2 = OpFunction %3 None %4 - %12 = OpLabel - %13 = OpINotEqual %8 %7 %7 - OpSelectionMerge %14 None - OpBranchConditional %13 %15 %14 - %15 = OpLabel - OpBranch %16 - %16 = OpLabel - %17 = OpPhi %5 %7 %15 %18 %19 - OpLoopMerge %20 %19 None - OpBranch %21 - %21 = OpLabel - %22 = OpSLessThan %8 %17 %9 - OpBranchConditional %22 %23 %20 - %23 = OpLabel - %24 = OpSGreaterThan %8 %17 %10 - OpSelectionMerge %25 None - OpBranchConditional %24 %26 %25 - %26 = OpLabel - OpBranch %20 - %25 = OpLabel - OpBranch %19 - %19 = OpLabel - %18 = OpIAdd %5 %17 %11 - OpBranch %16 - %20 = OpLabel - OpBranch %14 - %14 = OpLabel - %27 = OpPhi %5 %7 %12 %17 %20 - %28 = OpINotEqual %8 %27 %7 - OpSelectionMerge %29 None - OpBranchConditional %28 %30 %29 - %30 = OpLabel - OpBranch %29 - %29 = OpLabel - %31 = OpPhi %5 %27 %14 %11 %30 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - Loop* loop = ld[19]; - EXPECT_FALSE(loop->IsLCSSA()); - LoopUtils Util(context.get(), loop); - Util.MakeLoopClosedSSA(); - EXPECT_TRUE(loop->IsLCSSA()); - Match(text, context.get()); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -void main() { - int i = 0; - for (; i < 10; i++) {} - for (int j = i; j < 10;) { j = i + j; } -} -*/ -TEST_F(LCSSATest, LCSSAUseInNonEligiblePhi) { - const std::string text = R"( -; CHECK: %12 = OpLabel -; CHECK-NEXT: [[def_to_close:%\w+]] = OpPhi {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[closing_phi:%\w+]] = OpPhi {{%\w+}} [[def_to_close]] %17 -; CHECK: %16 = OpLabel -; CHECK-NEXT: [[use_in_phi:%\w+]] = OpPhi {{%\w+}} %21 %22 [[closing_phi]] [[merge]] -; CHECK: OpIAdd {{%\w+}} [[closing_phi]] [[use_in_phi]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpConstant %5 0 - %8 = OpConstant %5 10 - %9 = OpTypeBool - %10 = OpConstant %5 1 - %2 = OpFunction %3 None %4 - %11 = OpLabel - OpBranch %12 - %12 = OpLabel - %13 = OpPhi %5 %7 %11 %14 %15 - OpLoopMerge %16 %15 None - OpBranch %17 - %17 = OpLabel - %18 = OpSLessThan %9 %13 %8 - OpBranchConditional %18 %19 %16 - %19 = OpLabel - OpBranch %15 - %15 = OpLabel - %14 = OpIAdd %5 %13 %10 - OpBranch %12 - %16 = OpLabel - %20 = OpPhi %5 %13 %17 %21 %22 - OpLoopMerge %23 %22 None - OpBranch %24 - %24 = OpLabel - %25 = OpSLessThan %9 %20 %8 - OpBranchConditional %25 %26 %23 - %26 = OpLabel - %21 = OpIAdd %5 %13 %20 - OpBranch %22 - %22 = OpLabel - OpBranch %16 - %23 = OpLabel - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - Loop* loop = ld[12]; - EXPECT_FALSE(loop->IsLCSSA()); - LoopUtils Util(context.get(), loop); - Util.MakeLoopClosedSSA(); - EXPECT_TRUE(loop->IsLCSSA()); - Match(text, context.get()); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/loop_descriptions.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/loop_descriptions.cpp deleted file mode 100644 index 91dbdc6b5..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/loop_descriptions.cpp +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - for(; i < 10; ++i) { - } -} -*/ -TEST_F(PassClassTest, BasicVisitFromEntryPoint) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %5 "i" - OpName %3 "c" - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpConstant %8 1 - %14 = OpTypeFloat 32 - %15 = OpTypeVector %14 4 - %16 = OpTypePointer Output %15 - %3 = OpVariable %16 Output - %2 = OpFunction %6 None %7 - %17 = OpLabel - %5 = OpVariable %9 Function - OpStore %5 %10 - OpBranch %18 - %18 = OpLabel - OpLoopMerge %19 %20 None - OpBranch %21 - %21 = OpLabel - %22 = OpLoad %8 %5 - %23 = OpSLessThan %12 %22 %11 - OpBranchConditional %23 %24 %19 - %24 = OpLabel - OpBranch %20 - %20 = OpLabel - %25 = OpLoad %8 %5 - %26 = OpIAdd %8 %25 %13 - OpStore %5 %26 - OpBranch %18 - %19 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - Loop& loop = ld.GetLoopByIndex(0); - EXPECT_EQ(loop.GetHeaderBlock(), spvtest::GetBasicBlock(f, 18)); - EXPECT_EQ(loop.GetLatchBlock(), spvtest::GetBasicBlock(f, 20)); - EXPECT_EQ(loop.GetMergeBlock(), spvtest::GetBasicBlock(f, 19)); - - EXPECT_FALSE(loop.HasNestedLoops()); - EXPECT_FALSE(loop.IsNested()); - EXPECT_EQ(loop.GetDepth(), 1u); -} - -/* -Generated from the following GLSL: -#version 330 core -layout(location = 0) out vec4 c; -void main() { - for(int i = 0; i < 10; ++i) {} - for(int i = 0; i < 10; ++i) {} -} - -But it was "hacked" to make the first loop merge block the second loop header. -*/ -TEST_F(PassClassTest, LoopWithNoPreHeader) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - OpName %5 "i" - OpName %3 "c" - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpConstant %8 1 - %14 = OpTypeFloat 32 - %15 = OpTypeVector %14 4 - %16 = OpTypePointer Output %15 - %3 = OpVariable %16 Output - %2 = OpFunction %6 None %7 - %17 = OpLabel - %4 = OpVariable %9 Function - %5 = OpVariable %9 Function - OpStore %4 %10 - OpStore %5 %10 - OpBranch %18 - %18 = OpLabel - OpLoopMerge %27 %20 None - OpBranch %21 - %21 = OpLabel - %22 = OpLoad %8 %4 - %23 = OpSLessThan %12 %22 %11 - OpBranchConditional %23 %24 %27 - %24 = OpLabel - OpBranch %20 - %20 = OpLabel - %25 = OpLoad %8 %4 - %26 = OpIAdd %8 %25 %13 - OpStore %4 %26 - OpBranch %18 - %27 = OpLabel - OpLoopMerge %28 %29 None - OpBranch %30 - %30 = OpLabel - %31 = OpLoad %8 %5 - %32 = OpSLessThan %12 %31 %11 - OpBranchConditional %32 %33 %28 - %33 = OpLabel - OpBranch %29 - %29 = OpLabel - %34 = OpLoad %8 %5 - %35 = OpIAdd %8 %34 %13 - OpStore %5 %35 - OpBranch %27 - %28 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - EXPECT_EQ(ld.NumLoops(), 2u); - - Loop* loop = ld[27]; - EXPECT_EQ(loop->GetPreHeaderBlock(), nullptr); - EXPECT_NE(loop->GetOrCreatePreHeaderBlock(), nullptr); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -in vec4 c; -void main() { - int i = 0; - bool cond = c[0] == 0; - for (; i < 10; i++) { - if (cond) { - return; - } - else { - return; - } - } - bool cond2 = i == 9; -} -*/ -TEST_F(PassClassTest, NoLoop) { - const std::string text = R"(; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 3 -; Bound: 47 -; Schema: 0 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %16 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 330 - OpName %4 "main" - OpName %16 "c" - OpDecorate %16 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %10 = OpTypeBool - %11 = OpTypePointer Function %10 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Input %14 - %16 = OpVariable %15 Input - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 0 - %19 = OpTypePointer Input %13 - %22 = OpConstant %13 0 - %30 = OpConstant %6 10 - %39 = OpConstant %6 1 - %46 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %20 = OpAccessChain %19 %16 %18 - %21 = OpLoad %13 %20 - %23 = OpFOrdEqual %10 %21 %22 - OpBranch %24 - %24 = OpLabel - %45 = OpPhi %6 %9 %5 %40 %27 - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %31 = OpSLessThan %10 %45 %30 - OpBranchConditional %31 %25 %26 - %25 = OpLabel - OpSelectionMerge %34 None - OpBranchConditional %23 %33 %36 - %33 = OpLabel - OpReturn - %36 = OpLabel - OpReturn - %34 = OpLabel - OpBranch %27 - %27 = OpLabel - %40 = OpIAdd %6 %46 %39 - OpBranch %24 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor ld{context.get(), f}; - - EXPECT_EQ(ld.NumLoops(), 0u); -} - -/* -Generated from following GLSL with latch block artificially inserted to be -seperate from continue. -#version 430 -void main(void) { - float x[10]; - for (int i = 0; i < 10; ++i) { - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, LoopLatchNotContinue) { - const std::string text = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "x" - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeInt 32 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %10 = OpConstant %7 10 - %11 = OpTypeBool - %12 = OpTypeFloat 32 - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 10 - %15 = OpTypeArray %12 %14 - %16 = OpTypePointer Function %15 - %17 = OpTypePointer Function %12 - %18 = OpConstant %7 1 - %2 = OpFunction %5 None %6 - %19 = OpLabel - %3 = OpVariable %8 Function - %4 = OpVariable %16 Function - OpStore %3 %9 - OpBranch %20 - %20 = OpLabel - %21 = OpPhi %7 %9 %19 %22 %30 - OpLoopMerge %24 %23 None - OpBranch %25 - %25 = OpLabel - %26 = OpSLessThan %11 %21 %10 - OpBranchConditional %26 %27 %24 - %27 = OpLabel - %28 = OpConvertSToF %12 %21 - %29 = OpAccessChain %17 %4 %21 - OpStore %29 %28 - OpBranch %23 - %23 = OpLabel - %22 = OpIAdd %7 %21 %18 - OpStore %3 %22 - OpBranch %30 - %30 = OpLabel - OpBranch %20 - %24 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - EXPECT_EQ(ld.NumLoops(), 1u); - - Loop& loop = ld.GetLoopByIndex(0u); - - EXPECT_NE(loop.GetLatchBlock(), loop.GetContinueBlock()); - - EXPECT_EQ(loop.GetContinueBlock()->id(), 23u); - EXPECT_EQ(loop.GetLatchBlock()->id(), 30u); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/loop_fission.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/loop_fission.cpp deleted file mode 100644 index e513f4253..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/loop_fission.cpp +++ /dev/null @@ -1,3491 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/loop_fission.h" -#include "source/opt/loop_unroller.h" -#include "source/opt/loop_utils.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using FissionClassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL - -#version 430 - -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - A[i] = B[i]; - B[i] = A[i]; - } -} - -Result should be equivalent to: - -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - A[i] = B[i]; - } - - for (int i = 0; i < 10; i++) { - B[i] = A[i]; - } -} -*/ -TEST_F(FissionClassTest, SimpleFission) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "A" -OpName %5 "B" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %20 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%29 = OpAccessChain %18 %5 %22 -%30 = OpLoad %13 %29 -%31 = OpAccessChain %18 %4 %22 -OpStore %31 %30 -%32 = OpAccessChain %18 %4 %22 -%33 = OpLoad %13 %32 -%34 = OpAccessChain %18 %5 %22 -OpStore %34 %33 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - -const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "A" -OpName %5 "B" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpBranch %35 -%35 = OpLabel -%36 = OpPhi %8 %10 %20 %47 %46 -OpLoopMerge %48 %46 None -OpBranch %37 -%37 = OpLabel -%38 = OpSLessThan %12 %36 %11 -OpBranchConditional %38 %39 %48 -%39 = OpLabel -%40 = OpAccessChain %18 %5 %36 -%41 = OpLoad %13 %40 -%42 = OpAccessChain %18 %4 %36 -OpStore %42 %41 -OpBranch %46 -%46 = OpLabel -%47 = OpIAdd %8 %36 %19 -OpBranch %35 -%48 = OpLabel -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %48 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%32 = OpAccessChain %18 %4 %22 -%33 = OpLoad %13 %32 -%34 = OpAccessChain %18 %5 %22 -OpStore %34 %33 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); - - // Check that the loop will NOT be split when provided with a pass-through - // register pressure functor which just returns false. - SinglePassRunAndCheck( - source, source, true, - [](const RegisterLiveness::RegionRegisterLiveness&) { return false; }); -} - -/* -Generated from the following GLSL - -#version 430 - -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - A[i] = B[i]; - B[i] = A[i+1]; - } -} - -This loop should not be split, as the i+1 dependence would be broken by -splitting the loop. -*/ - -TEST_F(FissionClassTest, FissionInterdependency) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "A" -OpName %5 "B" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %20 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%29 = OpAccessChain %18 %5 %22 -%30 = OpLoad %13 %29 -%31 = OpAccessChain %18 %4 %22 -OpStore %31 %30 -%32 = OpIAdd %8 %22 %19 -%33 = OpAccessChain %18 %4 %32 -%34 = OpLoad %13 %33 -%35 = OpAccessChain %18 %5 %22 -OpStore %35 %34 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -Generated from the following GLSL - -#version 430 - -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - A[i] = B[i]; - B[i+1] = A[i]; - } -} - - -This should not be split as the load B[i] is dependent on the store B[i+1] -*/ -TEST_F(FissionClassTest, FissionInterdependency2) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "A" -OpName %5 "B" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %20 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%29 = OpAccessChain %18 %5 %22 -%30 = OpLoad %13 %29 -%31 = OpAccessChain %18 %4 %22 -OpStore %31 %30 -%32 = OpIAdd %8 %22 %19 -%33 = OpAccessChain %18 %4 %22 -%34 = OpLoad %13 %33 -%35 = OpAccessChain %18 %5 %32 -OpStore %35 %34 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -void main(void) { - float A[10]; - float B[10]; - float C[10] - float D[10] - for (int i = 0; i < 10; i++) { - A[i] = B[i]; - B[i] = A[i]; - C[i] = D[i]; - D[i] = C[i]; - } -} - -This should be split into the equivalent of: - - for (int i = 0; i < 10; i++) { - A[i] = B[i]; - B[i] = A[i]; - } - for (int i = 0; i < 10; i++) { - C[i] = D[i]; - D[i] = C[i]; - } - -We then check that the loop is broken into four for loops like so, if the pass -is run twice: - for (int i = 0; i < 10; i++) - A[i] = B[i]; - for (int i = 0; i < 10; i++) - B[i] = A[i]; - for (int i = 0; i < 10; i++) - C[i] = D[i]; - for (int i = 0; i < 10; i++) - D[i] = C[i]; - -*/ - -TEST_F(FissionClassTest, FissionMultipleLoadStores) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "A" - OpName %5 "B" - OpName %6 "C" - OpName %7 "D" - %8 = OpTypeVoid - %9 = OpTypeFunction %8 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %12 = OpConstant %10 0 - %13 = OpConstant %10 10 - %14 = OpTypeBool - %15 = OpTypeFloat 32 - %16 = OpTypeInt 32 0 - %17 = OpConstant %16 10 - %18 = OpTypeArray %15 %17 - %19 = OpTypePointer Function %18 - %20 = OpTypePointer Function %15 - %21 = OpConstant %10 1 - %2 = OpFunction %8 None %9 - %22 = OpLabel - %3 = OpVariable %11 Function - %4 = OpVariable %19 Function - %5 = OpVariable %19 Function - %6 = OpVariable %19 Function - %7 = OpVariable %19 Function - OpBranch %23 - %23 = OpLabel - %24 = OpPhi %10 %12 %22 %25 %26 - OpLoopMerge %27 %26 None - OpBranch %28 - %28 = OpLabel - %29 = OpSLessThan %14 %24 %13 - OpBranchConditional %29 %30 %27 - %30 = OpLabel - %31 = OpAccessChain %20 %5 %24 - %32 = OpLoad %15 %31 - %33 = OpAccessChain %20 %4 %24 - OpStore %33 %32 - %34 = OpAccessChain %20 %4 %24 - %35 = OpLoad %15 %34 - %36 = OpAccessChain %20 %5 %24 - OpStore %36 %35 - %37 = OpAccessChain %20 %7 %24 - %38 = OpLoad %15 %37 - %39 = OpAccessChain %20 %6 %24 - OpStore %39 %38 - %40 = OpAccessChain %20 %6 %24 - %41 = OpLoad %15 %40 - %42 = OpAccessChain %20 %7 %24 - OpStore %42 %41 - OpBranch %26 - %26 = OpLabel - %25 = OpIAdd %10 %24 %21 - OpBranch %23 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "A" -OpName %5 "B" -OpName %6 "C" -OpName %7 "D" -%8 = OpTypeVoid -%9 = OpTypeFunction %8 -%10 = OpTypeInt 32 1 -%11 = OpTypePointer Function %10 -%12 = OpConstant %10 0 -%13 = OpConstant %10 10 -%14 = OpTypeBool -%15 = OpTypeFloat 32 -%16 = OpTypeInt 32 0 -%17 = OpConstant %16 10 -%18 = OpTypeArray %15 %17 -%19 = OpTypePointer Function %18 -%20 = OpTypePointer Function %15 -%21 = OpConstant %10 1 -%2 = OpFunction %8 None %9 -%22 = OpLabel -%3 = OpVariable %11 Function -%4 = OpVariable %19 Function -%5 = OpVariable %19 Function -%6 = OpVariable %19 Function -%7 = OpVariable %19 Function -OpBranch %43 -%43 = OpLabel -%44 = OpPhi %10 %12 %22 %61 %60 -OpLoopMerge %62 %60 None -OpBranch %45 -%45 = OpLabel -%46 = OpSLessThan %14 %44 %13 -OpBranchConditional %46 %47 %62 -%47 = OpLabel -%48 = OpAccessChain %20 %5 %44 -%49 = OpLoad %15 %48 -%50 = OpAccessChain %20 %4 %44 -OpStore %50 %49 -%51 = OpAccessChain %20 %4 %44 -%52 = OpLoad %15 %51 -%53 = OpAccessChain %20 %5 %44 -OpStore %53 %52 -OpBranch %60 -%60 = OpLabel -%61 = OpIAdd %10 %44 %21 -OpBranch %43 -%62 = OpLabel -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %10 %12 %62 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %14 %24 %13 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -%37 = OpAccessChain %20 %7 %24 -%38 = OpLoad %15 %37 -%39 = OpAccessChain %20 %6 %24 -OpStore %39 %38 -%40 = OpAccessChain %20 %6 %24 -%41 = OpLoad %15 %40 -%42 = OpAccessChain %20 %7 %24 -OpStore %42 %41 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %10 %24 %21 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - -const std::string expected_multiple_passes = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "A" -OpName %5 "B" -OpName %6 "C" -OpName %7 "D" -%8 = OpTypeVoid -%9 = OpTypeFunction %8 -%10 = OpTypeInt 32 1 -%11 = OpTypePointer Function %10 -%12 = OpConstant %10 0 -%13 = OpConstant %10 10 -%14 = OpTypeBool -%15 = OpTypeFloat 32 -%16 = OpTypeInt 32 0 -%17 = OpConstant %16 10 -%18 = OpTypeArray %15 %17 -%19 = OpTypePointer Function %18 -%20 = OpTypePointer Function %15 -%21 = OpConstant %10 1 -%2 = OpFunction %8 None %9 -%22 = OpLabel -%3 = OpVariable %11 Function -%4 = OpVariable %19 Function -%5 = OpVariable %19 Function -%6 = OpVariable %19 Function -%7 = OpVariable %19 Function -OpBranch %63 -%63 = OpLabel -%64 = OpPhi %10 %12 %22 %75 %74 -OpLoopMerge %76 %74 None -OpBranch %65 -%65 = OpLabel -%66 = OpSLessThan %14 %64 %13 -OpBranchConditional %66 %67 %76 -%67 = OpLabel -%68 = OpAccessChain %20 %5 %64 -%69 = OpLoad %15 %68 -%70 = OpAccessChain %20 %4 %64 -OpStore %70 %69 -OpBranch %74 -%74 = OpLabel -%75 = OpIAdd %10 %64 %21 -OpBranch %63 -%76 = OpLabel -OpBranch %43 -%43 = OpLabel -%44 = OpPhi %10 %12 %76 %61 %60 -OpLoopMerge %62 %60 None -OpBranch %45 -%45 = OpLabel -%46 = OpSLessThan %14 %44 %13 -OpBranchConditional %46 %47 %62 -%47 = OpLabel -%51 = OpAccessChain %20 %4 %44 -%52 = OpLoad %15 %51 -%53 = OpAccessChain %20 %5 %44 -OpStore %53 %52 -OpBranch %60 -%60 = OpLabel -%61 = OpIAdd %10 %44 %21 -OpBranch %43 -%62 = OpLabel -OpBranch %77 -%77 = OpLabel -%78 = OpPhi %10 %12 %62 %89 %88 -OpLoopMerge %90 %88 None -OpBranch %79 -%79 = OpLabel -%80 = OpSLessThan %14 %78 %13 -OpBranchConditional %80 %81 %90 -%81 = OpLabel -%82 = OpAccessChain %20 %7 %78 -%83 = OpLoad %15 %82 -%84 = OpAccessChain %20 %6 %78 -OpStore %84 %83 -OpBranch %88 -%88 = OpLabel -%89 = OpIAdd %10 %78 %21 -OpBranch %77 -%90 = OpLabel -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %10 %12 %90 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %14 %24 %13 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -%40 = OpAccessChain %20 %6 %24 -%41 = OpLoad %15 %40 -%42 = OpAccessChain %20 %7 %24 -OpStore %42 %41 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %10 %24 %21 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on -std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); -Module* module = context->module(); -EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - -SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); -SinglePassRunAndCheck(source, expected, true); - -// By passing 1 as argument we are using the constructor which makes the -// critera to split the loop be if the registers in the loop exceede 1. By -// using this constructor we are also enabling multiple passes (disabled by -// default). -SinglePassRunAndCheck(source, expected_multiple_passes, true, - 1); -} - -/* -#version 430 -void main(void) { - int accumulator = 0; - float X[10]; - float Y[10]; - - for (int i = 0; i < 10; i++) { - X[i] = Y[i]; - Y[i] = X[i]; - accumulator += i; - } -} - -This should be split into the equivalent of: - -#version 430 -void main(void) { - int accumulator = 0; - float X[10]; - float Y[10]; - - for (int i = 0; i < 10; i++) { - X[i] = Y[i]; - } - for (int i = 0; i < 10; i++) { - Y[i] = X[i]; - accumulator += i; - } -} -*/ -TEST_F(FissionClassTest, FissionWithAccumulator) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "accumulator" - OpName %4 "i" - OpName %5 "X" - OpName %6 "Y" - %7 = OpTypeVoid - %8 = OpTypeFunction %7 - %9 = OpTypeInt 32 1 - %10 = OpTypePointer Function %9 - %11 = OpConstant %9 0 - %12 = OpConstant %9 10 - %13 = OpTypeBool - %14 = OpTypeFloat 32 - %15 = OpTypeInt 32 0 - %16 = OpConstant %15 10 - %17 = OpTypeArray %14 %16 - %18 = OpTypePointer Function %17 - %19 = OpTypePointer Function %14 - %20 = OpConstant %9 1 - %2 = OpFunction %7 None %8 - %21 = OpLabel - %3 = OpVariable %10 Function - %4 = OpVariable %10 Function - %5 = OpVariable %18 Function - %6 = OpVariable %18 Function - OpBranch %22 - %22 = OpLabel - %23 = OpPhi %9 %11 %21 %24 %25 - %26 = OpPhi %9 %11 %21 %27 %25 - OpLoopMerge %28 %25 None - OpBranch %29 - %29 = OpLabel - %30 = OpSLessThan %13 %26 %12 - OpBranchConditional %30 %31 %28 - %31 = OpLabel - %32 = OpAccessChain %19 %6 %26 - %33 = OpLoad %14 %32 - %34 = OpAccessChain %19 %5 %26 - OpStore %34 %33 - %35 = OpAccessChain %19 %5 %26 - %36 = OpLoad %14 %35 - %37 = OpAccessChain %19 %6 %26 - OpStore %37 %36 - %24 = OpIAdd %9 %23 %26 - OpBranch %25 - %25 = OpLabel - %27 = OpIAdd %9 %26 %20 - OpBranch %22 - %28 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "accumulator" -OpName %4 "i" -OpName %5 "X" -OpName %6 "Y" -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypePointer Function %17 -%19 = OpTypePointer Function %14 -%20 = OpConstant %9 1 -%2 = OpFunction %7 None %8 -%21 = OpLabel -%3 = OpVariable %10 Function -%4 = OpVariable %10 Function -%5 = OpVariable %18 Function -%6 = OpVariable %18 Function -OpBranch %38 -%38 = OpLabel -%40 = OpPhi %9 %11 %21 %52 %51 -OpLoopMerge %53 %51 None -OpBranch %41 -%41 = OpLabel -%42 = OpSLessThan %13 %40 %12 -OpBranchConditional %42 %43 %53 -%43 = OpLabel -%44 = OpAccessChain %19 %6 %40 -%45 = OpLoad %14 %44 -%46 = OpAccessChain %19 %5 %40 -OpStore %46 %45 -OpBranch %51 -%51 = OpLabel -%52 = OpIAdd %9 %40 %20 -OpBranch %38 -%53 = OpLabel -OpBranch %22 -%22 = OpLabel -%23 = OpPhi %9 %11 %53 %24 %25 -%26 = OpPhi %9 %11 %53 %27 %25 -OpLoopMerge %28 %25 None -OpBranch %29 -%29 = OpLabel -%30 = OpSLessThan %13 %26 %12 -OpBranchConditional %30 %31 %28 -%31 = OpLabel -%35 = OpAccessChain %19 %5 %26 -%36 = OpLoad %14 %35 -%37 = OpAccessChain %19 %6 %26 -OpStore %37 %36 -%24 = OpIAdd %9 %23 %26 -OpBranch %25 -%25 = OpLabel -%27 = OpIAdd %9 %26 %20 -OpBranch %22 -%28 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -/* -Generated from the following glsl: - -#version 430 -layout(location=0) out float x; -layout(location=1) out float y; - -void main(void) { - float accumulator_1 = 0; - float accumulator_2 = 0; - for (int i = 0; i < 10; i++) { - accumulator_1 += i; - accumulator_2 += i; - } - - x = accumulator_1; - y = accumulator_2; -} - -Should be split into equivalent of: - -void main(void) { - float accumulator_1 = 0; - float accumulator_2 = 0; - for (int i = 0; i < 10; i++) { - accumulator_1 += i; - } - - for (int i = 0; i < 10; i++) { - accumulator_2 += i; - } - x = accumulator_1; - y = accumulator_2; -} - -*/ -TEST_F(FissionClassTest, FissionWithPhisUsedOutwithLoop) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %5 "accumulator_1" - OpName %6 "accumulator_2" - OpName %7 "i" - OpName %3 "x" - OpName %4 "y" - OpDecorate %3 Location 0 - OpDecorate %4 Location 1 - %8 = OpTypeVoid - %9 = OpTypeFunction %8 - %10 = OpTypeFloat 32 - %11 = OpTypePointer Function %10 - %12 = OpConstant %10 0 - %13 = OpTypeInt 32 1 - %14 = OpTypePointer Function %13 - %15 = OpConstant %13 0 - %16 = OpConstant %13 10 - %17 = OpTypeBool - %18 = OpConstant %13 1 - %19 = OpTypePointer Output %10 - %3 = OpVariable %19 Output - %4 = OpVariable %19 Output - %2 = OpFunction %8 None %9 - %20 = OpLabel - %5 = OpVariable %11 Function - %6 = OpVariable %11 Function - %7 = OpVariable %14 Function - OpBranch %21 - %21 = OpLabel - %22 = OpPhi %10 %12 %20 %23 %24 - %25 = OpPhi %10 %12 %20 %26 %24 - %27 = OpPhi %13 %15 %20 %28 %24 - OpLoopMerge %29 %24 None - OpBranch %30 - %30 = OpLabel - %31 = OpSLessThan %17 %27 %16 - OpBranchConditional %31 %32 %29 - %32 = OpLabel - %33 = OpConvertSToF %10 %27 - %26 = OpFAdd %10 %25 %33 - %34 = OpConvertSToF %10 %27 - %23 = OpFAdd %10 %22 %34 - OpBranch %24 - %24 = OpLabel - %28 = OpIAdd %13 %27 %18 - OpStore %7 %28 - OpBranch %21 - %29 = OpLabel - OpStore %3 %25 - OpStore %4 %22 - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 %4 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %5 "accumulator_1" -OpName %6 "accumulator_2" -OpName %7 "i" -OpName %3 "x" -OpName %4 "y" -OpDecorate %3 Location 0 -OpDecorate %4 Location 1 -%8 = OpTypeVoid -%9 = OpTypeFunction %8 -%10 = OpTypeFloat 32 -%11 = OpTypePointer Function %10 -%12 = OpConstant %10 0 -%13 = OpTypeInt 32 1 -%14 = OpTypePointer Function %13 -%15 = OpConstant %13 0 -%16 = OpConstant %13 10 -%17 = OpTypeBool -%18 = OpConstant %13 1 -%19 = OpTypePointer Output %10 -%3 = OpVariable %19 Output -%4 = OpVariable %19 Output -%2 = OpFunction %8 None %9 -%20 = OpLabel -%5 = OpVariable %11 Function -%6 = OpVariable %11 Function -%7 = OpVariable %14 Function -OpBranch %35 -%35 = OpLabel -%37 = OpPhi %10 %12 %20 %43 %46 -%38 = OpPhi %13 %15 %20 %47 %46 -OpLoopMerge %48 %46 None -OpBranch %39 -%39 = OpLabel -%40 = OpSLessThan %17 %38 %16 -OpBranchConditional %40 %41 %48 -%41 = OpLabel -%42 = OpConvertSToF %10 %38 -%43 = OpFAdd %10 %37 %42 -OpBranch %46 -%46 = OpLabel -%47 = OpIAdd %13 %38 %18 -OpStore %7 %47 -OpBranch %35 -%48 = OpLabel -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %10 %12 %48 %23 %24 -%27 = OpPhi %13 %15 %48 %28 %24 -OpLoopMerge %29 %24 None -OpBranch %30 -%30 = OpLabel -%31 = OpSLessThan %17 %27 %16 -OpBranchConditional %31 %32 %29 -%32 = OpLabel -%34 = OpConvertSToF %10 %27 -%23 = OpFAdd %10 %22 %34 -OpBranch %24 -%24 = OpLabel -%28 = OpIAdd %13 %27 %18 -OpStore %7 %28 -OpBranch %21 -%29 = OpLabel -OpStore %3 %37 -OpStore %4 %22 -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -/* -#version 430 -void main(void) { - float A[10][10]; - float B[10][10]; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - A[i][j] = B[i][j]; - B[i][j] = A[i][j]; - } - } -} - -Should be split into equivalent of: - -#version 430 -void main(void) { - float A[10][10]; - float B[10][10]; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - A[i][j] = B[i][j]; - } - for (int j = 0; j < 10; j++) { - B[i][j] = A[i][j]; - } - } -} - - -*/ -TEST_F(FissionClassTest, FissionNested) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "j" - OpName %5 "A" - OpName %6 "B" - %7 = OpTypeVoid - %8 = OpTypeFunction %7 - %9 = OpTypeInt 32 1 - %10 = OpTypePointer Function %9 - %11 = OpConstant %9 0 - %12 = OpConstant %9 10 - %13 = OpTypeBool - %14 = OpTypeFloat 32 - %15 = OpTypeInt 32 0 - %16 = OpConstant %15 10 - %17 = OpTypeArray %14 %16 - %18 = OpTypeArray %17 %16 - %19 = OpTypePointer Function %18 - %20 = OpTypePointer Function %14 - %21 = OpConstant %9 1 - %2 = OpFunction %7 None %8 - %22 = OpLabel - %3 = OpVariable %10 Function - %4 = OpVariable %10 Function - %5 = OpVariable %19 Function - %6 = OpVariable %19 Function - OpStore %3 %11 - OpBranch %23 - %23 = OpLabel - %24 = OpPhi %9 %11 %22 %25 %26 - OpLoopMerge %27 %26 None - OpBranch %28 - %28 = OpLabel - %29 = OpSLessThan %13 %24 %12 - OpBranchConditional %29 %30 %27 - %30 = OpLabel - OpStore %4 %11 - OpBranch %31 - %31 = OpLabel - %32 = OpPhi %9 %11 %30 %33 %34 - OpLoopMerge %35 %34 None - OpBranch %36 - %36 = OpLabel - %37 = OpSLessThan %13 %32 %12 - OpBranchConditional %37 %38 %35 - %38 = OpLabel - %39 = OpAccessChain %20 %6 %24 %32 - %40 = OpLoad %14 %39 - %41 = OpAccessChain %20 %5 %24 %32 - OpStore %41 %40 - %42 = OpAccessChain %20 %5 %24 %32 - %43 = OpLoad %14 %42 - %44 = OpAccessChain %20 %6 %24 %32 - OpStore %44 %43 - OpBranch %34 - %34 = OpLabel - %33 = OpIAdd %9 %32 %21 - OpStore %4 %33 - OpBranch %31 - %35 = OpLabel - OpBranch %26 - %26 = OpLabel - %25 = OpIAdd %9 %24 %21 - OpStore %3 %25 - OpBranch %23 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "j" -OpName %5 "A" -OpName %6 "B" -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypeArray %17 %16 -%19 = OpTypePointer Function %18 -%20 = OpTypePointer Function %14 -%21 = OpConstant %9 1 -%2 = OpFunction %7 None %8 -%22 = OpLabel -%3 = OpVariable %10 Function -%4 = OpVariable %10 Function -%5 = OpVariable %19 Function -%6 = OpVariable %19 Function -OpStore %3 %11 -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %9 %11 %22 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %13 %24 %12 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -OpStore %4 %11 -OpBranch %45 -%45 = OpLabel -%46 = OpPhi %9 %11 %30 %57 %56 -OpLoopMerge %58 %56 None -OpBranch %47 -%47 = OpLabel -%48 = OpSLessThan %13 %46 %12 -OpBranchConditional %48 %49 %58 -%49 = OpLabel -%50 = OpAccessChain %20 %6 %24 %46 -%51 = OpLoad %14 %50 -%52 = OpAccessChain %20 %5 %24 %46 -OpStore %52 %51 -OpBranch %56 -%56 = OpLabel -%57 = OpIAdd %9 %46 %21 -OpStore %4 %57 -OpBranch %45 -%58 = OpLabel -OpBranch %31 -%31 = OpLabel -%32 = OpPhi %9 %11 %58 %33 %34 -OpLoopMerge %35 %34 None -OpBranch %36 -%36 = OpLabel -%37 = OpSLessThan %13 %32 %12 -OpBranchConditional %37 %38 %35 -%38 = OpLabel -%42 = OpAccessChain %20 %5 %24 %32 -%43 = OpLoad %14 %42 -%44 = OpAccessChain %20 %6 %24 %32 -OpStore %44 %43 -OpBranch %34 -%34 = OpLabel -%33 = OpIAdd %9 %32 %21 -OpStore %4 %33 -OpBranch %31 -%35 = OpLabel -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %9 %24 %21 -OpStore %3 %25 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -/* -#version 430 -void main(void) { - int accumulator = 0; - float A[10]; - float B[10]; - float C[10]; - - for (int i = 0; i < 10; i++) { - int c = C[i]; - A[i] = B[i]; - B[i] = A[i] + c; - } -} - -This loop should not be split as we would have to break the order of the loads -to do so. It would be grouped into two sets: - -1 - int c = C[i]; - B[i] = A[i] + c; - -2 - A[i] = B[i]; - -To keep the load C[i] in the same order we would need to put B[i] ahead of that -*/ -TEST_F(FissionClassTest, FissionLoad) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "c" -OpName %5 "C" -OpName %6 "A" -OpName %7 "B" -%8 = OpTypeVoid -%9 = OpTypeFunction %8 -%10 = OpTypeInt 32 1 -%11 = OpTypePointer Function %10 -%12 = OpConstant %10 0 -%13 = OpConstant %10 10 -%14 = OpTypeBool -%15 = OpTypeFloat 32 -%16 = OpTypePointer Function %15 -%17 = OpTypeInt 32 0 -%18 = OpConstant %17 10 -%19 = OpTypeArray %15 %18 -%20 = OpTypePointer Function %19 -%21 = OpConstant %10 1 -%2 = OpFunction %8 None %9 -%22 = OpLabel -%3 = OpVariable %11 Function -%4 = OpVariable %16 Function -%5 = OpVariable %20 Function -%6 = OpVariable %20 Function -%7 = OpVariable %20 Function -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %10 %12 %22 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %14 %24 %13 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -%31 = OpAccessChain %16 %5 %24 -%32 = OpLoad %15 %31 -OpStore %4 %32 -%33 = OpAccessChain %16 %7 %24 -%34 = OpLoad %15 %33 -%35 = OpAccessChain %16 %6 %24 -OpStore %35 %34 -%36 = OpAccessChain %16 %6 %24 -%37 = OpLoad %15 %36 -%38 = OpFAdd %15 %37 %32 -%39 = OpAccessChain %16 %7 %24 -OpStore %39 %38 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %10 %24 %21 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -layout(location=0) flat in int condition; -void main(void) { - float A[10]; - float B[10]; - - for (int i = 0; i < 10; i++) { - if (condition == 1) - A[i] = B[i]; - else - B[i] = A[i]; - } -} - - -When this is split we leave the condition check and control flow inplace and -leave its removal for dead code elimination. - -#version 430 -layout(location=0) flat in int condition; -void main(void) { - float A[10]; - float B[10]; - - for (int i = 0; i < 10; i++) { - if (condition == 1) - A[i] = B[i]; - else - ; - } - for (int i = 0; i < 10; i++) { - if (condition == 1) - ; - else - B[i] = A[i]; - } -} - - -*/ -TEST_F(FissionClassTest, FissionControlFlow) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %4 "i" - OpName %3 "condition" - OpName %5 "A" - OpName %6 "B" - OpDecorate %3 Flat - OpDecorate %3 Location 0 - %7 = OpTypeVoid - %8 = OpTypeFunction %7 - %9 = OpTypeInt 32 1 - %10 = OpTypePointer Function %9 - %11 = OpConstant %9 0 - %12 = OpConstant %9 10 - %13 = OpTypeBool - %14 = OpTypePointer Input %9 - %3 = OpVariable %14 Input - %15 = OpConstant %9 1 - %16 = OpTypeFloat 32 - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 10 - %19 = OpTypeArray %16 %18 - %20 = OpTypePointer Function %19 - %21 = OpTypePointer Function %16 - %2 = OpFunction %7 None %8 - %22 = OpLabel - %4 = OpVariable %10 Function - %5 = OpVariable %20 Function - %6 = OpVariable %20 Function - %31 = OpLoad %9 %3 - OpStore %4 %11 - OpBranch %23 - %23 = OpLabel - %24 = OpPhi %9 %11 %22 %25 %26 - OpLoopMerge %27 %26 None - OpBranch %28 - %28 = OpLabel - %29 = OpSLessThan %13 %24 %12 - OpBranchConditional %29 %30 %27 - %30 = OpLabel - %32 = OpIEqual %13 %31 %15 - OpSelectionMerge %33 None - OpBranchConditional %32 %34 %35 - %34 = OpLabel - %36 = OpAccessChain %21 %6 %24 - %37 = OpLoad %16 %36 - %38 = OpAccessChain %21 %5 %24 - OpStore %38 %37 - OpBranch %33 - %35 = OpLabel - %39 = OpAccessChain %21 %5 %24 - %40 = OpLoad %16 %39 - %41 = OpAccessChain %21 %6 %24 - OpStore %41 %40 - OpBranch %33 - %33 = OpLabel - OpBranch %26 - %26 = OpLabel - %25 = OpIAdd %9 %24 %15 - OpStore %4 %25 - OpBranch %23 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %4 "i" -OpName %3 "condition" -OpName %5 "A" -OpName %6 "B" -OpDecorate %3 Flat -OpDecorate %3 Location 0 -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypePointer Input %9 -%3 = OpVariable %14 Input -%15 = OpConstant %9 1 -%16 = OpTypeFloat 32 -%17 = OpTypeInt 32 0 -%18 = OpConstant %17 10 -%19 = OpTypeArray %16 %18 -%20 = OpTypePointer Function %19 -%21 = OpTypePointer Function %16 -%2 = OpFunction %7 None %8 -%22 = OpLabel -%4 = OpVariable %10 Function -%5 = OpVariable %20 Function -%6 = OpVariable %20 Function -%23 = OpLoad %9 %3 -OpStore %4 %11 -OpBranch %42 -%42 = OpLabel -%43 = OpPhi %9 %11 %22 %58 %57 -OpLoopMerge %59 %57 None -OpBranch %44 -%44 = OpLabel -%45 = OpSLessThan %13 %43 %12 -OpBranchConditional %45 %46 %59 -%46 = OpLabel -%47 = OpIEqual %13 %23 %15 -OpSelectionMerge %56 None -OpBranchConditional %47 %52 %48 -%48 = OpLabel -OpBranch %56 -%52 = OpLabel -%53 = OpAccessChain %21 %6 %43 -%54 = OpLoad %16 %53 -%55 = OpAccessChain %21 %5 %43 -OpStore %55 %54 -OpBranch %56 -%56 = OpLabel -OpBranch %57 -%57 = OpLabel -%58 = OpIAdd %9 %43 %15 -OpStore %4 %58 -OpBranch %42 -%59 = OpLabel -OpBranch %24 -%24 = OpLabel -%25 = OpPhi %9 %11 %59 %26 %27 -OpLoopMerge %28 %27 None -OpBranch %29 -%29 = OpLabel -%30 = OpSLessThan %13 %25 %12 -OpBranchConditional %30 %31 %28 -%31 = OpLabel -%32 = OpIEqual %13 %23 %15 -OpSelectionMerge %33 None -OpBranchConditional %32 %34 %35 -%34 = OpLabel -OpBranch %33 -%35 = OpLabel -%39 = OpAccessChain %21 %5 %25 -%40 = OpLoad %16 %39 -%41 = OpAccessChain %21 %6 %25 -OpStore %41 %40 -OpBranch %33 -%33 = OpLabel -OpBranch %27 -%27 = OpLabel -%26 = OpIAdd %9 %25 %15 -OpStore %4 %26 -OpBranch %24 -%28 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -/* -#version 430 -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - if (i == 1) - B[i] = A[i]; - else if (i == 2) - A[i] = B[i]; - else - A[i] = 0; - } -} - -After running the pass with multiple splits enabled (via register threshold of -1) we expect the equivalent of: - -#version 430 -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - if (i == 1) - B[i] = A[i]; - else if (i == 2) - else - } - for (int i = 0; i < 10; i++) { - if (i == 1) - else if (i == 2) - A[i] = B[i]; - else - } - for (int i = 0; i < 10; i++) { - if (i == 1) - else if (i == 2) - else - A[i] = 0; - } - -} - -*/ -TEST_F(FissionClassTest, FissionControlFlow2) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string source = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "B" - OpName %5 "A" - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpConstant %8 1 - %14 = OpTypeFloat 32 - %15 = OpTypeInt 32 0 - %16 = OpConstant %15 10 - %17 = OpTypeArray %14 %16 - %18 = OpTypePointer Function %17 - %19 = OpTypePointer Function %14 - %20 = OpConstant %8 2 - %21 = OpConstant %14 0 - %2 = OpFunction %6 None %7 - %22 = OpLabel - %3 = OpVariable %9 Function - %4 = OpVariable %18 Function - %5 = OpVariable %18 Function - OpStore %3 %10 - OpBranch %23 - %23 = OpLabel - %24 = OpPhi %8 %10 %22 %25 %26 - OpLoopMerge %27 %26 None - OpBranch %28 - %28 = OpLabel - %29 = OpSLessThan %12 %24 %11 - OpBranchConditional %29 %30 %27 - %30 = OpLabel - %31 = OpIEqual %12 %24 %13 - OpSelectionMerge %32 None - OpBranchConditional %31 %33 %34 - %33 = OpLabel - %35 = OpAccessChain %19 %5 %24 - %36 = OpLoad %14 %35 - %37 = OpAccessChain %19 %4 %24 - OpStore %37 %36 - OpBranch %32 - %34 = OpLabel - %38 = OpIEqual %12 %24 %20 - OpSelectionMerge %39 None - OpBranchConditional %38 %40 %41 - %40 = OpLabel - %42 = OpAccessChain %19 %4 %24 - %43 = OpLoad %14 %42 - %44 = OpAccessChain %19 %5 %24 - OpStore %44 %43 - OpBranch %39 - %41 = OpLabel - %45 = OpAccessChain %19 %5 %24 - OpStore %45 %21 - OpBranch %39 - %39 = OpLabel - OpBranch %32 - %32 = OpLabel - OpBranch %26 - %26 = OpLabel - %25 = OpIAdd %8 %24 %13 - OpStore %3 %25 - OpBranch %23 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpConstant %8 1 -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypePointer Function %17 -%19 = OpTypePointer Function %14 -%20 = OpConstant %8 2 -%21 = OpConstant %14 0 -%2 = OpFunction %6 None %7 -%22 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %18 Function -%5 = OpVariable %18 Function -OpStore %3 %10 -OpBranch %46 -%46 = OpLabel -%47 = OpPhi %8 %10 %22 %67 %66 -OpLoopMerge %68 %66 None -OpBranch %48 -%48 = OpLabel -%49 = OpSLessThan %12 %47 %11 -OpBranchConditional %49 %50 %68 -%50 = OpLabel -%51 = OpIEqual %12 %47 %13 -OpSelectionMerge %65 None -OpBranchConditional %51 %61 %52 -%52 = OpLabel -%53 = OpIEqual %12 %47 %20 -OpSelectionMerge %60 None -OpBranchConditional %53 %56 %54 -%54 = OpLabel -OpBranch %60 -%56 = OpLabel -OpBranch %60 -%60 = OpLabel -OpBranch %65 -%61 = OpLabel -%62 = OpAccessChain %19 %5 %47 -%63 = OpLoad %14 %62 -%64 = OpAccessChain %19 %4 %47 -OpStore %64 %63 -OpBranch %65 -%65 = OpLabel -OpBranch %66 -%66 = OpLabel -%67 = OpIAdd %8 %47 %13 -OpStore %3 %67 -OpBranch %46 -%68 = OpLabel -OpBranch %69 -%69 = OpLabel -%70 = OpPhi %8 %10 %68 %87 %86 -OpLoopMerge %88 %86 None -OpBranch %71 -%71 = OpLabel -%72 = OpSLessThan %12 %70 %11 -OpBranchConditional %72 %73 %88 -%73 = OpLabel -%74 = OpIEqual %12 %70 %13 -OpSelectionMerge %85 None -OpBranchConditional %74 %84 %75 -%75 = OpLabel -%76 = OpIEqual %12 %70 %20 -OpSelectionMerge %83 None -OpBranchConditional %76 %79 %77 -%77 = OpLabel -OpBranch %83 -%79 = OpLabel -%80 = OpAccessChain %19 %4 %70 -%81 = OpLoad %14 %80 -%82 = OpAccessChain %19 %5 %70 -OpStore %82 %81 -OpBranch %83 -%83 = OpLabel -OpBranch %85 -%84 = OpLabel -OpBranch %85 -%85 = OpLabel -OpBranch %86 -%86 = OpLabel -%87 = OpIAdd %8 %70 %13 -OpStore %3 %87 -OpBranch %69 -%88 = OpLabel -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %8 %10 %88 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %12 %24 %11 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -%31 = OpIEqual %12 %24 %13 -OpSelectionMerge %32 None -OpBranchConditional %31 %33 %34 -%33 = OpLabel -OpBranch %32 -%34 = OpLabel -%38 = OpIEqual %12 %24 %20 -OpSelectionMerge %39 None -OpBranchConditional %38 %40 %41 -%40 = OpLabel -OpBranch %39 -%41 = OpLabel -%45 = OpAccessChain %19 %5 %24 -OpStore %45 %21 -OpBranch %39 -%39 = OpLabel -OpBranch %32 -%32 = OpLabel -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %8 %24 %13 -OpStore %3 %25 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true, 1); -} - -/* -#version 430 -layout(location=0) flat in int condition; -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - B[i] = A[i]; - memoryBarrier(); - A[i] = B[i]; - } -} - -This should not be split due to the memory barrier. -*/ -TEST_F(FissionClassTest, FissionBarrier) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %4 "i" -OpName %5 "B" -OpName %6 "A" -OpName %3 "condition" -OpDecorate %3 Flat -OpDecorate %3 Location 0 -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypePointer Function %17 -%19 = OpTypePointer Function %14 -%20 = OpConstant %15 1 -%21 = OpConstant %15 4048 -%22 = OpConstant %9 1 -%23 = OpTypePointer Input %9 -%3 = OpVariable %23 Input -%2 = OpFunction %7 None %8 -%24 = OpLabel -%4 = OpVariable %10 Function -%5 = OpVariable %18 Function -%6 = OpVariable %18 Function -OpStore %4 %11 -OpBranch %25 -%25 = OpLabel -%26 = OpPhi %9 %11 %24 %27 %28 -OpLoopMerge %29 %28 None -OpBranch %30 -%30 = OpLabel -%31 = OpSLessThan %13 %26 %12 -OpBranchConditional %31 %32 %29 -%32 = OpLabel -%33 = OpAccessChain %19 %6 %26 -%34 = OpLoad %14 %33 -%35 = OpAccessChain %19 %5 %26 -OpStore %35 %34 -OpMemoryBarrier %20 %21 -%36 = OpAccessChain %19 %5 %26 -%37 = OpLoad %14 %36 -%38 = OpAccessChain %19 %6 %26 -OpStore %38 %37 -OpBranch %28 -%28 = OpLabel -%27 = OpIAdd %9 %26 %22 -OpStore %4 %27 -OpBranch %25 -%29 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - B[i] = A[i]; - if ( i== 1) - break; - A[i] = B[i]; - } -} - -This should not be split due to the break. -*/ -TEST_F(FissionClassTest, FissionBreak) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpStore %3 %10 -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %20 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%29 = OpAccessChain %18 %5 %22 -%30 = OpLoad %13 %29 -%31 = OpAccessChain %18 %4 %22 -OpStore %31 %30 -%32 = OpIEqual %12 %22 %19 -OpSelectionMerge %33 None -OpBranchConditional %32 %34 %33 -%34 = OpLabel -OpBranch %25 -%33 = OpLabel -%35 = OpAccessChain %18 %4 %22 -%36 = OpLoad %13 %35 -%37 = OpAccessChain %18 %5 %22 -OpStore %37 %36 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpStore %3 %23 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; i++) { - B[i] = A[i]; - if ( i== 1) - continue; - A[i] = B[i]; - } -} - -This loop should be split into: - - for (int i = 0; i < 10; i++) { - B[i] = A[i]; - if ( i== 1) - continue; - } - for (int i = 0; i < 10; i++) { - if ( i== 1) - continue; - A[i] = B[i]; - } -The continue block in the first loop is left to DCE. -} - - -*/ -TEST_F(FissionClassTest, FissionContinue) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpStore %3 %10 -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %20 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%29 = OpAccessChain %18 %5 %22 -%30 = OpLoad %13 %29 -%31 = OpAccessChain %18 %4 %22 -OpStore %31 %30 -%32 = OpIEqual %12 %22 %19 -OpSelectionMerge %33 None -OpBranchConditional %32 %34 %33 -%34 = OpLabel -OpBranch %24 -%33 = OpLabel -%35 = OpAccessChain %18 %4 %22 -%36 = OpLoad %13 %35 -%37 = OpAccessChain %18 %5 %22 -OpStore %37 %36 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpStore %3 %23 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - -const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpStore %3 %10 -OpBranch %38 -%38 = OpLabel -%39 = OpPhi %8 %10 %20 %53 %52 -OpLoopMerge %54 %52 None -OpBranch %40 -%40 = OpLabel -%41 = OpSLessThan %12 %39 %11 -OpBranchConditional %41 %42 %54 -%42 = OpLabel -%43 = OpAccessChain %18 %5 %39 -%44 = OpLoad %13 %43 -%45 = OpAccessChain %18 %4 %39 -OpStore %45 %44 -%46 = OpIEqual %12 %39 %19 -OpSelectionMerge %47 None -OpBranchConditional %46 %51 %47 -%47 = OpLabel -OpBranch %52 -%51 = OpLabel -OpBranch %52 -%52 = OpLabel -%53 = OpIAdd %8 %39 %19 -OpStore %3 %53 -OpBranch %38 -%54 = OpLabel -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %54 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%32 = OpIEqual %12 %22 %19 -OpSelectionMerge %33 None -OpBranchConditional %32 %34 %33 -%34 = OpLabel -OpBranch %24 -%33 = OpLabel -%35 = OpAccessChain %18 %4 %22 -%36 = OpLoad %13 %35 -%37 = OpAccessChain %18 %5 %22 -OpStore %37 %36 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpStore %3 %23 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -/* -#version 430 -void main(void) { - float A[10]; - float B[10]; - int i = 0; - do { - B[i] = A[i]; - A[i] = B[i]; - ++i; - } while (i < 10); -} - - -Check that this is split into: - int i = 0; - do { - B[i] = A[i]; - ++i; - } while (i < 10); - - i = 0; - do { - A[i] = B[i]; - ++i; - } while (i < 10); - - -*/ -TEST_F(FissionClassTest, FissionDoWhile) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpTypeFloat 32 -%12 = OpTypeInt 32 0 -%13 = OpConstant %12 10 -%14 = OpTypeArray %11 %13 -%15 = OpTypePointer Function %14 -%16 = OpTypePointer Function %11 -%17 = OpConstant %8 1 -%18 = OpConstant %8 10 -%19 = OpTypeBool -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %15 Function -%5 = OpVariable %15 Function -OpStore %3 %10 -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %20 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpAccessChain %16 %5 %22 -%28 = OpLoad %11 %27 -%29 = OpAccessChain %16 %4 %22 -OpStore %29 %28 -%30 = OpAccessChain %16 %4 %22 -%31 = OpLoad %11 %30 -%32 = OpAccessChain %16 %5 %22 -OpStore %32 %31 -%23 = OpIAdd %8 %22 %17 -OpStore %3 %23 -OpBranch %24 -%24 = OpLabel -%33 = OpSLessThan %19 %23 %18 -OpBranchConditional %33 %21 %25 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - -const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpTypeFloat 32 -%12 = OpTypeInt 32 0 -%13 = OpConstant %12 10 -%14 = OpTypeArray %11 %13 -%15 = OpTypePointer Function %14 -%16 = OpTypePointer Function %11 -%17 = OpConstant %8 1 -%18 = OpConstant %8 10 -%19 = OpTypeBool -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %15 Function -%5 = OpVariable %15 Function -OpStore %3 %10 -OpBranch %34 -%34 = OpLabel -%35 = OpPhi %8 %10 %20 %43 %44 -OpLoopMerge %46 %44 None -OpBranch %36 -%36 = OpLabel -%37 = OpAccessChain %16 %5 %35 -%38 = OpLoad %11 %37 -%39 = OpAccessChain %16 %4 %35 -OpStore %39 %38 -%43 = OpIAdd %8 %35 %17 -OpStore %3 %43 -OpBranch %44 -%44 = OpLabel -%45 = OpSLessThan %19 %43 %18 -OpBranchConditional %45 %34 %46 -%46 = OpLabel -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %46 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%30 = OpAccessChain %16 %4 %22 -%31 = OpLoad %11 %30 -%32 = OpAccessChain %16 %5 %22 -OpStore %32 %31 -%23 = OpIAdd %8 %22 %17 -OpStore %3 %23 -OpBranch %24 -%24 = OpLabel -%33 = OpSLessThan %19 %23 %18 -OpBranchConditional %33 %21 %25 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -/* - -#version 430 -void main(void) { - float A[10][10]; - float B[10][10]; - for (int j = 0; j < 10; ++j) { - for (int i = 0; i < 10; ++i) { - B[i][j] = A[i][i]; - A[i][i] = B[i][j + 1]; - } - } -} - - -This loop can't be split because the load B[i][j + 1] is dependent on the store -B[i][j]. - -*/ -TEST_F(FissionClassTest, FissionNestedDependency) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "j" -OpName %4 "i" -OpName %5 "B" -OpName %6 "A" -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypeArray %17 %16 -%19 = OpTypePointer Function %18 -%20 = OpTypePointer Function %14 -%21 = OpConstant %9 1 -%2 = OpFunction %7 None %8 -%22 = OpLabel -%3 = OpVariable %10 Function -%4 = OpVariable %10 Function -%5 = OpVariable %19 Function -%6 = OpVariable %19 Function -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %9 %11 %22 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %13 %24 %12 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -OpBranch %31 -%31 = OpLabel -%32 = OpPhi %9 %11 %30 %33 %34 -OpLoopMerge %35 %34 None -OpBranch %36 -%36 = OpLabel -%37 = OpSLessThan %13 %32 %12 -OpBranchConditional %37 %38 %35 -%38 = OpLabel -%39 = OpAccessChain %20 %6 %32 %32 -%40 = OpLoad %14 %39 -%41 = OpAccessChain %20 %5 %32 %24 -OpStore %41 %40 -%42 = OpIAdd %9 %24 %21 -%43 = OpAccessChain %20 %5 %32 %42 -%44 = OpLoad %14 %43 -%45 = OpAccessChain %20 %6 %32 %32 -OpStore %45 %44 -OpBranch %34 -%34 = OpLabel -%33 = OpIAdd %9 %32 %21 -OpBranch %31 -%35 = OpLabel -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %9 %24 %21 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -void main(void) { - float A[10][10]; - float B[10][10]; - for (int j = 0; j < 10; ++j) { - for (int i = 0; i < 10; ++i) { - B[i][i] = A[i][j]; - A[i][j+1] = B[i][i]; - } - } -} - -This loop should not be split as the load A[i][j+1] would be reading a value -written in the store A[i][j] which would be hit before A[i][j+1] if the loops -where split but would not get hit before the read currently. - -*/ -TEST_F(FissionClassTest, FissionNestedDependency2) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "j" -OpName %4 "i" -OpName %5 "B" -OpName %6 "A" -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypeArray %17 %16 -%19 = OpTypePointer Function %18 -%20 = OpTypePointer Function %14 -%21 = OpConstant %9 1 -%2 = OpFunction %7 None %8 -%22 = OpLabel -%3 = OpVariable %10 Function -%4 = OpVariable %10 Function -%5 = OpVariable %19 Function -%6 = OpVariable %19 Function -OpStore %3 %11 -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %9 %11 %22 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %13 %24 %12 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -OpStore %4 %11 -OpBranch %31 -%31 = OpLabel -%32 = OpPhi %9 %11 %30 %33 %34 -OpLoopMerge %35 %34 None -OpBranch %36 -%36 = OpLabel -%37 = OpSLessThan %13 %32 %12 -OpBranchConditional %37 %38 %35 -%38 = OpLabel -%39 = OpAccessChain %20 %6 %32 %24 -%40 = OpLoad %14 %39 -%41 = OpAccessChain %20 %5 %32 %32 -OpStore %41 %40 -%42 = OpIAdd %9 %24 %21 -%43 = OpAccessChain %20 %5 %32 %32 -%44 = OpLoad %14 %43 -%45 = OpAccessChain %20 %6 %32 %42 -OpStore %45 %44 -OpBranch %34 -%34 = OpLabel -%33 = OpIAdd %9 %32 %21 -OpStore %4 %33 -OpBranch %31 -%35 = OpLabel -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %9 %24 %21 -OpStore %3 %25 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -void main(void) { - float A[10][10]; - float B[10][10]; - for (int j = 0; j < 10; ++j) { - for (int i = 0; i < 10; ++i) { - B[i][j] = A[i][j]; - A[i][j] = B[i][j]; - } - for (int i = 0; i < 10; ++i) { - B[i][j] = A[i][j]; - A[i][j] = B[i][j]; - } - } -} - - - -Should be split into: - -for (int j = 0; j < 10; ++j) { - for (int i = 0; i < 10; ++i) - B[i][j] = A[i][j]; - for (int i = 0; i < 10; ++i) - A[i][j] = B[i][j]; - for (int i = 0; i < 10; ++i) - B[i][j] = A[i][j]; - for (int i = 0; i < 10; ++i) - A[i][j] = B[i][j]; -*/ -TEST_F(FissionClassTest, FissionMultipleLoopsNested) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "j" - OpName %4 "i" - OpName %5 "B" - OpName %6 "A" - OpName %7 "i" - %8 = OpTypeVoid - %9 = OpTypeFunction %8 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %12 = OpConstant %10 0 - %13 = OpConstant %10 10 - %14 = OpTypeBool - %15 = OpTypeFloat 32 - %16 = OpTypeInt 32 0 - %17 = OpConstant %16 10 - %18 = OpTypeArray %15 %17 - %19 = OpTypeArray %18 %17 - %20 = OpTypePointer Function %19 - %21 = OpTypePointer Function %15 - %22 = OpConstant %10 1 - %2 = OpFunction %8 None %9 - %23 = OpLabel - %3 = OpVariable %11 Function - %4 = OpVariable %11 Function - %5 = OpVariable %20 Function - %6 = OpVariable %20 Function - %7 = OpVariable %11 Function - OpStore %3 %12 - OpBranch %24 - %24 = OpLabel - %25 = OpPhi %10 %12 %23 %26 %27 - OpLoopMerge %28 %27 None - OpBranch %29 - %29 = OpLabel - %30 = OpSLessThan %14 %25 %13 - OpBranchConditional %30 %31 %28 - %31 = OpLabel - OpStore %4 %12 - OpBranch %32 - %32 = OpLabel - %33 = OpPhi %10 %12 %31 %34 %35 - OpLoopMerge %36 %35 None - OpBranch %37 - %37 = OpLabel - %38 = OpSLessThan %14 %33 %13 - OpBranchConditional %38 %39 %36 - %39 = OpLabel - %40 = OpAccessChain %21 %6 %33 %25 - %41 = OpLoad %15 %40 - %42 = OpAccessChain %21 %5 %33 %25 - OpStore %42 %41 - %43 = OpAccessChain %21 %5 %33 %25 - %44 = OpLoad %15 %43 - %45 = OpAccessChain %21 %6 %33 %25 - OpStore %45 %44 - OpBranch %35 - %35 = OpLabel - %34 = OpIAdd %10 %33 %22 - OpStore %4 %34 - OpBranch %32 - %36 = OpLabel - OpStore %7 %12 - OpBranch %46 - %46 = OpLabel - %47 = OpPhi %10 %12 %36 %48 %49 - OpLoopMerge %50 %49 None - OpBranch %51 - %51 = OpLabel - %52 = OpSLessThan %14 %47 %13 - OpBranchConditional %52 %53 %50 - %53 = OpLabel - %54 = OpAccessChain %21 %6 %47 %25 - %55 = OpLoad %15 %54 - %56 = OpAccessChain %21 %5 %47 %25 - OpStore %56 %55 - %57 = OpAccessChain %21 %5 %47 %25 - %58 = OpLoad %15 %57 - %59 = OpAccessChain %21 %6 %47 %25 - OpStore %59 %58 - OpBranch %49 - %49 = OpLabel - %48 = OpIAdd %10 %47 %22 - OpStore %7 %48 - OpBranch %46 - %50 = OpLabel - OpBranch %27 - %27 = OpLabel - %26 = OpIAdd %10 %25 %22 - OpStore %3 %26 - OpBranch %24 - %28 = OpLabel - OpReturn - OpFunctionEnd -)"; - -const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "j" -OpName %4 "i" -OpName %5 "B" -OpName %6 "A" -OpName %7 "i" -%8 = OpTypeVoid -%9 = OpTypeFunction %8 -%10 = OpTypeInt 32 1 -%11 = OpTypePointer Function %10 -%12 = OpConstant %10 0 -%13 = OpConstant %10 10 -%14 = OpTypeBool -%15 = OpTypeFloat 32 -%16 = OpTypeInt 32 0 -%17 = OpConstant %16 10 -%18 = OpTypeArray %15 %17 -%19 = OpTypeArray %18 %17 -%20 = OpTypePointer Function %19 -%21 = OpTypePointer Function %15 -%22 = OpConstant %10 1 -%2 = OpFunction %8 None %9 -%23 = OpLabel -%3 = OpVariable %11 Function -%4 = OpVariable %11 Function -%5 = OpVariable %20 Function -%6 = OpVariable %20 Function -%7 = OpVariable %11 Function -OpStore %3 %12 -OpBranch %24 -%24 = OpLabel -%25 = OpPhi %10 %12 %23 %26 %27 -OpLoopMerge %28 %27 None -OpBranch %29 -%29 = OpLabel -%30 = OpSLessThan %14 %25 %13 -OpBranchConditional %30 %31 %28 -%31 = OpLabel -OpStore %4 %12 -OpBranch %60 -%60 = OpLabel -%61 = OpPhi %10 %12 %31 %72 %71 -OpLoopMerge %73 %71 None -OpBranch %62 -%62 = OpLabel -%63 = OpSLessThan %14 %61 %13 -OpBranchConditional %63 %64 %73 -%64 = OpLabel -%65 = OpAccessChain %21 %6 %61 %25 -%66 = OpLoad %15 %65 -%67 = OpAccessChain %21 %5 %61 %25 -OpStore %67 %66 -OpBranch %71 -%71 = OpLabel -%72 = OpIAdd %10 %61 %22 -OpStore %4 %72 -OpBranch %60 -%73 = OpLabel -OpBranch %32 -%32 = OpLabel -%33 = OpPhi %10 %12 %73 %34 %35 -OpLoopMerge %36 %35 None -OpBranch %37 -%37 = OpLabel -%38 = OpSLessThan %14 %33 %13 -OpBranchConditional %38 %39 %36 -%39 = OpLabel -%43 = OpAccessChain %21 %5 %33 %25 -%44 = OpLoad %15 %43 -%45 = OpAccessChain %21 %6 %33 %25 -OpStore %45 %44 -OpBranch %35 -%35 = OpLabel -%34 = OpIAdd %10 %33 %22 -OpStore %4 %34 -OpBranch %32 -%36 = OpLabel -OpStore %7 %12 -OpBranch %74 -%74 = OpLabel -%75 = OpPhi %10 %12 %36 %86 %85 -OpLoopMerge %87 %85 None -OpBranch %76 -%76 = OpLabel -%77 = OpSLessThan %14 %75 %13 -OpBranchConditional %77 %78 %87 -%78 = OpLabel -%79 = OpAccessChain %21 %6 %75 %25 -%80 = OpLoad %15 %79 -%81 = OpAccessChain %21 %5 %75 %25 -OpStore %81 %80 -OpBranch %85 -%85 = OpLabel -%86 = OpIAdd %10 %75 %22 -OpStore %7 %86 -OpBranch %74 -%87 = OpLabel -OpBranch %46 -%46 = OpLabel -%47 = OpPhi %10 %12 %87 %48 %49 -OpLoopMerge %50 %49 None -OpBranch %51 -%51 = OpLabel -%52 = OpSLessThan %14 %47 %13 -OpBranchConditional %52 %53 %50 -%53 = OpLabel -%57 = OpAccessChain %21 %5 %47 %25 -%58 = OpLoad %15 %57 -%59 = OpAccessChain %21 %6 %47 %25 -OpStore %59 %58 -OpBranch %49 -%49 = OpLabel -%48 = OpIAdd %10 %47 %22 -OpStore %7 %48 -OpBranch %46 -%50 = OpLabel -OpBranch %27 -%27 = OpLabel -%26 = OpIAdd %10 %25 %22 -OpStore %3 %26 -OpBranch %24 -%28 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - const Function* function = spvtest::GetFunction(module, 2); - LoopDescriptor& pre_pass_descriptor = *context->GetLoopDescriptor(function); - EXPECT_EQ(pre_pass_descriptor.NumLoops(), 3u); - EXPECT_EQ(pre_pass_descriptor.pre_begin()->NumImmediateChildren(), 2u); - - // Test that the pass transforms the ir into the expected output. - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); - - // Test that the loop descriptor is correctly maintained and updated by the - // pass. - LoopFissionPass loop_fission; - loop_fission.SetContextForTesting(context.get()); - loop_fission.Process(); - - function = spvtest::GetFunction(module, 2); - LoopDescriptor& post_pass_descriptor = *context->GetLoopDescriptor(function); - EXPECT_EQ(post_pass_descriptor.NumLoops(), 5u); - EXPECT_EQ(post_pass_descriptor.pre_begin()->NumImmediateChildren(), 4u); -} - -/* -#version 430 -void main(void) { - float A[10][10]; - float B[10][10]; - for (int i = 0; i < 10; ++i) { - B[i][i] = A[i][i]; - A[i][i] = B[i][i]; - } - for (int i = 0; i < 10; ++i) { - B[i][i] = A[i][i]; - A[i][i] = B[i][i] - } -} - - - -Should be split into: - - for (int i = 0; i < 10; ++i) - B[i][i] = A[i][i]; - for (int i = 0; i < 10; ++i) - A[i][i] = B[i][i]; - for (int i = 0; i < 10; ++i) - B[i][i] = A[i][i]; - for (int i = 0; i < 10; ++i) - A[i][i] = B[i][i]; -*/ -TEST_F(FissionClassTest, FissionMultipleLoops) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "B" - OpName %5 "A" - OpName %6 "i" - %7 = OpTypeVoid - %8 = OpTypeFunction %7 - %9 = OpTypeInt 32 1 - %10 = OpTypePointer Function %9 - %11 = OpConstant %9 0 - %12 = OpConstant %9 10 - %13 = OpTypeBool - %14 = OpTypeFloat 32 - %15 = OpTypeInt 32 0 - %16 = OpConstant %15 10 - %17 = OpTypeArray %14 %16 - %18 = OpTypePointer Function %17 - %19 = OpTypePointer Function %14 - %20 = OpConstant %9 1 - %2 = OpFunction %7 None %8 - %21 = OpLabel - %3 = OpVariable %10 Function - %4 = OpVariable %18 Function - %5 = OpVariable %18 Function - %6 = OpVariable %10 Function - OpStore %3 %11 - OpBranch %22 - %22 = OpLabel - %23 = OpPhi %9 %11 %21 %24 %25 - OpLoopMerge %26 %25 None - OpBranch %27 - %27 = OpLabel - %28 = OpSLessThan %13 %23 %12 - OpBranchConditional %28 %29 %26 - %29 = OpLabel - %30 = OpAccessChain %19 %5 %23 - %31 = OpLoad %14 %30 - %32 = OpAccessChain %19 %4 %23 - OpStore %32 %31 - %33 = OpAccessChain %19 %4 %23 - %34 = OpLoad %14 %33 - %35 = OpAccessChain %19 %5 %23 - OpStore %35 %34 - OpBranch %25 - %25 = OpLabel - %24 = OpIAdd %9 %23 %20 - OpStore %3 %24 - OpBranch %22 - %26 = OpLabel - OpStore %6 %11 - OpBranch %36 - %36 = OpLabel - %37 = OpPhi %9 %11 %26 %38 %39 - OpLoopMerge %40 %39 None - OpBranch %41 - %41 = OpLabel - %42 = OpSLessThan %13 %37 %12 - OpBranchConditional %42 %43 %40 - %43 = OpLabel - %44 = OpAccessChain %19 %5 %37 - %45 = OpLoad %14 %44 - %46 = OpAccessChain %19 %4 %37 - OpStore %46 %45 - %47 = OpAccessChain %19 %4 %37 - %48 = OpLoad %14 %47 - %49 = OpAccessChain %19 %5 %37 - OpStore %49 %48 - OpBranch %39 - %39 = OpLabel - %38 = OpIAdd %9 %37 %20 - OpStore %6 %38 - OpBranch %36 - %40 = OpLabel - OpReturn - OpFunctionEnd -)"; - -const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -OpName %6 "i" -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpTypeFloat 32 -%15 = OpTypeInt 32 0 -%16 = OpConstant %15 10 -%17 = OpTypeArray %14 %16 -%18 = OpTypePointer Function %17 -%19 = OpTypePointer Function %14 -%20 = OpConstant %9 1 -%2 = OpFunction %7 None %8 -%21 = OpLabel -%3 = OpVariable %10 Function -%4 = OpVariable %18 Function -%5 = OpVariable %18 Function -%6 = OpVariable %10 Function -OpStore %3 %11 -OpBranch %64 -%64 = OpLabel -%65 = OpPhi %9 %11 %21 %76 %75 -OpLoopMerge %77 %75 None -OpBranch %66 -%66 = OpLabel -%67 = OpSLessThan %13 %65 %12 -OpBranchConditional %67 %68 %77 -%68 = OpLabel -%69 = OpAccessChain %19 %5 %65 -%70 = OpLoad %14 %69 -%71 = OpAccessChain %19 %4 %65 -OpStore %71 %70 -OpBranch %75 -%75 = OpLabel -%76 = OpIAdd %9 %65 %20 -OpStore %3 %76 -OpBranch %64 -%77 = OpLabel -OpBranch %22 -%22 = OpLabel -%23 = OpPhi %9 %11 %77 %24 %25 -OpLoopMerge %26 %25 None -OpBranch %27 -%27 = OpLabel -%28 = OpSLessThan %13 %23 %12 -OpBranchConditional %28 %29 %26 -%29 = OpLabel -%33 = OpAccessChain %19 %4 %23 -%34 = OpLoad %14 %33 -%35 = OpAccessChain %19 %5 %23 -OpStore %35 %34 -OpBranch %25 -%25 = OpLabel -%24 = OpIAdd %9 %23 %20 -OpStore %3 %24 -OpBranch %22 -%26 = OpLabel -OpStore %6 %11 -OpBranch %50 -%50 = OpLabel -%51 = OpPhi %9 %11 %26 %62 %61 -OpLoopMerge %63 %61 None -OpBranch %52 -%52 = OpLabel -%53 = OpSLessThan %13 %51 %12 -OpBranchConditional %53 %54 %63 -%54 = OpLabel -%55 = OpAccessChain %19 %5 %51 -%56 = OpLoad %14 %55 -%57 = OpAccessChain %19 %4 %51 -OpStore %57 %56 -OpBranch %61 -%61 = OpLabel -%62 = OpIAdd %9 %51 %20 -OpStore %6 %62 -OpBranch %50 -%63 = OpLabel -OpBranch %36 -%36 = OpLabel -%37 = OpPhi %9 %11 %63 %38 %39 -OpLoopMerge %40 %39 None -OpBranch %41 -%41 = OpLabel -%42 = OpSLessThan %13 %37 %12 -OpBranchConditional %42 %43 %40 -%43 = OpLabel -%47 = OpAccessChain %19 %4 %37 -%48 = OpLoad %14 %47 -%49 = OpAccessChain %19 %5 %37 -OpStore %49 %48 -OpBranch %39 -%39 = OpLabel -%38 = OpIAdd %9 %37 %20 -OpStore %6 %38 -OpBranch %36 -%40 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); - - const Function* function = spvtest::GetFunction(module, 2); - LoopDescriptor& pre_pass_descriptor = *context->GetLoopDescriptor(function); - EXPECT_EQ(pre_pass_descriptor.NumLoops(), 2u); - EXPECT_EQ(pre_pass_descriptor.pre_begin()->NumImmediateChildren(), 0u); - - // Test that the pass transforms the ir into the expected output. - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); - - // Test that the loop descriptor is correctly maintained and updated by the - // pass. - LoopFissionPass loop_fission; - loop_fission.SetContextForTesting(context.get()); - loop_fission.Process(); - - function = spvtest::GetFunction(module, 2); - LoopDescriptor& post_pass_descriptor = *context->GetLoopDescriptor(function); - EXPECT_EQ(post_pass_descriptor.NumLoops(), 4u); - EXPECT_EQ(post_pass_descriptor.pre_begin()->NumImmediateChildren(), 0u); -} - -/* -#version 430 -int foo() { return 1; } -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; ++i) { - B[i] = A[i]; - foo(); - A[i] = B[i]; - } -} - -This should not be split as it has a function call in it so we can't determine -if it has side effects. -*/ -TEST_F(FissionClassTest, FissionFunctionCall) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "foo(" -OpName %4 "i" -OpName %5 "B" -OpName %6 "A" -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 1 -%10 = OpTypeFunction %9 -%11 = OpConstant %9 1 -%12 = OpTypePointer Function %9 -%13 = OpConstant %9 0 -%14 = OpConstant %9 10 -%15 = OpTypeBool -%16 = OpTypeFloat 32 -%17 = OpTypeInt 32 0 -%18 = OpConstant %17 10 -%19 = OpTypeArray %16 %18 -%20 = OpTypePointer Function %19 -%21 = OpTypePointer Function %16 -%2 = OpFunction %7 None %8 -%22 = OpLabel -%4 = OpVariable %12 Function -%5 = OpVariable %20 Function -%6 = OpVariable %20 Function -OpStore %4 %13 -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %9 %13 %22 %25 %26 -OpLoopMerge %27 %26 None -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %15 %24 %14 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -%31 = OpAccessChain %21 %6 %24 -%32 = OpLoad %16 %31 -%33 = OpAccessChain %21 %5 %24 -OpStore %33 %32 -%34 = OpFunctionCall %9 %3 -%35 = OpAccessChain %21 %5 %24 -%36 = OpLoad %16 %35 -%37 = OpAccessChain %21 %6 %24 -OpStore %37 %36 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %9 %24 %11 -OpStore %4 %25 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -%3 = OpFunction %9 None %10 -%38 = OpLabel -OpReturnValue %11 -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, source, true); -} - -/* -#version 430 -void main(void) { - float A[10]; - float B[10]; - for (int i = 0; i < 10; ++i) { - switch (i) { - case 1: - B[i] = A[i]; - break; - default: - A[i] = B[i]; - } - } -} - -This should be split into: - for (int i = 0; i < 10; ++i) { - switch (i) { - case 1: - break; - default: - A[i] = B[i]; - } - } - - for (int i = 0; i < 10; ++i) { - switch (i) { - case 1: - B[i] = A[i]; - break; - default: - break; - } - } - -*/ -TEST_F(FissionClassTest, FissionSwitchStatement) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string source = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "B" - OpName %5 "A" - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Function %16 - %18 = OpTypePointer Function %13 - %19 = OpConstant %8 1 - %2 = OpFunction %6 None %7 - %20 = OpLabel - %3 = OpVariable %9 Function - %4 = OpVariable %17 Function - %5 = OpVariable %17 Function - OpStore %3 %10 - OpBranch %21 - %21 = OpLabel - %22 = OpPhi %8 %10 %20 %23 %24 - OpLoopMerge %25 %24 None - OpBranch %26 - %26 = OpLabel - %27 = OpSLessThan %12 %22 %11 - OpBranchConditional %27 %28 %25 - %28 = OpLabel - OpSelectionMerge %29 None - OpSwitch %22 %30 1 %31 - %30 = OpLabel - %32 = OpAccessChain %18 %4 %22 - %33 = OpLoad %13 %32 - %34 = OpAccessChain %18 %5 %22 - OpStore %34 %33 - OpBranch %29 - %31 = OpLabel - %35 = OpAccessChain %18 %5 %22 - %36 = OpLoad %13 %35 - %37 = OpAccessChain %18 %4 %22 - OpStore %37 %36 - OpBranch %29 - %29 = OpLabel - OpBranch %24 - %24 = OpLabel - %23 = OpIAdd %8 %22 %19 - OpStore %3 %23 - OpBranch %21 - %25 = OpLabel - OpReturn - OpFunctionEnd -)"; - -const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "B" -OpName %5 "A" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %8 10 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 1 -%2 = OpFunction %6 None %7 -%20 = OpLabel -%3 = OpVariable %9 Function -%4 = OpVariable %17 Function -%5 = OpVariable %17 Function -OpStore %3 %10 -OpBranch %38 -%38 = OpLabel -%39 = OpPhi %8 %10 %20 %53 %52 -OpLoopMerge %54 %52 None -OpBranch %40 -%40 = OpLabel -%41 = OpSLessThan %12 %39 %11 -OpBranchConditional %41 %42 %54 -%42 = OpLabel -OpSelectionMerge %51 None -OpSwitch %39 %47 1 %43 -%43 = OpLabel -OpBranch %51 -%47 = OpLabel -%48 = OpAccessChain %18 %4 %39 -%49 = OpLoad %13 %48 -%50 = OpAccessChain %18 %5 %39 -OpStore %50 %49 -OpBranch %51 -%51 = OpLabel -OpBranch %52 -%52 = OpLabel -%53 = OpIAdd %8 %39 %19 -OpStore %3 %53 -OpBranch %38 -%54 = OpLabel -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %8 %10 %54 %23 %24 -OpLoopMerge %25 %24 None -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %22 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -OpSelectionMerge %29 None -OpSwitch %22 %30 1 %31 -%30 = OpLabel -OpBranch %29 -%31 = OpLabel -%35 = OpAccessChain %18 %5 %22 -%36 = OpLoad %13 %35 -%37 = OpAccessChain %18 %4 %22 -OpStore %37 %36 -OpBranch %29 -%29 = OpLabel -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %8 %22 %19 -OpStore %3 %23 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(source, expected, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/nested_loops.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/nested_loops.cpp deleted file mode 100644 index 651cdef44..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/nested_loops.cpp +++ /dev/null @@ -1,795 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/tree_iterator.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; - -bool Validate(const std::vector& bin) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - spv_context spvContext = spvContextCreate(target_env); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {bin.data(), bin.size()}; - spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - return error == 0; -} - -using PassClassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - for (; i < 10; ++i) { - int j = 0; - int k = 0; - for (; j < 11; ++j) {} - for (; k < 12; ++k) {} - } -} -*/ -TEST_F(PassClassTest, BasicVisitFromEntryPoint) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - OpName %5 "j" - OpName %6 "k" - OpName %3 "c" - OpDecorate %3 Location 0 - %7 = OpTypeVoid - %8 = OpTypeFunction %7 - %9 = OpTypeInt 32 1 - %10 = OpTypePointer Function %9 - %11 = OpConstant %9 0 - %12 = OpConstant %9 10 - %13 = OpTypeBool - %14 = OpConstant %9 11 - %15 = OpConstant %9 1 - %16 = OpConstant %9 12 - %17 = OpTypeFloat 32 - %18 = OpTypeVector %17 4 - %19 = OpTypePointer Output %18 - %3 = OpVariable %19 Output - %2 = OpFunction %7 None %8 - %20 = OpLabel - %4 = OpVariable %10 Function - %5 = OpVariable %10 Function - %6 = OpVariable %10 Function - OpStore %4 %11 - OpBranch %21 - %21 = OpLabel - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %25 = OpLoad %9 %4 - %26 = OpSLessThan %13 %25 %12 - OpBranchConditional %26 %27 %22 - %27 = OpLabel - OpStore %5 %11 - OpStore %6 %11 - OpBranch %28 - %28 = OpLabel - OpLoopMerge %29 %30 None - OpBranch %31 - %31 = OpLabel - %32 = OpLoad %9 %5 - %33 = OpSLessThan %13 %32 %14 - OpBranchConditional %33 %34 %29 - %34 = OpLabel - OpBranch %30 - %30 = OpLabel - %35 = OpLoad %9 %5 - %36 = OpIAdd %9 %35 %15 - OpStore %5 %36 - OpBranch %28 - %29 = OpLabel - OpBranch %37 - %37 = OpLabel - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %41 = OpLoad %9 %6 - %42 = OpSLessThan %13 %41 %16 - OpBranchConditional %42 %43 %38 - %43 = OpLabel - OpBranch %39 - %39 = OpLabel - %44 = OpLoad %9 %6 - %45 = OpIAdd %9 %44 %15 - OpStore %6 %45 - OpBranch %37 - %38 = OpLabel - OpBranch %23 - %23 = OpLabel - %46 = OpLoad %9 %4 - %47 = OpIAdd %9 %46 %15 - OpStore %4 %47 - OpBranch %21 - %22 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - EXPECT_EQ(ld.NumLoops(), 3u); - - // Invalid basic block id. - EXPECT_EQ(ld[0u], nullptr); - // Not a loop header. - EXPECT_EQ(ld[20], nullptr); - - Loop& parent_loop = *ld[21]; - EXPECT_TRUE(parent_loop.HasNestedLoops()); - EXPECT_FALSE(parent_loop.IsNested()); - EXPECT_EQ(parent_loop.GetDepth(), 1u); - EXPECT_EQ(std::distance(parent_loop.begin(), parent_loop.end()), 2u); - EXPECT_EQ(parent_loop.GetHeaderBlock(), spvtest::GetBasicBlock(f, 21)); - EXPECT_EQ(parent_loop.GetLatchBlock(), spvtest::GetBasicBlock(f, 23)); - EXPECT_EQ(parent_loop.GetMergeBlock(), spvtest::GetBasicBlock(f, 22)); - - Loop& child_loop_1 = *ld[28]; - EXPECT_FALSE(child_loop_1.HasNestedLoops()); - EXPECT_TRUE(child_loop_1.IsNested()); - EXPECT_EQ(child_loop_1.GetDepth(), 2u); - EXPECT_EQ(std::distance(child_loop_1.begin(), child_loop_1.end()), 0u); - EXPECT_EQ(child_loop_1.GetHeaderBlock(), spvtest::GetBasicBlock(f, 28)); - EXPECT_EQ(child_loop_1.GetLatchBlock(), spvtest::GetBasicBlock(f, 30)); - EXPECT_EQ(child_loop_1.GetMergeBlock(), spvtest::GetBasicBlock(f, 29)); - - Loop& child_loop_2 = *ld[37]; - EXPECT_FALSE(child_loop_2.HasNestedLoops()); - EXPECT_TRUE(child_loop_2.IsNested()); - EXPECT_EQ(child_loop_2.GetDepth(), 2u); - EXPECT_EQ(std::distance(child_loop_2.begin(), child_loop_2.end()), 0u); - EXPECT_EQ(child_loop_2.GetHeaderBlock(), spvtest::GetBasicBlock(f, 37)); - EXPECT_EQ(child_loop_2.GetLatchBlock(), spvtest::GetBasicBlock(f, 39)); - EXPECT_EQ(child_loop_2.GetMergeBlock(), spvtest::GetBasicBlock(f, 38)); -} - -static void CheckLoopBlocks(Loop* loop, - std::unordered_set* expected_ids) { - SCOPED_TRACE("Check loop " + std::to_string(loop->GetHeaderBlock()->id())); - for (uint32_t bb_id : loop->GetBlocks()) { - EXPECT_EQ(expected_ids->count(bb_id), 1u); - expected_ids->erase(bb_id); - } - EXPECT_FALSE(loop->IsInsideLoop(loop->GetMergeBlock())); - EXPECT_EQ(expected_ids->size(), 0u); -} - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - int i = 0; - for (; i < 10; ++i) { - for (int j = 0; j < 11; ++j) { - if (j < 5) { - for (int k = 0; k < 12; ++k) {} - } - else {} - for (int k = 0; k < 12; ++k) {} - } - } -}*/ -TEST_F(PassClassTest, TripleNestedLoop) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - OpName %5 "j" - OpName %6 "k" - OpName %7 "k" - OpName %3 "c" - OpDecorate %3 Location 0 - %8 = OpTypeVoid - %9 = OpTypeFunction %8 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %12 = OpConstant %10 0 - %13 = OpConstant %10 10 - %14 = OpTypeBool - %15 = OpConstant %10 11 - %16 = OpConstant %10 5 - %17 = OpConstant %10 12 - %18 = OpConstant %10 1 - %19 = OpTypeFloat 32 - %20 = OpTypeVector %19 4 - %21 = OpTypePointer Output %20 - %3 = OpVariable %21 Output - %2 = OpFunction %8 None %9 - %22 = OpLabel - %4 = OpVariable %11 Function - %5 = OpVariable %11 Function - %6 = OpVariable %11 Function - %7 = OpVariable %11 Function - OpStore %4 %12 - OpBranch %23 - %23 = OpLabel - OpLoopMerge %24 %25 None - OpBranch %26 - %26 = OpLabel - %27 = OpLoad %10 %4 - %28 = OpSLessThan %14 %27 %13 - OpBranchConditional %28 %29 %24 - %29 = OpLabel - OpStore %5 %12 - OpBranch %30 - %30 = OpLabel - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel - %34 = OpLoad %10 %5 - %35 = OpSLessThan %14 %34 %15 - OpBranchConditional %35 %36 %31 - %36 = OpLabel - %37 = OpLoad %10 %5 - %38 = OpSLessThan %14 %37 %16 - OpSelectionMerge %39 None - OpBranchConditional %38 %40 %39 - %40 = OpLabel - OpStore %6 %12 - OpBranch %41 - %41 = OpLabel - OpLoopMerge %42 %43 None - OpBranch %44 - %44 = OpLabel - %45 = OpLoad %10 %6 - %46 = OpSLessThan %14 %45 %17 - OpBranchConditional %46 %47 %42 - %47 = OpLabel - OpBranch %43 - %43 = OpLabel - %48 = OpLoad %10 %6 - %49 = OpIAdd %10 %48 %18 - OpStore %6 %49 - OpBranch %41 - %42 = OpLabel - OpBranch %39 - %39 = OpLabel - OpStore %7 %12 - OpBranch %50 - %50 = OpLabel - OpLoopMerge %51 %52 None - OpBranch %53 - %53 = OpLabel - %54 = OpLoad %10 %7 - %55 = OpSLessThan %14 %54 %17 - OpBranchConditional %55 %56 %51 - %56 = OpLabel - OpBranch %52 - %52 = OpLabel - %57 = OpLoad %10 %7 - %58 = OpIAdd %10 %57 %18 - OpStore %7 %58 - OpBranch %50 - %51 = OpLabel - OpBranch %32 - %32 = OpLabel - %59 = OpLoad %10 %5 - %60 = OpIAdd %10 %59 %18 - OpStore %5 %60 - OpBranch %30 - %31 = OpLabel - OpBranch %25 - %25 = OpLabel - %61 = OpLoad %10 %4 - %62 = OpIAdd %10 %61 %18 - OpStore %4 %62 - OpBranch %23 - %24 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - EXPECT_EQ(ld.NumLoops(), 4u); - - // Invalid basic block id. - EXPECT_EQ(ld[0u], nullptr); - // Not in a loop. - EXPECT_EQ(ld[22], nullptr); - - // Check that we can map basic block to the correct loop. - // The following block ids do not belong to a loop. - for (uint32_t bb_id : {22, 24}) EXPECT_EQ(ld[bb_id], nullptr); - - { - std::unordered_set basic_block_in_loop = { - {23, 26, 29, 30, 33, 36, 40, 41, 44, 47, 43, - 42, 39, 50, 53, 56, 52, 51, 32, 31, 25}}; - Loop* loop = ld[23]; - CheckLoopBlocks(loop, &basic_block_in_loop); - - EXPECT_TRUE(loop->HasNestedLoops()); - EXPECT_FALSE(loop->IsNested()); - EXPECT_EQ(loop->GetDepth(), 1u); - EXPECT_EQ(std::distance(loop->begin(), loop->end()), 1u); - EXPECT_EQ(loop->GetPreHeaderBlock(), spvtest::GetBasicBlock(f, 22)); - EXPECT_EQ(loop->GetHeaderBlock(), spvtest::GetBasicBlock(f, 23)); - EXPECT_EQ(loop->GetLatchBlock(), spvtest::GetBasicBlock(f, 25)); - EXPECT_EQ(loop->GetMergeBlock(), spvtest::GetBasicBlock(f, 24)); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetMergeBlock())); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetPreHeaderBlock())); - } - - { - std::unordered_set basic_block_in_loop = { - {30, 33, 36, 40, 41, 44, 47, 43, 42, 39, 50, 53, 56, 52, 51, 32}}; - Loop* loop = ld[30]; - CheckLoopBlocks(loop, &basic_block_in_loop); - - EXPECT_TRUE(loop->HasNestedLoops()); - EXPECT_TRUE(loop->IsNested()); - EXPECT_EQ(loop->GetDepth(), 2u); - EXPECT_EQ(std::distance(loop->begin(), loop->end()), 2u); - EXPECT_EQ(loop->GetPreHeaderBlock(), spvtest::GetBasicBlock(f, 29)); - EXPECT_EQ(loop->GetHeaderBlock(), spvtest::GetBasicBlock(f, 30)); - EXPECT_EQ(loop->GetLatchBlock(), spvtest::GetBasicBlock(f, 32)); - EXPECT_EQ(loop->GetMergeBlock(), spvtest::GetBasicBlock(f, 31)); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetMergeBlock())); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetPreHeaderBlock())); - } - - { - std::unordered_set basic_block_in_loop = {{41, 44, 47, 43}}; - Loop* loop = ld[41]; - CheckLoopBlocks(loop, &basic_block_in_loop); - - EXPECT_FALSE(loop->HasNestedLoops()); - EXPECT_TRUE(loop->IsNested()); - EXPECT_EQ(loop->GetDepth(), 3u); - EXPECT_EQ(std::distance(loop->begin(), loop->end()), 0u); - EXPECT_EQ(loop->GetPreHeaderBlock(), spvtest::GetBasicBlock(f, 40)); - EXPECT_EQ(loop->GetHeaderBlock(), spvtest::GetBasicBlock(f, 41)); - EXPECT_EQ(loop->GetLatchBlock(), spvtest::GetBasicBlock(f, 43)); - EXPECT_EQ(loop->GetMergeBlock(), spvtest::GetBasicBlock(f, 42)); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetMergeBlock())); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetPreHeaderBlock())); - } - - { - std::unordered_set basic_block_in_loop = {{50, 53, 56, 52}}; - Loop* loop = ld[50]; - CheckLoopBlocks(loop, &basic_block_in_loop); - - EXPECT_FALSE(loop->HasNestedLoops()); - EXPECT_TRUE(loop->IsNested()); - EXPECT_EQ(loop->GetDepth(), 3u); - EXPECT_EQ(std::distance(loop->begin(), loop->end()), 0u); - EXPECT_EQ(loop->GetPreHeaderBlock(), spvtest::GetBasicBlock(f, 39)); - EXPECT_EQ(loop->GetHeaderBlock(), spvtest::GetBasicBlock(f, 50)); - EXPECT_EQ(loop->GetLatchBlock(), spvtest::GetBasicBlock(f, 52)); - EXPECT_EQ(loop->GetMergeBlock(), spvtest::GetBasicBlock(f, 51)); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetMergeBlock())); - EXPECT_FALSE(loop->IsInsideLoop(loop->GetPreHeaderBlock())); - } - - // Make sure LoopDescriptor gives us the inner most loop when we query for - // loops. - for (const BasicBlock& bb : *f) { - if (Loop* loop = ld[&bb]) { - for (Loop& sub_loop : - make_range(++TreeDFIterator(loop), TreeDFIterator())) { - EXPECT_FALSE(sub_loop.IsInsideLoop(bb.id())); - } - } - } -} - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 11; ++j) { - for (int k = 0; k < 11; ++k) {} - } - for (int k = 0; k < 12; ++k) {} - } -} -*/ -TEST_F(PassClassTest, LoopParentTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - OpName %5 "j" - OpName %6 "k" - OpName %7 "k" - OpName %3 "c" - OpDecorate %3 Location 0 - %8 = OpTypeVoid - %9 = OpTypeFunction %8 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Function %10 - %12 = OpConstant %10 0 - %13 = OpConstant %10 10 - %14 = OpTypeBool - %15 = OpConstant %10 11 - %16 = OpConstant %10 1 - %17 = OpConstant %10 12 - %18 = OpTypeFloat 32 - %19 = OpTypeVector %18 4 - %20 = OpTypePointer Output %19 - %3 = OpVariable %20 Output - %2 = OpFunction %8 None %9 - %21 = OpLabel - %4 = OpVariable %11 Function - %5 = OpVariable %11 Function - %6 = OpVariable %11 Function - %7 = OpVariable %11 Function - OpStore %4 %12 - OpBranch %22 - %22 = OpLabel - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %26 = OpLoad %10 %4 - %27 = OpSLessThan %14 %26 %13 - OpBranchConditional %27 %28 %23 - %28 = OpLabel - OpStore %5 %12 - OpBranch %29 - %29 = OpLabel - OpLoopMerge %30 %31 None - OpBranch %32 - %32 = OpLabel - %33 = OpLoad %10 %5 - %34 = OpSLessThan %14 %33 %15 - OpBranchConditional %34 %35 %30 - %35 = OpLabel - OpStore %6 %12 - OpBranch %36 - %36 = OpLabel - OpLoopMerge %37 %38 None - OpBranch %39 - %39 = OpLabel - %40 = OpLoad %10 %6 - %41 = OpSLessThan %14 %40 %15 - OpBranchConditional %41 %42 %37 - %42 = OpLabel - OpBranch %38 - %38 = OpLabel - %43 = OpLoad %10 %6 - %44 = OpIAdd %10 %43 %16 - OpStore %6 %44 - OpBranch %36 - %37 = OpLabel - OpBranch %31 - %31 = OpLabel - %45 = OpLoad %10 %5 - %46 = OpIAdd %10 %45 %16 - OpStore %5 %46 - OpBranch %29 - %30 = OpLabel - OpStore %7 %12 - OpBranch %47 - %47 = OpLabel - OpLoopMerge %48 %49 None - OpBranch %50 - %50 = OpLabel - %51 = OpLoad %10 %7 - %52 = OpSLessThan %14 %51 %17 - OpBranchConditional %52 %53 %48 - %53 = OpLabel - OpBranch %49 - %49 = OpLabel - %54 = OpLoad %10 %7 - %55 = OpIAdd %10 %54 %16 - OpStore %7 %55 - OpBranch %47 - %48 = OpLabel - OpBranch %24 - %24 = OpLabel - %56 = OpLoad %10 %4 - %57 = OpIAdd %10 %56 %16 - OpStore %4 %57 - OpBranch %22 - %23 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - EXPECT_EQ(ld.NumLoops(), 4u); - - { - Loop& loop = *ld[22]; - EXPECT_TRUE(loop.HasNestedLoops()); - EXPECT_FALSE(loop.IsNested()); - EXPECT_EQ(loop.GetDepth(), 1u); - EXPECT_EQ(loop.GetParent(), nullptr); - } - - { - Loop& loop = *ld[29]; - EXPECT_TRUE(loop.HasNestedLoops()); - EXPECT_TRUE(loop.IsNested()); - EXPECT_EQ(loop.GetDepth(), 2u); - EXPECT_EQ(loop.GetParent(), ld[22]); - } - - { - Loop& loop = *ld[36]; - EXPECT_FALSE(loop.HasNestedLoops()); - EXPECT_TRUE(loop.IsNested()); - EXPECT_EQ(loop.GetDepth(), 3u); - EXPECT_EQ(loop.GetParent(), ld[29]); - } - - { - Loop& loop = *ld[47]; - EXPECT_FALSE(loop.HasNestedLoops()); - EXPECT_TRUE(loop.IsNested()); - EXPECT_EQ(loop.GetDepth(), 2u); - EXPECT_EQ(loop.GetParent(), ld[22]); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store -The preheader of loop %33 and %41 were removed as well. - -#version 330 core -void main() { - int a = 0; - for (int i = 0; i < 10; ++i) { - if (i == 0) { - a = 1; - } else { - a = 2; - } - for (int j = 0; j < 11; ++j) { - a++; - } - } - for (int k = 0; k < 12; ++k) {} -} -*/ -TEST_F(PassClassTest, CreatePreheaderTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpConstant %5 0 - %8 = OpConstant %5 10 - %9 = OpTypeBool - %10 = OpConstant %5 1 - %11 = OpConstant %5 2 - %12 = OpConstant %5 11 - %13 = OpConstant %5 12 - %14 = OpUndef %5 - %2 = OpFunction %3 None %4 - %15 = OpLabel - OpBranch %16 - %16 = OpLabel - %17 = OpPhi %5 %7 %15 %18 %19 - %20 = OpPhi %5 %7 %15 %21 %19 - %22 = OpPhi %5 %14 %15 %23 %19 - OpLoopMerge %41 %19 None - OpBranch %25 - %25 = OpLabel - %26 = OpSLessThan %9 %20 %8 - OpBranchConditional %26 %27 %41 - %27 = OpLabel - %28 = OpIEqual %9 %20 %7 - OpSelectionMerge %33 None - OpBranchConditional %28 %30 %31 - %30 = OpLabel - OpBranch %33 - %31 = OpLabel - OpBranch %33 - %33 = OpLabel - %18 = OpPhi %5 %10 %30 %11 %31 %34 %35 - %23 = OpPhi %5 %7 %30 %7 %31 %36 %35 - OpLoopMerge %37 %35 None - OpBranch %38 - %38 = OpLabel - %39 = OpSLessThan %9 %23 %12 - OpBranchConditional %39 %40 %37 - %40 = OpLabel - %34 = OpIAdd %5 %18 %10 - OpBranch %35 - %35 = OpLabel - %36 = OpIAdd %5 %23 %10 - OpBranch %33 - %37 = OpLabel - OpBranch %19 - %19 = OpLabel - %21 = OpIAdd %5 %20 %10 - OpBranch %16 - %41 = OpLabel - %42 = OpPhi %5 %7 %25 %43 %44 - OpLoopMerge %45 %44 None - OpBranch %46 - %46 = OpLabel - %47 = OpSLessThan %9 %42 %13 - OpBranchConditional %47 %48 %45 - %48 = OpLabel - OpBranch %44 - %44 = OpLabel - %43 = OpIAdd %5 %42 %10 - OpBranch %41 - %45 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - // No invalidation of the cfg should occur during this test. - CFG* cfg = context->cfg(); - - EXPECT_EQ(ld.NumLoops(), 3u); - - { - Loop& loop = *ld[16]; - EXPECT_TRUE(loop.HasNestedLoops()); - EXPECT_FALSE(loop.IsNested()); - EXPECT_EQ(loop.GetDepth(), 1u); - EXPECT_EQ(loop.GetParent(), nullptr); - } - - { - Loop& loop = *ld[33]; - EXPECT_EQ(loop.GetPreHeaderBlock(), nullptr); - EXPECT_NE(loop.GetOrCreatePreHeaderBlock(), nullptr); - // Make sure the loop descriptor was properly updated. - EXPECT_EQ(ld[loop.GetPreHeaderBlock()], ld[16]); - { - const std::vector& preds = - cfg->preds(loop.GetPreHeaderBlock()->id()); - std::unordered_set pred_set(preds.begin(), preds.end()); - EXPECT_EQ(pred_set.size(), 2u); - EXPECT_TRUE(pred_set.count(30)); - EXPECT_TRUE(pred_set.count(31)); - // Check the phi instructions. - loop.GetPreHeaderBlock()->ForEachPhiInst([&pred_set](Instruction* phi) { - for (uint32_t i = 1; i < phi->NumInOperands(); i += 2) { - EXPECT_TRUE(pred_set.count(phi->GetSingleWordInOperand(i))); - } - }); - } - { - const std::vector& preds = - cfg->preds(loop.GetHeaderBlock()->id()); - std::unordered_set pred_set(preds.begin(), preds.end()); - EXPECT_EQ(pred_set.size(), 2u); - EXPECT_TRUE(pred_set.count(loop.GetPreHeaderBlock()->id())); - EXPECT_TRUE(pred_set.count(35)); - // Check the phi instructions. - loop.GetHeaderBlock()->ForEachPhiInst([&pred_set](Instruction* phi) { - for (uint32_t i = 1; i < phi->NumInOperands(); i += 2) { - EXPECT_TRUE(pred_set.count(phi->GetSingleWordInOperand(i))); - } - }); - } - } - - { - Loop& loop = *ld[41]; - EXPECT_EQ(loop.GetPreHeaderBlock(), nullptr); - EXPECT_NE(loop.GetOrCreatePreHeaderBlock(), nullptr); - EXPECT_EQ(ld[loop.GetPreHeaderBlock()], nullptr); - EXPECT_EQ(cfg->preds(loop.GetPreHeaderBlock()->id()).size(), 1u); - EXPECT_EQ(cfg->preds(loop.GetPreHeaderBlock()->id())[0], 25u); - // Check the phi instructions. - loop.GetPreHeaderBlock()->ForEachPhiInst([](Instruction* phi) { - EXPECT_EQ(phi->NumInOperands(), 2u); - EXPECT_EQ(phi->GetSingleWordInOperand(1), 25u); - }); - { - const std::vector& preds = - cfg->preds(loop.GetHeaderBlock()->id()); - std::unordered_set pred_set(preds.begin(), preds.end()); - EXPECT_EQ(pred_set.size(), 2u); - EXPECT_TRUE(pred_set.count(loop.GetPreHeaderBlock()->id())); - EXPECT_TRUE(pred_set.count(44)); - // Check the phi instructions. - loop.GetHeaderBlock()->ForEachPhiInst([&pred_set](Instruction* phi) { - for (uint32_t i = 1; i < phi->NumInOperands(); i += 2) { - EXPECT_TRUE(pred_set.count(phi->GetSingleWordInOperand(i))); - } - }); - } - } - - // Make sure pre-header insertion leaves the module valid. - std::vector bin; - context->module()->ToBinary(&bin, true); - EXPECT_TRUE(Validate(bin)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/pch_test_opt_loop.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/pch_test_opt_loop.cpp deleted file mode 100644 index f4ac7b298..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/pch_test_opt_loop.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "pch_test_opt_loop.h" diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/pch_test_opt_loop.h b/3rdparty/spirv-tools/test/opt/loop_optimizations/pch_test_opt_loop.h deleted file mode 100644 index 4e8106fbf..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/pch_test_opt_loop.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_dependence.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/scalar_analysis.h" -#include "source/opt/tree_iterator.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/peeling.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/peeling.cpp deleted file mode 100644 index 10d8add38..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/peeling.cpp +++ /dev/null @@ -1,1186 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "effcee/effcee.h" -#include "gmock/gmock.h" -#include "source/opt/ir_builder.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/loop_peeling.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using PeelingTest = PassTest<::testing::Test>; - -bool Validate(const std::vector& bin) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - spv_context spvContext = spvContextCreate(target_env); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {bin.data(), bin.size()}; - spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - return error == 0; -} - -void Match(const std::string& checks, IRContext* context) { - // Silence unused warnings with !defined(SPIRV_EFFCE) - (void)checks; - - std::vector bin; - context->module()->ToBinary(&bin, true); - EXPECT_TRUE(Validate(bin)); - std::string assembly; - SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); - EXPECT_TRUE( - tools.Disassemble(bin, &assembly, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) - << "Disassembling failed for shader:\n" - << assembly << std::endl; - auto match_result = effcee::Match(assembly, checks); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking result:\n" - << assembly; -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -First test: -#version 330 core -void main() { - for(int i = 0; i < 10; ++i) { - if (i < 4) - break; - } -} - -Second test (with a common sub-expression elimination): -#version 330 core -void main() { - for(int i = 0; i + 1 < 10; ++i) { - } -} - -Third test: -#version 330 core -void main() { - int a[10]; - for (int i = 0; a[i] != 0; i++) {} -} - -Forth test: -#version 330 core -void main() { - for (long i = 0; i < 10; i++) {} -} - -Fifth test: -#version 330 core -void main() { - for (float i = 0; i < 10; i++) {} -} - -Sixth test: -#version 450 -layout(location = 0)out float o; -void main() { - o = 0.0; - for( int i = 0; true; i++ ) { - o += 1.0; - if (i > 10) break; - } -} -*/ -TEST_F(PeelingTest, CannotPeel) { - // Build the given SPIR-V program in |text|, take the first loop in the first - // function and test that it is not peelable. |loop_count_id| is the id - // representing the loop count, if equals to 0, then the function build a 10 - // constant as loop count. - auto test_cannot_peel = [](const std::string& text, uint32_t loop_count_id) { - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - Instruction* loop_count = nullptr; - if (loop_count_id) { - loop_count = context->get_def_use_mgr()->GetDef(loop_count_id); - } else { - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - loop_count = builder.GetSintConstant(10); - } - - LoopPeeling peel(&*ld.begin(), loop_count); - EXPECT_FALSE(peel.CanPeelLoop()); - }; - { - SCOPED_TRACE("loop with break"); - - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_4 = OpConstant %int 4 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %28 = OpPhi %int %int_0 %5 %27 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %bool %28 %int_10 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %21 = OpSLessThan %bool %28 %int_4 - OpSelectionMerge %23 None - OpBranchConditional %21 %22 %23 - %22 = OpLabel - OpBranch %12 - %23 = OpLabel - OpBranch %13 - %13 = OpLabel - %27 = OpIAdd %int %28 %int_1 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - test_cannot_peel(text, 0); - } - - { - SCOPED_TRACE("Ambiguous iterator update"); - - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %23 = OpPhi %int %int_0 %5 %17 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %17 = OpIAdd %int %23 %int_1 - %20 = OpSLessThan %bool %17 %int_10 - OpBranchConditional %20 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - test_cannot_peel(text, 0); - } - - { - SCOPED_TRACE("No loop static bounds"); - - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - OpName %i "i" - OpName %a "a" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_int_uint_10 = OpTypeArray %int %uint_10 -%_ptr_Function__arr_int_uint_10 = OpTypePointer Function %_arr_int_uint_10 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %i = OpVariable %_ptr_Function_int Function - %a = OpVariable %_ptr_Function__arr_int_uint_10 Function - OpStore %i %int_0 - OpBranch %10 - %10 = OpLabel - %28 = OpPhi %int %int_0 %5 %27 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %21 = OpAccessChain %_ptr_Function_int %a %28 - %22 = OpLoad %int %21 - %24 = OpINotEqual %bool %22 %int_0 - OpBranchConditional %24 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %27 = OpIAdd %int %28 %int_1 - OpStore %i %27 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - test_cannot_peel(text, 22); - } - { - SCOPED_TRACE("Int 64 type for conditions"); - - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginLowerLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - %6 = OpTypeVoid - %3 = OpTypeFunction %6 - %7 = OpTypeInt 64 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %15 = OpConstant %7 10 - %16 = OpTypeBool - %17 = OpConstant %7 1 - %2 = OpFunction %6 None %3 - %5 = OpLabel - %4 = OpVariable %8 Function - OpStore %4 %9 - OpBranch %10 - %10 = OpLabel - %22 = OpPhi %7 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %16 %22 %15 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %7 %22 %17 - OpStore %4 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - // %15 is a constant for a 64 int. Currently rejected. - test_cannot_peel(text, 15); - } - { - SCOPED_TRACE("Float type for conditions"); - - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginLowerLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %4 "i" - %6 = OpTypeVoid - %3 = OpTypeFunction %6 - %7 = OpTypeFloat 32 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %15 = OpConstant %7 10 - %16 = OpTypeBool - %17 = OpConstant %7 1 - %2 = OpFunction %6 None %3 - %5 = OpLabel - %4 = OpVariable %8 Function - OpStore %4 %9 - OpBranch %10 - %10 = OpLabel - %22 = OpPhi %7 %9 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpFOrdLessThan %16 %22 %15 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpFAdd %7 %22 %17 - OpStore %4 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - // %15 is a constant for a float. Currently rejected. - test_cannot_peel(text, 15); - } - { - SCOPED_TRACE("Side effect before exit"); - - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %o - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 450 - OpName %main "main" - OpName %o "o" - OpName %i "i" - OpDecorate %o Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float - %o = OpVariable %_ptr_Output_float Output - %float_0 = OpConstant %float 0 - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %float_1 = OpConstant %float 1 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %i = OpVariable %_ptr_Function_int Function - OpStore %o %float_0 - OpStore %i %int_0 - OpBranch %14 - %14 = OpLabel - %33 = OpPhi %int %int_0 %5 %32 %17 - OpLoopMerge %16 %17 None - OpBranch %15 - %15 = OpLabel - %22 = OpLoad %float %o - %23 = OpFAdd %float %22 %float_1 - OpStore %o %23 - %26 = OpSGreaterThan %bool %33 %int_10 - OpSelectionMerge %28 None - OpBranchConditional %26 %27 %28 - %27 = OpLabel - OpBranch %16 - %28 = OpLabel - OpBranch %17 - %17 = OpLabel - %32 = OpIAdd %int %33 %int_1 - OpStore %i %32 - OpBranch %14 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - test_cannot_peel(text, 0); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -void main() { - int i = 0; - for (; i < 10; i++) {} -} -*/ -TEST_F(PeelingTest, SimplePeeling) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %22 = OpPhi %int %int_0 %5 %21 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %bool %22 %int_10 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %21 = OpIAdd %int %22 %int_1 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Peel before. - { - SCOPED_TRACE("Peel before"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - Instruction* ten_cst = builder.GetSintConstant(10); - - LoopPeeling peel(&*ld.begin(), ten_cst); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelBefore(2); - - const std::string check = R"( -CHECK: [[CST_TEN:%\w+]] = OpConstant {{%\w+}} 10 -CHECK: [[CST_TWO:%\w+]] = OpConstant {{%\w+}} 2 -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} [[CST_TWO]] [[CST_TEN]] -CHECK-NEXT: [[LOOP_COUNT:%\w+]] = OpSelect {{%\w+}} [[MIN_LOOP_COUNT]] [[CST_TWO]] [[CST_TEN]] -CHECK: [[BEFORE_LOOP:%\w+]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[i:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[AFTER_LOOP_PREHEADER:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[AFTER_LOOP_PREHEADER]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[i]] -CHECK-NEXT: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[AFTER_LOOP_PREHEADER]] = OpLabel -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[AFTER_LOOP:%\w+]] [[IF_MERGE]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[i]] [[AFTER_LOOP_PREHEADER]] -CHECK-NEXT: OpLoopMerge -)"; - - Match(check, context.get()); - } - - // Peel after. - { - SCOPED_TRACE("Peel after"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - Instruction* ten_cst = builder.GetSintConstant(10); - - LoopPeeling peel(&*ld.begin(), ten_cst); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelAfter(2); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[BEFORE_LOOP:%\w+]] [[IF_MERGE]] -CHECK: [[BEFORE_LOOP]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[I:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[BEFORE_LOOP_MERGE:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[TMP:%\w+]] = OpIAdd {{%\w+}} [[DUMMY_IT]] {{%\w+}} -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[TMP]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[BEFORE_LOOP_MERGE]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[I]] -CHECK-NEXT: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[IF_MERGE]] = OpLabel -CHECK-NEXT: [[TMP:%\w+]] = OpPhi {{%\w+}} [[I]] [[BEFORE_LOOP_MERGE]] -CHECK-NEXT: OpBranch [[AFTER_LOOP:%\w+]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[TMP]] [[IF_MERGE]] -CHECK-NEXT: OpLoopMerge - -)"; - - Match(check, context.get()); - } - - // Same as above, but reuse the induction variable. - // Peel before. - { - SCOPED_TRACE("Peel before with IV reuse"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - Instruction* ten_cst = builder.GetSintConstant(10); - - LoopPeeling peel(&*ld.begin(), ten_cst, - context->get_def_use_mgr()->GetDef(22)); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelBefore(2); - - const std::string check = R"( -CHECK: [[CST_TEN:%\w+]] = OpConstant {{%\w+}} 10 -CHECK: [[CST_TWO:%\w+]] = OpConstant {{%\w+}} 2 -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} [[CST_TWO]] [[CST_TEN]] -CHECK-NEXT: [[LOOP_COUNT:%\w+]] = OpSelect {{%\w+}} [[MIN_LOOP_COUNT]] [[CST_TWO]] [[CST_TEN]] -CHECK: [[BEFORE_LOOP:%\w+]] = OpLabel -CHECK-NEXT: [[i:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: OpLoopMerge [[AFTER_LOOP_PREHEADER:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[i]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[AFTER_LOOP_PREHEADER]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[i]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[AFTER_LOOP_PREHEADER]] = OpLabel -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[AFTER_LOOP:%\w+]] [[IF_MERGE]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[i]] [[AFTER_LOOP_PREHEADER]] -CHECK-NEXT: OpLoopMerge -)"; - - Match(check, context.get()); - } - - // Peel after. - { - SCOPED_TRACE("Peel after IV reuse"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - Instruction* ten_cst = builder.GetSintConstant(10); - - LoopPeeling peel(&*ld.begin(), ten_cst, - context->get_def_use_mgr()->GetDef(22)); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelAfter(2); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[BEFORE_LOOP:%\w+]] [[IF_MERGE]] -CHECK: [[BEFORE_LOOP]] = OpLabel -CHECK-NEXT: [[I:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: OpLoopMerge [[BEFORE_LOOP_MERGE:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[TMP:%\w+]] = OpIAdd {{%\w+}} [[I]] {{%\w+}} -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[TMP]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[BEFORE_LOOP_MERGE]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[I]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[IF_MERGE]] = OpLabel -CHECK-NEXT: [[TMP:%\w+]] = OpPhi {{%\w+}} [[I]] [[BEFORE_LOOP_MERGE]] -CHECK-NEXT: OpBranch [[AFTER_LOOP:%\w+]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[TMP]] [[IF_MERGE]] -CHECK-NEXT: OpLoopMerge - -)"; - - Match(check, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -void main() { - int a[10]; - int n = a[0]; - for(int i = 0; i < n; ++i) {} -} -*/ -TEST_F(PeelingTest, PeelingUncountable) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - OpName %a "a" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_int_uint_10 = OpTypeArray %int %uint_10 -%_ptr_Function__arr_int_uint_10 = OpTypePointer Function %_arr_int_uint_10 - %int_0 = OpConstant %int 0 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %a = OpVariable %_ptr_Function__arr_int_uint_10 Function - %15 = OpAccessChain %_ptr_Function_int %a %int_0 - %16 = OpLoad %int %15 - OpBranch %18 - %18 = OpLabel - %30 = OpPhi %int %int_0 %5 %29 %21 - OpLoopMerge %20 %21 None - OpBranch %22 - %22 = OpLabel - %26 = OpSLessThan %bool %30 %16 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - OpBranch %21 - %21 = OpLabel - %29 = OpIAdd %int %30 %int_1 - OpBranch %18 - %20 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Peel before. - { - SCOPED_TRACE("Peel before"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - Instruction* loop_count = context->get_def_use_mgr()->GetDef(16); - EXPECT_EQ(loop_count->opcode(), SpvOpLoad); - - LoopPeeling peel(&*ld.begin(), loop_count); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelBefore(1); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[LOOP_COUNT:%\w+]] = OpLoad -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} {{%\w+}} [[LOOP_COUNT]] -CHECK-NEXT: [[LOOP_COUNT:%\w+]] = OpSelect {{%\w+}} [[MIN_LOOP_COUNT]] {{%\w+}} [[LOOP_COUNT]] -CHECK: [[BEFORE_LOOP:%\w+]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[i:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[AFTER_LOOP_PREHEADER:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[AFTER_LOOP_PREHEADER]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[i]] -CHECK-NEXT: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[AFTER_LOOP_PREHEADER]] = OpLabel -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[AFTER_LOOP:%\w+]] [[IF_MERGE]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[i]] [[AFTER_LOOP_PREHEADER]] -CHECK-NEXT: OpLoopMerge -)"; - - Match(check, context.get()); - } - - // Peel after. - { - SCOPED_TRACE("Peel after"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - Instruction* loop_count = context->get_def_use_mgr()->GetDef(16); - EXPECT_EQ(loop_count->opcode(), SpvOpLoad); - - LoopPeeling peel(&*ld.begin(), loop_count); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelAfter(1); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[BEFORE_LOOP:%\w+]] [[IF_MERGE]] -CHECK: [[BEFORE_LOOP]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[I:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[BEFORE_LOOP_MERGE:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[TMP:%\w+]] = OpIAdd {{%\w+}} [[DUMMY_IT]] {{%\w+}} -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[TMP]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[BEFORE_LOOP_MERGE]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[I]] -CHECK-NEXT: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[IF_MERGE]] = OpLabel -CHECK-NEXT: [[TMP:%\w+]] = OpPhi {{%\w+}} [[I]] [[BEFORE_LOOP_MERGE]] -CHECK-NEXT: OpBranch [[AFTER_LOOP:%\w+]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[TMP]] [[IF_MERGE]] -CHECK-NEXT: OpLoopMerge - -)"; - - Match(check, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -void main() { - int i = 0; - do { - i++; - } while (i < 10); -} -*/ -TEST_F(PeelingTest, DoWhilePeeling) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %21 = OpPhi %int %int_0 %5 %16 %13 - OpLoopMerge %12 %13 None - OpBranch %11 - %11 = OpLabel - %16 = OpIAdd %int %21 %int_1 - OpBranch %13 - %13 = OpLabel - %20 = OpSLessThan %bool %16 %int_10 - OpBranchConditional %20 %10 %12 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Peel before. - { - SCOPED_TRACE("Peel before"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - Instruction* ten_cst = builder.GetUintConstant(10); - - LoopPeeling peel(&*ld.begin(), ten_cst); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelBefore(2); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpULessThan {{%\w+}} -CHECK-NEXT: [[LOOP_COUNT:%\w+]] = OpSelect {{%\w+}} [[MIN_LOOP_COUNT]] -CHECK: [[BEFORE_LOOP:%\w+]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[i:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[AFTER_LOOP_PREHEADER:%\w+]] [[BE]] None -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[i]] -CHECK: [[BE]] = OpLabel -CHECK: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpULessThan {{%\w+}} [[DUMMY_IT_1]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] [[BEFORE_LOOP]] [[AFTER_LOOP_PREHEADER]] - -CHECK: [[AFTER_LOOP_PREHEADER]] = OpLabel -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[AFTER_LOOP:%\w+]] [[IF_MERGE]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[I_1]] [[AFTER_LOOP_PREHEADER]] -CHECK-NEXT: OpLoopMerge -)"; - - Match(check, context.get()); - } - - // Peel after. - { - SCOPED_TRACE("Peel after"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - InstructionBuilder builder(context.get(), &*f.begin()); - // Exit condition. - Instruction* ten_cst = builder.GetUintConstant(10); - - LoopPeeling peel(&*ld.begin(), ten_cst); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelAfter(2); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpULessThan {{%\w+}} -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[BEFORE_LOOP:%\w+]] [[IF_MERGE]] -CHECK: [[BEFORE_LOOP]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[I:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[BEFORE_LOOP_MERGE:%\w+]] [[BE]] None -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[I]] -CHECK: [[BE]] = OpLabel -CHECK: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: [[EXIT_VAL:%\w+]] = OpIAdd {{%\w+}} [[DUMMY_IT_1]] -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpULessThan {{%\w+}} [[EXIT_VAL]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] [[BEFORE_LOOP]] [[BEFORE_LOOP_MERGE]] - -CHECK: [[IF_MERGE]] = OpLabel -CHECK-NEXT: [[TMP:%\w+]] = OpPhi {{%\w+}} [[I_1]] [[BEFORE_LOOP_MERGE]] -CHECK-NEXT: OpBranch [[AFTER_LOOP:%\w+]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[TMP]] [[IF_MERGE]] -CHECK-NEXT: OpLoopMerge -)"; - - Match(check, context.get()); - } -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -void main() { - int a[10]; - int n = a[0]; - for(int i = 0; i < n; ++i) {} -} -*/ -TEST_F(PeelingTest, PeelingLoopWithStore) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %o %n - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 450 - OpName %main "main" - OpName %o "o" - OpName %end "end" - OpName %n "n" - OpName %i "i" - OpDecorate %o Location 0 - OpDecorate %n Flat - OpDecorate %n Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float - %o = OpVariable %_ptr_Output_float Output - %float_0 = OpConstant %float 0 - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%_ptr_Input_int = OpTypePointer Input %int - %n = OpVariable %_ptr_Input_int Input - %int_0 = OpConstant %int 0 - %bool = OpTypeBool - %float_1 = OpConstant %float 1 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %end = OpVariable %_ptr_Function_int Function - %i = OpVariable %_ptr_Function_int Function - OpStore %o %float_0 - %15 = OpLoad %int %n - OpStore %end %15 - OpStore %i %int_0 - OpBranch %18 - %18 = OpLabel - %33 = OpPhi %int %int_0 %5 %32 %21 - OpLoopMerge %20 %21 None - OpBranch %22 - %22 = OpLabel - %26 = OpSLessThan %bool %33 %15 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %28 = OpLoad %float %o - %29 = OpFAdd %float %28 %float_1 - OpStore %o %29 - OpBranch %21 - %21 = OpLabel - %32 = OpIAdd %int %33 %int_1 - OpStore %i %32 - OpBranch %18 - %20 = OpLabel - OpReturn - OpFunctionEnd - )"; - - // Peel before. - { - SCOPED_TRACE("Peel before"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - Instruction* loop_count = context->get_def_use_mgr()->GetDef(15); - EXPECT_EQ(loop_count->opcode(), SpvOpLoad); - - LoopPeeling peel(&*ld.begin(), loop_count); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelBefore(1); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[LOOP_COUNT:%\w+]] = OpLoad -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} {{%\w+}} [[LOOP_COUNT]] -CHECK-NEXT: [[LOOP_COUNT:%\w+]] = OpSelect {{%\w+}} [[MIN_LOOP_COUNT]] {{%\w+}} [[LOOP_COUNT]] -CHECK: [[BEFORE_LOOP:%\w+]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[i:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[AFTER_LOOP_PREHEADER:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[AFTER_LOOP_PREHEADER]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[i]] -CHECK: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[AFTER_LOOP_PREHEADER]] = OpLabel -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[AFTER_LOOP:%\w+]] [[IF_MERGE]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[i]] [[AFTER_LOOP_PREHEADER]] -CHECK-NEXT: OpLoopMerge -)"; - - Match(check, context.get()); - } - - // Peel after. - { - SCOPED_TRACE("Peel after"); - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function& f = *module->begin(); - LoopDescriptor& ld = *context->GetLoopDescriptor(&f); - - EXPECT_EQ(ld.NumLoops(), 1u); - - Instruction* loop_count = context->get_def_use_mgr()->GetDef(15); - EXPECT_EQ(loop_count->opcode(), SpvOpLoad); - - LoopPeeling peel(&*ld.begin(), loop_count); - EXPECT_TRUE(peel.CanPeelLoop()); - peel.PeelAfter(1); - - const std::string check = R"( -CHECK: OpFunction -CHECK-NEXT: [[ENTRY:%\w+]] = OpLabel -CHECK: [[MIN_LOOP_COUNT:%\w+]] = OpSLessThan {{%\w+}} -CHECK-NEXT: OpSelectionMerge [[IF_MERGE:%\w+]] -CHECK-NEXT: OpBranchConditional [[MIN_LOOP_COUNT]] [[BEFORE_LOOP:%\w+]] [[IF_MERGE]] -CHECK: [[BEFORE_LOOP]] = OpLabel -CHECK-NEXT: [[DUMMY_IT:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[DUMMY_IT_1:%\w+]] [[BE:%\w+]] -CHECK-NEXT: [[I:%\w+]] = OpPhi {{%\w+}} {{%\w+}} [[ENTRY]] [[I_1:%\w+]] [[BE]] -CHECK-NEXT: OpLoopMerge [[BEFORE_LOOP_MERGE:%\w+]] [[BE]] None -CHECK: [[COND_BLOCK:%\w+]] = OpLabel -CHECK-NEXT: OpSLessThan -CHECK-NEXT: [[TMP:%\w+]] = OpIAdd {{%\w+}} [[DUMMY_IT]] {{%\w+}} -CHECK-NEXT: [[EXIT_COND:%\w+]] = OpSLessThan {{%\w+}} [[TMP]] -CHECK-NEXT: OpBranchConditional [[EXIT_COND]] {{%\w+}} [[BEFORE_LOOP_MERGE]] -CHECK: [[I_1]] = OpIAdd {{%\w+}} [[I]] -CHECK: [[DUMMY_IT_1]] = OpIAdd {{%\w+}} [[DUMMY_IT]] -CHECK-NEXT: OpBranch [[BEFORE_LOOP]] - -CHECK: [[IF_MERGE]] = OpLabel -CHECK-NEXT: [[TMP:%\w+]] = OpPhi {{%\w+}} [[I]] [[BEFORE_LOOP_MERGE]] -CHECK-NEXT: OpBranch [[AFTER_LOOP:%\w+]] - -CHECK: [[AFTER_LOOP]] = OpLabel -CHECK-NEXT: OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[TMP]] [[IF_MERGE]] -CHECK-NEXT: OpLoopMerge - -)"; - - Match(check, context.get()); - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/peeling_pass.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/peeling_pass.cpp deleted file mode 100644 index 284ad838d..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/peeling_pass.cpp +++ /dev/null @@ -1,1099 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/ir_builder.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/loop_peeling.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -class PeelingPassTest : public PassTest<::testing::Test> { - public: - // Generic routine to run the loop peeling pass and check - LoopPeelingPass::LoopPeelingStats AssembleAndRunPeelingTest( - const std::string& text_head, const std::string& text_tail, SpvOp opcode, - const std::string& res_id, const std::string& op1, - const std::string& op2) { - std::string opcode_str; - switch (opcode) { - case SpvOpSLessThan: - opcode_str = "OpSLessThan"; - break; - case SpvOpSGreaterThan: - opcode_str = "OpSGreaterThan"; - break; - case SpvOpSLessThanEqual: - opcode_str = "OpSLessThanEqual"; - break; - case SpvOpSGreaterThanEqual: - opcode_str = "OpSGreaterThanEqual"; - break; - case SpvOpIEqual: - opcode_str = "OpIEqual"; - break; - case SpvOpINotEqual: - opcode_str = "OpINotEqual"; - break; - default: - assert(false && "Unhandled"); - break; - } - std::string test_cond = - res_id + " = " + opcode_str + " %bool " + op1 + " " + op2 + "\n"; - - LoopPeelingPass::LoopPeelingStats stats; - SinglePassRunAndDisassemble( - text_head + test_cond + text_tail, true, true, &stats); - - return stats; - } - - // Generic routine to run the loop peeling pass and check - LoopPeelingPass::LoopPeelingStats RunPeelingTest( - const std::string& text_head, const std::string& text_tail, SpvOp opcode, - const std::string& res_id, const std::string& op1, const std::string& op2, - size_t nb_of_loops) { - LoopPeelingPass::LoopPeelingStats stats = AssembleAndRunPeelingTest( - text_head, text_tail, opcode, res_id, op1, op2); - - Function& f = *context()->module()->begin(); - LoopDescriptor& ld = *context()->GetLoopDescriptor(&f); - EXPECT_EQ(ld.NumLoops(), nb_of_loops); - - return stats; - } - - using PeelTraceType = - std::vector>; - - void BuildAndCheckTrace(const std::string& text_head, - const std::string& text_tail, SpvOp opcode, - const std::string& res_id, const std::string& op1, - const std::string& op2, - const PeelTraceType& expected_peel_trace, - size_t expected_nb_of_loops) { - auto stats = RunPeelingTest(text_head, text_tail, opcode, res_id, op1, op2, - expected_nb_of_loops); - - EXPECT_EQ(stats.peeled_loops_.size(), expected_peel_trace.size()); - if (stats.peeled_loops_.size() != expected_peel_trace.size()) { - return; - } - - PeelTraceType::const_iterator expected_trace_it = - expected_peel_trace.begin(); - decltype(stats.peeled_loops_)::const_iterator stats_it = - stats.peeled_loops_.begin(); - - while (expected_trace_it != expected_peel_trace.end()) { - EXPECT_EQ(expected_trace_it->first, std::get<1>(*stats_it)); - EXPECT_EQ(expected_trace_it->second, std::get<2>(*stats_it)); - ++expected_trace_it; - ++stats_it; - } - } -}; - -/* -Test are derivation of the following generated test from the following GLSL + ---eliminate-local-multi-store - -#version 330 core -void main() { - int a = 0; - for(int i = 1; i < 10; i += 2) { - if (i < 3) { - a += 2; - } - } -} - -The condition is interchanged to test < > <= >= == and peel before/after -opportunities. -*/ -TEST_F(PeelingPassTest, PeelingPassBasic) { - const std::string text_head = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - OpName %a "a" - OpName %i "i" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %bool = OpTypeBool - %int_20 = OpConstant %int 20 - %int_19 = OpConstant %int 19 - %int_18 = OpConstant %int 18 - %int_17 = OpConstant %int 17 - %int_16 = OpConstant %int 16 - %int_15 = OpConstant %int 15 - %int_14 = OpConstant %int 14 - %int_13 = OpConstant %int 13 - %int_12 = OpConstant %int 12 - %int_11 = OpConstant %int 11 - %int_10 = OpConstant %int 10 - %int_9 = OpConstant %int 9 - %int_8 = OpConstant %int 8 - %int_7 = OpConstant %int 7 - %int_6 = OpConstant %int 6 - %int_5 = OpConstant %int 5 - %int_4 = OpConstant %int 4 - %int_3 = OpConstant %int 3 - %int_2 = OpConstant %int 2 - %int_1 = OpConstant %int 1 - %int_0 = OpConstant %int 0 - %main = OpFunction %void None %3 - %5 = OpLabel - %a = OpVariable %_ptr_Function_int Function - %i = OpVariable %_ptr_Function_int Function - OpStore %a %int_0 - OpStore %i %int_0 - OpBranch %11 - %11 = OpLabel - %31 = OpPhi %int %int_0 %5 %33 %14 - %32 = OpPhi %int %int_1 %5 %30 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %bool %32 %int_20 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - )"; - const std::string text_tail = R"( - OpSelectionMerge %24 None - OpBranchConditional %22 %23 %24 - %23 = OpLabel - %27 = OpIAdd %int %31 %int_2 - OpStore %a %27 - OpBranch %24 - %24 = OpLabel - %33 = OpPhi %int %31 %12 %27 %23 - OpBranch %14 - %14 = OpLabel - %30 = OpIAdd %int %32 %int_2 - OpStore %i %30 - OpBranch %11 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto run_test = [&text_head, &text_tail, this](SpvOp opcode, - const std::string& op1, - const std::string& op2) { - auto stats = - RunPeelingTest(text_head, text_tail, opcode, "%22", op1, op2, 2); - - EXPECT_EQ(stats.peeled_loops_.size(), 1u); - if (stats.peeled_loops_.size() != 1u) - return std::pair{ - LoopPeelingPass::PeelDirection::kNone, 0}; - - return std::pair{ - std::get<1>(*stats.peeled_loops_.begin()), - std::get<2>(*stats.peeled_loops_.begin())}; - }; - - // Test LT - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv < 4"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%32", "%int_4"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 4 > iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%int_4", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before iv < 5"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%32", "%int_5"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 5 > iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%int_5", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv < 16"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%32", "%int_16"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 16 > iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%int_16", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after iv < 17"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%32", "%int_17"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 17 > iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%int_17", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - - // Test GT - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv > 5"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%32", "%int_5"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 5 < iv"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%int_5", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before iv > 4"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%32", "%int_4"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 4 < iv"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%int_4", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv > 16"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%32", "%int_16"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 16 < iv"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%int_16", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after iv > 17"); - - std::pair peel_info = - run_test(SpvOpSGreaterThan, "%32", "%int_17"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 17 < iv"); - - std::pair peel_info = - run_test(SpvOpSLessThan, "%int_17", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - - // Test LE - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv <= 4"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%32", "%int_4"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 4 => iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%int_4", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before iv <= 3"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%32", "%int_3"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 3 => iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%int_3", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv <= 16"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%32", "%int_16"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 16 => iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%int_16", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after iv <= 15"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%32", "%int_15"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 15 => iv"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%int_15", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - - // Test GE - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv >= 5"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%32", "%int_5"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 35 >= iv"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%int_5", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before iv >= 4"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%32", "%int_4"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel before 4 <= iv"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%int_4", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 2u); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv >= 17"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%32", "%int_17"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 17 <= iv"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%int_17", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after iv >= 16"); - - std::pair peel_info = - run_test(SpvOpSGreaterThanEqual, "%32", "%int_16"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - { - SCOPED_TRACE("Peel after 16 <= iv"); - - std::pair peel_info = - run_test(SpvOpSLessThanEqual, "%int_16", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 2u); - } - - // Test EQ - // Peel before by a factor of 1. - { - SCOPED_TRACE("Peel before iv == 1"); - - std::pair peel_info = - run_test(SpvOpIEqual, "%32", "%int_1"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 1u); - } - { - SCOPED_TRACE("Peel before 1 == iv"); - - std::pair peel_info = - run_test(SpvOpIEqual, "%int_1", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 1u); - } - - // Peel after by a factor of 1. - { - SCOPED_TRACE("Peel after iv == 19"); - - std::pair peel_info = - run_test(SpvOpIEqual, "%32", "%int_19"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 1u); - } - { - SCOPED_TRACE("Peel after 19 == iv"); - - std::pair peel_info = - run_test(SpvOpIEqual, "%int_19", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 1u); - } - - // Test NE - // Peel before by a factor of 1. - { - SCOPED_TRACE("Peel before iv != 1"); - - std::pair peel_info = - run_test(SpvOpINotEqual, "%32", "%int_1"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 1u); - } - { - SCOPED_TRACE("Peel before 1 != iv"); - - std::pair peel_info = - run_test(SpvOpINotEqual, "%int_1", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); - EXPECT_EQ(peel_info.second, 1u); - } - - // Peel after by a factor of 1. - { - SCOPED_TRACE("Peel after iv != 19"); - - std::pair peel_info = - run_test(SpvOpINotEqual, "%32", "%int_19"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 1u); - } - { - SCOPED_TRACE("Peel after 19 != iv"); - - std::pair peel_info = - run_test(SpvOpINotEqual, "%int_19", "%32"); - EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); - EXPECT_EQ(peel_info.second, 1u); - } - - // No peel. - { - SCOPED_TRACE("No Peel: 20 => iv"); - - auto stats = RunPeelingTest(text_head, text_tail, SpvOpSLessThanEqual, - "%22", "%int_20", "%32", 1); - - EXPECT_EQ(stats.peeled_loops_.size(), 0u); - } -} - -/* -Test are derivation of the following generated test from the following GLSL + ---eliminate-local-multi-store - -#version 330 core -void main() { - int a = 0; - for(int i = 0; i < 10; ++i) { - if (i < 3) { - a += 2; - } - if (i < 1) { - a += 2; - } - } -} - -The condition is interchanged to test < > <= >= == and peel before/after -opportunities. -*/ -TEST_F(PeelingPassTest, MultiplePeelingPass) { - const std::string text_head = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - OpName %a "a" - OpName %i "i" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %bool = OpTypeBool - %int_10 = OpConstant %int 10 - %int_9 = OpConstant %int 9 - %int_8 = OpConstant %int 8 - %int_7 = OpConstant %int 7 - %int_6 = OpConstant %int 6 - %int_5 = OpConstant %int 5 - %int_4 = OpConstant %int 4 - %int_3 = OpConstant %int 3 - %int_2 = OpConstant %int 2 - %int_1 = OpConstant %int 1 - %int_0 = OpConstant %int 0 - %main = OpFunction %void None %3 - %5 = OpLabel - %a = OpVariable %_ptr_Function_int Function - %i = OpVariable %_ptr_Function_int Function - OpStore %a %int_0 - OpStore %i %int_0 - OpBranch %11 - %11 = OpLabel - %37 = OpPhi %int %int_0 %5 %40 %14 - %38 = OpPhi %int %int_0 %5 %36 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %bool %38 %int_10 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - )"; - const std::string text_tail = R"( - OpSelectionMerge %24 None - OpBranchConditional %22 %23 %24 - %23 = OpLabel - %27 = OpIAdd %int %37 %int_2 - OpStore %a %27 - OpBranch %24 - %24 = OpLabel - %39 = OpPhi %int %37 %12 %27 %23 - %30 = OpSLessThan %bool %38 %int_1 - OpSelectionMerge %32 None - OpBranchConditional %30 %31 %32 - %31 = OpLabel - %34 = OpIAdd %int %39 %int_2 - OpStore %a %34 - OpBranch %32 - %32 = OpLabel - %40 = OpPhi %int %39 %24 %34 %31 - OpBranch %14 - %14 = OpLabel - %36 = OpIAdd %int %38 %int_1 - OpStore %i %36 - OpBranch %11 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto run_test = [&text_head, &text_tail, this]( - SpvOp opcode, const std::string& op1, - const std::string& op2, - const PeelTraceType& expected_peel_trace) { - BuildAndCheckTrace(text_head, text_tail, opcode, "%22", op1, op2, - expected_peel_trace, expected_peel_trace.size() + 1); - }; - - // Test LT - // Peel before by a factor of 3. - { - SCOPED_TRACE("Peel before iv < 3"); - - run_test(SpvOpSLessThan, "%38", "%int_3", - {{LoopPeelingPass::PeelDirection::kBefore, 3u}}); - } - { - SCOPED_TRACE("Peel before 3 > iv"); - - run_test(SpvOpSGreaterThan, "%int_3", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 3u}}); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv < 8"); - - run_test(SpvOpSLessThan, "%38", "%int_8", - {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); - } - { - SCOPED_TRACE("Peel after 8 > iv"); - - run_test(SpvOpSGreaterThan, "%int_8", "%38", - {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); - } - - // Test GT - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv > 2"); - - run_test(SpvOpSGreaterThan, "%38", "%int_2", - {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); - } - { - SCOPED_TRACE("Peel before 2 < iv"); - - run_test(SpvOpSLessThan, "%int_2", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); - } - - // Peel after by a factor of 3. - { - SCOPED_TRACE("Peel after iv > 7"); - - run_test(SpvOpSGreaterThan, "%38", "%int_7", - {{LoopPeelingPass::PeelDirection::kAfter, 3u}}); - } - { - SCOPED_TRACE("Peel after 7 < iv"); - - run_test(SpvOpSLessThan, "%int_7", "%38", - {{LoopPeelingPass::PeelDirection::kAfter, 3u}}); - } - - // Test LE - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv <= 1"); - - run_test(SpvOpSLessThanEqual, "%38", "%int_1", - {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); - } - { - SCOPED_TRACE("Peel before 1 => iv"); - - run_test(SpvOpSGreaterThanEqual, "%int_1", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv <= 7"); - - run_test(SpvOpSLessThanEqual, "%38", "%int_7", - {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); - } - { - SCOPED_TRACE("Peel after 7 => iv"); - - run_test(SpvOpSGreaterThanEqual, "%int_7", "%38", - {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); - } - - // Test GE - // Peel before by a factor of 2. - { - SCOPED_TRACE("Peel before iv >= 2"); - - run_test(SpvOpSGreaterThanEqual, "%38", "%int_2", - {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); - } - { - SCOPED_TRACE("Peel before 2 <= iv"); - - run_test(SpvOpSLessThanEqual, "%int_2", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); - } - - // Peel after by a factor of 2. - { - SCOPED_TRACE("Peel after iv >= 8"); - - run_test(SpvOpSGreaterThanEqual, "%38", "%int_8", - {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); - } - { - SCOPED_TRACE("Peel after 8 <= iv"); - - run_test(SpvOpSLessThanEqual, "%int_8", "%38", - {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); - } - // Test EQ - // Peel before by a factor of 1. - { - SCOPED_TRACE("Peel before iv == 0"); - - run_test(SpvOpIEqual, "%38", "%int_0", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - { - SCOPED_TRACE("Peel before 0 == iv"); - - run_test(SpvOpIEqual, "%int_0", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - - // Peel after by a factor of 1. - { - SCOPED_TRACE("Peel after iv == 9"); - - run_test(SpvOpIEqual, "%38", "%int_9", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - { - SCOPED_TRACE("Peel after 9 == iv"); - - run_test(SpvOpIEqual, "%int_9", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - - // Test NE - // Peel before by a factor of 1. - { - SCOPED_TRACE("Peel before iv != 0"); - - run_test(SpvOpINotEqual, "%38", "%int_0", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - { - SCOPED_TRACE("Peel before 0 != iv"); - - run_test(SpvOpINotEqual, "%int_0", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - - // Peel after by a factor of 1. - { - SCOPED_TRACE("Peel after iv != 9"); - - run_test(SpvOpINotEqual, "%38", "%int_9", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } - { - SCOPED_TRACE("Peel after 9 != iv"); - - run_test(SpvOpINotEqual, "%int_9", "%38", - {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); - } -} - -/* -Test are derivation of the following generated test from the following GLSL + ---eliminate-local-multi-store - -#version 330 core -void main() { - int a = 0; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - if (i < 3) { - a += 2; - } - } - } -} -*/ -TEST_F(PeelingPassTest, PeelingNestedPass) { - const std::string text_head = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - OpName %a "a" - OpName %i "i" - OpName %j "j" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_7 = OpConstant %int 7 - %int_3 = OpConstant %int 3 - %int_2 = OpConstant %int 2 - %int_1 = OpConstant %int 1 - %43 = OpUndef %int - %main = OpFunction %void None %3 - %5 = OpLabel - %a = OpVariable %_ptr_Function_int Function - %i = OpVariable %_ptr_Function_int Function - %j = OpVariable %_ptr_Function_int Function - OpStore %a %int_0 - OpStore %i %int_0 - OpBranch %11 - %11 = OpLabel - %41 = OpPhi %int %int_0 %5 %45 %14 - %42 = OpPhi %int %int_0 %5 %40 %14 - %44 = OpPhi %int %43 %5 %46 %14 - OpLoopMerge %13 %14 None - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThan %bool %42 %int_10 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - OpStore %j %int_0 - OpBranch %21 - %21 = OpLabel - %45 = OpPhi %int %41 %12 %47 %24 - %46 = OpPhi %int %int_0 %12 %38 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %27 = OpSLessThan %bool %46 %int_10 - OpBranchConditional %27 %22 %23 - %22 = OpLabel - )"; - - const std::string text_tail = R"( - OpSelectionMerge %32 None - OpBranchConditional %30 %31 %32 - %31 = OpLabel - %35 = OpIAdd %int %45 %int_2 - OpStore %a %35 - OpBranch %32 - %32 = OpLabel - %47 = OpPhi %int %45 %22 %35 %31 - OpBranch %24 - %24 = OpLabel - %38 = OpIAdd %int %46 %int_1 - OpStore %j %38 - OpBranch %21 - %23 = OpLabel - OpBranch %14 - %14 = OpLabel - %40 = OpIAdd %int %42 %int_1 - OpStore %i %40 - OpBranch %11 - %13 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto run_test = - [&text_head, &text_tail, this]( - SpvOp opcode, const std::string& op1, const std::string& op2, - const PeelTraceType& expected_peel_trace, size_t nb_of_loops) { - BuildAndCheckTrace(text_head, text_tail, opcode, "%30", op1, op2, - expected_peel_trace, nb_of_loops); - }; - - // Peeling outer before by a factor of 3. - { - SCOPED_TRACE("Peel before iv_i < 3"); - - // Expect peel before by a factor of 3 and 4 loops at the end. - run_test(SpvOpSLessThan, "%42", "%int_3", - {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 4); - } - // Peeling outer loop after by a factor of 3. - { - SCOPED_TRACE("Peel after iv_i < 7"); - - // Expect peel after by a factor of 3 and 4 loops at the end. - run_test(SpvOpSLessThan, "%42", "%int_7", - {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 4); - } - - // Peeling inner loop before by a factor of 3. - { - SCOPED_TRACE("Peel before iv_j < 3"); - - // Expect peel before by a factor of 3 and 3 loops at the end. - run_test(SpvOpSLessThan, "%46", "%int_3", - {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 3); - } - // Peeling inner loop after by a factor of 3. - { - SCOPED_TRACE("Peel after iv_j < 7"); - - // Expect peel after by a factor of 3 and 3 loops at the end. - run_test(SpvOpSLessThan, "%46", "%int_7", - {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 3); - } - - // Not unworkable condition. - { - SCOPED_TRACE("No peel"); - - // Expect no peeling and 2 loops at the end. - run_test(SpvOpSLessThan, "%46", "%42", {}, 2); - } - - // Could do a peeling of 3, but the goes over the threshold. - { - SCOPED_TRACE("Over threshold"); - - size_t current_threshold = LoopPeelingPass::GetLoopPeelingThreshold(); - LoopPeelingPass::SetLoopPeelingThreshold(1u); - // Expect no peeling and 2 loops at the end. - run_test(SpvOpSLessThan, "%46", "%int_7", {}, 2); - LoopPeelingPass::SetLoopPeelingThreshold(current_threshold); - } -} -/* -Test are derivation of the following generated test from the following GLSL + ---eliminate-local-multi-store - -#version 330 core -void main() { - int a = 0; - for (int i = 0, j = 0; i < 10; j++, i++) { - if (i < j) { - a += 2; - } - } -} -*/ -TEST_F(PeelingPassTest, PeelingNoChanges) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 330 - OpName %main "main" - OpName %a "a" - OpName %i "i" - OpName %j "j" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_2 = OpConstant %int 2 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %a = OpVariable %_ptr_Function_int Function - %i = OpVariable %_ptr_Function_int Function - %j = OpVariable %_ptr_Function_int Function - OpStore %a %int_0 - OpStore %i %int_0 - OpStore %j %int_0 - OpBranch %12 - %12 = OpLabel - %34 = OpPhi %int %int_0 %5 %37 %15 - %35 = OpPhi %int %int_0 %5 %33 %15 - %36 = OpPhi %int %int_0 %5 %31 %15 - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %20 = OpSLessThan %bool %35 %int_10 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %23 = OpSLessThan %bool %35 %36 - OpSelectionMerge %25 None - OpBranchConditional %23 %24 %25 - %24 = OpLabel - %28 = OpIAdd %int %34 %int_2 - OpStore %a %28 - OpBranch %25 - %25 = OpLabel - %37 = OpPhi %int %34 %13 %28 %24 - OpBranch %15 - %15 = OpLabel - %31 = OpIAdd %int %36 %int_1 - OpStore %j %31 - %33 = OpIAdd %int %35 %int_1 - OpStore %i %33 - OpBranch %12 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - { - auto result = - SinglePassRunAndDisassemble(text, true, false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); - } -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/unroll_assumptions.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/unroll_assumptions.cpp deleted file mode 100644 index 62f77d782..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/unroll_assumptions.cpp +++ /dev/null @@ -1,1448 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/loop_unroller.h" -#include "source/opt/loop_utils.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -template -class PartialUnrollerTestPass : public Pass { - public: - PartialUnrollerTestPass() : Pass() {} - - const char* name() const override { return "Loop unroller"; } - - Status Process() override { - bool changed = false; - for (Function& f : *context()->module()) { - LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(&f); - for (auto& loop : loop_descriptor) { - LoopUtils loop_utils{context(), &loop}; - if (loop_utils.PartiallyUnroll(factor)) { - changed = true; - } - } - } - - if (changed) return Pass::Status::SuccessWithChange; - return Pass::Status::SuccessWithoutChange; - } -}; - -/* -Generated from the following GLSL -#version 410 core -layout(location = 0) flat in int in_upper_bound; -void main() { - for (int i = 0; i < in_upper_bound; ++i) { - x[i] = 1.0f; - } -} -*/ -TEST_F(PassClassTest, CheckUpperBound) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "in_upper_bound" -OpName %4 "x" -OpDecorate %3 Flat -OpDecorate %3 Location 0 -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpTypeInt 32 1 -%8 = OpTypePointer Function %7 -%9 = OpConstant %7 0 -%10 = OpTypePointer Input %7 -%3 = OpVariable %10 Input -%11 = OpTypeBool -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpConstant %12 1 -%18 = OpTypePointer Function %12 -%19 = OpConstant %7 1 -%2 = OpFunction %5 None %6 -%20 = OpLabel -%4 = OpVariable %16 Function -OpBranch %21 -%21 = OpLabel -%22 = OpPhi %7 %9 %20 %23 %24 -OpLoopMerge %25 %24 Unroll -OpBranch %26 -%26 = OpLabel -%27 = OpLoad %7 %3 -%28 = OpSLessThan %11 %22 %27 -OpBranchConditional %28 %29 %25 -%29 = OpLabel -%30 = OpAccessChain %18 %4 %22 -OpStore %30 %17 -OpBranch %24 -%24 = OpLabel -%23 = OpIAdd %7 %22 %19 -OpBranch %21 -%25 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[10]; - for (uint i = 0; i < 2; i++) { - for (float x = 0; x < 5; ++x) { - out_array[x + i*5] = i; - } - } -} -*/ -TEST_F(PassClassTest, UnrollNestedLoopsInvalid) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 0 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpConstant %6 2 -%10 = OpTypeBool -%11 = OpTypeInt 32 1 -%12 = OpTypePointer Function %11 -%13 = OpConstant %11 0 -%14 = OpConstant %11 5 -%15 = OpTypeFloat 32 -%16 = OpConstant %6 10 -%17 = OpTypeArray %15 %16 -%18 = OpTypePointer Function %17 -%19 = OpConstant %6 5 -%20 = OpTypePointer Function %15 -%21 = OpConstant %11 1 -%22 = OpUndef %11 -%2 = OpFunction %4 None %5 -%23 = OpLabel -%3 = OpVariable %18 Function -OpBranch %24 -%24 = OpLabel -%25 = OpPhi %6 %8 %23 %26 %27 -%28 = OpPhi %11 %22 %23 %29 %27 -OpLoopMerge %30 %27 Unroll -OpBranch %31 -%31 = OpLabel -%32 = OpULessThan %10 %25 %9 -OpBranchConditional %32 %33 %30 -%33 = OpLabel -OpBranch %34 -%34 = OpLabel -%29 = OpPhi %11 %13 %33 %35 %36 -OpLoopMerge %37 %36 None -OpBranch %38 -%38 = OpLabel -%39 = OpSLessThan %10 %29 %14 -OpBranchConditional %39 %40 %37 -%40 = OpLabel -%41 = OpBitcast %6 %29 -%42 = OpIMul %6 %25 %19 -%43 = OpIAdd %6 %41 %42 -%44 = OpConvertUToF %15 %25 -%45 = OpAccessChain %20 %3 %43 -OpStore %45 %44 -OpBranch %36 -%36 = OpLabel -%35 = OpIAdd %11 %29 %21 -OpBranch %34 -%37 = OpLabel -OpBranch %27 -%27 = OpLabel -%26 = OpIAdd %6 %25 %21 -OpBranch %24 -%30 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main(){ - float x[10]; - for (int i = 0; i < 10; i++) { - if (i == 5) { - break; - } - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, BreakInBody) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -OpName %3 "x" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpConstant %6 10 -%10 = OpTypeBool -%11 = OpConstant %6 5 -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpTypePointer Function %12 -%18 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%19 = OpLabel -%3 = OpVariable %16 Function -OpBranch %20 -%20 = OpLabel -%21 = OpPhi %6 %8 %19 %22 %23 -OpLoopMerge %24 %23 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %10 %21 %9 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%28 = OpIEqual %10 %21 %11 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -OpBranch %24 -%29 = OpLabel -%31 = OpConvertSToF %12 %21 -%32 = OpAccessChain %17 %3 %21 -OpStore %32 %31 -OpBranch %23 -%23 = OpLabel -%22 = OpIAdd %6 %21 %18 -OpBranch %20 -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main(){ - float x[10]; - for (int i = 0; i < 10; i++) { - if (i == 5) { - continue; - } - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, ContinueInBody) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -OpName %3 "x" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpConstant %6 10 -%10 = OpTypeBool -%11 = OpConstant %6 5 -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpTypePointer Function %12 -%18 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%19 = OpLabel -%3 = OpVariable %16 Function -OpBranch %20 -%20 = OpLabel -%21 = OpPhi %6 %8 %19 %22 %23 -OpLoopMerge %24 %23 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %10 %21 %9 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%28 = OpIEqual %10 %21 %11 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -OpBranch %23 -%29 = OpLabel -%31 = OpConvertSToF %12 %21 -%32 = OpAccessChain %17 %3 %21 -OpStore %32 %31 -OpBranch %23 -%23 = OpLabel -%22 = OpIAdd %6 %21 %18 -OpBranch %20 -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main(){ - float x[10]; - for (int i = 0; i < 10; i++) { - if (i == 5) { - return; - } - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, ReturnInBody) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -OpName %3 "x" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpConstant %6 10 -%10 = OpTypeBool -%11 = OpConstant %6 5 -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpTypePointer Function %12 -%18 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%19 = OpLabel -%3 = OpVariable %16 Function -OpBranch %20 -%20 = OpLabel -%21 = OpPhi %6 %8 %19 %22 %23 -OpLoopMerge %24 %23 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %10 %21 %9 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%28 = OpIEqual %10 %21 %11 -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %29 -%30 = OpLabel -OpReturn -%29 = OpLabel -%31 = OpConvertSToF %12 %21 -%32 = OpAccessChain %17 %3 %21 -OpStore %32 %31 -OpBranch %23 -%23 = OpLabel -%22 = OpIAdd %6 %21 %18 -OpBranch %20 -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main() { - int j = 0; - for (int i = 0; i < 10 && i > 0; i++) { - j++; - } -} -*/ -TEST_F(PassClassTest, MultipleConditionsSingleVariable) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpTypePointer Function %5 -%7 = OpConstant %5 0 -%8 = OpConstant %5 10 -%9 = OpTypeBool -%10 = OpConstant %5 1 -%2 = OpFunction %3 None %4 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -%13 = OpPhi %5 %7 %11 %14 %15 -%16 = OpPhi %5 %7 %11 %17 %15 -OpLoopMerge %18 %15 Unroll -OpBranch %19 -%19 = OpLabel -%20 = OpSLessThan %9 %16 %8 -%21 = OpSGreaterThan %9 %16 %7 -%22 = OpLogicalAnd %9 %20 %21 -OpBranchConditional %22 %23 %18 -%23 = OpLabel -%14 = OpIAdd %5 %13 %10 -OpBranch %15 -%15 = OpLabel -%17 = OpIAdd %5 %16 %10 -OpBranch %12 -%18 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main() { - int i = 0; - int j = 0; - int k = 0; - for (; i < 10 && j > 0; i++, j++) { - k++; - } -} -*/ -TEST_F(PassClassTest, MultipleConditionsMultipleVariables) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpTypePointer Function %5 -%7 = OpConstant %5 0 -%8 = OpConstant %5 10 -%9 = OpTypeBool -%10 = OpConstant %5 1 -%2 = OpFunction %3 None %4 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -%13 = OpPhi %5 %7 %11 %14 %15 -%16 = OpPhi %5 %7 %11 %17 %15 -%18 = OpPhi %5 %7 %11 %19 %15 -OpLoopMerge %20 %15 Unroll -OpBranch %21 -%21 = OpLabel -%22 = OpSLessThan %9 %13 %8 -%23 = OpSGreaterThan %9 %16 %7 -%24 = OpLogicalAnd %9 %22 %23 -OpBranchConditional %24 %25 %20 -%25 = OpLabel -%19 = OpIAdd %5 %18 %10 -OpBranch %15 -%15 = OpLabel -%14 = OpIAdd %5 %13 %10 -%17 = OpIAdd %5 %16 %10 -OpBranch %12 -%20 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main() { - float i = 0.0; - int j = 0; - for (; i < 10; i++) { - j++; - } -} -*/ -TEST_F(PassClassTest, FloatingPointLoop) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeFloat 32 -%6 = OpTypePointer Function %5 -%7 = OpConstant %5 0 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 0 -%11 = OpConstant %5 10 -%12 = OpTypeBool -%13 = OpConstant %8 1 -%14 = OpConstant %5 1 -%2 = OpFunction %3 None %4 -%15 = OpLabel -OpBranch %16 -%16 = OpLabel -%17 = OpPhi %5 %7 %15 %18 %19 -%20 = OpPhi %8 %10 %15 %21 %19 -OpLoopMerge %22 %19 Unroll -OpBranch %23 -%23 = OpLabel -%24 = OpFOrdLessThan %12 %17 %11 -OpBranchConditional %24 %25 %22 -%25 = OpLabel -%21 = OpIAdd %8 %20 %13 -OpBranch %19 -%19 = OpLabel -%18 = OpFAdd %5 %17 %14 -OpBranch %16 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main() { - int i = 2; - int j = 0; - if (j == 0) { i = 5; } - for (; i < 3; ++i) { - j++; - } -} -*/ -TEST_F(PassClassTest, InductionPhiOutsideLoop) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpTypePointer Function %5 -%7 = OpConstant %5 2 -%8 = OpConstant %5 0 -%9 = OpTypeBool -%10 = OpConstant %5 5 -%11 = OpConstant %5 3 -%12 = OpConstant %5 1 -%2 = OpFunction %3 None %4 -%13 = OpLabel -%14 = OpIEqual %9 %8 %8 -OpSelectionMerge %15 None -OpBranchConditional %14 %16 %15 -%16 = OpLabel -OpBranch %15 -%15 = OpLabel -%17 = OpPhi %5 %7 %13 %10 %16 -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %5 %17 %15 %20 %21 -%22 = OpPhi %5 %8 %15 %23 %21 -OpLoopMerge %24 %21 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %9 %19 %11 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%23 = OpIAdd %5 %22 %12 -OpBranch %21 -%21 = OpLabel -%20 = OpIAdd %5 %19 %12 -OpBranch %18 -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main() { - int j = 0; - for (int i = 0; i == 0; ++i) { - ++j; - } - for (int i = 0; i != 3; ++i) { - ++j; - } - for (int i = 0; i < 3; i *= 2) { - ++j; - } - for (int i = 10; i > 3; i /= 2) { - ++j; - } - for (int i = 10; i > 3; i |= 2) { - ++j; - } - for (int i = 10; i > 3; i &= 2) { - ++j; - } - for (int i = 10; i > 3; i ^= 2) { - ++j; - } - for (int i = 0; i < 3; i << 2) { - ++j; - } - for (int i = 10; i > 3; i >> 2) { - ++j; - } -} -*/ -TEST_F(PassClassTest, UnsupportedLoopTypes) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpTypePointer Function %5 -%7 = OpConstant %5 0 -%8 = OpTypeBool -%9 = OpConstant %5 1 -%10 = OpConstant %5 3 -%11 = OpConstant %5 2 -%12 = OpConstant %5 10 -%2 = OpFunction %3 None %4 -%13 = OpLabel -OpBranch %14 -%14 = OpLabel -%15 = OpPhi %5 %7 %13 %16 %17 -%18 = OpPhi %5 %7 %13 %19 %17 -OpLoopMerge %20 %17 Unroll -OpBranch %21 -%21 = OpLabel -%22 = OpIEqual %8 %18 %7 -OpBranchConditional %22 %23 %20 -%23 = OpLabel -%16 = OpIAdd %5 %15 %9 -OpBranch %17 -%17 = OpLabel -%19 = OpIAdd %5 %18 %9 -OpBranch %14 -%20 = OpLabel -OpBranch %24 -%24 = OpLabel -%25 = OpPhi %5 %15 %20 %26 %27 -%28 = OpPhi %5 %7 %20 %29 %27 -OpLoopMerge %30 %27 Unroll -OpBranch %31 -%31 = OpLabel -%32 = OpINotEqual %8 %28 %10 -OpBranchConditional %32 %33 %30 -%33 = OpLabel -%26 = OpIAdd %5 %25 %9 -OpBranch %27 -%27 = OpLabel -%29 = OpIAdd %5 %28 %9 -OpBranch %24 -%30 = OpLabel -OpBranch %34 -%34 = OpLabel -%35 = OpPhi %5 %25 %30 %36 %37 -%38 = OpPhi %5 %7 %30 %39 %37 -OpLoopMerge %40 %37 Unroll -OpBranch %41 -%41 = OpLabel -%42 = OpSLessThan %8 %38 %10 -OpBranchConditional %42 %43 %40 -%43 = OpLabel -%36 = OpIAdd %5 %35 %9 -OpBranch %37 -%37 = OpLabel -%39 = OpIMul %5 %38 %11 -OpBranch %34 -%40 = OpLabel -OpBranch %44 -%44 = OpLabel -%45 = OpPhi %5 %35 %40 %46 %47 -%48 = OpPhi %5 %12 %40 %49 %47 -OpLoopMerge %50 %47 Unroll -OpBranch %51 -%51 = OpLabel -%52 = OpSGreaterThan %8 %48 %10 -OpBranchConditional %52 %53 %50 -%53 = OpLabel -%46 = OpIAdd %5 %45 %9 -OpBranch %47 -%47 = OpLabel -%49 = OpSDiv %5 %48 %11 -OpBranch %44 -%50 = OpLabel -OpBranch %54 -%54 = OpLabel -%55 = OpPhi %5 %45 %50 %56 %57 -%58 = OpPhi %5 %12 %50 %59 %57 -OpLoopMerge %60 %57 Unroll -OpBranch %61 -%61 = OpLabel -%62 = OpSGreaterThan %8 %58 %10 -OpBranchConditional %62 %63 %60 -%63 = OpLabel -%56 = OpIAdd %5 %55 %9 -OpBranch %57 -%57 = OpLabel -%59 = OpBitwiseOr %5 %58 %11 -OpBranch %54 -%60 = OpLabel -OpBranch %64 -%64 = OpLabel -%65 = OpPhi %5 %55 %60 %66 %67 -%68 = OpPhi %5 %12 %60 %69 %67 -OpLoopMerge %70 %67 Unroll -OpBranch %71 -%71 = OpLabel -%72 = OpSGreaterThan %8 %68 %10 -OpBranchConditional %72 %73 %70 -%73 = OpLabel -%66 = OpIAdd %5 %65 %9 -OpBranch %67 -%67 = OpLabel -%69 = OpBitwiseAnd %5 %68 %11 -OpBranch %64 -%70 = OpLabel -OpBranch %74 -%74 = OpLabel -%75 = OpPhi %5 %65 %70 %76 %77 -%78 = OpPhi %5 %12 %70 %79 %77 -OpLoopMerge %80 %77 Unroll -OpBranch %81 -%81 = OpLabel -%82 = OpSGreaterThan %8 %78 %10 -OpBranchConditional %82 %83 %80 -%83 = OpLabel -%76 = OpIAdd %5 %75 %9 -OpBranch %77 -%77 = OpLabel -%79 = OpBitwiseXor %5 %78 %11 -OpBranch %74 -%80 = OpLabel -OpBranch %84 -%84 = OpLabel -%85 = OpPhi %5 %75 %80 %86 %87 -OpLoopMerge %88 %87 Unroll -OpBranch %89 -%89 = OpLabel -%90 = OpSLessThan %8 %7 %10 -OpBranchConditional %90 %91 %88 -%91 = OpLabel -%86 = OpIAdd %5 %85 %9 -OpBranch %87 -%87 = OpLabel -%92 = OpShiftLeftLogical %5 %7 %11 -OpBranch %84 -%88 = OpLabel -OpBranch %93 -%93 = OpLabel -%94 = OpPhi %5 %85 %88 %95 %96 -OpLoopMerge %97 %96 Unroll -OpBranch %98 -%98 = OpLabel -%99 = OpSGreaterThan %8 %12 %10 -OpBranchConditional %99 %100 %97 -%100 = OpLabel -%95 = OpIAdd %5 %94 %9 -OpBranch %96 -%96 = OpLabel -%101 = OpShiftRightArithmetic %5 %12 %11 -OpBranch %93 -%97 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -#version 430 - -layout(location = 0) out float o; - -void main(void) { - for (int j = 2; j < 0; j += 1) { - o += 1.0; - } -} -*/ -TEST_F(PassClassTest, NegativeNumberOfIterations) { - // clang-format off - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "o" -OpDecorate %3 Location 0 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 2 -%9 = OpConstant %6 0 -%10 = OpTypeBool -%11 = OpTypeFloat 32 -%12 = OpTypePointer Output %11 -%3 = OpVariable %12 Output -%13 = OpConstant %11 1 -%14 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%15 = OpLabel -OpBranch %16 -%16 = OpLabel -%17 = OpPhi %6 %8 %15 %18 %19 -OpLoopMerge %20 %19 None -OpBranch %21 -%21 = OpLabel -%22 = OpSLessThan %10 %17 %9 -OpBranchConditional %22 %23 %20 -%23 = OpLabel -%24 = OpLoad %11 %3 -%25 = OpFAdd %11 %24 %13 -OpStore %3 %25 -OpBranch %19 -%19 = OpLabel -%18 = OpIAdd %6 %17 %14 -OpBranch %16 -%20 = OpLabel -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -#version 430 - -layout(location = 0) out float o; - -void main(void) { - float s = 0.0; - for (int j = 0; j < 3; j += 1) { - s += 1.0; - j += 1; - } - o = s; -} -*/ -TEST_F(PassClassTest, MultipleStepOperations) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "o" -OpDecorate %3 Location 0 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeFloat 32 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 0 -%12 = OpConstant %9 3 -%13 = OpTypeBool -%14 = OpConstant %6 1 -%15 = OpConstant %9 1 -%16 = OpTypePointer Output %6 -%3 = OpVariable %16 Output -%2 = OpFunction %4 None %5 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %6 %8 %17 %20 %21 -%22 = OpPhi %9 %11 %17 %23 %21 -OpLoopMerge %24 %21 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %13 %22 %12 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%20 = OpFAdd %6 %19 %14 -%28 = OpIAdd %9 %22 %15 -OpBranch %21 -%21 = OpLabel -%23 = OpIAdd %9 %28 %15 -OpBranch %18 -%24 = OpLabel -OpStore %3 %19 -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -#version 430 - -layout(location = 0) out float o; - -void main(void) { - float s = 0.0; - for (int j = 10; j > 20; j -= 1) { - s += 1.0; - } - o = s; -} -*/ - -TEST_F(PassClassTest, ConditionFalseFromStartGreaterThan) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "o" -OpDecorate %3 Location 0 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeFloat 32 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 10 -%12 = OpConstant %9 20 -%13 = OpTypeBool -%14 = OpConstant %6 1 -%15 = OpConstant %9 1 -%16 = OpTypePointer Output %6 -%3 = OpVariable %16 Output -%2 = OpFunction %4 None %5 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %6 %8 %17 %20 %21 -%22 = OpPhi %9 %11 %17 %23 %21 -OpLoopMerge %24 %21 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSGreaterThan %13 %22 %12 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%20 = OpFAdd %6 %19 %14 -OpBranch %21 -%21 = OpLabel -%23 = OpISub %9 %22 %15 -OpBranch %18 -%24 = OpLabel -OpStore %3 %19 -OpReturn -OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -#version 430 - -layout(location = 0) out float o; - -void main(void) { - float s = 0.0; - for (int j = 10; j >= 20; j -= 1) { - s += 1.0; - } - o = s; -} -*/ -TEST_F(PassClassTest, ConditionFalseFromStartGreaterThanOrEqual) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "o" -OpDecorate %3 Location 0 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeFloat 32 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 10 -%12 = OpConstant %9 20 -%13 = OpTypeBool -%14 = OpConstant %6 1 -%15 = OpConstant %9 1 -%16 = OpTypePointer Output %6 -%3 = OpVariable %16 Output -%2 = OpFunction %4 None %5 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %6 %8 %17 %20 %21 -%22 = OpPhi %9 %11 %17 %23 %21 -OpLoopMerge %24 %21 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSGreaterThanEqual %13 %22 %12 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%20 = OpFAdd %6 %19 %14 -OpBranch %21 -%21 = OpLabel -%23 = OpISub %9 %22 %15 -OpBranch %18 -%24 = OpLabel -OpStore %3 %19 -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -#version 430 - -layout(location = 0) out float o; - -void main(void) { - float s = 0.0; - for (int j = 20; j < 10; j -= 1) { - s += 1.0; - } - o = s; -} -*/ -TEST_F(PassClassTest, ConditionFalseFromStartLessThan) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "o" -OpDecorate %3 Location 0 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeFloat 32 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 20 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpConstant %6 1 -%15 = OpConstant %9 1 -%16 = OpTypePointer Output %6 -%3 = OpVariable %16 Output -%2 = OpFunction %4 None %5 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %6 %8 %17 %20 %21 -%22 = OpPhi %9 %11 %17 %23 %21 -OpLoopMerge %24 %21 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThan %13 %22 %12 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%20 = OpFAdd %6 %19 %14 -OpBranch %21 -%21 = OpLabel -%23 = OpISub %9 %22 %15 -OpBranch %18 -%24 = OpLabel -OpStore %3 %19 -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -/* -#version 430 - -layout(location = 0) out float o; - -void main(void) { - float s = 0.0; - for (int j = 20; j <= 10; j -= 1) { - s += 1.0; - } - o = s; -} -*/ -TEST_F(PassClassTest, ConditionFalseFromStartLessThanEqual) { - // clang-format off - // With LocalMultiStoreElimPass -const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "o" -OpDecorate %3 Location 0 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeFloat 32 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpTypeInt 32 1 -%10 = OpTypePointer Function %9 -%11 = OpConstant %9 20 -%12 = OpConstant %9 10 -%13 = OpTypeBool -%14 = OpConstant %6 1 -%15 = OpConstant %9 1 -%16 = OpTypePointer Output %6 -%3 = OpVariable %16 Output -%2 = OpFunction %4 None %5 -%17 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %6 %8 %17 %20 %21 -%22 = OpPhi %9 %11 %17 %23 %21 -OpLoopMerge %24 %21 Unroll -OpBranch %25 -%25 = OpLabel -%26 = OpSLessThanEqual %13 %22 %12 -OpBranchConditional %26 %27 %24 -%27 = OpLabel -%20 = OpFAdd %6 %19 %14 -OpBranch %21 -%21 = OpLabel -%23 = OpISub %9 %22 %15 -OpBranch %18 -%24 = OpLabel -OpStore %3 %19 -OpReturn -OpFunctionEnd -)"; - - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - // Make sure the pass doesn't run - SinglePassRunAndCheck(text, text, false); - SinglePassRunAndCheck>(text, text, false); - SinglePassRunAndCheck>(text, text, false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/unroll_simple.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/unroll_simple.cpp deleted file mode 100644 index f551e7ca9..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/unroll_simple.cpp +++ /dev/null @@ -1,3003 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/loop_unroller.h" -#include "source/opt/loop_utils.h" -#include "source/opt/pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - float x[4]; - for (int i = 0; i < 4; ++i) { - x[i] = 1.0f; - } -} -*/ -TEST_F(PassClassTest, SimpleFullyUnrollTest) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %5 "x" - OpName %3 "c" - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 4 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 4 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Function %16 - %18 = OpConstant %13 1 - %19 = OpTypePointer Function %13 - %20 = OpConstant %8 1 - %21 = OpTypeVector %13 4 - %22 = OpTypePointer Output %21 - %3 = OpVariable %22 Output - %2 = OpFunction %6 None %7 - %23 = OpLabel - %5 = OpVariable %17 Function - OpBranch %24 - %24 = OpLabel - %35 = OpPhi %8 %10 %23 %34 %26 - OpLoopMerge %25 %26 Unroll - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %12 %35 %11 - OpBranchConditional %29 %30 %25 - %30 = OpLabel - %32 = OpAccessChain %19 %5 %35 - OpStore %32 %18 - OpBranch %26 - %26 = OpLabel - %34 = OpIAdd %8 %35 %20 - OpBranch %24 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 330 -OpName %2 "main" -OpName %4 "x" -OpName %3 "c" -OpDecorate %3 Location 0 -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpTypeInt 32 1 -%8 = OpTypePointer Function %7 -%9 = OpConstant %7 0 -%10 = OpConstant %7 4 -%11 = OpTypeBool -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 4 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpConstant %12 1 -%18 = OpTypePointer Function %12 -%19 = OpConstant %7 1 -%20 = OpTypeVector %12 4 -%21 = OpTypePointer Output %20 -%3 = OpVariable %21 Output -%2 = OpFunction %5 None %6 -%22 = OpLabel -%4 = OpVariable %16 Function -OpBranch %23 -%23 = OpLabel -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %11 %9 %10 -OpBranch %30 -%30 = OpLabel -%31 = OpAccessChain %18 %4 %9 -OpStore %31 %17 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %7 %9 %19 -OpBranch %32 -%32 = OpLabel -OpBranch %34 -%34 = OpLabel -%35 = OpSLessThan %11 %25 %10 -OpBranch %36 -%36 = OpLabel -%37 = OpAccessChain %18 %4 %25 -OpStore %37 %17 -OpBranch %38 -%38 = OpLabel -%39 = OpIAdd %7 %25 %19 -OpBranch %40 -%40 = OpLabel -OpBranch %42 -%42 = OpLabel -%43 = OpSLessThan %11 %39 %10 -OpBranch %44 -%44 = OpLabel -%45 = OpAccessChain %18 %4 %39 -OpStore %45 %17 -OpBranch %46 -%46 = OpLabel -%47 = OpIAdd %7 %39 %19 -OpBranch %48 -%48 = OpLabel -OpBranch %50 -%50 = OpLabel -%51 = OpSLessThan %11 %47 %10 -OpBranch %52 -%52 = OpLabel -%53 = OpAccessChain %18 %4 %47 -OpStore %53 %17 -OpBranch %54 -%54 = OpLabel -%55 = OpIAdd %7 %47 %19 -OpBranch %27 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -template -class PartialUnrollerTestPass : public Pass { - public: - PartialUnrollerTestPass() : Pass() {} - - const char* name() const override { return "Loop unroller"; } - - Status Process() override { - for (Function& f : *context()->module()) { - LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(&f); - for (auto& loop : loop_descriptor) { - LoopUtils loop_utils{context(), &loop}; - loop_utils.PartiallyUnroll(factor); - } - } - - return Pass::Status::SuccessWithChange; - } -}; - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - float x[10]; - for (int i = 0; i < 10; ++i) { - x[i] = 1.0f; - } -} -*/ -TEST_F(PassClassTest, SimplePartialUnroll) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %5 "x" - OpName %3 "c" - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Function %16 - %18 = OpConstant %13 1 - %19 = OpTypePointer Function %13 - %20 = OpConstant %8 1 - %21 = OpTypeVector %13 4 - %22 = OpTypePointer Output %21 - %3 = OpVariable %22 Output - %2 = OpFunction %6 None %7 - %23 = OpLabel - %5 = OpVariable %17 Function - OpBranch %24 - %24 = OpLabel - %35 = OpPhi %8 %10 %23 %34 %26 - OpLoopMerge %25 %26 Unroll - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %12 %35 %11 - OpBranchConditional %29 %30 %25 - %30 = OpLabel - %32 = OpAccessChain %19 %5 %35 - OpStore %32 %18 - OpBranch %26 - %26 = OpLabel - %34 = OpIAdd %8 %35 %20 - OpBranch %24 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 330 -OpName %2 "main" -OpName %4 "x" -OpName %3 "c" -OpDecorate %3 Location 0 -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpTypeInt 32 1 -%8 = OpTypePointer Function %7 -%9 = OpConstant %7 0 -%10 = OpConstant %7 10 -%11 = OpTypeBool -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpConstant %12 1 -%18 = OpTypePointer Function %12 -%19 = OpConstant %7 1 -%20 = OpTypeVector %12 4 -%21 = OpTypePointer Output %20 -%3 = OpVariable %21 Output -%2 = OpFunction %5 None %6 -%22 = OpLabel -%4 = OpVariable %16 Function -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %7 %9 %22 %39 %38 -OpLoopMerge %27 %38 DontUnroll -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %11 %24 %10 -OpBranchConditional %29 %30 %27 -%30 = OpLabel -%31 = OpAccessChain %18 %4 %24 -OpStore %31 %17 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %7 %24 %19 -OpBranch %32 -%32 = OpLabel -OpBranch %34 -%34 = OpLabel -%35 = OpSLessThan %11 %25 %10 -OpBranch %36 -%36 = OpLabel -%37 = OpAccessChain %18 %4 %25 -OpStore %37 %17 -OpBranch %38 -%38 = OpLabel -%39 = OpIAdd %7 %25 %19 -OpBranch %23 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck>(text, output, false); -} - -/* -Generated from the following GLSL -#version 330 core -layout(location = 0) out vec4 c; -void main() { - float x[10]; - for (int i = 0; i < 10; ++i) { - x[i] = 1.0f; - } -} -*/ -TEST_F(PassClassTest, SimpleUnevenPartialUnroll) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 330 - OpName %2 "main" - OpName %5 "x" - OpName %3 "c" - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Function %16 - %18 = OpConstant %13 1 - %19 = OpTypePointer Function %13 - %20 = OpConstant %8 1 - %21 = OpTypeVector %13 4 - %22 = OpTypePointer Output %21 - %3 = OpVariable %22 Output - %2 = OpFunction %6 None %7 - %23 = OpLabel - %5 = OpVariable %17 Function - OpBranch %24 - %24 = OpLabel - %35 = OpPhi %8 %10 %23 %34 %26 - OpLoopMerge %25 %26 Unroll - OpBranch %27 - %27 = OpLabel - %29 = OpSLessThan %12 %35 %11 - OpBranchConditional %29 %30 %25 - %30 = OpLabel - %32 = OpAccessChain %19 %5 %35 - OpStore %32 %18 - OpBranch %26 - %26 = OpLabel - %34 = OpIAdd %8 %35 %20 - OpBranch %24 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 330 -OpName %2 "main" -OpName %4 "x" -OpName %3 "c" -OpDecorate %3 Location 0 -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpTypeInt 32 1 -%8 = OpTypePointer Function %7 -%9 = OpConstant %7 0 -%10 = OpConstant %7 10 -%11 = OpTypeBool -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpConstant %12 1 -%18 = OpTypePointer Function %12 -%19 = OpConstant %7 1 -%20 = OpTypeVector %12 4 -%21 = OpTypePointer Output %20 -%3 = OpVariable %21 Output -%58 = OpConstant %13 1 -%2 = OpFunction %5 None %6 -%22 = OpLabel -%4 = OpVariable %16 Function -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %7 %9 %22 %25 %26 -OpLoopMerge %32 %26 Unroll -OpBranch %28 -%28 = OpLabel -%29 = OpSLessThan %11 %24 %58 -OpBranchConditional %29 %30 %32 -%30 = OpLabel -%31 = OpAccessChain %18 %4 %24 -OpStore %31 %17 -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %7 %24 %19 -OpBranch %23 -%32 = OpLabel -OpBranch %33 -%33 = OpLabel -%34 = OpPhi %7 %24 %32 %57 %56 -OpLoopMerge %41 %56 DontUnroll -OpBranch %35 -%35 = OpLabel -%36 = OpSLessThan %11 %34 %10 -OpBranchConditional %36 %37 %41 -%37 = OpLabel -%38 = OpAccessChain %18 %4 %34 -OpStore %38 %17 -OpBranch %39 -%39 = OpLabel -%40 = OpIAdd %7 %34 %19 -OpBranch %42 -%42 = OpLabel -OpBranch %44 -%44 = OpLabel -%45 = OpSLessThan %11 %40 %10 -OpBranch %46 -%46 = OpLabel -%47 = OpAccessChain %18 %4 %40 -OpStore %47 %17 -OpBranch %48 -%48 = OpLabel -%49 = OpIAdd %7 %40 %19 -OpBranch %50 -%50 = OpLabel -OpBranch %52 -%52 = OpLabel -%53 = OpSLessThan %11 %49 %10 -OpBranch %54 -%54 = OpLabel -%55 = OpAccessChain %18 %4 %49 -OpStore %55 %17 -OpBranch %56 -%56 = OpLabel -%57 = OpIAdd %7 %49 %19 -OpBranch %33 -%41 = OpLabel -OpReturn -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - // By unrolling by a factor that doesn't divide evenly into the number of loop - // iterations we perfom an additional transform when partially unrolling to - // account for the remainder. - SinglePassRunAndCheck>(text, output, false); -} - -/* Generated from -#version 410 core -layout(location=0) flat in int upper_bound; -void main() { - float x[10]; - for (int i = 2; i < 8; i+=2) { - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, SimpleLoopIterationsCheck) { - // With LocalMultiStoreElimPass - const std::string text = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %5 "x" -OpName %3 "upper_bound" -OpDecorate %3 Flat -OpDecorate %3 Location 0 -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 2 -%11 = OpConstant %8 8 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpTypePointer Input %8 -%3 = OpVariable %19 Input -%2 = OpFunction %6 None %7 -%20 = OpLabel -%5 = OpVariable %17 Function -OpBranch %21 -%21 = OpLabel -%34 = OpPhi %8 %10 %20 %33 %23 -OpLoopMerge %22 %23 Unroll -OpBranch %24 -%24 = OpLabel -%26 = OpSLessThan %12 %34 %11 -OpBranchConditional %26 %27 %22 -%27 = OpLabel -%30 = OpConvertSToF %13 %34 -%31 = OpAccessChain %18 %5 %34 -OpStore %31 %30 -OpBranch %23 -%23 = OpLabel -%33 = OpIAdd %8 %34 %10 -OpBranch %21 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - Function* f = spvtest::GetFunction(module, 2); - - LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f); - EXPECT_EQ(loop_descriptor.NumLoops(), 1u); - - Loop& loop = loop_descriptor.GetLoopByIndex(0); - - EXPECT_TRUE(loop.HasUnrollLoopControl()); - - BasicBlock* condition = loop.FindConditionBlock(); - EXPECT_EQ(condition->id(), 24u); - - Instruction* induction = loop.FindConditionVariable(condition); - EXPECT_EQ(induction->result_id(), 34u); - - LoopUtils loop_utils{context.get(), &loop}; - EXPECT_TRUE(loop_utils.CanPerformUnroll()); - - size_t iterations = 0; - EXPECT_TRUE(loop.FindNumberOfIterations(induction, &*condition->ctail(), - &iterations)); - EXPECT_EQ(iterations, 3u); -} - -/* Generated from -#version 410 core -void main() { - float x[10]; - for (int i = -1; i < 6; i+=3) { - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, SimpleLoopIterationsCheckSignedInit) { - // With LocalMultiStoreElimPass - const std::string text = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" %3 -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %5 "x" -OpName %3 "upper_bound" -OpDecorate %3 Flat -OpDecorate %3 Location 0 -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 1 -%9 = OpTypePointer Function %8 -%10 = OpConstant %8 -1 -%11 = OpConstant %8 6 -%12 = OpTypeBool -%13 = OpTypeFloat 32 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 10 -%16 = OpTypeArray %13 %15 -%17 = OpTypePointer Function %16 -%18 = OpTypePointer Function %13 -%19 = OpConstant %8 3 -%20 = OpTypePointer Input %8 -%3 = OpVariable %20 Input -%2 = OpFunction %6 None %7 -%21 = OpLabel -%5 = OpVariable %17 Function -OpBranch %22 -%22 = OpLabel -%35 = OpPhi %8 %10 %21 %34 %24 -OpLoopMerge %23 %24 None -OpBranch %25 -%25 = OpLabel -%27 = OpSLessThan %12 %35 %11 -OpBranchConditional %27 %28 %23 -%28 = OpLabel -%31 = OpConvertSToF %13 %35 -%32 = OpAccessChain %18 %5 %35 -OpStore %32 %31 -OpBranch %24 -%24 = OpLabel -%34 = OpIAdd %8 %35 %19 -OpBranch %22 -%23 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - Function* f = spvtest::GetFunction(module, 2); - - LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f); - - EXPECT_EQ(loop_descriptor.NumLoops(), 1u); - - Loop& loop = loop_descriptor.GetLoopByIndex(0); - - EXPECT_FALSE(loop.HasUnrollLoopControl()); - - BasicBlock* condition = loop.FindConditionBlock(); - EXPECT_EQ(condition->id(), 25u); - - Instruction* induction = loop.FindConditionVariable(condition); - EXPECT_EQ(induction->result_id(), 35u); - - LoopUtils loop_utils{context.get(), &loop}; - EXPECT_TRUE(loop_utils.CanPerformUnroll()); - - size_t iterations = 0; - EXPECT_TRUE(loop.FindNumberOfIterations(induction, &*condition->ctail(), - &iterations)); - EXPECT_EQ(iterations, 3u); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[6]; - for (uint i = 0; i < 2; i++) { - for (int x = 0; x < 3; ++x) { - out_array[x + i*3] = i; - } - } -} -*/ -TEST_F(PassClassTest, UnrollNestedLoops) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %35 "out_array" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 0 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 2 - %17 = OpTypeBool - %19 = OpTypeInt 32 1 - %20 = OpTypePointer Function %19 - %22 = OpConstant %19 0 - %29 = OpConstant %19 3 - %31 = OpTypeFloat 32 - %32 = OpConstant %6 6 - %33 = OpTypeArray %31 %32 - %34 = OpTypePointer Function %33 - %39 = OpConstant %6 3 - %44 = OpTypePointer Function %31 - %47 = OpConstant %19 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %35 = OpVariable %34 Function - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %50 %13 - OpLoopMerge %12 %13 Unroll - OpBranch %14 - %14 = OpLabel - %18 = OpULessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %23 - %23 = OpLabel - %54 = OpPhi %19 %22 %11 %48 %26 - OpLoopMerge %25 %26 Unroll - OpBranch %27 - %27 = OpLabel - %30 = OpSLessThan %17 %54 %29 - OpBranchConditional %30 %24 %25 - %24 = OpLabel - %37 = OpBitcast %6 %54 - %40 = OpIMul %6 %51 %39 - %41 = OpIAdd %6 %37 %40 - %43 = OpConvertUToF %31 %51 - %45 = OpAccessChain %44 %35 %41 - OpStore %45 %43 - OpBranch %26 - %26 = OpLabel - %48 = OpIAdd %19 %54 %47 - OpBranch %23 - %25 = OpLabel - OpBranch %13 - %13 = OpLabel - %50 = OpIAdd %6 %51 %47 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 0 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpConstant %6 2 -%10 = OpTypeBool -%11 = OpTypeInt 32 1 -%12 = OpTypePointer Function %11 -%13 = OpConstant %11 0 -%14 = OpConstant %11 3 -%15 = OpTypeFloat 32 -%16 = OpConstant %6 6 -%17 = OpTypeArray %15 %16 -%18 = OpTypePointer Function %17 -%19 = OpConstant %6 3 -%20 = OpTypePointer Function %15 -%21 = OpConstant %11 1 -%2 = OpFunction %4 None %5 -%22 = OpLabel -%3 = OpVariable %18 Function -OpBranch %23 -%23 = OpLabel -OpBranch %28 -%28 = OpLabel -%29 = OpULessThan %10 %8 %9 -OpBranch %30 -%30 = OpLabel -OpBranch %31 -%31 = OpLabel -OpBranch %36 -%36 = OpLabel -%37 = OpSLessThan %10 %13 %14 -OpBranch %38 -%38 = OpLabel -%39 = OpBitcast %6 %13 -%40 = OpIMul %6 %8 %19 -%41 = OpIAdd %6 %39 %40 -%42 = OpConvertUToF %15 %8 -%43 = OpAccessChain %20 %3 %41 -OpStore %43 %42 -OpBranch %34 -%34 = OpLabel -%33 = OpIAdd %11 %13 %21 -OpBranch %44 -%44 = OpLabel -OpBranch %46 -%46 = OpLabel -%47 = OpSLessThan %10 %33 %14 -OpBranch %48 -%48 = OpLabel -%49 = OpBitcast %6 %33 -%50 = OpIMul %6 %8 %19 -%51 = OpIAdd %6 %49 %50 -%52 = OpConvertUToF %15 %8 -%53 = OpAccessChain %20 %3 %51 -OpStore %53 %52 -OpBranch %54 -%54 = OpLabel -%55 = OpIAdd %11 %33 %21 -OpBranch %56 -%56 = OpLabel -OpBranch %58 -%58 = OpLabel -%59 = OpSLessThan %10 %55 %14 -OpBranch %60 -%60 = OpLabel -%61 = OpBitcast %6 %55 -%62 = OpIMul %6 %8 %19 -%63 = OpIAdd %6 %61 %62 -%64 = OpConvertUToF %15 %8 -%65 = OpAccessChain %20 %3 %63 -OpStore %65 %64 -OpBranch %66 -%66 = OpLabel -%67 = OpIAdd %11 %55 %21 -OpBranch %35 -%35 = OpLabel -OpBranch %26 -%26 = OpLabel -%25 = OpIAdd %6 %8 %21 -OpBranch %68 -%68 = OpLabel -OpBranch %70 -%70 = OpLabel -%71 = OpULessThan %10 %25 %9 -OpBranch %72 -%72 = OpLabel -OpBranch %73 -%73 = OpLabel -OpBranch %74 -%74 = OpLabel -%75 = OpSLessThan %10 %13 %14 -OpBranch %76 -%76 = OpLabel -%77 = OpBitcast %6 %13 -%78 = OpIMul %6 %25 %19 -%79 = OpIAdd %6 %77 %78 -%80 = OpConvertUToF %15 %25 -%81 = OpAccessChain %20 %3 %79 -OpStore %81 %80 -OpBranch %82 -%82 = OpLabel -%83 = OpIAdd %11 %13 %21 -OpBranch %84 -%84 = OpLabel -OpBranch %85 -%85 = OpLabel -%86 = OpSLessThan %10 %83 %14 -OpBranch %87 -%87 = OpLabel -%88 = OpBitcast %6 %83 -%89 = OpIMul %6 %25 %19 -%90 = OpIAdd %6 %88 %89 -%91 = OpConvertUToF %15 %25 -%92 = OpAccessChain %20 %3 %90 -OpStore %92 %91 -OpBranch %93 -%93 = OpLabel -%94 = OpIAdd %11 %83 %21 -OpBranch %95 -%95 = OpLabel -OpBranch %96 -%96 = OpLabel -%97 = OpSLessThan %10 %94 %14 -OpBranch %98 -%98 = OpLabel -%99 = OpBitcast %6 %94 -%100 = OpIMul %6 %25 %19 -%101 = OpIAdd %6 %99 %100 -%102 = OpConvertUToF %15 %25 -%103 = OpAccessChain %20 %3 %101 -OpStore %103 %102 -OpBranch %104 -%104 = OpLabel -%105 = OpIAdd %11 %94 %21 -OpBranch %106 -%106 = OpLabel -OpBranch %107 -%107 = OpLabel -%108 = OpIAdd %6 %25 %21 -OpBranch %27 -%27 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[2]; - for (int i = -3; i < -1; i++) { - out_array[3 + i] = i; - } -} -*/ -TEST_F(PassClassTest, NegativeConditionAndInit) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %23 "out_array" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 -3 - %16 = OpConstant %6 -1 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 2 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %25 = OpConstant %6 3 - %30 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %23 = OpVariable %22 Function - OpBranch %10 - %10 = OpLabel - %32 = OpPhi %6 %9 %5 %31 %13 - OpLoopMerge %12 %13 Unroll - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %32 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpIAdd %6 %32 %25 - %28 = OpAccessChain %7 %23 %26 - OpStore %28 %32 - OpBranch %13 - %13 = OpLabel - %31 = OpIAdd %6 %32 %30 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 -3 -%9 = OpConstant %6 -1 -%10 = OpTypeBool -%11 = OpTypeInt 32 0 -%12 = OpConstant %11 2 -%13 = OpTypeArray %6 %12 -%14 = OpTypePointer Function %13 -%15 = OpConstant %6 3 -%16 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%17 = OpLabel -%3 = OpVariable %14 Function -OpBranch %18 -%18 = OpLabel -OpBranch %23 -%23 = OpLabel -%24 = OpSLessThan %10 %8 %9 -OpBranch %25 -%25 = OpLabel -%26 = OpIAdd %6 %8 %15 -%27 = OpAccessChain %7 %3 %26 -OpStore %27 %8 -OpBranch %21 -%21 = OpLabel -%20 = OpIAdd %6 %8 %16 -OpBranch %28 -%28 = OpLabel -OpBranch %30 -%30 = OpLabel -%31 = OpSLessThan %10 %20 %9 -OpBranch %32 -%32 = OpLabel -%33 = OpIAdd %6 %20 %15 -%34 = OpAccessChain %7 %3 %33 -OpStore %34 %20 -OpBranch %35 -%35 = OpLabel -%36 = OpIAdd %6 %20 %16 -OpBranch %22 -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - // SinglePassRunAndCheck(text, expected, false); - - Function* f = spvtest::GetFunction(module, 4); - - LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f); - EXPECT_EQ(loop_descriptor.NumLoops(), 1u); - - Loop& loop = loop_descriptor.GetLoopByIndex(0); - - EXPECT_TRUE(loop.HasUnrollLoopControl()); - - BasicBlock* condition = loop.FindConditionBlock(); - EXPECT_EQ(condition->id(), 14u); - - Instruction* induction = loop.FindConditionVariable(condition); - EXPECT_EQ(induction->result_id(), 32u); - - LoopUtils loop_utils{context.get(), &loop}; - EXPECT_TRUE(loop_utils.CanPerformUnroll()); - - size_t iterations = 0; - EXPECT_TRUE(loop.FindNumberOfIterations(induction, &*condition->ctail(), - &iterations)); - EXPECT_EQ(iterations, 2u); - SinglePassRunAndCheck(text, expected, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[9]; - for (int i = -10; i < -1; i++) { - out_array[i] = i; - } -} -*/ -TEST_F(PassClassTest, NegativeConditionAndInitResidualUnroll) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %23 "out_array" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 -10 - %16 = OpConstant %6 -1 - %17 = OpTypeBool - %19 = OpTypeInt 32 0 - %20 = OpConstant %19 9 - %21 = OpTypeArray %6 %20 - %22 = OpTypePointer Function %21 - %25 = OpConstant %6 10 - %30 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %23 = OpVariable %22 Function - OpBranch %10 - %10 = OpLabel - %32 = OpPhi %6 %9 %5 %31 %13 - OpLoopMerge %12 %13 Unroll - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %32 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %26 = OpIAdd %6 %32 %25 - %28 = OpAccessChain %7 %23 %26 - OpStore %28 %32 - OpBranch %13 - %13 = OpLabel - %31 = OpIAdd %6 %32 %30 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd -)"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 -10 -%9 = OpConstant %6 -1 -%10 = OpTypeBool -%11 = OpTypeInt 32 0 -%12 = OpConstant %11 9 -%13 = OpTypeArray %6 %12 -%14 = OpTypePointer Function %13 -%15 = OpConstant %6 10 -%16 = OpConstant %6 1 -%48 = OpConstant %6 -9 -%2 = OpFunction %4 None %5 -%17 = OpLabel -%3 = OpVariable %14 Function -OpBranch %18 -%18 = OpLabel -%19 = OpPhi %6 %8 %17 %20 %21 -OpLoopMerge %28 %21 Unroll -OpBranch %23 -%23 = OpLabel -%24 = OpSLessThan %10 %19 %48 -OpBranchConditional %24 %25 %28 -%25 = OpLabel -%26 = OpIAdd %6 %19 %15 -%27 = OpAccessChain %7 %3 %26 -OpStore %27 %19 -OpBranch %21 -%21 = OpLabel -%20 = OpIAdd %6 %19 %16 -OpBranch %18 -%28 = OpLabel -OpBranch %29 -%29 = OpLabel -%30 = OpPhi %6 %19 %28 %47 %46 -OpLoopMerge %38 %46 DontUnroll -OpBranch %31 -%31 = OpLabel -%32 = OpSLessThan %10 %30 %9 -OpBranchConditional %32 %33 %38 -%33 = OpLabel -%34 = OpIAdd %6 %30 %15 -%35 = OpAccessChain %7 %3 %34 -OpStore %35 %30 -OpBranch %36 -%36 = OpLabel -%37 = OpIAdd %6 %30 %16 -OpBranch %39 -%39 = OpLabel -OpBranch %41 -%41 = OpLabel -%42 = OpSLessThan %10 %37 %9 -OpBranch %43 -%43 = OpLabel -%44 = OpIAdd %6 %37 %15 -%45 = OpAccessChain %7 %3 %44 -OpStore %45 %37 -OpBranch %46 -%46 = OpLabel -%47 = OpIAdd %6 %37 %16 -OpBranch %29 -%38 = OpLabel -OpReturn -%22 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - Function* f = spvtest::GetFunction(module, 4); - - LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f); - EXPECT_EQ(loop_descriptor.NumLoops(), 1u); - - Loop& loop = loop_descriptor.GetLoopByIndex(0); - - EXPECT_TRUE(loop.HasUnrollLoopControl()); - - BasicBlock* condition = loop.FindConditionBlock(); - EXPECT_EQ(condition->id(), 14u); - - Instruction* induction = loop.FindConditionVariable(condition); - EXPECT_EQ(induction->result_id(), 32u); - - LoopUtils loop_utils{context.get(), &loop}; - EXPECT_TRUE(loop_utils.CanPerformUnroll()); - - size_t iterations = 0; - EXPECT_TRUE(loop.FindNumberOfIterations(induction, &*condition->ctail(), - &iterations)); - EXPECT_EQ(iterations, 9u); - SinglePassRunAndCheck>(text, expected, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[10]; - for (uint i = 0; i < 2; i++) { - for (int x = 0; x < 5; ++x) { - out_array[x + i*5] = i; - } - } -} -*/ -TEST_F(PassClassTest, UnrollNestedLoopsValidateDescriptor) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %35 "out_array" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 0 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 2 - %17 = OpTypeBool - %19 = OpTypeInt 32 1 - %20 = OpTypePointer Function %19 - %22 = OpConstant %19 0 - %29 = OpConstant %19 5 - %31 = OpTypeFloat 32 - %32 = OpConstant %6 10 - %33 = OpTypeArray %31 %32 - %34 = OpTypePointer Function %33 - %39 = OpConstant %6 5 - %44 = OpTypePointer Function %31 - %47 = OpConstant %19 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %35 = OpVariable %34 Function - OpBranch %10 - %10 = OpLabel - %51 = OpPhi %6 %9 %5 %50 %13 - OpLoopMerge %12 %13 Unroll - OpBranch %14 - %14 = OpLabel - %18 = OpULessThan %17 %51 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %23 - %23 = OpLabel - %54 = OpPhi %19 %22 %11 %48 %26 - OpLoopMerge %25 %26 Unroll - OpBranch %27 - %27 = OpLabel - %30 = OpSLessThan %17 %54 %29 - OpBranchConditional %30 %24 %25 - %24 = OpLabel - %37 = OpBitcast %6 %54 - %40 = OpIMul %6 %51 %39 - %41 = OpIAdd %6 %37 %40 - %43 = OpConvertUToF %31 %51 - %45 = OpAccessChain %44 %35 %41 - OpStore %45 %43 - OpBranch %26 - %26 = OpLabel - %48 = OpIAdd %19 %54 %47 - OpBranch %23 - %25 = OpLabel - OpBranch %13 - %13 = OpLabel - %50 = OpIAdd %6 %51 %47 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - { // Test fully unroll - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f); - EXPECT_EQ(loop_descriptor.NumLoops(), 2u); - - Loop& outer_loop = loop_descriptor.GetLoopByIndex(1); - - EXPECT_TRUE(outer_loop.HasUnrollLoopControl()); - - Loop& inner_loop = loop_descriptor.GetLoopByIndex(0); - - EXPECT_TRUE(inner_loop.HasUnrollLoopControl()); - - EXPECT_EQ(outer_loop.GetBlocks().size(), 9u); - - EXPECT_EQ(inner_loop.GetBlocks().size(), 4u); - EXPECT_EQ(outer_loop.NumImmediateChildren(), 1u); - EXPECT_EQ(inner_loop.NumImmediateChildren(), 0u); - - { - LoopUtils loop_utils{context.get(), &inner_loop}; - loop_utils.FullyUnroll(); - loop_utils.Finalize(); - } - - EXPECT_EQ(loop_descriptor.NumLoops(), 1u); - EXPECT_EQ(outer_loop.GetBlocks().size(), 25u); - EXPECT_EQ(outer_loop.NumImmediateChildren(), 0u); - { - LoopUtils loop_utils{context.get(), &outer_loop}; - loop_utils.FullyUnroll(); - loop_utils.Finalize(); - } - EXPECT_EQ(loop_descriptor.NumLoops(), 0u); - } - - { // Test partially unroll - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - - Function* f = spvtest::GetFunction(module, 4); - LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f); - EXPECT_EQ(loop_descriptor.NumLoops(), 2u); - - Loop& outer_loop = loop_descriptor.GetLoopByIndex(1); - - EXPECT_TRUE(outer_loop.HasUnrollLoopControl()); - - Loop& inner_loop = loop_descriptor.GetLoopByIndex(0); - - EXPECT_TRUE(inner_loop.HasUnrollLoopControl()); - - EXPECT_EQ(outer_loop.GetBlocks().size(), 9u); - - EXPECT_EQ(inner_loop.GetBlocks().size(), 4u); - - EXPECT_EQ(outer_loop.NumImmediateChildren(), 1u); - EXPECT_EQ(inner_loop.NumImmediateChildren(), 0u); - - LoopUtils loop_utils{context.get(), &inner_loop}; - loop_utils.PartiallyUnroll(2); - loop_utils.Finalize(); - - // The number of loops should actually grow. - EXPECT_EQ(loop_descriptor.NumLoops(), 3u); - EXPECT_EQ(outer_loop.GetBlocks().size(), 18u); - EXPECT_EQ(outer_loop.NumImmediateChildren(), 2u); - } -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[3]; - for (int i = 3; i > 0; --i) { - out_array[i] = i; - } -} -*/ -TEST_F(PassClassTest, FullyUnrollNegativeStepLoopTest) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %24 "out_array" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 3 - %16 = OpConstant %6 0 - %17 = OpTypeBool - %19 = OpTypeFloat 32 - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 3 - %22 = OpTypeArray %19 %21 - %23 = OpTypePointer Function %22 - %28 = OpTypePointer Function %19 - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %24 = OpVariable %23 Function - OpBranch %10 - %10 = OpLabel - %33 = OpPhi %6 %9 %5 %32 %13 - OpLoopMerge %12 %13 Unroll - OpBranch %14 - %14 = OpLabel - %18 = OpSGreaterThan %17 %33 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpConvertSToF %19 %33 - %29 = OpAccessChain %28 %24 %33 - OpStore %29 %27 - OpBranch %13 - %13 = OpLabel - %32 = OpISub %6 %33 %31 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 3 -%9 = OpConstant %6 0 -%10 = OpTypeBool -%11 = OpTypeFloat 32 -%12 = OpTypeInt 32 0 -%13 = OpConstant %12 3 -%14 = OpTypeArray %11 %13 -%15 = OpTypePointer Function %14 -%16 = OpTypePointer Function %11 -%17 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%18 = OpLabel -%3 = OpVariable %15 Function -OpBranch %19 -%19 = OpLabel -OpBranch %24 -%24 = OpLabel -%25 = OpSGreaterThan %10 %8 %9 -OpBranch %26 -%26 = OpLabel -%27 = OpConvertSToF %11 %8 -%28 = OpAccessChain %16 %3 %8 -OpStore %28 %27 -OpBranch %22 -%22 = OpLabel -%21 = OpISub %6 %8 %17 -OpBranch %29 -%29 = OpLabel -OpBranch %31 -%31 = OpLabel -%32 = OpSGreaterThan %10 %21 %9 -OpBranch %33 -%33 = OpLabel -%34 = OpConvertSToF %11 %21 -%35 = OpAccessChain %16 %3 %21 -OpStore %35 %34 -OpBranch %36 -%36 = OpLabel -%37 = OpISub %6 %21 %17 -OpBranch %38 -%38 = OpLabel -OpBranch %40 -%40 = OpLabel -%41 = OpSGreaterThan %10 %37 %9 -OpBranch %42 -%42 = OpLabel -%43 = OpConvertSToF %11 %37 -%44 = OpAccessChain %16 %3 %37 -OpStore %44 %43 -OpBranch %45 -%45 = OpLabel -%46 = OpISub %6 %37 %17 -OpBranch %23 -%23 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[3]; - for (int i = 9; i > 0; i-=3) { - out_array[i] = i; - } -} -*/ -TEST_F(PassClassTest, FullyUnrollNegativeNonOneStepLoop) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %24 "out_array" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 9 - %16 = OpConstant %6 0 - %17 = OpTypeBool - %19 = OpTypeFloat 32 - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 3 - %22 = OpTypeArray %19 %21 - %23 = OpTypePointer Function %22 - %28 = OpTypePointer Function %19 - %30 = OpConstant %6 3 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %24 = OpVariable %23 Function - OpBranch %10 - %10 = OpLabel - %33 = OpPhi %6 %9 %5 %32 %13 - OpLoopMerge %12 %13 Unroll - OpBranch %14 - %14 = OpLabel - %18 = OpSGreaterThan %17 %33 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %27 = OpConvertSToF %19 %33 - %29 = OpAccessChain %28 %24 %33 - OpStore %29 %27 - OpBranch %13 - %13 = OpLabel - %32 = OpISub %6 %33 %30 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 9 -%9 = OpConstant %6 0 -%10 = OpTypeBool -%11 = OpTypeFloat 32 -%12 = OpTypeInt 32 0 -%13 = OpConstant %12 3 -%14 = OpTypeArray %11 %13 -%15 = OpTypePointer Function %14 -%16 = OpTypePointer Function %11 -%17 = OpConstant %6 3 -%2 = OpFunction %4 None %5 -%18 = OpLabel -%3 = OpVariable %15 Function -OpBranch %19 -%19 = OpLabel -OpBranch %24 -%24 = OpLabel -%25 = OpSGreaterThan %10 %8 %9 -OpBranch %26 -%26 = OpLabel -%27 = OpConvertSToF %11 %8 -%28 = OpAccessChain %16 %3 %8 -OpStore %28 %27 -OpBranch %22 -%22 = OpLabel -%21 = OpISub %6 %8 %17 -OpBranch %29 -%29 = OpLabel -OpBranch %31 -%31 = OpLabel -%32 = OpSGreaterThan %10 %21 %9 -OpBranch %33 -%33 = OpLabel -%34 = OpConvertSToF %11 %21 -%35 = OpAccessChain %16 %3 %21 -OpStore %35 %34 -OpBranch %36 -%36 = OpLabel -%37 = OpISub %6 %21 %17 -OpBranch %38 -%38 = OpLabel -OpBranch %40 -%40 = OpLabel -%41 = OpSGreaterThan %10 %37 %9 -OpBranch %42 -%42 = OpLabel -%43 = OpConvertSToF %11 %37 -%44 = OpAccessChain %16 %3 %37 -OpStore %44 %43 -OpBranch %45 -%45 = OpLabel -%46 = OpISub %6 %37 %17 -OpBranch %23 -%23 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[3]; - for (int i = 0; i < 7; i+=3) { - out_array[i] = i; - } -} -*/ -TEST_F(PassClassTest, FullyUnrollNonDivisibleStepLoop) { - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" -OpExecutionMode %4 OriginUpperLeft -OpSource GLSL 410 -OpName %4 "main" -OpName %24 "out_array" -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%9 = OpConstant %6 0 -%16 = OpConstant %6 7 -%17 = OpTypeBool -%19 = OpTypeFloat 32 -%20 = OpTypeInt 32 0 -%21 = OpConstant %20 3 -%22 = OpTypeArray %19 %21 -%23 = OpTypePointer Function %22 -%28 = OpTypePointer Function %19 -%30 = OpConstant %6 3 -%4 = OpFunction %2 None %3 -%5 = OpLabel -%24 = OpVariable %23 Function -OpBranch %10 -%10 = OpLabel -%33 = OpPhi %6 %9 %5 %32 %13 -OpLoopMerge %12 %13 Unroll -OpBranch %14 -%14 = OpLabel -%18 = OpSLessThan %17 %33 %16 -OpBranchConditional %18 %11 %12 -%11 = OpLabel -%27 = OpConvertSToF %19 %33 -%29 = OpAccessChain %28 %24 %33 -OpStore %29 %27 -OpBranch %13 -%13 = OpLabel -%32 = OpIAdd %6 %33 %30 -OpBranch %10 -%12 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 0 -%9 = OpConstant %6 7 -%10 = OpTypeBool -%11 = OpTypeFloat 32 -%12 = OpTypeInt 32 0 -%13 = OpConstant %12 3 -%14 = OpTypeArray %11 %13 -%15 = OpTypePointer Function %14 -%16 = OpTypePointer Function %11 -%17 = OpConstant %6 3 -%2 = OpFunction %4 None %5 -%18 = OpLabel -%3 = OpVariable %15 Function -OpBranch %19 -%19 = OpLabel -OpBranch %24 -%24 = OpLabel -%25 = OpSLessThan %10 %8 %9 -OpBranch %26 -%26 = OpLabel -%27 = OpConvertSToF %11 %8 -%28 = OpAccessChain %16 %3 %8 -OpStore %28 %27 -OpBranch %22 -%22 = OpLabel -%21 = OpIAdd %6 %8 %17 -OpBranch %29 -%29 = OpLabel -OpBranch %31 -%31 = OpLabel -%32 = OpSLessThan %10 %21 %9 -OpBranch %33 -%33 = OpLabel -%34 = OpConvertSToF %11 %21 -%35 = OpAccessChain %16 %3 %21 -OpStore %35 %34 -OpBranch %36 -%36 = OpLabel -%37 = OpIAdd %6 %21 %17 -OpBranch %38 -%38 = OpLabel -OpBranch %40 -%40 = OpLabel -%41 = OpSLessThan %10 %37 %9 -OpBranch %42 -%42 = OpLabel -%43 = OpConvertSToF %11 %37 -%44 = OpAccessChain %16 %3 %37 -OpStore %44 %43 -OpBranch %45 -%45 = OpLabel -%46 = OpIAdd %6 %37 %17 -OpBranch %23 -%23 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -/* -Generated from the following GLSL -#version 410 core -void main() { - float out_array[4]; - for (int i = 11; i > 0; i-=3) { - out_array[i] = i; - } -} -*/ -TEST_F(PassClassTest, FullyUnrollNegativeNonDivisibleStepLoop) { - // With LocalMultiStoreElimPass - const std::string text = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" -OpExecutionMode %4 OriginUpperLeft -OpSource GLSL 410 -OpName %4 "main" -OpName %24 "out_array" -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%9 = OpConstant %6 11 -%16 = OpConstant %6 0 -%17 = OpTypeBool -%19 = OpTypeFloat 32 -%20 = OpTypeInt 32 0 -%21 = OpConstant %20 4 -%22 = OpTypeArray %19 %21 -%23 = OpTypePointer Function %22 -%28 = OpTypePointer Function %19 -%30 = OpConstant %6 3 -%4 = OpFunction %2 None %3 -%5 = OpLabel -%24 = OpVariable %23 Function -OpBranch %10 -%10 = OpLabel -%33 = OpPhi %6 %9 %5 %32 %13 -OpLoopMerge %12 %13 Unroll -OpBranch %14 -%14 = OpLabel -%18 = OpSGreaterThan %17 %33 %16 -OpBranchConditional %18 %11 %12 -%11 = OpLabel -%27 = OpConvertSToF %19 %33 -%29 = OpAccessChain %28 %24 %33 -OpStore %29 %27 -OpBranch %13 -%13 = OpLabel -%32 = OpISub %6 %33 %30 -OpBranch %10 -%12 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "out_array" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypePointer Function %6 -%8 = OpConstant %6 11 -%9 = OpConstant %6 0 -%10 = OpTypeBool -%11 = OpTypeFloat 32 -%12 = OpTypeInt 32 0 -%13 = OpConstant %12 4 -%14 = OpTypeArray %11 %13 -%15 = OpTypePointer Function %14 -%16 = OpTypePointer Function %11 -%17 = OpConstant %6 3 -%2 = OpFunction %4 None %5 -%18 = OpLabel -%3 = OpVariable %15 Function -OpBranch %19 -%19 = OpLabel -OpBranch %24 -%24 = OpLabel -%25 = OpSGreaterThan %10 %8 %9 -OpBranch %26 -%26 = OpLabel -%27 = OpConvertSToF %11 %8 -%28 = OpAccessChain %16 %3 %8 -OpStore %28 %27 -OpBranch %22 -%22 = OpLabel -%21 = OpISub %6 %8 %17 -OpBranch %29 -%29 = OpLabel -OpBranch %31 -%31 = OpLabel -%32 = OpSGreaterThan %10 %21 %9 -OpBranch %33 -%33 = OpLabel -%34 = OpConvertSToF %11 %21 -%35 = OpAccessChain %16 %3 %21 -OpStore %35 %34 -OpBranch %36 -%36 = OpLabel -%37 = OpISub %6 %21 %17 -OpBranch %38 -%38 = OpLabel -OpBranch %40 -%40 = OpLabel -%41 = OpSGreaterThan %10 %37 %9 -OpBranch %42 -%42 = OpLabel -%43 = OpConvertSToF %11 %37 -%44 = OpAccessChain %16 %3 %37 -OpStore %44 %43 -OpBranch %45 -%45 = OpLabel -%46 = OpISub %6 %37 %17 -OpBranch %47 -%47 = OpLabel -OpBranch %49 -%49 = OpLabel -%50 = OpSGreaterThan %10 %46 %9 -OpBranch %51 -%51 = OpLabel -%52 = OpConvertSToF %11 %46 -%53 = OpAccessChain %16 %3 %46 -OpStore %53 %52 -OpBranch %54 -%54 = OpLabel -%55 = OpISub %6 %46 %17 -OpBranch %23 -%23 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -// With LocalMultiStoreElimPass -static const std::string multiple_phi_shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %8 "foo(" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeFunction %6 - %10 = OpTypePointer Function %6 - %12 = OpConstant %6 0 - %14 = OpConstant %6 3 - %22 = OpConstant %6 6 - %23 = OpTypeBool - %31 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %40 = OpFunctionCall %6 %8 - OpReturn - OpFunctionEnd - %8 = OpFunction %6 None %7 - %9 = OpLabel - OpBranch %16 - %16 = OpLabel - %41 = OpPhi %6 %12 %9 %34 %19 - %42 = OpPhi %6 %14 %9 %29 %19 - %43 = OpPhi %6 %12 %9 %32 %19 - OpLoopMerge %18 %19 Unroll - OpBranch %20 - %20 = OpLabel - %24 = OpSLessThan %23 %43 %22 - OpBranchConditional %24 %17 %18 - %17 = OpLabel - %27 = OpIMul %6 %43 %41 - %29 = OpIAdd %6 %42 %27 - OpBranch %19 - %19 = OpLabel - %32 = OpIAdd %6 %43 %31 - %34 = OpISub %6 %41 %31 - OpBranch %16 - %18 = OpLabel - %37 = OpIAdd %6 %42 %41 - OpReturnValue %37 - OpFunctionEnd - )"; - -TEST_F(PassClassTest, PartiallyUnrollResidualMultipleInductionVariables) { - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "foo(" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypeFunction %6 -%8 = OpTypePointer Function %6 -%9 = OpConstant %6 0 -%10 = OpConstant %6 3 -%11 = OpConstant %6 6 -%12 = OpTypeBool -%13 = OpConstant %6 1 -%82 = OpTypeInt 32 0 -%83 = OpConstant %82 2 -%2 = OpFunction %4 None %5 -%14 = OpLabel -%15 = OpFunctionCall %6 %3 -OpReturn -OpFunctionEnd -%3 = OpFunction %6 None %7 -%16 = OpLabel -OpBranch %17 -%17 = OpLabel -%18 = OpPhi %6 %9 %16 %19 %20 -%21 = OpPhi %6 %10 %16 %22 %20 -%23 = OpPhi %6 %9 %16 %24 %20 -OpLoopMerge %31 %20 Unroll -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %23 %83 -OpBranchConditional %27 %28 %31 -%28 = OpLabel -%29 = OpIMul %6 %23 %18 -%22 = OpIAdd %6 %21 %29 -OpBranch %20 -%20 = OpLabel -%24 = OpIAdd %6 %23 %13 -%19 = OpISub %6 %18 %13 -OpBranch %17 -%31 = OpLabel -OpBranch %32 -%32 = OpLabel -%33 = OpPhi %6 %18 %31 %81 %79 -%34 = OpPhi %6 %21 %31 %78 %79 -%35 = OpPhi %6 %23 %31 %80 %79 -OpLoopMerge %44 %79 DontUnroll -OpBranch %36 -%36 = OpLabel -%37 = OpSLessThan %12 %35 %11 -OpBranchConditional %37 %38 %44 -%38 = OpLabel -%39 = OpIMul %6 %35 %33 -%40 = OpIAdd %6 %34 %39 -OpBranch %41 -%41 = OpLabel -%42 = OpIAdd %6 %35 %13 -%43 = OpISub %6 %33 %13 -OpBranch %46 -%46 = OpLabel -OpBranch %50 -%50 = OpLabel -%51 = OpSLessThan %12 %42 %11 -OpBranch %52 -%52 = OpLabel -%53 = OpIMul %6 %42 %43 -%54 = OpIAdd %6 %40 %53 -OpBranch %55 -%55 = OpLabel -%56 = OpIAdd %6 %42 %13 -%57 = OpISub %6 %43 %13 -OpBranch %58 -%58 = OpLabel -OpBranch %62 -%62 = OpLabel -%63 = OpSLessThan %12 %56 %11 -OpBranch %64 -%64 = OpLabel -%65 = OpIMul %6 %56 %57 -%66 = OpIAdd %6 %54 %65 -OpBranch %67 -%67 = OpLabel -%68 = OpIAdd %6 %56 %13 -%69 = OpISub %6 %57 %13 -OpBranch %70 -%70 = OpLabel -OpBranch %74 -%74 = OpLabel -%75 = OpSLessThan %12 %68 %11 -OpBranch %76 -%76 = OpLabel -%77 = OpIMul %6 %68 %69 -%78 = OpIAdd %6 %66 %77 -OpBranch %79 -%79 = OpLabel -%80 = OpIAdd %6 %68 %13 -%81 = OpISub %6 %69 %13 -OpBranch %32 -%44 = OpLabel -%45 = OpIAdd %6 %34 %33 -OpReturnValue %45 -%25 = OpLabel -%30 = OpIAdd %6 %34 %33 -OpReturnValue %30 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << multiple_phi_shader << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck>(multiple_phi_shader, output, - false); -} - -TEST_F(PassClassTest, PartiallyUnrollMultipleInductionVariables) { - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "foo(" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypeFunction %6 -%8 = OpTypePointer Function %6 -%9 = OpConstant %6 0 -%10 = OpConstant %6 3 -%11 = OpConstant %6 6 -%12 = OpTypeBool -%13 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%14 = OpLabel -%15 = OpFunctionCall %6 %3 -OpReturn -OpFunctionEnd -%3 = OpFunction %6 None %7 -%16 = OpLabel -OpBranch %17 -%17 = OpLabel -%18 = OpPhi %6 %9 %16 %42 %40 -%21 = OpPhi %6 %10 %16 %39 %40 -%23 = OpPhi %6 %9 %16 %41 %40 -OpLoopMerge %25 %40 DontUnroll -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %23 %11 -OpBranchConditional %27 %28 %25 -%28 = OpLabel -%29 = OpIMul %6 %23 %18 -%22 = OpIAdd %6 %21 %29 -OpBranch %20 -%20 = OpLabel -%24 = OpIAdd %6 %23 %13 -%19 = OpISub %6 %18 %13 -OpBranch %31 -%31 = OpLabel -OpBranch %35 -%35 = OpLabel -%36 = OpSLessThan %12 %24 %11 -OpBranch %37 -%37 = OpLabel -%38 = OpIMul %6 %24 %19 -%39 = OpIAdd %6 %22 %38 -OpBranch %40 -%40 = OpLabel -%41 = OpIAdd %6 %24 %13 -%42 = OpISub %6 %19 %13 -OpBranch %17 -%25 = OpLabel -%30 = OpIAdd %6 %21 %18 -OpReturnValue %30 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << multiple_phi_shader << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck>(multiple_phi_shader, output, - false); -} - -TEST_F(PassClassTest, FullyUnrollMultipleInductionVariables) { - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 410 -OpName %2 "main" -OpName %3 "foo(" -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpTypeInt 32 1 -%7 = OpTypeFunction %6 -%8 = OpTypePointer Function %6 -%9 = OpConstant %6 0 -%10 = OpConstant %6 3 -%11 = OpConstant %6 6 -%12 = OpTypeBool -%13 = OpConstant %6 1 -%2 = OpFunction %4 None %5 -%14 = OpLabel -%15 = OpFunctionCall %6 %3 -OpReturn -OpFunctionEnd -%3 = OpFunction %6 None %7 -%16 = OpLabel -OpBranch %17 -%17 = OpLabel -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %12 %9 %11 -OpBranch %28 -%28 = OpLabel -%29 = OpIMul %6 %9 %9 -%22 = OpIAdd %6 %10 %29 -OpBranch %20 -%20 = OpLabel -%24 = OpIAdd %6 %9 %13 -%19 = OpISub %6 %9 %13 -OpBranch %31 -%31 = OpLabel -OpBranch %35 -%35 = OpLabel -%36 = OpSLessThan %12 %24 %11 -OpBranch %37 -%37 = OpLabel -%38 = OpIMul %6 %24 %19 -%39 = OpIAdd %6 %22 %38 -OpBranch %40 -%40 = OpLabel -%41 = OpIAdd %6 %24 %13 -%42 = OpISub %6 %19 %13 -OpBranch %43 -%43 = OpLabel -OpBranch %47 -%47 = OpLabel -%48 = OpSLessThan %12 %41 %11 -OpBranch %49 -%49 = OpLabel -%50 = OpIMul %6 %41 %42 -%51 = OpIAdd %6 %39 %50 -OpBranch %52 -%52 = OpLabel -%53 = OpIAdd %6 %41 %13 -%54 = OpISub %6 %42 %13 -OpBranch %55 -%55 = OpLabel -OpBranch %59 -%59 = OpLabel -%60 = OpSLessThan %12 %53 %11 -OpBranch %61 -%61 = OpLabel -%62 = OpIMul %6 %53 %54 -%63 = OpIAdd %6 %51 %62 -OpBranch %64 -%64 = OpLabel -%65 = OpIAdd %6 %53 %13 -%66 = OpISub %6 %54 %13 -OpBranch %67 -%67 = OpLabel -OpBranch %71 -%71 = OpLabel -%72 = OpSLessThan %12 %65 %11 -OpBranch %73 -%73 = OpLabel -%74 = OpIMul %6 %65 %66 -%75 = OpIAdd %6 %63 %74 -OpBranch %76 -%76 = OpLabel -%77 = OpIAdd %6 %65 %13 -%78 = OpISub %6 %66 %13 -OpBranch %79 -%79 = OpLabel -OpBranch %83 -%83 = OpLabel -%84 = OpSLessThan %12 %77 %11 -OpBranch %85 -%85 = OpLabel -%86 = OpIMul %6 %77 %78 -%87 = OpIAdd %6 %75 %86 -OpBranch %88 -%88 = OpLabel -%89 = OpIAdd %6 %77 %13 -%90 = OpISub %6 %78 %13 -OpBranch %25 -%25 = OpLabel -%30 = OpIAdd %6 %87 %90 -OpReturnValue %30 -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << multiple_phi_shader << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(multiple_phi_shader, output, false); -} - -/* -Generated from the following GLSL -#version 440 core -void main() -{ - int j = 0; - for (int i = 0; i <= 2; ++i) - ++j; - - for (int i = 1; i >= 0; --i) - ++j; -} -*/ -TEST_F(PassClassTest, FullyUnrollEqualToOperations) { - // With LocalMultiStoreElimPass - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 440 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %17 = OpConstant %6 2 - %18 = OpTypeBool - %21 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %11 - %11 = OpLabel - %37 = OpPhi %6 %9 %5 %22 %14 - %38 = OpPhi %6 %9 %5 %24 %14 - OpLoopMerge %13 %14 Unroll - OpBranch %15 - %15 = OpLabel - %19 = OpSLessThanEqual %18 %38 %17 - OpBranchConditional %19 %12 %13 - %12 = OpLabel - %22 = OpIAdd %6 %37 %21 - OpBranch %14 - %14 = OpLabel - %24 = OpIAdd %6 %38 %21 - OpBranch %11 - %13 = OpLabel - OpBranch %26 - %26 = OpLabel - %39 = OpPhi %6 %37 %13 %34 %29 - %40 = OpPhi %6 %21 %13 %36 %29 - OpLoopMerge %28 %29 Unroll - OpBranch %30 - %30 = OpLabel - %32 = OpSGreaterThanEqual %18 %40 %9 - OpBranchConditional %32 %27 %28 - %27 = OpLabel - %34 = OpIAdd %6 %39 %21 - OpBranch %29 - %29 = OpLabel - %36 = OpISub %6 %40 %21 - OpBranch %26 - %28 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string output = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 440 -OpName %2 "main" -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpTypePointer Function %5 -%7 = OpConstant %5 0 -%8 = OpConstant %5 2 -%9 = OpTypeBool -%10 = OpConstant %5 1 -%2 = OpFunction %3 None %4 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -OpBranch %19 -%19 = OpLabel -%20 = OpSLessThanEqual %9 %7 %8 -OpBranch %21 -%21 = OpLabel -%14 = OpIAdd %5 %7 %10 -OpBranch %15 -%15 = OpLabel -%17 = OpIAdd %5 %7 %10 -OpBranch %41 -%41 = OpLabel -OpBranch %44 -%44 = OpLabel -%45 = OpSLessThanEqual %9 %17 %8 -OpBranch %46 -%46 = OpLabel -%47 = OpIAdd %5 %14 %10 -OpBranch %48 -%48 = OpLabel -%49 = OpIAdd %5 %17 %10 -OpBranch %50 -%50 = OpLabel -OpBranch %53 -%53 = OpLabel -%54 = OpSLessThanEqual %9 %49 %8 -OpBranch %55 -%55 = OpLabel -%56 = OpIAdd %5 %47 %10 -OpBranch %57 -%57 = OpLabel -%58 = OpIAdd %5 %49 %10 -OpBranch %18 -%18 = OpLabel -OpBranch %22 -%22 = OpLabel -OpBranch %29 -%29 = OpLabel -%30 = OpSGreaterThanEqual %9 %10 %7 -OpBranch %31 -%31 = OpLabel -%24 = OpIAdd %5 %56 %10 -OpBranch %25 -%25 = OpLabel -%27 = OpISub %5 %10 %10 -OpBranch %32 -%32 = OpLabel -OpBranch %35 -%35 = OpLabel -%36 = OpSGreaterThanEqual %9 %27 %7 -OpBranch %37 -%37 = OpLabel -%38 = OpIAdd %5 %24 %10 -OpBranch %39 -%39 = OpLabel -%40 = OpISub %5 %27 %10 -OpBranch %28 -%28 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << text << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(text, output, false); -} - -// With LocalMultiStoreElimPass -const std::string condition_in_header = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %o - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpDecorate %o Location 0 - %void = OpTypeVoid - %6 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %int_n2 = OpConstant %int -2 - %int_2 = OpConstant %int 2 - %bool = OpTypeBool - %float = OpTypeFloat 32 -%_ptr_Output_float = OpTypePointer Output %float - %o = OpVariable %_ptr_Output_float Output - %float_1 = OpConstant %float 1 - %main = OpFunction %void None %6 - %15 = OpLabel - OpBranch %16 - %16 = OpLabel - %27 = OpPhi %int %int_n2 %15 %26 %18 - %21 = OpSLessThanEqual %bool %27 %int_2 - OpLoopMerge %17 %18 Unroll - OpBranchConditional %21 %22 %17 - %22 = OpLabel - %23 = OpLoad %float %o - %24 = OpFAdd %float %23 %float_1 - OpStore %o %24 - OpBranch %18 - %18 = OpLabel - %26 = OpIAdd %int %27 %int_2 - OpBranch %16 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - -TEST_F(PassClassTest, FullyUnrollConditionIsInHeaderBlock) { - const std::string output = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpSource GLSL 430 -OpDecorate %2 Location 0 -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpConstant %5 -2 -%7 = OpConstant %5 2 -%8 = OpTypeBool -%9 = OpTypeFloat 32 -%10 = OpTypePointer Output %9 -%2 = OpVariable %10 Output -%11 = OpConstant %9 1 -%1 = OpFunction %3 None %4 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%17 = OpSLessThanEqual %8 %6 %7 -OpBranch %19 -%19 = OpLabel -%20 = OpLoad %9 %2 -%21 = OpFAdd %9 %20 %11 -OpStore %2 %21 -OpBranch %16 -%16 = OpLabel -%15 = OpIAdd %5 %6 %7 -OpBranch %22 -%22 = OpLabel -%24 = OpSLessThanEqual %8 %15 %7 -OpBranch %25 -%25 = OpLabel -%26 = OpLoad %9 %2 -%27 = OpFAdd %9 %26 %11 -OpStore %2 %27 -OpBranch %28 -%28 = OpLabel -%29 = OpIAdd %5 %15 %7 -OpBranch %30 -%30 = OpLabel -%32 = OpSLessThanEqual %8 %29 %7 -OpBranch %33 -%33 = OpLabel -%34 = OpLoad %9 %2 -%35 = OpFAdd %9 %34 %11 -OpStore %2 %35 -OpBranch %36 -%36 = OpLabel -%37 = OpIAdd %5 %29 %7 -OpBranch %18 -%18 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, condition_in_header, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << condition_in_header << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(condition_in_header, output, false); -} - -TEST_F(PassClassTest, PartiallyUnrollResidualConditionIsInHeaderBlock) { - const std::string output = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" %2 -OpExecutionMode %1 OriginUpperLeft -OpSource GLSL 430 -OpDecorate %2 Location 0 -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeInt 32 1 -%6 = OpConstant %5 -2 -%7 = OpConstant %5 2 -%8 = OpTypeBool -%9 = OpTypeFloat 32 -%10 = OpTypePointer Output %9 -%2 = OpVariable %10 Output -%11 = OpConstant %9 1 -%40 = OpTypeInt 32 0 -%41 = OpConstant %40 1 -%1 = OpFunction %3 None %4 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%14 = OpPhi %5 %6 %12 %15 %16 -%17 = OpSLessThanEqual %8 %14 %41 -OpLoopMerge %22 %16 Unroll -OpBranchConditional %17 %19 %22 -%19 = OpLabel -%20 = OpLoad %9 %2 -%21 = OpFAdd %9 %20 %11 -OpStore %2 %21 -OpBranch %16 -%16 = OpLabel -%15 = OpIAdd %5 %14 %7 -OpBranch %13 -%22 = OpLabel -OpBranch %23 -%23 = OpLabel -%24 = OpPhi %5 %14 %22 %39 %38 -%25 = OpSLessThanEqual %8 %24 %7 -OpLoopMerge %31 %38 DontUnroll -OpBranchConditional %25 %26 %31 -%26 = OpLabel -%27 = OpLoad %9 %2 -%28 = OpFAdd %9 %27 %11 -OpStore %2 %28 -OpBranch %29 -%29 = OpLabel -%30 = OpIAdd %5 %24 %7 -OpBranch %32 -%32 = OpLabel -%34 = OpSLessThanEqual %8 %30 %7 -OpBranch %35 -%35 = OpLabel -%36 = OpLoad %9 %2 -%37 = OpFAdd %9 %36 %11 -OpStore %2 %37 -OpBranch %38 -%38 = OpLabel -%39 = OpIAdd %5 %30 %7 -OpBranch %23 -%31 = OpLabel -OpReturn -%18 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, condition_in_header, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n" - << condition_in_header << std::endl; - - LoopUnroller loop_unroller; - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck>(condition_in_header, output, - false); -} - -/* -Generated from following GLSL with latch block artificially inserted to be -seperate from continue. -#version 430 -void main(void) { - float x[10]; - for (int i = 0; i < 10; ++i) { - x[i] = i; - } -} -*/ -TEST_F(PassClassTest, PartiallyUnrollLatchNotContinue) { - const std::string text = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "x" - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeInt 32 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %10 = OpConstant %7 10 - %11 = OpTypeBool - %12 = OpTypeFloat 32 - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 10 - %15 = OpTypeArray %12 %14 - %16 = OpTypePointer Function %15 - %17 = OpTypePointer Function %12 - %18 = OpConstant %7 1 - %2 = OpFunction %5 None %6 - %19 = OpLabel - %3 = OpVariable %8 Function - %4 = OpVariable %16 Function - OpStore %3 %9 - OpBranch %20 - %20 = OpLabel - %21 = OpPhi %7 %9 %19 %22 %30 - OpLoopMerge %24 %23 Unroll - OpBranch %25 - %25 = OpLabel - %26 = OpSLessThan %11 %21 %10 - OpBranchConditional %26 %27 %24 - %27 = OpLabel - %28 = OpConvertSToF %12 %21 - %29 = OpAccessChain %17 %4 %21 - OpStore %29 %28 - OpBranch %23 - %23 = OpLabel - %22 = OpIAdd %7 %21 %18 - OpStore %3 %22 - OpBranch %30 - %30 = OpLabel - OpBranch %20 - %24 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const std::string expected = R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpName %2 "main" -OpName %3 "i" -OpName %4 "x" -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpTypeInt 32 1 -%8 = OpTypePointer Function %7 -%9 = OpConstant %7 0 -%10 = OpConstant %7 10 -%11 = OpTypeBool -%12 = OpTypeFloat 32 -%13 = OpTypeInt 32 0 -%14 = OpConstant %13 10 -%15 = OpTypeArray %12 %14 -%16 = OpTypePointer Function %15 -%17 = OpTypePointer Function %12 -%18 = OpConstant %7 1 -%63 = OpConstant %13 1 -%2 = OpFunction %5 None %6 -%19 = OpLabel -%3 = OpVariable %8 Function -%4 = OpVariable %16 Function -OpStore %3 %9 -OpBranch %20 -%20 = OpLabel -%21 = OpPhi %7 %9 %19 %22 %23 -OpLoopMerge %31 %25 Unroll -OpBranch %26 -%26 = OpLabel -%27 = OpSLessThan %11 %21 %63 -OpBranchConditional %27 %28 %31 -%28 = OpLabel -%29 = OpConvertSToF %12 %21 -%30 = OpAccessChain %17 %4 %21 -OpStore %30 %29 -OpBranch %25 -%25 = OpLabel -%22 = OpIAdd %7 %21 %18 -OpStore %3 %22 -OpBranch %23 -%23 = OpLabel -OpBranch %20 -%31 = OpLabel -OpBranch %32 -%32 = OpLabel -%33 = OpPhi %7 %21 %31 %61 %62 -OpLoopMerge %42 %60 DontUnroll -OpBranch %34 -%34 = OpLabel -%35 = OpSLessThan %11 %33 %10 -OpBranchConditional %35 %36 %42 -%36 = OpLabel -%37 = OpConvertSToF %12 %33 -%38 = OpAccessChain %17 %4 %33 -OpStore %38 %37 -OpBranch %39 -%39 = OpLabel -%40 = OpIAdd %7 %33 %18 -OpStore %3 %40 -OpBranch %41 -%41 = OpLabel -OpBranch %43 -%43 = OpLabel -OpBranch %45 -%45 = OpLabel -%46 = OpSLessThan %11 %40 %10 -OpBranch %47 -%47 = OpLabel -%48 = OpConvertSToF %12 %40 -%49 = OpAccessChain %17 %4 %40 -OpStore %49 %48 -OpBranch %50 -%50 = OpLabel -%51 = OpIAdd %7 %40 %18 -OpStore %3 %51 -OpBranch %52 -%52 = OpLabel -OpBranch %53 -%53 = OpLabel -OpBranch %55 -%55 = OpLabel -%56 = OpSLessThan %11 %51 %10 -OpBranch %57 -%57 = OpLabel -%58 = OpConvertSToF %12 %51 -%59 = OpAccessChain %17 %4 %51 -OpStore %59 %58 -OpBranch %60 -%60 = OpLabel -%61 = OpIAdd %7 %51 %18 -OpStore %3 %61 -OpBranch %62 -%62 = OpLabel -OpBranch %32 -%42 = OpLabel -OpReturn -%24 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck>(text, expected, true); - - // Make sure the latch block information is preserved and propagated correctly - // by the pass. - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - PartialUnrollerTestPass<3> unroller; - unroller.SetContextForTesting(context.get()); - unroller.Process(); - - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - LoopDescriptor ld{context.get(), f}; - - EXPECT_EQ(ld.NumLoops(), 2u); - - Loop& loop_1 = ld.GetLoopByIndex(0u); - EXPECT_NE(loop_1.GetLatchBlock(), loop_1.GetContinueBlock()); - - Loop& loop_2 = ld.GetLoopByIndex(1u); - EXPECT_NE(loop_2.GetLatchBlock(), loop_2.GetContinueBlock()); -} - -// Test that a loop with a self-referencing OpPhi instruction is handled -// correctly. -TEST_F(PassClassTest, OpPhiSelfReference) { - const std::string text = R"( - ; Find the two adds from the unrolled loop - ; CHECK: OpIAdd - ; CHECK: OpIAdd - ; CHECK: OpIAdd %uint %uint_0 %uint_1 - ; CHECK-NEXT: OpReturn - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 8 8 1 - OpSource HLSL 600 - %uint = OpTypeInt 32 0 - %void = OpTypeVoid - %5 = OpTypeFunction %void -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %2 = OpFunction %void None %5 - %10 = OpLabel - OpBranch %19 - %19 = OpLabel - %20 = OpPhi %uint %uint_0 %10 %20 %21 - %22 = OpPhi %uint %uint_0 %10 %23 %21 - %24 = OpULessThanEqual %bool %22 %uint_1 - OpLoopMerge %25 %21 Unroll - OpBranchConditional %24 %21 %25 - %21 = OpLabel - %23 = OpIAdd %uint %22 %uint_1 - OpBranch %19 - %25 = OpLabel - %14 = OpIAdd %uint %20 %uint_1 - OpReturn - OpFunctionEnd - )"; - - const bool kFullyUnroll = true; - const uint32_t kUnrollFactor = 0; - SinglePassRunAndMatch(text, true, kFullyUnroll, - kUnrollFactor); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/loop_optimizations/unswitch.cpp b/3rdparty/spirv-tools/test/opt/loop_optimizations/unswitch.cpp deleted file mode 100644 index dc7073fd5..000000000 --- a/3rdparty/spirv-tools/test/opt/loop_optimizations/unswitch.cpp +++ /dev/null @@ -1,967 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "effcee/effcee.h" -#include "gmock/gmock.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using UnswitchTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 450 core -uniform vec4 c; -void main() { - int i = 0; - int j = 0; - bool cond = c[0] == 0; - for (; i < 10; i++, j++) { - if (cond) { - i++; - } - else { - j++; - } - } -} -*/ -TEST_F(UnswitchTest, SimpleUnswitch) { - const std::string text = R"( -; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual -; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]] - -; Loop specialized for false. -; CHECK: [[loop_f]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_f]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: [[phi_j:%\w+]] = OpPhi %int %int_0 [[loop_f]] [[iv_j:%\w+]] [[continue]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; [[loop_body]] = OpLabel -; CHECK: OpSelectionMerge [[sel_merge:%\w+]] None -; CHECK: OpBranchConditional %false [[bb1:%\w+]] [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: [[inc_j:%\w+]] = OpIAdd %int [[phi_j]] %int_1 -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: [[inc_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1 -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK: OpBranch [[if_merge]] - -; Loop specialized for true. -; CHECK: [[loop_t]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: [[phi_j:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_j:%\w+]] [[continue]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; [[loop_body]] = OpLabel -; CHECK: OpSelectionMerge [[sel_merge:%\w+]] None -; CHECK: OpBranchConditional %true [[bb1:%\w+]] [[bb2:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: [[inc_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1 -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: [[inc_j:%\w+]] = OpIAdd %int [[phi_j]] %int_1 -; CHECK-NEXT: OpBranch [[sel_merge]] -; CHECK: [[sel_merge]] = OpLabel -; CHECK: OpBranch [[if_merge]] - -; CHECK: [[if_merge]] = OpLabel -; CHECK-NEXT: OpReturn - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 450 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - OpDecorate %c DescriptorSet 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_UniformConstant_v4float = OpTypePointer UniformConstant %v4float - %c = OpVariable %_ptr_UniformConstant_v4float UniformConstant - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_UniformConstant_float = OpTypePointer UniformConstant %float - %float_0 = OpConstant %float 0 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %21 = OpAccessChain %_ptr_UniformConstant_float %c %uint_0 - %22 = OpLoad %float %21 - %24 = OpFOrdEqual %bool %22 %float_0 - OpBranch %25 - %25 = OpLabel - %46 = OpPhi %int %int_0 %5 %43 %28 - %47 = OpPhi %int %int_0 %5 %45 %28 - OpLoopMerge %27 %28 None - OpBranch %29 - %29 = OpLabel - %32 = OpSLessThan %bool %46 %int_10 - OpBranchConditional %32 %26 %27 - %26 = OpLabel - OpSelectionMerge %35 None - OpBranchConditional %24 %34 %39 - %34 = OpLabel - %38 = OpIAdd %int %46 %int_1 - OpBranch %35 - %39 = OpLabel - %41 = OpIAdd %int %47 %int_1 - OpBranch %35 - %35 = OpLabel - %48 = OpPhi %int %38 %34 %46 %39 - %49 = OpPhi %int %47 %34 %41 %39 - OpBranch %28 - %28 = OpLabel - %43 = OpIAdd %int %48 %int_1 - %45 = OpIAdd %int %49 %int_1 - OpBranch %25 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -in vec4 c; -void main() { - int i = 0; - bool cond = c[0] == 0; - for (; i < 10; i++) { - if (cond) { - i++; - } - else { - return; - } - } -} -*/ -TEST_F(UnswitchTest, UnswitchExit) { - const std::string text = R"( -; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual -; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]] - -; Loop specialized for false. -; CHECK: [[loop_f]] = OpLabel -; CHECK: OpReturn - -; Loop specialized for true. -; CHECK: [[loop_t]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] {{%\w+}} [[merge]] -; Check that we have i+=2. -; CHECK: [[phi_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1 -; CHECK: [[iv_i]] = OpIAdd %int [[phi_i]] %int_1 -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; CHECK: [[if_merge]] = OpLabel -; CHECK-NEXT: OpReturn - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %c - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - OpDecorate %23 Uniform - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %c = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %20 = OpAccessChain %_ptr_Input_float %c %uint_0 - %21 = OpLoad %float %20 - %23 = OpFOrdEqual %bool %21 %float_0 - OpBranch %24 - %24 = OpLabel - %42 = OpPhi %int %int_0 %5 %41 %27 - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %31 = OpSLessThan %bool %42 %int_10 - OpBranchConditional %31 %25 %26 - %25 = OpLabel - OpSelectionMerge %34 None - OpBranchConditional %23 %33 %38 - %33 = OpLabel - %37 = OpIAdd %int %42 %int_1 - OpBranch %34 - %38 = OpLabel - OpReturn - %34 = OpLabel - OpBranch %27 - %27 = OpLabel - %41 = OpIAdd %int %37 %int_1 - OpBranch %24 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -in vec4 c; -void main() { - int i = 0; - bool cond = c[0] == 0; - for (; i < 10; i++) { - if (cond) { - continue; - } - else { - i++; - } - } -} -*/ -TEST_F(UnswitchTest, UnswitchContinue) { - const std::string text = R"( -; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual -; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]] - -; Loop specialized for false. -; CHECK: [[loop_f]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_f]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; CHECK: [[loop_body:%\w+]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpBranchConditional %false -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; Loop specialized for true. -; CHECK: [[loop_t]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; CHECK: [[loop_body:%\w+]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpBranchConditional %true -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; CHECK: [[if_merge]] = OpLabel -; CHECK-NEXT: OpReturn - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %c - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - OpDecorate %23 Uniform - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %c = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %20 = OpAccessChain %_ptr_Input_float %c %uint_0 - %21 = OpLoad %float %20 - %23 = OpFOrdEqual %bool %21 %float_0 - OpBranch %24 - %24 = OpLabel - %42 = OpPhi %int %int_0 %5 %41 %27 - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %31 = OpSLessThan %bool %42 %int_10 - OpBranchConditional %31 %25 %26 - %25 = OpLabel - OpSelectionMerge %34 None - OpBranchConditional %23 %33 %36 - %33 = OpLabel - OpBranch %27 - %36 = OpLabel - %39 = OpIAdd %int %42 %int_1 - OpBranch %34 - %34 = OpLabel - OpBranch %27 - %27 = OpLabel - %43 = OpPhi %int %42 %33 %39 %34 - %41 = OpIAdd %int %43 %int_1 - OpBranch %24 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -in vec4 c; -void main() { - int i = 0; - bool cond = c[0] == 0; - for (; i < 10; i++) { - if (cond) { - i++; - } - else { - break; - } - } -} -*/ -TEST_F(UnswitchTest, UnswitchKillLoop) { - const std::string text = R"( -; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual -; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]] - -; Loop specialized for false. -; CHECK: [[loop_f]] = OpLabel -; CHECK: OpBranch [[if_merge]] - -; Loop specialized for true. -; CHECK: [[loop_t]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] {{%\w+}} [[merge]] -; Check that we have i+=2. -; CHECK: [[phi_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1 -; CHECK: [[iv_i]] = OpIAdd %int [[phi_i]] %int_1 -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; CHECK: [[if_merge]] = OpLabel -; CHECK-NEXT: OpReturn - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %c - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - OpDecorate %23 Uniform - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %c = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %20 = OpAccessChain %_ptr_Input_float %c %uint_0 - %21 = OpLoad %float %20 - %23 = OpFOrdEqual %bool %21 %float_0 - OpBranch %24 - %24 = OpLabel - %42 = OpPhi %int %int_0 %5 %41 %27 - OpLoopMerge %26 %27 None - OpBranch %28 - %28 = OpLabel - %31 = OpSLessThan %bool %42 %int_10 - OpBranchConditional %31 %25 %26 - %25 = OpLabel - OpSelectionMerge %34 None - OpBranchConditional %23 %33 %38 - %33 = OpLabel - %37 = OpIAdd %int %42 %int_1 - OpBranch %34 - %38 = OpLabel - OpBranch %26 - %34 = OpLabel - OpBranch %27 - %27 = OpLabel - %41 = OpIAdd %int %37 %int_1 - OpBranch %24 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -in vec4 c; -void main() { - int i = 0; - int cond = int(c[0]); - for (; i < 10; i++) { - switch (cond) { - case 0: - return; - case 1: - discard; - case 2: - break; - default: - break; - } - } - bool cond2 = i == 9; -} -*/ -TEST_F(UnswitchTest, UnswitchSwitch) { - const std::string text = R"( -; CHECK: [[cst_cond:%\w+]] = OpConvertFToS -; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None -; CHECK-NEXT: OpSwitch [[cst_cond]] [[default:%\w+]] 0 [[loop_0:%\w+]] 1 [[loop_1:%\w+]] 2 [[loop_2:%\w+]] - -; Loop specialized for 2. -; CHECK: [[loop_2]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_2]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; CHECK: [[loop_body]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpSwitch %int_2 -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; Loop specialized for 1. -; CHECK: [[loop_1]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_1]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; CHECK: [[loop_body]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpSwitch %int_1 -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; Loop specialized for 0. -; CHECK: [[loop_0]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_0]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; CHECK: [[loop_body]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpSwitch %int_0 -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; Loop specialized for the default case. -; CHECK: [[default]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[default]] [[iv_i:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]] -; CHECK: [[loop_body]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpSwitch %uint_3 -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: OpBranch [[if_merge]] - -; CHECK: [[if_merge]] = OpLabel -; CHECK-NEXT: OpReturn - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %c - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - OpDecorate %20 Uniform - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %c = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 -%_ptr_Function_bool = OpTypePointer Function %bool - %main = OpFunction %void None %3 - %5 = OpLabel - %18 = OpAccessChain %_ptr_Input_float %c %uint_0 - %19 = OpLoad %float %18 - %20 = OpConvertFToS %int %19 - OpBranch %21 - %21 = OpLabel - %49 = OpPhi %int %int_0 %5 %43 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %29 = OpSLessThan %bool %49 %int_10 - OpBranchConditional %29 %22 %23 - %22 = OpLabel - OpSelectionMerge %35 None - OpSwitch %20 %34 0 %31 1 %32 2 %33 - %34 = OpLabel - OpBranch %35 - %31 = OpLabel - OpReturn - %32 = OpLabel - OpKill - %33 = OpLabel - OpBranch %35 - %35 = OpLabel - OpBranch %24 - %24 = OpLabel - %43 = OpIAdd %int %49 %int_1 - OpBranch %21 - %23 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 440 core -layout(location = 0)in vec4 c; -void main() { - int i = 0; - int j = 0; - int k = 0; - bool cond = c[0] == 0; - for (; i < 10; i++) { - for (; j < 10; j++) { - if (cond) { - i++; - } else { - j++; - } - } - } -} -*/ -TEST_F(UnswitchTest, UnSwitchNested) { - // Test that an branch can be unswitched out of two nested loops. - const std::string text = R"( -; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual -; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None -; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]] - -; Loop specialized for false -; CHECK: [[loop_f]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_f]] {{%\w+}} [[continue:%\w+]] -; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_f]] {{%\w+}} [[continue]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK-NOT: [[merge]] = OpLabel -; CHECK: OpLoopMerge -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpSLessThan -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpBranchConditional %false -; CHECK: [[merge]] = OpLabel - -; Loop specialized for true. Same as first loop except the branch condition is true. -; CHECK: [[loop_t]] = OpLabel -; CHECK-NEXT: OpBranch [[loop:%\w+]] -; CHECK: [[loop]] = OpLabel -; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_t]] {{%\w+}} [[continue:%\w+]] -; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_t]] {{%\w+}} [[continue]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None -; CHECK-NOT: [[merge]] = OpLabel -; CHECK: OpLoopMerge -; CHECK-NEXT: OpBranch [[bb1:%\w+]] -; CHECK: [[bb1]] = OpLabel -; CHECK-NEXT: OpSLessThan -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpBranchConditional %true -; CHECK: [[merge]] = OpLabel - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %c - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 440 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - OpDecorate %25 Uniform - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %c = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %22 = OpAccessChain %_ptr_Input_float %c %uint_0 - %23 = OpLoad %float %22 - %25 = OpFOrdEqual %bool %23 %float_0 - OpBranch %26 - %26 = OpLabel - %67 = OpPhi %int %int_0 %5 %52 %29 - %68 = OpPhi %int %int_0 %5 %70 %29 - OpLoopMerge %28 %29 None - OpBranch %30 - %30 = OpLabel - %33 = OpSLessThan %bool %67 %int_10 - OpBranchConditional %33 %27 %28 - %27 = OpLabel - OpBranch %34 - %34 = OpLabel - %69 = OpPhi %int %67 %27 %46 %37 - %70 = OpPhi %int %68 %27 %50 %37 - OpLoopMerge %36 %37 None - OpBranch %38 - %38 = OpLabel - %40 = OpSLessThan %bool %70 %int_10 - OpBranchConditional %40 %35 %36 - %35 = OpLabel - OpSelectionMerge %43 None - OpBranchConditional %25 %42 %47 - %42 = OpLabel - %46 = OpIAdd %int %69 %int_1 - OpBranch %43 - %47 = OpLabel - OpReturn - %43 = OpLabel - OpBranch %37 - %37 = OpLabel - %50 = OpIAdd %int %70 %int_1 - OpBranch %34 - %36 = OpLabel - OpBranch %29 - %29 = OpLabel - %52 = OpIAdd %int %69 %int_1 - OpBranch %26 - %28 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 330 core -in vec4 c; -void main() { - bool cond = false; - if (c[0] == 0) { - cond = c[1] == 0; - } else { - cond = c[2] == 0; - } - for (int i = 0; i < 10; i++) { - if (cond) { - i++; - } - } -} -*/ -TEST_F(UnswitchTest, UnswitchNotUniform) { - // Check that the unswitch is not triggered (condition loop invariant but not - // uniform) - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %c - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - OpName %c "c" - OpDecorate %c Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %c = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_10 = OpConstant %int 10 - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %3 - %5 = OpLabel - %17 = OpAccessChain %_ptr_Input_float %c %uint_0 - %18 = OpLoad %float %17 - %20 = OpFOrdEqual %bool %18 %float_0 - OpSelectionMerge %22 None - OpBranchConditional %20 %21 %27 - %21 = OpLabel - %24 = OpAccessChain %_ptr_Input_float %c %uint_1 - %25 = OpLoad %float %24 - %26 = OpFOrdEqual %bool %25 %float_0 - OpBranch %22 - %27 = OpLabel - %29 = OpAccessChain %_ptr_Input_float %c %uint_2 - %30 = OpLoad %float %29 - %31 = OpFOrdEqual %bool %30 %float_0 - OpBranch %22 - %22 = OpLabel - %52 = OpPhi %bool %26 %21 %31 %27 - OpBranch %36 - %36 = OpLabel - %53 = OpPhi %int %int_0 %22 %51 %39 - OpLoopMerge %38 %39 None - OpBranch %40 - %40 = OpLabel - %43 = OpSLessThan %bool %53 %int_10 - OpBranchConditional %43 %37 %38 - %37 = OpLabel - OpSelectionMerge %46 None - OpBranchConditional %52 %45 %46 - %45 = OpLabel - %49 = OpIAdd %int %53 %int_1 - OpBranch %46 - %46 = OpLabel - %54 = OpPhi %int %53 %37 %49 %45 - OpBranch %39 - %39 = OpLabel - %51 = OpIAdd %int %54 %int_1 - OpBranch %36 - %38 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto result = - SinglePassRunAndDisassemble(text, true, false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(UnswitchTest, DontUnswitchLatch) { - // Check that the unswitch is not triggered for the latch branch. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %bool = OpTypeBool -%false = OpConstantFalse %bool - %4 = OpFunction %void None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - OpBranch %9 - %9 = OpLabel - OpBranchConditional %false %6 %8 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto result = - SinglePassRunAndDisassemble(text, true, false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(UnswitchTest, DontUnswitchConstantCondition) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginLowerLeft - OpSource GLSL 450 - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %int_1 = OpConstant %int 1 - %main = OpFunction %void None %4 - %10 = OpLabel - OpBranch %11 - %11 = OpLabel - %12 = OpPhi %int %int_0 %10 %13 %14 - OpLoopMerge %15 %14 None - OpBranch %16 - %16 = OpLabel - %17 = OpSLessThan %bool %12 %int_1 - OpBranchConditional %17 %18 %15 - %18 = OpLabel - OpSelectionMerge %19 None - OpBranchConditional %true %20 %19 - %20 = OpLabel - %21 = OpIAdd %int %12 %int_1 - OpBranch %19 - %19 = OpLabel - %22 = OpPhi %int %21 %20 %12 %18 - OpBranch %14 - %14 = OpLabel - %13 = OpIAdd %int %22 %int_1 - OpBranch %11 - %15 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto result = - SinglePassRunAndDisassemble(text, true, false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/module_test.cpp b/3rdparty/spirv-tools/test/opt/module_test.cpp deleted file mode 100644 index 406da0939..000000000 --- a/3rdparty/spirv-tools/test/opt/module_test.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/module.h" -#include "source/opt/pass.h" -#include "spirv-tools/libspirv.hpp" -#include "test/opt/module_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::Eq; -using spvtest::GetIdBound; - -TEST(ModuleTest, SetIdBound) { - Module m; - // It's initialized to 0. - EXPECT_EQ(0u, GetIdBound(m)); - - m.SetIdBound(19); - EXPECT_EQ(19u, GetIdBound(m)); - - m.SetIdBound(102); - EXPECT_EQ(102u, GetIdBound(m)); -} - -// Returns an IRContext owning the module formed by assembling the given text, -// then loading the result. -inline std::unique_ptr BuildModule(std::string text) { - return spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); -} - -TEST(ModuleTest, ComputeIdBound) { - // Emtpy module case. - EXPECT_EQ(1u, BuildModule("")->module()->ComputeIdBound()); - // Sensitive to result id - EXPECT_EQ(2u, BuildModule("%void = OpTypeVoid")->module()->ComputeIdBound()); - // Sensitive to type id - EXPECT_EQ(1000u, - BuildModule("%a = OpTypeArray !999 3")->module()->ComputeIdBound()); - // Sensitive to a regular Id parameter - EXPECT_EQ(2000u, - BuildModule("OpDecorate !1999 0")->module()->ComputeIdBound()); - // Sensitive to a scope Id parameter. - EXPECT_EQ(3000u, - BuildModule("%f = OpFunction %void None %fntype %a = OpLabel " - "OpMemoryBarrier !2999 %b\n") - ->module() - ->ComputeIdBound()); - // Sensitive to a semantics Id parameter - EXPECT_EQ(4000u, - BuildModule("%f = OpFunction %void None %fntype %a = OpLabel " - "OpMemoryBarrier %b !3999\n") - ->module() - ->ComputeIdBound()); -} - -TEST(ModuleTest, OstreamOperator) { - const std::string text = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %7 "restrict" -OpDecorate %8 Restrict -%9 = OpTypeVoid -%10 = OpTypeInt 32 0 -%11 = OpTypeStruct %10 %10 -%12 = OpTypePointer Function %10 -%13 = OpTypePointer Function %11 -%14 = OpConstant %10 0 -%15 = OpConstant %10 1 -%7 = OpTypeFunction %9 -%1 = OpFunction %9 None %7 -%2 = OpLabel -%8 = OpVariable %13 Function -%3 = OpAccessChain %12 %8 %14 -%4 = OpLoad %10 %3 -%5 = OpAccessChain %12 %8 %15 -%6 = OpLoad %10 %5 -OpReturn -OpFunctionEnd)"; - - std::string s; - std::ostringstream str(s); - str << *BuildModule(text)->module(); - EXPECT_EQ(text, str.str()); -} - -TEST(ModuleTest, OstreamOperatorInt64) { - const std::string text = R"(OpCapability Shader -OpCapability Linkage -OpCapability Int64 -OpMemoryModel Logical GLSL450 -OpName %7 "restrict" -OpDecorate %5 Restrict -%9 = OpTypeVoid -%10 = OpTypeInt 64 0 -%11 = OpTypeStruct %10 %10 -%12 = OpTypePointer Function %10 -%13 = OpTypePointer Function %11 -%14 = OpConstant %10 0 -%15 = OpConstant %10 1 -%16 = OpConstant %10 4294967297 -%7 = OpTypeFunction %9 -%1 = OpFunction %9 None %7 -%2 = OpLabel -%5 = OpVariable %12 Function -%6 = OpLoad %10 %5 -OpSelectionMerge %3 None -OpSwitch %6 %3 4294967297 %4 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::string s; - std::ostringstream str(s); - str << *BuildModule(text)->module(); - EXPECT_EQ(text, str.str()); -} - -TEST(ModuleTest, IdBoundTestAtLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = BuildModule(text); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound); - uint32_t next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, 0); - EXPECT_EQ(current_bound, context->module()->id_bound()); - next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, 0); -} - -TEST(ModuleTest, IdBoundTestBelowLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = BuildModule(text); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound + 100); - uint32_t next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, current_bound); - EXPECT_EQ(current_bound + 1, context->module()->id_bound()); - next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, current_bound + 1); -} - -TEST(ModuleTest, IdBoundTestNearLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = BuildModule(text); - uint32_t current_bound = context->module()->id_bound(); - context->set_max_id_bound(current_bound + 1); - uint32_t next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, current_bound); - EXPECT_EQ(current_bound + 1, context->module()->id_bound()); - next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, 0); -} - -TEST(ModuleTest, IdBoundTestUIntMax) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4294967294 = OpLabel ; ID is UINT_MAX-1 -OpReturn -OpFunctionEnd)"; - - std::unique_ptr context = BuildModule(text); - uint32_t current_bound = context->module()->id_bound(); - - // Expecting |BuildModule| to preserve the numeric ids. - EXPECT_EQ(current_bound, std::numeric_limits::max()); - - context->set_max_id_bound(current_bound); - uint32_t next_id_bound = context->module()->TakeNextIdBound(); - EXPECT_EQ(next_id_bound, 0); - EXPECT_EQ(current_bound, context->module()->id_bound()); -} - -// Tests that "text" does not change when it is assembled, converted into a -// module, converted back to a binary, and then disassembled. -void AssembleAndDisassemble(const std::string& text) { - std::unique_ptr context = BuildModule(text); - std::vector binary; - - context->module()->ToBinary(&binary, false); - - SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); - std::string s; - tools.Disassemble(binary, &s); - EXPECT_EQ(s, text); -} - -TEST(ModuleTest, TrailingOpLine) { - const std::string text = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%5 = OpString "file.ext" -%void = OpTypeVoid -%2 = OpTypeFunction %void -%3 = OpFunction %void None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd -OpLine %5 1 0 -)"; - - AssembleAndDisassemble(text); -} - -TEST(ModuleTest, TrailingOpNoLine) { - const std::string text = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%2 = OpTypeFunction %void -%3 = OpFunction %void None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd -OpNoLine -)"; - - AssembleAndDisassemble(text); -} - -TEST(ModuleTest, MulitpleTrailingOpLine) { - const std::string text = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%5 = OpString "file.ext" -%void = OpTypeVoid -%2 = OpTypeFunction %void -%3 = OpFunction %void None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd -OpLine %5 1 0 -OpNoLine -OpLine %5 1 1 -)"; - - AssembleAndDisassemble(text); -} -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/module_utils.h b/3rdparty/spirv-tools/test/opt/module_utils.h deleted file mode 100644 index 007f132c2..000000000 --- a/3rdparty/spirv-tools/test/opt/module_utils.h +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -#ifndef TEST_OPT_MODULE_UTILS_H_ -#define TEST_OPT_MODULE_UTILS_H_ - -#include -#include "source/opt/module.h" - -namespace spvtest { - -inline uint32_t GetIdBound(const spvtools::opt::Module& m) { - std::vector binary; - m.ToBinary(&binary, false); - // The 5-word header must always exist. - EXPECT_LE(5u, binary.size()); - // The bound is the fourth word. - return binary[3]; -} - -} // namespace spvtest - -#endif // TEST_OPT_MODULE_UTILS_H_ diff --git a/3rdparty/spirv-tools/test/opt/optimizer_test.cpp b/3rdparty/spirv-tools/test/opt/optimizer_test.cpp deleted file mode 100644 index 945aa7826..000000000 --- a/3rdparty/spirv-tools/test/opt/optimizer_test.cpp +++ /dev/null @@ -1,767 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "spirv-tools/libspirv.hpp" -#include "spirv-tools/optimizer.hpp" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::Eq; - -// Return a string that contains the minimum instructions needed to form -// a valid module. Other instructions can be appended to this string. -std::string Header() { - return R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -)"; -} - -TEST(Optimizer, CanRunNullPassWithDistinctInputOutputVectors) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); - std::vector binary_in; - tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid", - &binary_in); - - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - opt.RegisterPass(CreateNullPass()); - std::vector binary_out; - opt.Run(binary_in.data(), binary_in.size(), &binary_out); - - std::string disassembly; - tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly); - EXPECT_THAT(disassembly, - Eq(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid\n")); -} - -TEST(Optimizer, CanRunTransformingPassWithDistinctInputOutputVectors) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); - std::vector binary_in; - tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid", - &binary_in); - - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - opt.RegisterPass(CreateStripDebugInfoPass()); - std::vector binary_out; - opt.Run(binary_in.data(), binary_in.size(), &binary_out); - - std::string disassembly; - tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly); - EXPECT_THAT(disassembly, Eq(Header() + "%void = OpTypeVoid\n")); -} - -TEST(Optimizer, CanRunNullPassWithAliasedVectors) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); - std::vector binary; - tools.Assemble("OpName %foo \"foo\"\n%foo = OpTypeVoid", &binary); - - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - opt.RegisterPass(CreateNullPass()); - opt.Run(binary.data(), binary.size(), &binary); // This is the key. - - std::string disassembly; - tools.Disassemble(binary.data(), binary.size(), &disassembly); - EXPECT_THAT(disassembly, Eq("OpName %foo \"foo\"\n%foo = OpTypeVoid\n")); -} - -TEST(Optimizer, CanRunNullPassWithAliasedVectorDataButDifferentSize) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); - std::vector binary; - tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid", &binary); - - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - opt.RegisterPass(CreateNullPass()); - auto orig_size = binary.size(); - // Now change the size. Add a word that will be ignored - // by the optimizer. - binary.push_back(42); - EXPECT_THAT(orig_size + 1, Eq(binary.size())); - opt.Run(binary.data(), orig_size, &binary); // This is the key. - // The binary vector should have been rewritten. - EXPECT_THAT(binary.size(), Eq(orig_size)); - - std::string disassembly; - tools.Disassemble(binary.data(), binary.size(), &disassembly); - EXPECT_THAT(disassembly, - Eq(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid\n")); -} - -TEST(Optimizer, CanRunTransformingPassWithAliasedVectors) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); - std::vector binary; - tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid", &binary); - - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - opt.RegisterPass(CreateStripDebugInfoPass()); - opt.Run(binary.data(), binary.size(), &binary); // This is the key - - std::string disassembly; - tools.Disassemble(binary.data(), binary.size(), &disassembly); - EXPECT_THAT(disassembly, Eq(Header() + "%void = OpTypeVoid\n")); -} - -TEST(Optimizer, CanValidateFlags) { - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - EXPECT_FALSE(opt.FlagHasValidForm("bad-flag")); - EXPECT_TRUE(opt.FlagHasValidForm("-O")); - EXPECT_TRUE(opt.FlagHasValidForm("-Os")); - EXPECT_FALSE(opt.FlagHasValidForm("-O2")); - EXPECT_TRUE(opt.FlagHasValidForm("--this_flag")); -} - -TEST(Optimizer, CanRegisterPassesFromFlags) { - SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); - Optimizer opt(SPV_ENV_UNIVERSAL_1_0); - - spv_message_level_t msg_level; - const char* msg_fname; - spv_position_t msg_position; - const char* msg; - auto examine_message = [&msg_level, &msg_fname, &msg_position, &msg]( - spv_message_level_t ml, const char* f, - const spv_position_t& p, const char* m) { - msg_level = ml; - msg_fname = f; - msg_position = p; - msg = m; - }; - opt.SetMessageConsumer(examine_message); - - std::vector pass_flags = { - "--strip-debug", - "--strip-reflect", - "--set-spec-const-default-value=23:42 21:12", - "--if-conversion", - "--freeze-spec-const", - "--inline-entry-points-exhaustive", - "--inline-entry-points-opaque", - "--convert-local-access-chains", - "--eliminate-dead-code-aggressive", - "--eliminate-insert-extract", - "--eliminate-local-single-block", - "--eliminate-local-single-store", - "--merge-blocks", - "--merge-return", - "--eliminate-dead-branches", - "--eliminate-dead-functions", - "--eliminate-local-multi-store", - "--eliminate-dead-const", - "--eliminate-dead-inserts", - "--eliminate-dead-variables", - "--fold-spec-const-op-composite", - "--loop-unswitch", - "--scalar-replacement=300", - "--scalar-replacement", - "--strength-reduction", - "--unify-const", - "--flatten-decorations", - "--compact-ids", - "--cfg-cleanup", - "--local-redundancy-elimination", - "--loop-invariant-code-motion", - "--reduce-load-size", - "--redundancy-elimination", - "--private-to-local", - "--remove-duplicates", - "--workaround-1209", - "--replace-invalid-opcode", - "--simplify-instructions", - "--ssa-rewrite", - "--copy-propagate-arrays", - "--loop-fission=20", - "--loop-fusion=2", - "--loop-unroll", - "--vector-dce", - "--loop-unroll-partial=3", - "--loop-peeling", - "--ccp", - "-O", - "-Os", - "--legalize-hlsl"}; - EXPECT_TRUE(opt.RegisterPassesFromFlags(pass_flags)); - - // Test some invalid flags. - EXPECT_FALSE(opt.RegisterPassFromFlag("-O2")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); - - EXPECT_FALSE(opt.RegisterPassFromFlag("-loop-unroll")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); - - EXPECT_FALSE(opt.RegisterPassFromFlag("--set-spec-const-default-value")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); - - EXPECT_FALSE(opt.RegisterPassFromFlag("--scalar-replacement=s")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); - - EXPECT_FALSE(opt.RegisterPassFromFlag("--loop-fission=-4")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); - - EXPECT_FALSE(opt.RegisterPassFromFlag("--loop-fusion=xx")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); - - EXPECT_FALSE(opt.RegisterPassFromFlag("--loop-unroll-partial")); - EXPECT_EQ(msg_level, SPV_MSG_ERROR); -} - -TEST(Optimizer, VulkanToWebGPUSetsCorrectPasses) { - Optimizer opt(SPV_ENV_VULKAN_1_1); - opt.RegisterVulkanToWebGPUPasses(); - std::vector pass_names = opt.GetPassNames(); - - std::vector registered_passes; - for (auto name = pass_names.begin(); name != pass_names.end(); ++name) - registered_passes.push_back(*name); - - std::vector expected_passes = {"eliminate-dead-branches", - "eliminate-dead-code-aggressive", - "eliminate-dead-const", - "flatten-decorations", - "strip-atomic-counter-memory", - "generate-webgpu-initializers", - "legalize-vector-shuffle", - "split-invalid-unreachable", - "compact-ids"}; - std::sort(registered_passes.begin(), registered_passes.end()); - std::sort(expected_passes.begin(), expected_passes.end()); - - ASSERT_EQ(registered_passes.size(), expected_passes.size()); - for (size_t i = 0; i < registered_passes.size(); i++) - EXPECT_EQ(registered_passes[i], expected_passes[i]); -} - -struct VulkanToWebGPUPassCase { - // Input SPIR-V - std::string input; - // Expected result SPIR-V - std::string expected; - // Specific pass under test, used for logging messages. - std::string pass; -}; - -using VulkanToWebGPUPassTest = - PassTest<::testing::TestWithParam>; - -TEST_P(VulkanToWebGPUPassTest, Ran) { - std::vector binary; - { - SpirvTools tools(SPV_ENV_VULKAN_1_1); - tools.Assemble(GetParam().input, &binary); - } - - Optimizer opt(SPV_ENV_VULKAN_1_1); - opt.RegisterVulkanToWebGPUPasses(); - - std::vector optimized; - class ValidatorOptions validator_options; - ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized, - validator_options, true)) - << GetParam().input << "\n"; - std::string disassembly; - { - SpirvTools tools(SPV_ENV_WEBGPU_0); - tools.Disassemble(optimized.data(), optimized.size(), &disassembly); - } - - EXPECT_EQ(GetParam().expected, disassembly) - << "Was expecting pass '" << GetParam().pass << "' to have been run.\n"; -} - -INSTANTIATE_TEST_SUITE_P( - Optimizer, VulkanToWebGPUPassTest, - ::testing::ValuesIn(std::vector{ - // FlattenDecorations - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Fragment %main \"main\" %hue %saturation %value\n" - "OpExecutionMode %main OriginUpperLeft\n" - "OpDecorate %group Flat\n" - "OpDecorate %group NoPerspective\n" - "%group = OpDecorationGroup\n" - "%void = OpTypeVoid\n" - "%void_fn = OpTypeFunction %void\n" - "%float = OpTypeFloat 32\n" - "%_ptr_Input_float = OpTypePointer Input %float\n" - "%hue = OpVariable %_ptr_Input_float Input\n" - "%saturation = OpVariable %_ptr_Input_float Input\n" - "%value = OpVariable %_ptr_Input_float Input\n" - "%main = OpFunction %void None %void_fn\n" - "%entry = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Fragment %1 \"main\" %2 %3 %4\n" - "OpExecutionMode %1 OriginUpperLeft\n" - "%void = OpTypeVoid\n" - "%6 = OpTypeFunction %void\n" - "%float = OpTypeFloat 32\n" - "%_ptr_Input_float = OpTypePointer Input %float\n" - "%2 = OpVariable %_ptr_Input_float Input\n" - "%3 = OpVariable %_ptr_Input_float Input\n" - "%4 = OpVariable %_ptr_Input_float Input\n" - "%1 = OpFunction %void None %6\n" - "%9 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "flatten-decorations"}, - // Eliminate Dead Constants - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %func \"shader\"\n" - "%u32 = OpTypeInt 32 0\n" - "%u32_ptr = OpTypePointer Workgroup %u32\n" - "%u32_var = OpVariable %u32_ptr Workgroup\n" - "%u32_1 = OpConstant %u32 1\n" - "%cross_device = OpConstant %u32 0\n" - "%relaxed = OpConstant %u32 0\n" - "%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n" - "%void = OpTypeVoid\n" - "%void_f = OpTypeFunction %void\n" - "%func = OpFunction %void None %void_f\n" - "%label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n" - "%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n" - "%void = OpTypeVoid\n" - "%6 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %6\n" - "%7 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - "eliminate-dead-const"}, - // Strip Atomic Counter Memory - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %func \"shader\"\n" - "%u32 = OpTypeInt 32 0\n" - "%u32_ptr = OpTypePointer Workgroup %u32\n" - "%u32_var = OpVariable %u32_ptr Workgroup\n" - "%u32_0 = OpConstant %u32 0\n" - "%u32_1 = OpConstant %u32 1\n" - "%cross_device = OpConstant %u32 0\n" - "%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n" - "%void = OpTypeVoid\n" - "%void_f = OpTypeFunction %void\n" - "%func = OpFunction %void None %void_f\n" - "%label = OpLabel\n" - " OpAtomicStore %u32_var %cross_device " - "%acquire_release_atomic_counter_workgroup %u32_1\n" - "%val1 = OpAtomicIIncrement %u32 %u32_var %cross_device " - "%acquire_release_atomic_counter_workgroup\n" - "%val2 = OpAtomicCompareExchange %u32 %u32_var %cross_device " - "%acquire_release_atomic_counter_workgroup " - "%acquire_release_atomic_counter_workgroup %u32_0 %u32_0\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n" - "%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n" - "%uint_0 = OpConstant %uint 0\n" - "%uint_1 = OpConstant %uint 1\n" - "%uint_0_0 = OpConstant %uint 0\n" - "%void = OpTypeVoid\n" - "%9 = OpTypeFunction %void\n" - "%uint_264 = OpConstant %uint 264\n" - "%1 = OpFunction %void None %9\n" - "%11 = OpLabel\n" - "OpAtomicStore %4 %uint_0_0 %uint_264 %uint_1\n" - "%12 = OpAtomicIIncrement %uint %4 %uint_0_0 %uint_264\n" - "%13 = OpAtomicCompareExchange %uint %4 %uint_0_0 %uint_264 %uint_264 " - "%uint_0 %uint_0\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "strip-atomic-counter-memory"}, - // Generate WebGPU Initializers - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %func \"shader\"\n" - "%u32 = OpTypeInt 32 0\n" - "%u32_ptr = OpTypePointer Private %u32\n" - "%u32_var = OpVariable %u32_ptr Private\n" - "%u32_0 = OpConstant %u32 0\n" - "%void = OpTypeVoid\n" - "%void_f = OpTypeFunction %void\n" - "%func = OpFunction %void None %void_f\n" - "%label = OpLabel\n" - "OpStore %u32_var %u32_0\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%_ptr_Private_uint = OpTypePointer Private %uint\n" - "%4 = OpConstantNull %uint\n" - "%5 = OpVariable %_ptr_Private_uint Private %4\n" - "%uint_0 = OpConstant %uint 0\n" - "%void = OpTypeVoid\n" - "%8 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %8\n" - "%9 = OpLabel\n" - "OpStore %5 %uint_0\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "generate-webgpu-initializers"}, - // Legalize Vector Shuffle - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%v3uint = OpTypeVector %uint 3\n" - "%_ptr_Function_v3uint = OpTypePointer Function %v3uint\n" - "%void = OpTypeVoid\n" - "%6 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %6\n" - "%7 = OpLabel\n" - "%8 = OpVariable %_ptr_Function_v3uint Function\n" - "%9 = OpLoad %v3uint %8\n" - "%10 = OpLoad %v3uint %8\n" - "%11 = OpVectorShuffle %v3uint %9 %10 2 1 0xFFFFFFFF\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%v3uint = OpTypeVector %uint 3\n" - "%_ptr_Function_v3uint = OpTypePointer Function %v3uint\n" - "%void = OpTypeVoid\n" - "%6 = OpTypeFunction %void\n" - "%7 = OpConstantNull %v3uint\n" - "%1 = OpFunction %void None %6\n" - "%8 = OpLabel\n" - "%9 = OpVariable %_ptr_Function_v3uint Function %7\n" - "%10 = OpLoad %v3uint %9\n" - "%11 = OpLoad %v3uint %9\n" - "%12 = OpVectorShuffle %v3uint %10 %11 2 1 0\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "legalize-vector-shuffle"}, - // Split Invalid Unreachable - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%uint_1 = OpConstant %uint 1\n" - "%uint_2 = OpConstant %uint 2\n" - "%void = OpTypeVoid\n" - "%bool = OpTypeBool\n" - "%7 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %7\n" - "%8 = OpLabel\n" - "OpBranch %9\n" - "%9 = OpLabel\n" - "OpLoopMerge %10 %11 None\n" - "OpBranch %12\n" - "%12 = OpLabel\n" - "%13 = OpSLessThan %bool %uint_1 %uint_2\n" - "OpSelectionMerge %11 None\n" - "OpBranchConditional %13 %14 %15\n" - "%14 = OpLabel\n" - "OpReturn\n" - "%15 = OpLabel\n" - "OpReturn\n" - "%10 = OpLabel\n" - "OpUnreachable\n" - "%11 = OpLabel\n" - "OpBranch %9\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%uint_1 = OpConstant %uint 1\n" - "%uint_2 = OpConstant %uint 2\n" - "%void = OpTypeVoid\n" - "%bool = OpTypeBool\n" - "%7 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %7\n" - "%8 = OpLabel\n" - "OpBranch %9\n" - "%9 = OpLabel\n" - "OpLoopMerge %10 %11 None\n" - "OpBranch %12\n" - "%12 = OpLabel\n" - "%13 = OpSLessThan %bool %uint_1 %uint_2\n" - "OpSelectionMerge %14 None\n" - "OpBranchConditional %13 %15 %16\n" - "%15 = OpLabel\n" - "OpReturn\n" - "%16 = OpLabel\n" - "OpReturn\n" - "%10 = OpLabel\n" - "OpUnreachable\n" - "%14 = OpLabel\n" - "OpUnreachable\n" - "%11 = OpLabel\n" - "OpBranch %9\n" - "OpFunctionEnd\n", - // pass - "split-invalid-unreachable"}, - // Compact IDs - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1000 \"shader\"\n" - "%10 = OpTypeVoid\n" - "%100 = OpTypeFunction %10\n" - "%1000 = OpFunction %10 None %100\n" - "%10000 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%void = OpTypeVoid\n" - "%3 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %3\n" - "%4 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "compact-ids"}})); - -TEST(Optimizer, WebGPUToVulkanSetsCorrectPasses) { - Optimizer opt(SPV_ENV_WEBGPU_0); - opt.RegisterWebGPUToVulkanPasses(); - std::vector pass_names = opt.GetPassNames(); - - std::vector registered_passes; - for (auto name = pass_names.begin(); name != pass_names.end(); ++name) - registered_passes.push_back(*name); - - std::vector expected_passes = {"decompose-initialized-variables", - "compact-ids"}; - std::sort(registered_passes.begin(), registered_passes.end()); - std::sort(expected_passes.begin(), expected_passes.end()); - - ASSERT_EQ(registered_passes.size(), expected_passes.size()); - for (size_t i = 0; i < registered_passes.size(); i++) - EXPECT_EQ(registered_passes[i], expected_passes[i]); -} - -struct WebGPUToVulkanPassCase { - // Input SPIR-V - std::string input; - // Expected result SPIR-V - std::string expected; - // Specific pass under test, used for logging messages. - std::string pass; -}; - -using WebGPUToVulkanPassTest = - PassTest<::testing::TestWithParam>; - -TEST_P(WebGPUToVulkanPassTest, Ran) { - std::vector binary; - { - SpirvTools tools(SPV_ENV_WEBGPU_0); - tools.Assemble(GetParam().input, &binary); - } - - Optimizer opt(SPV_ENV_WEBGPU_0); - opt.RegisterWebGPUToVulkanPasses(); - - std::vector optimized; - class ValidatorOptions validator_options; - ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized, - validator_options, true)); - std::string disassembly; - { - SpirvTools tools(SPV_ENV_VULKAN_1_1); - tools.Disassemble(optimized.data(), optimized.size(), &disassembly); - } - - EXPECT_EQ(GetParam().expected, disassembly) - << "Was expecting pass '" << GetParam().pass << "' to have been run.\n"; -} - -INSTANTIATE_TEST_SUITE_P( - Optimizer, WebGPUToVulkanPassTest, - ::testing::ValuesIn(std::vector{ - // Decompose Initialized Variables - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%_ptr_Function_uint = OpTypePointer Function %uint\n" - "%4 = OpConstantNull %uint\n" - "%void = OpTypeVoid\n" - "%6 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %6\n" - "%7 = OpLabel\n" - "%8 = OpVariable %_ptr_Function_uint Function %4\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%uint = OpTypeInt 32 0\n" - "%_ptr_Function_uint = OpTypePointer Function %uint\n" - "%4 = OpConstantNull %uint\n" - "%void = OpTypeVoid\n" - "%6 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %6\n" - "%7 = OpLabel\n" - "%8 = OpVariable %_ptr_Function_uint Function\n" - "OpStore %8 %4\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "decompose-initialized-variables"}, - // Compact IDs - {// input - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1000 \"shader\"\n" - "%10 = OpTypeVoid\n" - "%100 = OpTypeFunction %10\n" - "%1000 = OpFunction %10 None %100\n" - "%10000 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // expected - "OpCapability Shader\n" - "OpCapability VulkanMemoryModel\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical Vulkan\n" - "OpEntryPoint Vertex %1 \"shader\"\n" - "%void = OpTypeVoid\n" - "%3 = OpTypeFunction %void\n" - "%1 = OpFunction %void None %3\n" - "%4 = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n", - // pass - "compact-ids"}})); - -TEST(Optimizer, RemoveNop) { - // Test that OpNops are removed even if no optimizations are run. - const std::string before = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%2 = OpTypeFunction %void -%3 = OpFunction %void None %2 -%4 = OpLabel -OpNop -OpReturn -OpFunctionEnd -)"; - - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%2 = OpTypeFunction %void -%3 = OpFunction %void None %2 -%4 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::vector binary; - { - SpirvTools tools(SPV_ENV_VULKAN_1_1); - tools.Assemble(before, &binary); - } - - Optimizer opt(SPV_ENV_VULKAN_1_1); - - std::vector optimized; - class ValidatorOptions validator_options; - ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized, - validator_options, true)) - << before << "\n"; - std::string disassembly; - { - SpirvTools tools(SPV_ENV_WEBGPU_0); - tools.Disassemble(optimized.data(), optimized.size(), &disassembly); - } - - EXPECT_EQ(after, disassembly) - << "Was expecting the OpNop to have been removed."; -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/pass_fixture.h b/3rdparty/spirv-tools/test/opt/pass_fixture.h deleted file mode 100644 index 53fb206fa..000000000 --- a/3rdparty/spirv-tools/test/opt/pass_fixture.h +++ /dev/null @@ -1,295 +0,0 @@ -// 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. - -#ifndef TEST_OPT_PASS_FIXTURE_H_ -#define TEST_OPT_PASS_FIXTURE_H_ - -#include -#include -#include -#include -#include -#include - -#include "effcee/effcee.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/pass_manager.h" -#include "source/opt/passes.h" -#include "source/spirv_optimizer_options.h" -#include "source/spirv_validator_options.h" -#include "source/util/make_unique.h" -#include "spirv-tools/libspirv.hpp" - -namespace spvtools { -namespace opt { - -// Template class for testing passes. It contains some handy utility methods for -// running passes and checking results. -// -// To write value-Parameterized tests: -// using ValueParamTest = PassTest<::testing::TestWithParam>; -// To use as normal fixture: -// using FixtureTest = PassTest<::testing::Test>; -template -class PassTest : public TestT { - public: - PassTest() - : consumer_( - [](spv_message_level_t, const char*, const spv_position_t&, - const char* message) { std::cerr << message << std::endl; }), - context_(nullptr), - manager_(new PassManager()), - assemble_options_(SpirvTools::kDefaultAssembleOption), - disassemble_options_(SpirvTools::kDefaultDisassembleOption), - env_(SPV_ENV_UNIVERSAL_1_3) {} - - // Runs the given |pass| on the binary assembled from the |original|. - // Returns a tuple of the optimized binary and the boolean value returned - // from pass Process() function. - std::tuple, Pass::Status> OptimizeToBinary( - Pass* pass, const std::string& original, bool skip_nop) { - context_ = - std::move(BuildModule(env_, consumer_, original, assemble_options_)); - EXPECT_NE(nullptr, context()) << "Assembling failed for shader:\n" - << original << std::endl; - if (!context()) { - return std::make_tuple(std::vector(), Pass::Status::Failure); - } - - context()->set_preserve_bindings(OptimizerOptions()->preserve_bindings_); - context()->set_preserve_spec_constants( - OptimizerOptions()->preserve_spec_constants_); - - const auto status = pass->Run(context()); - - std::vector binary; - if (status != Pass::Status::Failure) { - context()->module()->ToBinary(&binary, skip_nop); - } - return std::make_tuple(binary, status); - } - - // Runs a single pass of class |PassT| on the binary assembled from the - // |assembly|. Returns a tuple of the optimized binary and the boolean value - // from the pass Process() function. - template - std::tuple, Pass::Status> SinglePassRunToBinary( - const std::string& assembly, bool skip_nop, Args&&... args) { - auto pass = MakeUnique(std::forward(args)...); - pass->SetMessageConsumer(consumer_); - return OptimizeToBinary(pass.get(), assembly, skip_nop); - } - - // Runs a single pass of class |PassT| on the binary assembled from the - // |assembly|, disassembles the optimized binary. Returns a tuple of - // disassembly string and the boolean value from the pass Process() function. - template - std::tuple SinglePassRunAndDisassemble( - const std::string& assembly, bool skip_nop, bool do_validation, - Args&&... args) { - std::vector optimized_bin; - auto status = Pass::Status::SuccessWithoutChange; - std::tie(optimized_bin, status) = SinglePassRunToBinary( - assembly, skip_nop, std::forward(args)...); - if (do_validation) { - spv_context spvContext = spvContextCreate(env_); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {optimized_bin.data(), optimized_bin.size()}; - spv_result_t error = spvValidateWithOptions( - spvContext, ValidatorOptions(), &binary, &diagnostic); - EXPECT_EQ(error, 0); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - } - std::string optimized_asm; - SpirvTools tools(env_); - EXPECT_TRUE( - tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options_)) - << "Disassembling failed for shader:\n" - << assembly << std::endl; - return std::make_tuple(optimized_asm, status); - } - - // Runs a single pass of class |PassT| on the binary assembled from the - // |original| assembly, and checks whether the optimized binary can be - // disassembled to the |expected| assembly. Optionally will also validate - // the optimized binary. This does *not* involve pass manager. Callers - // are suggested to use SCOPED_TRACE() for better messages. - template - void SinglePassRunAndCheck(const std::string& original, - const std::string& expected, bool skip_nop, - bool do_validation, Args&&... args) { - std::vector optimized_bin; - auto status = Pass::Status::SuccessWithoutChange; - std::tie(optimized_bin, status) = SinglePassRunToBinary( - original, skip_nop, std::forward(args)...); - // Check whether the pass returns the correct modification indication. - EXPECT_NE(Pass::Status::Failure, status); - EXPECT_EQ(original == expected, - status == Pass::Status::SuccessWithoutChange); - if (do_validation) { - spv_context spvContext = spvContextCreate(env_); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {optimized_bin.data(), optimized_bin.size()}; - spv_result_t error = spvValidateWithOptions( - spvContext, ValidatorOptions(), &binary, &diagnostic); - EXPECT_EQ(error, 0); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - } - std::string optimized_asm; - SpirvTools tools(env_); - EXPECT_TRUE( - tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options_)) - << "Disassembling failed for shader:\n" - << original << std::endl; - EXPECT_EQ(expected, optimized_asm); - } - - // Runs a single pass of class |PassT| on the binary assembled from the - // |original| assembly, and checks whether the optimized binary can be - // disassembled to the |expected| assembly. This does *not* involve pass - // manager. Callers are suggested to use SCOPED_TRACE() for better messages. - template - void SinglePassRunAndCheck(const std::string& original, - const std::string& expected, bool skip_nop, - Args&&... args) { - SinglePassRunAndCheck(original, expected, skip_nop, false, - std::forward(args)...); - } - - // Runs a single pass of class |PassT| on the binary assembled from the - // |original| assembly, then runs an Effcee matcher over the disassembled - // result, using checks parsed from |original|. Always skips OpNop. - // This does *not* involve pass manager. Callers are suggested to use - // SCOPED_TRACE() for better messages. - template - void SinglePassRunAndMatch(const std::string& original, bool do_validation, - Args&&... args) { - const bool skip_nop = true; - auto pass_result = SinglePassRunAndDisassemble( - original, skip_nop, do_validation, std::forward(args)...); - auto disassembly = std::get<0>(pass_result); - auto match_result = effcee::Match(disassembly, original); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking result:\n" - << disassembly; - } - - // Runs a single pass of class |PassT| on the binary assembled from the - // |original| assembly. Check for failure and expect an Effcee matcher - // to pass when run on the diagnostic messages. This does *not* involve - // pass manager. Callers are suggested to use SCOPED_TRACE() for better - // messages. - template - void SinglePassRunAndFail(const std::string& original, Args&&... args) { - context_ = - std::move(BuildModule(env_, consumer_, original, assemble_options_)); - EXPECT_NE(nullptr, context()) << "Assembling failed for shader:\n" - << original << std::endl; - std::ostringstream errs; - auto error_consumer = [&errs](spv_message_level_t, const char*, - const spv_position_t&, const char* message) { - errs << message << std::endl; - }; - auto pass = MakeUnique(std::forward(args)...); - pass->SetMessageConsumer(error_consumer); - const auto status = pass->Run(context()); - EXPECT_EQ(Pass::Status::Failure, status); - auto match_result = effcee::Match(errs.str(), original); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking messages:\n" - << errs.str(); - } - - // Adds a pass to be run. - template - void AddPass(Args&&... args) { - manager_->AddPass(std::forward(args)...); - } - - // Renews the pass manager, including clearing all previously added passes. - void RenewPassManger() { - manager_ = MakeUnique(); - manager_->SetMessageConsumer(consumer_); - } - - // Runs the passes added thus far using a pass manager on the binary assembled - // from the |original| assembly, and checks whether the optimized binary can - // be disassembled to the |expected| assembly. Callers are suggested to use - // SCOPED_TRACE() for better messages. - void RunAndCheck(const std::string& original, const std::string& expected) { - assert(manager_->NumPasses()); - - context_ = - std::move(BuildModule(env_, nullptr, original, assemble_options_)); - ASSERT_NE(nullptr, context()); - - context()->set_preserve_bindings(OptimizerOptions()->preserve_bindings_); - context()->set_preserve_spec_constants( - OptimizerOptions()->preserve_spec_constants_); - - auto status = manager_->Run(context()); - EXPECT_NE(status, Pass::Status::Failure); - - if (status != Pass::Status::Failure) { - std::vector binary; - context()->module()->ToBinary(&binary, /* skip_nop = */ false); - - std::string optimized; - SpirvTools tools(env_); - EXPECT_TRUE(tools.Disassemble(binary, &optimized, disassemble_options_)); - EXPECT_EQ(expected, optimized); - } - } - - void SetAssembleOptions(uint32_t assemble_options) { - assemble_options_ = assemble_options; - } - - void SetDisassembleOptions(uint32_t disassemble_options) { - disassemble_options_ = disassemble_options; - } - - MessageConsumer consumer() { return consumer_; } - IRContext* context() { return context_.get(); } - - void SetMessageConsumer(MessageConsumer msg_consumer) { - consumer_ = msg_consumer; - } - - spv_optimizer_options OptimizerOptions() { return &optimizer_options_; } - - spv_validator_options ValidatorOptions() { return &validator_options_; } - - void SetTargetEnv(spv_target_env env) { env_ = env; } - - private: - MessageConsumer consumer_; // Message consumer. - std::unique_ptr context_; // IR context - std::unique_ptr manager_; // The pass manager. - uint32_t assemble_options_; - uint32_t disassemble_options_; - spv_optimizer_options_t optimizer_options_; - spv_validator_options_t validator_options_; - spv_target_env env_; -}; - -} // namespace opt -} // namespace spvtools - -#endif // TEST_OPT_PASS_FIXTURE_H_ diff --git a/3rdparty/spirv-tools/test/opt/pass_manager_test.cpp b/3rdparty/spirv-tools/test/opt/pass_manager_test.cpp deleted file mode 100644 index 22d5e22ec..000000000 --- a/3rdparty/spirv-tools/test/opt/pass_manager_test.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// 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 "gmock/gmock.h" -#include "source/util/make_unique.h" -#include "test/opt/module_utils.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using spvtest::GetIdBound; -using ::testing::Eq; - -// A null pass whose construtors accept arguments -class NullPassWithArgs : public NullPass { - public: - NullPassWithArgs(uint32_t) {} - NullPassWithArgs(std::string) {} - NullPassWithArgs(const std::vector&) {} - NullPassWithArgs(const std::vector&, uint32_t) {} - - const char* name() const override { return "null-with-args"; } -}; - -TEST(PassManager, Interface) { - PassManager manager; - EXPECT_EQ(0u, manager.NumPasses()); - - manager.AddPass(); - EXPECT_EQ(1u, manager.NumPasses()); - EXPECT_STREQ("strip-debug", manager.GetPass(0)->name()); - - manager.AddPass(MakeUnique()); - EXPECT_EQ(2u, manager.NumPasses()); - EXPECT_STREQ("strip-debug", manager.GetPass(0)->name()); - EXPECT_STREQ("null", manager.GetPass(1)->name()); - - manager.AddPass(); - EXPECT_EQ(3u, manager.NumPasses()); - EXPECT_STREQ("strip-debug", manager.GetPass(0)->name()); - EXPECT_STREQ("null", manager.GetPass(1)->name()); - EXPECT_STREQ("strip-debug", manager.GetPass(2)->name()); - - manager.AddPass(1u); - manager.AddPass("null pass args"); - manager.AddPass(std::initializer_list{1, 2}); - manager.AddPass(std::initializer_list{1, 2}, 3); - EXPECT_EQ(7u, manager.NumPasses()); - EXPECT_STREQ("strip-debug", manager.GetPass(0)->name()); - EXPECT_STREQ("null", manager.GetPass(1)->name()); - EXPECT_STREQ("strip-debug", manager.GetPass(2)->name()); - EXPECT_STREQ("null-with-args", manager.GetPass(3)->name()); - EXPECT_STREQ("null-with-args", manager.GetPass(4)->name()); - EXPECT_STREQ("null-with-args", manager.GetPass(5)->name()); - EXPECT_STREQ("null-with-args", manager.GetPass(6)->name()); -} - -// A pass that appends an OpNop instruction to the debug1 section. -class AppendOpNopPass : public Pass { - public: - const char* name() const override { return "AppendOpNop"; } - Status Process() override { - context()->AddDebug1Inst(MakeUnique(context())); - return Status::SuccessWithChange; - } -}; - -// A pass that appends specified number of OpNop instructions to the debug1 -// section. -class AppendMultipleOpNopPass : public Pass { - public: - explicit AppendMultipleOpNopPass(uint32_t num_nop) : num_nop_(num_nop) {} - - const char* name() const override { return "AppendOpNop"; } - Status Process() override { - for (uint32_t i = 0; i < num_nop_; i++) { - context()->AddDebug1Inst(MakeUnique(context())); - } - return Status::SuccessWithChange; - } - - private: - uint32_t num_nop_; -}; - -// A pass that duplicates the last instruction in the debug1 section. -class DuplicateInstPass : public Pass { - public: - const char* name() const override { return "DuplicateInst"; } - Status Process() override { - auto inst = MakeUnique(*(--context()->debug1_end())); - context()->AddDebug1Inst(std::move(inst)); - return Status::SuccessWithChange; - } -}; - -using PassManagerTest = PassTest<::testing::Test>; - -TEST_F(PassManagerTest, Run) { - const std::string text = "OpMemoryModel Logical GLSL450\nOpSource ESSL 310\n"; - - AddPass(); - AddPass(); - RunAndCheck(text, text + "OpNop\nOpNop\n"); - - RenewPassManger(); - AddPass(); - AddPass(); - RunAndCheck(text, text + "OpNop\nOpNop\n"); - - RenewPassManger(); - AddPass(); - AddPass(); - RunAndCheck(text, text + "OpSource ESSL 310\nOpNop\n"); - - RenewPassManger(); - AddPass(3); - RunAndCheck(text, text + "OpNop\nOpNop\nOpNop\n"); -} - -// A pass that appends an OpTypeVoid instruction that uses a given id. -class AppendTypeVoidInstPass : public Pass { - public: - explicit AppendTypeVoidInstPass(uint32_t result_id) : result_id_(result_id) {} - - const char* name() const override { return "AppendTypeVoidInstPass"; } - Status Process() override { - auto inst = MakeUnique(context(), SpvOpTypeVoid, 0, result_id_, - std::vector{}); - context()->AddType(std::move(inst)); - return Status::SuccessWithChange; - } - - private: - uint32_t result_id_; -}; - -TEST(PassManager, RecomputeIdBoundAutomatically) { - PassManager manager; - std::unique_ptr module(new Module()); - IRContext context(SPV_ENV_UNIVERSAL_1_2, std::move(module), - manager.consumer()); - EXPECT_THAT(GetIdBound(*context.module()), Eq(0u)); - - manager.Run(&context); - manager.AddPass(); - // With no ID changes, the ID bound does not change. - EXPECT_THAT(GetIdBound(*context.module()), Eq(0u)); - - // Now we force an Id of 100 to be used. - manager.AddPass(MakeUnique(100)); - EXPECT_THAT(GetIdBound(*context.module()), Eq(0u)); - manager.Run(&context); - // The Id has been updated automatically, even though the pass - // did not update it. - EXPECT_THAT(GetIdBound(*context.module()), Eq(101u)); - - // Try one more time! - manager.AddPass(MakeUnique(200)); - manager.Run(&context); - EXPECT_THAT(GetIdBound(*context.module()), Eq(201u)); - - // Add another pass, but which uses a lower Id. - manager.AddPass(MakeUnique(10)); - manager.Run(&context); - // The Id stays high. - EXPECT_THAT(GetIdBound(*context.module()), Eq(201u)); -} - -} // anonymous namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/pass_merge_return_test.cpp b/3rdparty/spirv-tools/test/opt/pass_merge_return_test.cpp deleted file mode 100644 index 411816960..000000000 --- a/3rdparty/spirv-tools/test/opt/pass_merge_return_test.cpp +++ /dev/null @@ -1,1880 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "spirv-tools/libspirv.hpp" -#include "spirv-tools/optimizer.hpp" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using MergeReturnPassTest = PassTest<::testing::Test>; - -TEST_F(MergeReturnPassTest, OneReturn) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %1 "simple_kernel" -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%1 = OpFunction %2 None %3 -%4 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = before; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(MergeReturnPassTest, TwoReturnsNoValue) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %6 "simple_kernel" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpBranchConditional %4 %8 %9 -%8 = OpLabel -OpReturn -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %6 "simple_kernel" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpBranchConditional %4 %8 %9 -%8 = OpLabel -OpBranch %10 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(MergeReturnPassTest, TwoReturnsWithValues) { - const std::string before = - R"(OpCapability Linkage -OpCapability Kernel -OpMemoryModel Logical OpenCL -OpDecorate %7 LinkageAttributes "simple_kernel" Export -%1 = OpTypeInt 32 0 -%2 = OpTypeBool -%3 = OpConstantFalse %2 -%4 = OpConstant %1 0 -%5 = OpConstant %1 1 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpBranchConditional %3 %9 %10 -%9 = OpLabel -OpReturnValue %4 -%10 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Linkage -OpCapability Kernel -OpMemoryModel Logical OpenCL -OpDecorate %7 LinkageAttributes "simple_kernel" Export -%1 = OpTypeInt 32 0 -%2 = OpTypeBool -%3 = OpConstantFalse %2 -%4 = OpConstant %1 0 -%5 = OpConstant %1 1 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpBranchConditional %3 %9 %10 -%9 = OpLabel -OpBranch %11 -%10 = OpLabel -OpBranch %11 -%11 = OpLabel -%12 = OpPhi %1 %4 %9 %5 %10 -OpReturnValue %12 -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(MergeReturnPassTest, UnreachableReturnsNoValue) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %6 "simple_kernel" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpReturn -%8 = OpLabel -OpBranchConditional %4 %9 %10 -%9 = OpLabel -OpReturn -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %6 "simple_kernel" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpBranch %11 -%8 = OpLabel -OpBranchConditional %4 %9 %10 -%9 = OpLabel -OpBranch %11 -%10 = OpLabel -OpBranch %11 -%11 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(MergeReturnPassTest, UnreachableReturnsWithValues) { - const std::string before = - R"(OpCapability Linkage -OpCapability Kernel -OpMemoryModel Logical OpenCL -OpDecorate %7 LinkageAttributes "simple_kernel" Export -%1 = OpTypeInt 32 0 -%2 = OpTypeBool -%3 = OpConstantFalse %2 -%4 = OpConstant %1 0 -%5 = OpConstant %1 1 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -%9 = OpIAdd %1 %4 %5 -OpReturnValue %9 -%10 = OpLabel -OpBranchConditional %3 %11 %12 -%11 = OpLabel -OpReturnValue %4 -%12 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Linkage -OpCapability Kernel -OpMemoryModel Logical OpenCL -OpDecorate %7 LinkageAttributes "simple_kernel" Export -%1 = OpTypeInt 32 0 -%2 = OpTypeBool -%3 = OpConstantFalse %2 -%4 = OpConstant %1 0 -%5 = OpConstant %1 1 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -%9 = OpIAdd %1 %4 %5 -OpBranch %13 -%10 = OpLabel -OpBranchConditional %3 %11 %12 -%11 = OpLabel -OpBranch %13 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -%14 = OpPhi %1 %9 %8 %4 %11 %5 %12 -OpReturnValue %14 -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(MergeReturnPassTest, StructuredControlFlowWithUnreachableMerge) { - const std::string before = - R"( -; CHECK: [[false:%\w+]] = OpConstantFalse -; CHECK: [[true:%\w+]] = OpConstantTrue -; CHECK: OpFunction -; CHECK: [[var:%\w+]] = OpVariable [[:%\w+]] Function [[false]] -; CHECK: OpLoopMerge [[return_block:%\w+]] -; CHECK: OpSelectionMerge [[merge_lab:%\w+]] -; CHECK: OpBranchConditional [[cond:%\w+]] [[if_lab:%\w+]] [[then_lab:%\w+]] -; CHECK: [[if_lab]] = OpLabel -; CHECK-NEXT: OpStore [[var]] [[true]] -; CHECK-NEXT: OpBranch [[return_block]] -; CHECK: [[then_lab]] = OpLabel -; CHECK-NEXT: OpStore [[var]] [[true]] -; CHECK-NEXT: OpBranch [[return_block]] -; CHECK: [[merge_lab]] = OpLabel -; CHECK-NEXT: OpBranch [[return_block]] -; CHECK: [[return_block]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %6 "simple_shader" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %4 %8 %9 -%8 = OpLabel -OpReturn -%9 = OpLabel -OpReturn -%10 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, StructuredControlFlowAddPhi) { - const std::string before = - R"( -; CHECK: [[false:%\w+]] = OpConstantFalse -; CHECK: [[true:%\w+]] = OpConstantTrue -; CHECK: OpFunction -; CHECK: [[var:%\w+]] = OpVariable [[:%\w+]] Function [[false]] -; CHECK: OpLoopMerge [[dummy_loop_merge:%\w+]] -; CHECK: OpSelectionMerge [[merge_lab:%\w+]] -; CHECK: OpBranchConditional [[cond:%\w+]] [[if_lab:%\w+]] [[then_lab:%\w+]] -; CHECK: [[if_lab]] = OpLabel -; CHECK-NEXT: [[add:%\w+]] = OpIAdd [[type:%\w+]] -; CHECK-NEXT: OpBranch -; CHECK: [[then_lab]] = OpLabel -; CHECK-NEXT: OpStore [[var]] [[true]] -; CHECK-NEXT: OpBranch [[dummy_loop_merge]] -; CHECK: [[merge_lab]] = OpLabel -; CHECK: [[dummy_loop_merge]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %6 "simple_shader" -%2 = OpTypeVoid -%3 = OpTypeBool -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %4 %8 %9 -%8 = OpLabel -%11 = OpIAdd %int %int_0 %int_0 -OpBranch %10 -%9 = OpLabel -OpReturn -%10 = OpLabel -%12 = OpIAdd %int %11 %11 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, StructuredControlDecoration) { - const std::string before = - R"( -; CHECK: OpDecorate [[dec_id:%\w+]] RelaxedPrecision -; CHECK: [[false:%\w+]] = OpConstantFalse -; CHECK: [[true:%\w+]] = OpConstantTrue -; CHECK: OpFunction -; CHECK: [[var:%\w+]] = OpVariable [[:%\w+]] Function [[false]] -; CHECK: OpLoopMerge [[return_block:%\w+]] -; CHECK: OpSelectionMerge [[merge_lab:%\w+]] -; CHECK: OpBranchConditional [[cond:%\w+]] [[if_lab:%\w+]] [[then_lab:%\w+]] -; CHECK: [[if_lab]] = OpLabel -; CHECK-NEXT: [[dec_id]] = OpIAdd [[type:%\w+]] -; CHECK-NEXT: OpBranch -; CHECK: [[then_lab]] = OpLabel -; CHECK-NEXT: OpStore [[var]] [[true]] -; CHECK-NEXT: OpBranch [[return_block]] -; CHECK: [[merge_lab]] = OpLabel -; CHECK-NEXT: OpStore [[var]] [[true]] -; CHECK-NEXT: OpBranch [[return_block]] -; CHECK: [[return_block]] = OpLabel -; CHECK-NEXT: OpReturn -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %6 "simple_shader" -OpDecorate %11 RelaxedPrecision -%2 = OpTypeVoid -%3 = OpTypeBool -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %4 %8 %9 -%8 = OpLabel -%11 = OpIAdd %int %int_0 %int_0 -OpBranch %10 -%9 = OpLabel -OpReturn -%10 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, SplitBlockUsedInPhi) { - const std::string before = - R"( -; CHECK: OpFunction -; CHECK: OpLoopMerge [[dummy_loop_merge:%\w+]] -; CHECK: OpLoopMerge [[loop_merge:%\w+]] -; CHECK: [[loop_merge]] = OpLabel -; CHECK: OpBranchConditional {{%\w+}} [[dummy_loop_merge]] [[old_code_path:%\w+]] -; CHECK: [[old_code_path:%\w+]] = OpLabel -; CHECK: OpBranchConditional {{%\w+}} [[side_node:%\w+]] [[phi_block:%\w+]] -; CHECK: [[phi_block]] = OpLabel -; CHECK-NEXT: OpPhi %bool %false [[side_node]] %true [[old_code_path]] - OpCapability Addresses - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "simple_shader" - %void = OpTypeVoid - %bool = OpTypeBool - %false = OpConstantFalse %bool - %true = OpConstantTrue %bool - %6 = OpTypeFunction %void - %1 = OpFunction %void None %6 - %7 = OpLabel - OpLoopMerge %merge %cont None - OpBranchConditional %false %9 %merge - %9 = OpLabel - OpReturn - %cont = OpLabel - OpBranch %7 - %merge = OpLabel - OpSelectionMerge %merge2 None - OpBranchConditional %false %if %merge2 - %if = OpLabel - OpBranch %merge2 - %merge2 = OpLabel - %12 = OpPhi %bool %false %if %true %merge - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(before, false); -} - -// TODO(#1861): Reenable these test when the breaks from selection constructs -// are reenabled. -/* -TEST_F(MergeReturnPassTest, UpdateOrderWhenPredicating) { - const std::string before = - R"( -; CHECK: OpFunction -; CHECK: OpFunction -; CHECK: OpSelectionMerge [[m1:%\w+]] None -; CHECK-NOT: OpReturn -; CHECK: [[m1]] = OpLabel -; CHECK: OpSelectionMerge [[m2:%\w+]] None -; CHECK: OpSelectionMerge [[m3:%\w+]] None -; CHECK: OpSelectionMerge [[m4:%\w+]] None -; CHECK: OpLabel -; CHECK-NEXT: OpStore -; CHECK-NEXT: OpBranch [[m4]] -; CHECK: [[m4]] = OpLabel -; CHECK-NEXT: [[ld4:%\w+]] = OpLoad %bool -; CHECK-NEXT: OpBranchConditional [[ld4]] [[m3]] -; CHECK: [[m3]] = OpLabel -; CHECK-NEXT: [[ld3:%\w+]] = OpLoad %bool -; CHECK-NEXT: OpBranchConditional [[ld3]] [[m2]] -; CHECK: [[m2]] = OpLabel - OpCapability SampledBuffer - OpCapability StorageImageExtendedFormats - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "PS_DebugTiles" - OpExecutionMode %1 OriginUpperLeft - OpSource HLSL 600 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %bool = OpTypeBool - %1 = OpFunction %void None %3 - %5 = OpLabel - %6 = OpFunctionCall %void %7 - OpReturn - OpFunctionEnd - %7 = OpFunction %void None %3 - %8 = OpLabel - %9 = OpUndef %bool - OpSelectionMerge %10 None - OpBranchConditional %9 %11 %10 - %11 = OpLabel - OpReturn - %10 = OpLabel - %12 = OpUndef %bool - OpSelectionMerge %13 None - OpBranchConditional %12 %14 %15 - %15 = OpLabel - %16 = OpUndef %bool - OpSelectionMerge %17 None - OpBranchConditional %16 %18 %17 - %18 = OpLabel - OpReturn - %17 = OpLabel - OpBranch %13 - %14 = OpLabel - OpReturn - %13 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(before, false); -} -*/ - -TEST_F(MergeReturnPassTest, StructuredControlFlowBothMergeAndHeader) { - const std::string test = - R"( -; CHECK: OpFunction -; CHECK: [[ret_flag:%\w+]] = OpVariable %_ptr_Function_bool Function %false -; CHECK: OpLoopMerge [[dummy_loop_merge:%\w+]] -; CHECK: OpLoopMerge [[loop1_merge:%\w+]] {{%\w+}} -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_lab:%\w+]] {{%\w+}} -; CHECK: [[if_lab]] = OpLabel -; CHECK: OpStore [[ret_flag]] %true -; CHECK-NEXT: OpBranch [[loop1_merge]] -; CHECK: [[loop1_merge]] = OpLabel -; CHECK-NEXT: [[ld:%\w+]] = OpLoad %bool [[ret_flag]] -; CHECK-NOT: OpLabel -; CHECK: OpBranchConditional [[ld]] [[dummy_loop_merge]] [[empty_block:%\w+]] -; CHECK: [[empty_block]] = OpLabel -; CHECK-NEXT: OpBranch [[loop2:%\w+]] -; CHECK: [[loop2]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpLoopMerge - OpCapability Addresses - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "simple_shader" - %void = OpTypeVoid - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %false = OpConstantFalse %bool - %7 = OpTypeFunction %void - %1 = OpFunction %void None %7 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %10 %11 None - OpBranchConditional %false %12 %13 - %12 = OpLabel - OpReturn - %13 = OpLabel - OpBranch %10 - %11 = OpLabel - OpBranch %9 - %10 = OpLabel - OpLoopMerge %14 %15 None - OpBranch %15 - %15 = OpLabel - %16 = OpIAdd %uint %uint_0 %uint_0 - OpBranchConditional %false %10 %14 - %14 = OpLabel - %17 = OpIAdd %uint %16 %16 - OpReturn - OpFunctionEnd - -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "simple_shader" -%void = OpTypeVoid -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%false = OpConstantFalse %bool -%7 = OpTypeFunction %void -%_ptr_Function_bool = OpTypePointer Function %bool -%true = OpConstantTrue %bool -%1 = OpFunction %void None %7 -%8 = OpLabel -%18 = OpVariable %_ptr_Function_bool Function %false -OpSelectionMerge %9 None -OpBranchConditional %false %10 %11 -%10 = OpLabel -OpStore %18 %true -OpBranch %9 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -%23 = OpLoad %bool %18 -OpSelectionMerge %22 None -OpBranchConditional %23 %22 %21 -%21 = OpLabel -OpBranch %20 -%20 = OpLabel -OpLoopMerge %12 %13 None -OpBranch %13 -%13 = OpLabel -%14 = OpIAdd %uint %uint_0 %uint_0 -OpBranchConditional %false %20 %12 -%12 = OpLabel -%15 = OpIAdd %uint %14 %14 -OpStore %18 %true -OpBranch %22 -%22 = OpLabel -OpBranch %16 -%16 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(test, false); -} - -// TODO(#1861): Reenable these test when the breaks from selection constructs -// are reenabled. -/* -TEST_F(MergeReturnPassTest, NestedSelectionMerge) { - const std::string before = - R"( - OpCapability Addresses - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "simple_shader" - %void = OpTypeVoid - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %false = OpConstantFalse %bool - %7 = OpTypeFunction %void - %1 = OpFunction %void None %7 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %false %10 %11 - %10 = OpLabel - OpReturn - %11 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %false %13 %14 - %13 = OpLabel - %15 = OpIAdd %uint %uint_0 %uint_0 - OpBranch %12 - %14 = OpLabel - OpReturn - %12 = OpLabel - OpBranch %9 - %9 = OpLabel - %16 = OpIAdd %uint %15 %15 - OpReturn - OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "simple_shader" -%void = OpTypeVoid -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%false = OpConstantFalse %bool -%7 = OpTypeFunction %void -%_ptr_Function_bool = OpTypePointer Function %bool -%true = OpConstantTrue %bool -%26 = OpUndef %uint -%1 = OpFunction %void None %7 -%8 = OpLabel -%19 = OpVariable %_ptr_Function_bool Function %false -OpSelectionMerge %9 None -OpBranchConditional %false %10 %11 -%10 = OpLabel -OpStore %19 %true -OpBranch %9 -%11 = OpLabel -OpSelectionMerge %12 None -OpBranchConditional %false %13 %14 -%13 = OpLabel -%15 = OpIAdd %uint %uint_0 %uint_0 -OpBranch %12 -%14 = OpLabel -OpStore %19 %true -OpBranch %12 -%12 = OpLabel -%27 = OpPhi %uint %15 %13 %26 %14 -%22 = OpLoad %bool %19 -OpBranchConditional %22 %9 %21 -%21 = OpLabel -OpBranch %9 -%9 = OpLabel -%28 = OpPhi %uint %27 %21 %26 %10 %26 %12 -%25 = OpLoad %bool %19 -OpSelectionMerge %24 None -OpBranchConditional %25 %24 %23 -%23 = OpLabel -%16 = OpIAdd %uint %28 %28 -OpStore %19 %true -OpBranch %24 -%24 = OpLabel -OpBranch %17 -%17 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, after, false, true); -} - -// This is essentially the same as NestedSelectionMerge, except -// the order of the first branch is changed. This is to make sure things -// work even if the order of the traversals change. -TEST_F(MergeReturnPassTest, NestedSelectionMerge2) { - const std::string before = - R"( OpCapability Addresses - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "simple_shader" - %void = OpTypeVoid - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %false = OpConstantFalse %bool - %7 = OpTypeFunction %void - %1 = OpFunction %void None %7 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %false %10 %11 - %11 = OpLabel - OpReturn - %10 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %false %13 %14 - %13 = OpLabel - %15 = OpIAdd %uint %uint_0 %uint_0 - OpBranch %12 - %14 = OpLabel - OpReturn - %12 = OpLabel - OpBranch %9 - %9 = OpLabel - %16 = OpIAdd %uint %15 %15 - OpReturn - OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "simple_shader" -%void = OpTypeVoid -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%false = OpConstantFalse %bool -%7 = OpTypeFunction %void -%_ptr_Function_bool = OpTypePointer Function %bool -%true = OpConstantTrue %bool -%26 = OpUndef %uint -%1 = OpFunction %void None %7 -%8 = OpLabel -%19 = OpVariable %_ptr_Function_bool Function %false -OpSelectionMerge %9 None -OpBranchConditional %false %10 %11 -%11 = OpLabel -OpStore %19 %true -OpBranch %9 -%10 = OpLabel -OpSelectionMerge %12 None -OpBranchConditional %false %13 %14 -%13 = OpLabel -%15 = OpIAdd %uint %uint_0 %uint_0 -OpBranch %12 -%14 = OpLabel -OpStore %19 %true -OpBranch %12 -%12 = OpLabel -%27 = OpPhi %uint %15 %13 %26 %14 -%25 = OpLoad %bool %19 -OpBranchConditional %25 %9 %24 -%24 = OpLabel -OpBranch %9 -%9 = OpLabel -%28 = OpPhi %uint %27 %24 %26 %11 %26 %12 -%23 = OpLoad %bool %19 -OpSelectionMerge %22 None -OpBranchConditional %23 %22 %21 -%21 = OpLabel -%16 = OpIAdd %uint %28 %28 -OpStore %19 %true -OpBranch %22 -%22 = OpLabel -OpBranch %17 -%17 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, false, true); -} - -TEST_F(MergeReturnPassTest, NestedSelectionMerge3) { - const std::string before = - R"( OpCapability Addresses - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "simple_shader" - %void = OpTypeVoid - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %false = OpConstantFalse %bool - %7 = OpTypeFunction %void - %1 = OpFunction %void None %7 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %false %10 %11 - %11 = OpLabel - OpReturn - %10 = OpLabel - %12 = OpIAdd %uint %uint_0 %uint_0 - OpSelectionMerge %13 None - OpBranchConditional %false %14 %15 - %14 = OpLabel - OpBranch %13 - %15 = OpLabel - OpReturn - %13 = OpLabel - OpBranch %9 - %9 = OpLabel - %16 = OpIAdd %uint %12 %12 - OpReturn - OpFunctionEnd -)"; - - const std::string after = - R"(OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "simple_shader" -%void = OpTypeVoid -%bool = OpTypeBool -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%false = OpConstantFalse %bool -%7 = OpTypeFunction %void -%_ptr_Function_bool = OpTypePointer Function %bool -%true = OpConstantTrue %bool -%26 = OpUndef %uint -%1 = OpFunction %void None %7 -%8 = OpLabel -%19 = OpVariable %_ptr_Function_bool Function %false -OpSelectionMerge %9 None -OpBranchConditional %false %10 %11 -%11 = OpLabel -OpStore %19 %true -OpBranch %9 -%10 = OpLabel -%12 = OpIAdd %uint %uint_0 %uint_0 -OpSelectionMerge %13 None -OpBranchConditional %false %14 %15 -%14 = OpLabel -OpBranch %13 -%15 = OpLabel -OpStore %19 %true -OpBranch %13 -%13 = OpLabel -%25 = OpLoad %bool %19 -OpBranchConditional %25 %9 %24 -%24 = OpLabel -OpBranch %9 -%9 = OpLabel -%27 = OpPhi %uint %12 %24 %26 %11 %26 %13 -%23 = OpLoad %bool %19 -OpSelectionMerge %22 None -OpBranchConditional %23 %22 %21 -%21 = OpLabel -%16 = OpIAdd %uint %27 %27 -OpStore %19 %true -OpBranch %22 -%22 = OpLabel -OpBranch %17 -%17 = OpLabel -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, false, true); -} -*/ - -TEST_F(MergeReturnPassTest, NestedLoopMerge) { - const std::string test = - R"( -; CHECK: OpFunction -; CHECK: OpLoopMerge [[dummy_loop_merge:%\w+]] -; CHECK: OpLoopMerge [[outer_loop_merge:%\w+]] -; CHECK: OpLoopMerge [[inner_loop_merge:%\w+]] -; CHECK: OpSelectionMerge -; CHECK-NEXT: OpBranchConditional %true [[early_exit_block:%\w+]] -; CHECK: [[early_exit_block]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpBranch [[inner_loop_merge]] -; CHECK: [[inner_loop_merge]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpBranchConditional {{%\w+}} [[outer_loop_merge]] -; CHECK: [[outer_loop_merge]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpBranchConditional {{%\w+}} [[dummy_loop_merge]] -; CHECK: [[dummy_loop_merge]] = OpLabel -; CHECK-NOT: OpLabel -; CHECK: OpReturn - OpCapability SampledBuffer - OpCapability StorageImageExtendedFormats - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "CS" - OpExecutionMode %2 LocalSize 8 8 1 - OpSource HLSL 600 - %uint = OpTypeInt 32 0 - %void = OpTypeVoid - %6 = OpTypeFunction %void - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %v3uint = OpTypeVector %uint 3 - %bool = OpTypeBool - %true = OpConstantTrue %bool -%_ptr_Function_uint = OpTypePointer Function %uint - %2 = OpFunction %void None %6 - %14 = OpLabel - OpBranch %19 - %19 = OpLabel - %20 = OpPhi %uint %uint_0 %2 %34 %23 - %21 = OpULessThan %bool %20 %uint_1 - OpLoopMerge %22 %23 DontUnroll - OpBranchConditional %21 %24 %22 - %24 = OpLabel - OpBranch %25 - %25 = OpLabel - %27 = OpINotEqual %bool %uint_1 %uint_0 - OpLoopMerge %28 %29 DontUnroll - OpBranchConditional %27 %30 %28 - %30 = OpLabel - OpSelectionMerge %31 None - OpBranchConditional %true %32 %31 - %32 = OpLabel - OpReturn - %31 = OpLabel - OpBranch %29 - %29 = OpLabel - OpBranch %25 - %28 = OpLabel - OpBranch %23 - %23 = OpLabel - %34 = OpIAdd %uint %20 %uint_1 - OpBranch %19 - %22 = OpLabel - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(test, false); -} - -TEST_F(MergeReturnPassTest, ReturnValueDecoration) { - const std::string test = - R"( -; CHECK: OpDecorate [[func:%\w+]] RelaxedPrecision -; CHECK: OpDecorate [[ret_val:%\w+]] RelaxedPrecision -; CHECK: [[func]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NOT: OpLabel -; CHECK: [[ret_val]] = OpVariable -OpCapability Linkage -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %11 "simple_shader" -OpDecorate %7 RelaxedPrecision -%12 = OpTypeVoid -%1 = OpTypeInt 32 0 -%2 = OpTypeBool -%3 = OpConstantFalse %2 -%4 = OpConstant %1 0 -%5 = OpConstant %1 1 -%6 = OpTypeFunction %1 -%13 = OpTypeFunction %12 -%11 = OpFunction %12 None %13 -%l1 = OpLabel -%fc = OpFunctionCall %1 %7 -OpReturn -OpFunctionEnd -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpBranchConditional %3 %9 %10 -%9 = OpLabel -OpReturnValue %4 -%10 = OpLabel -OpReturnValue %5 -OpFunctionEnd -)"; - - SinglePassRunAndMatch(test, false); -} - -TEST_F(MergeReturnPassTest, - StructuredControlFlowWithNonTrivialUnreachableMerge) { - const std::string before = - R"( -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %6 "simple_shader" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %4 %8 %9 -%8 = OpLabel -OpReturn -%9 = OpLabel -OpReturn -%10 = OpLabel -%11 = OpUndef %3 -OpUnreachable -OpFunctionEnd -)"; - - std::vector messages = { - {SPV_MSG_ERROR, nullptr, 0, 0, - "Module contains unreachable blocks during merge return. Run dead " - "branch elimination before merge return."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto result = SinglePassRunToBinary(before, false); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); - EXPECT_TRUE(messages.empty()); -} - -TEST_F(MergeReturnPassTest, - StructuredControlFlowWithNonTrivialUnreachableContinue) { - const std::string before = - R"( -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %6 "simple_shader" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpBranch %header -%header = OpLabel -OpLoopMerge %merge %continue None -OpBranchConditional %4 %8 %merge -%8 = OpLabel -OpReturn -%continue = OpLabel -%11 = OpUndef %3 -OpBranch %header -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::vector messages = { - {SPV_MSG_ERROR, nullptr, 0, 0, - "Module contains unreachable blocks during merge return. Run dead " - "branch elimination before merge return."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto result = SinglePassRunToBinary(before, false); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); - EXPECT_TRUE(messages.empty()); -} - -TEST_F(MergeReturnPassTest, StructuredControlFlowWithUnreachableBlock) { - const std::string before = - R"( -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %6 "simple_shader" -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantFalse %3 -%1 = OpTypeFunction %2 -%6 = OpFunction %2 None %1 -%7 = OpLabel -OpBranch %header -%header = OpLabel -OpLoopMerge %merge %continue None -OpBranchConditional %4 %8 %merge -%8 = OpLabel -OpReturn -%continue = OpLabel -OpBranch %header -%merge = OpLabel -OpReturn -%unreachable = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - std::vector messages = { - {SPV_MSG_ERROR, nullptr, 0, 0, - "Module contains unreachable blocks during merge return. Run dead " - "branch elimination before merge return."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto result = SinglePassRunToBinary(before, false); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); - EXPECT_TRUE(messages.empty()); -} - -TEST_F(MergeReturnPassTest, StructuredControlFlowDontChangeEntryPhi) { - const std::string before = - R"( -; CHECK: OpFunction %void -; CHECK: OpLabel -; CHECK: OpLabel -; CHECK: [[pre_header:%\w+]] = OpLabel -; CHECK: [[header:%\w+]] = OpLabel -; CHECK-NEXT: OpPhi %bool {{%\w+}} [[pre_header]] [[iv:%\w+]] [[continue:%\w+]] -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] -; CHECK: [[continue]] = OpLabel -; CHECK-NEXT: [[iv]] = Op -; CHECK: [[merge]] = OpLabel - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %4 = OpTypeFunction %void - %1 = OpFunction %void None %4 - %5 = OpLabel - %6 = OpUndef %bool - OpBranch %7 - %7 = OpLabel - %8 = OpPhi %bool %6 %5 %9 %10 - OpLoopMerge %11 %10 None - OpBranch %12 - %12 = OpLabel - %13 = OpUndef %bool - OpSelectionMerge %10 DontFlatten - OpBranchConditional %13 %10 %14 - %14 = OpLabel - OpReturn - %10 = OpLabel - %9 = OpUndef %bool - OpBranchConditional %13 %7 %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, StructuredControlFlowPartialReplacePhi) { - const std::string before = - R"( -; CHECK: OpFunction %void -; CHECK: OpLabel -; CHECK: OpLabel -; CHECK: [[pre_header:%\w+]] = OpLabel -; CHECK: [[header:%\w+]] = OpLabel -; CHECK-NEXT: OpPhi -; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] -; CHECK: OpLabel -; CHECK: [[old_ret_block:%\w+]] = OpLabel -; CHECK: [[bb:%\w+]] = OpLabel -; CHECK-NEXT: [[val:%\w+]] = OpUndef %bool -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi1:%\w+]] = OpPhi %bool {{%\w+}} [[old_ret_block]] [[val]] [[bb]] -; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} [[bb2:%\w+]] -; CHECK: [[bb2]] = OpLabel -; CHECK: OpBranch [[header2:%\w+]] -; CHECK: [[header2]] = OpLabel -; CHECK-NEXT: [[phi2:%\w+]] = OpPhi %bool [[phi1]] [[continue2:%\w+]] [[phi1]] [[bb2]] -; CHECK-NEXT: OpLoopMerge {{%\w+}} [[continue2]] -; CHECK: [[continue2]] = OpLabel -; CHECK-NEXT: OpBranch [[header2]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %4 = OpTypeFunction %void - %1 = OpFunction %void None %4 - %5 = OpLabel - %6 = OpUndef %bool - OpBranch %7 - %7 = OpLabel - %8 = OpPhi %bool %6 %5 %9 %10 - OpLoopMerge %11 %10 None - OpBranch %12 - %12 = OpLabel - %13 = OpUndef %bool - OpSelectionMerge %10 DontFlatten - OpBranchConditional %13 %10 %14 - %14 = OpLabel - OpReturn - %10 = OpLabel - %9 = OpUndef %bool - OpBranchConditional %13 %7 %11 - %11 = OpLabel - %phi = OpPhi %bool %9 %10 %9 %cont - OpLoopMerge %ret %cont None - OpBranch %bb - %bb = OpLabel - OpBranchConditional %13 %ret %cont - %cont = OpLabel - OpBranch %11 - %ret = OpLabel - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, GeneratePhiInOuterLoop) { - const std::string before = - R"( - ; CHECK: OpLoopMerge - ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] - ; CHECK: [[continue]] = OpLabel - ; CHECK-NEXT: [[undef:%\w+]] = OpUndef - ; CHECK: [[merge]] = OpLabel - ; CHECK-NEXT: [[phi:%\w+]] = OpPhi %bool {{%\w+}} {{%\w+}} [[undef]] [[continue]] - ; CHECK: OpCopyObject %bool [[phi]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %bool = OpTypeBool - %8 = OpTypeFunction %bool - %false = OpConstantFalse %bool - %4 = OpFunction %void None %3 - %5 = OpLabel - %63 = OpFunctionCall %bool %9 - OpReturn - OpFunctionEnd - %9 = OpFunction %bool None %8 - %10 = OpLabel - OpBranch %31 - %31 = OpLabel - OpLoopMerge %33 %34 None - OpBranch %32 - %32 = OpLabel - OpSelectionMerge %34 None - OpBranchConditional %false %46 %34 - %46 = OpLabel - OpLoopMerge %51 %52 None - OpBranch %53 - %53 = OpLabel - OpBranchConditional %false %50 %51 - %50 = OpLabel - OpReturnValue %false - %52 = OpLabel - OpBranch %46 - %51 = OpLabel - OpBranch %34 - %34 = OpLabel - %64 = OpUndef %bool - OpBranchConditional %false %31 %33 - %33 = OpLabel - OpBranch %28 - %28 = OpLabel - %60 = OpCopyObject %bool %64 - OpBranch %17 - %17 = OpLabel - OpReturnValue %false - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, SerialLoopsUpdateBlockMapping) { - // #2455: This test case triggers phi insertions that use previously inserted - // phis. Without the fix, it fails to validate. - const std::string spirv = R"( -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge [[merge:%\w+]] -; CHECK: [[def:%\w+]] = OpFOrdLessThan -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} {{%\w+}} {{%\w+}} [[def]] -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] -; CHECK: [[cont]] = OpLabel -; CHECK-NEXT: OpBranchConditional [[phi]] -; CHECK-NOT: [[def]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %53 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpDecorate %20 RelaxedPrecision - OpDecorate %27 RelaxedPrecision - OpDecorate %53 BuiltIn FragCoord - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 3 - %8 = OpTypeFunction %7 - %11 = OpTypeBool - %12 = OpConstantFalse %11 - %15 = OpConstant %6 1 - %16 = OpConstantComposite %7 %15 %15 %15 - %18 = OpTypeInt 32 1 - %19 = OpTypePointer Function %18 - %21 = OpConstant %18 1 - %28 = OpConstant %18 0 - %31 = OpTypePointer Function %11 - %33 = OpConstantTrue %11 - %51 = OpTypeVector %6 4 - %52 = OpTypePointer Input %51 - %53 = OpVariable %52 Input - %54 = OpTypeInt 32 0 - %55 = OpConstant %54 0 - %56 = OpTypePointer Input %6 - %59 = OpConstant %6 0 - %76 = OpUndef %18 - %77 = OpUndef %11 - %78 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %75 = OpFunctionCall %7 %9 - OpReturn - OpFunctionEnd - %9 = OpFunction %7 None %8 - %10 = OpLabel - %20 = OpVariable %19 Function - OpBranch %14 - %14 = OpLabel - OpBranch %22 - %22 = OpLabel - %27 = OpLoad %18 %20 - OpLoopMerge %24 %25 None - OpBranch %24 - %25 = OpLabel - OpBranch %22 - %24 = OpLabel - OpBranch %34 - %34 = OpLabel - OpLoopMerge %36 %40 None - OpBranch %35 - %35 = OpLabel - OpBranchConditional %77 %39 %40 - %39 = OpLabel - OpReturnValue %16 - %40 = OpLabel - OpBranchConditional %12 %34 %36 - %36 = OpLabel - OpBranch %43 - %43 = OpLabel - OpLoopMerge %45 %49 None - OpBranch %44 - %44 = OpLabel - OpBranchConditional %77 %48 %49 - %48 = OpLabel - OpReturnValue %16 - %49 = OpLabel - %60 = OpFOrdLessThan %11 %15 %59 - OpBranchConditional %12 %43 %45 - %45 = OpLabel - OpBranch %62 - %62 = OpLabel - OpLoopMerge %64 %68 None - OpBranch %63 - %63 = OpLabel - OpBranchConditional %77 %67 %68 - %67 = OpLabel - OpReturnValue %16 - %68 = OpLabel - OpBranchConditional %60 %62 %64 - %64 = OpLabel - OpReturnValue %16 - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(MergeReturnPassTest, InnerLoopMergeIsOuterLoopContinue) { - const std::string before = - R"( - ; CHECK: OpLoopMerge - ; CHECK-NEXT: OpBranch [[bb1:%\w+]] - ; CHECK: [[bb1]] = OpLabel - ; CHECK-NEXT: OpBranch [[outer_loop_header:%\w+]] - ; CHECK: [[outer_loop_header]] = OpLabel - ; CHECK-NEXT: OpLoopMerge [[outer_loop_merge:%\w+]] [[outer_loop_continue:%\w+]] None - ; CHECK: [[outer_loop_continue]] = OpLabel - ; CHECK-NEXT: OpBranch [[outer_loop_header]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %6 = OpTypeFunction %bool - %true = OpConstantTrue %bool - %2 = OpFunction %void None %4 - %8 = OpLabel - %9 = OpFunctionCall %bool %10 - OpReturn - OpFunctionEnd - %10 = OpFunction %bool None %6 - %11 = OpLabel - OpBranch %12 - %12 = OpLabel - OpLoopMerge %13 %14 None - OpBranchConditional %true %15 %13 - %15 = OpLabel - OpLoopMerge %14 %16 None - OpBranchConditional %true %17 %14 - %17 = OpLabel - OpReturnValue %true - %16 = OpLabel - OpBranch %15 - %14 = OpLabel - OpBranch %12 - %13 = OpLabel - OpReturnValue %true - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(before, false); -} - -TEST_F(MergeReturnPassTest, BreakFromLoopUseNoLongerDominated) { - const std::string spirv = R"( -; CHECK: [[undef:%\w+]] = OpUndef -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] -; CHECK-NEXT: OpBranch [[body:%\w+]] -; CHECK: [[body]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[non_ret:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[ret:%\w+]] [[non_ret]] -; CHECK: [[ret]] = OpLabel -; CHECK-NEXT: OpStore -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[non_ret]] = OpLabel -; CHECK-NEXT: [[def:%\w+]] = OpLogicalNot -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[break:%\w+]] [[cont]] -; CHECK: [[break]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[cont]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} {{%\w+}} [[merge]] -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} [[undef]] [[ret]] [[def]] [[break]] [[def]] [[cont]] -; CHECK: OpLogicalNot {{%\w+}} [[phi]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" -OpExecutionMode %func LocalSize 1 1 1 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%func = OpFunction %void None %void_fn -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %8 %7 None -OpBranch %3 -%3 = OpLabel -OpSelectionMerge %5 None -OpBranchConditional %true %4 %5 -%4 = OpLabel -OpReturn -%5 = OpLabel -%def = OpLogicalNot %bool %true -OpBranchConditional %true %6 %7 -%6 = OpLabel -OpBranch %8 -%7 = OpLabel -OpBranchConditional %true %2 %8 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -%use = OpLogicalNot %bool %def -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(MergeReturnPassTest, TwoBreaksFromLoopUsesNoLongerDominated) { - const std::string spirv = R"( -; CHECK: [[undef:%\w+]] = OpUndef -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] -; CHECK-NEXT: OpBranch [[body:%\w+]] -; CHECK: [[body]] = OpLabel -; CHECK-NEXT: OpSelectionMerge [[body2:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[ret1:%\w+]] [[body2]] -; CHECK: [[ret1]] = OpLabel -; CHECK-NEXT: OpStore -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[body2]] = OpLabel -; CHECK-NEXT: [[def1:%\w+]] = OpLogicalNot -; CHECK-NEXT: OpSelectionMerge [[body3:%\w+]] -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[ret2:%\w+]] [[body3:%\w+]] -; CHECK: [[ret2]] = OpLabel -; CHECK-NEXT: OpStore -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[body3]] = OpLabel -; CHECK-NEXT: [[def2:%\w+]] = OpLogicalAnd -; CHECK-NEXT: OpBranchConditional {{%\w+}} [[break:%\w+]] [[cont]] -; CHECK: [[break]] = OpLabel -; CHECK-NEXT: OpBranch [[merge]] -; CHECK: [[cont]] = OpLabel -; CHECK-NEXT: OpBranchConditional {{%\w+}} {{%\w+}} [[merge]] -; CHECK: [[merge]] = OpLabel -; CHECK-NEXT: [[phi1:%\w+]] = OpPhi {{%\w+}} [[undef]] [[ret1]] [[undef]] [[ret2]] [[def1]] [[break]] [[def1]] [[cont]] -; CHECK-NEXT: [[phi2:%\w+]] = OpPhi {{%\w+}} [[undef]] [[ret1]] [[undef]] [[ret2]] [[def2]] [[break]] [[def2]] [[cont]] -; CHECK: OpLogicalNot {{%\w+}} [[phi1]] -; CHECK: OpLogicalAnd {{%\w+}} [[phi2]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" -OpExecutionMode %func LocalSize 1 1 1 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%true = OpConstantTrue %bool -%func = OpFunction %void None %void_fn -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %10 %9 None -OpBranch %3 -%3 = OpLabel -OpSelectionMerge %5 None -OpBranchConditional %true %4 %5 -%4 = OpLabel -OpReturn -%5 = OpLabel -%def1 = OpLogicalNot %bool %true -OpSelectionMerge %7 None -OpBranchConditional %true %6 %7 -%6 = OpLabel -OpReturn -%7 = OpLabel -%def2 = OpLogicalAnd %bool %true %true -OpBranchConditional %true %8 %9 -%8 = OpLabel -OpBranch %10 -%9 = OpLabel -OpBranchConditional %true %2 %10 -%10 = OpLabel -OpBranch %11 -%11 = OpLabel -%use1 = OpLogicalNot %bool %def1 -%use2 = OpLogicalAnd %bool %def2 %true -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(MergeReturnPassTest, PredicateBreakBlock) { - const std::string spirv = R"( -; IDs are being preserved so we can rely on basic block labels. -; CHECK: [[undef:%\w+]] = OpUndef -; CHECK: [[undef:%\w+]] = OpUndef -; CHECK: %13 = OpLabel -; CHECK-NEXT: [[def:%\w+]] = OpLogicalNot -; CHECK: %8 = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi {{%\w+}} [[undef]] {{%\w+}} [[undef]] {{%\w+}} [[def]] %13 [[undef]] {{%\w+}} -; CHECK: OpLogicalAnd {{%\w+}} [[phi]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "func" -OpExecutionMode %1 LocalSize 1 1 1 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%bool = OpTypeBool -%true = OpUndef %bool -%1 = OpFunction %void None %3 -%6 = OpLabel -OpBranch %7 -%7 = OpLabel -OpLoopMerge %8 %9 None -OpBranch %10 -%10 = OpLabel -OpSelectionMerge %11 None -OpBranchConditional %true %12 %13 -%12 = OpLabel -OpLoopMerge %14 %15 None -OpBranch %16 -%16 = OpLabel -OpReturn -%15 = OpLabel -OpBranch %12 -%14 = OpLabel -OpUnreachable -%13 = OpLabel -%17 = OpLogicalNot %bool %true -OpBranch %8 -%11 = OpLabel -OpUnreachable -%9 = OpLabel -OpBranch %7 -%8 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpLogicalAnd %bool %17 %true -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(spirv, true); -} - -TEST_F(MergeReturnPassTest, SingleReturnInLoop) { - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource ESSL 310 -%void = OpTypeVoid -%7 = OpTypeFunction %void -%float = OpTypeFloat 32 -%9 = OpTypeFunction %float -%float_1 = OpConstant %float 1 -)"; - - const std::string caller = - R"( -; CHECK: OpFunction -; CHECK: OpFunctionEnd -%main = OpFunction %void None %7 -%22 = OpLabel -%30 = OpFunctionCall %float %f_ -OpReturn -OpFunctionEnd -)"; - - const std::string callee = - R"( -; CHECK: OpFunction -; CHECK: OpLoopMerge [[merge:%\w+]] -; CHECK: [[merge]] = OpLabel -; CHECK: OpReturnValue -; CHECK-NEXT: OpFunctionEnd -%f_ = OpFunction %float None %9 -%33 = OpLabel -OpBranch %34 -%34 = OpLabel -OpLoopMerge %35 %36 None -OpBranch %37 -%37 = OpLabel -OpReturnValue %float_1 -%36 = OpLabel -OpBranch %34 -%35 = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(predefs + caller + callee, true); -} - -TEST_F(MergeReturnPassTest, MergeToMergeBranch) { - const std::string text = - R"( -; CHECK: [[new_undef:%\w+]] = OpUndef %uint -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge [[merge1:%\w+]] -; CHECK: OpLoopMerge [[merge2:%\w+]] -; CHECK: [[merge1]] = OpLabel -; CHECK-NEXT: OpPhi %uint [[new_undef]] [[merge2]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "main" - OpExecutionMode %2 LocalSize 100 1 1 - OpSource ESSL 310 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 - %bool = OpTypeBool - %false = OpConstantFalse %bool - %uint_0 = OpConstant %uint 0 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %13 = OpUndef %bool - %2 = OpFunction %void None %4 - %14 = OpLabel - OpBranch %15 - %15 = OpLabel - OpLoopMerge %16 %17 None - OpBranch %18 - %18 = OpLabel - OpLoopMerge %19 %20 None - OpBranchConditional %13 %21 %19 - %21 = OpLabel - OpReturn - %20 = OpLabel - OpBranch %18 - %19 = OpLabel - %22 = OpUndef %uint - OpBranch %23 - %23 = OpLabel - OpBranch %16 - %17 = OpLabel - OpBranch %15 - %16 = OpLabel - %24 = OpCopyObject %uint %22 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(text, true); -} - -TEST_F(MergeReturnPassTest, PhiInSecondMerge) { - // Add and use a phi in the second merge block from the return. - const std::string text = - R"( -; CHECK: OpLoopMerge -; CHECK: OpLoopMerge [[merge_bb:%\w+]] [[continue_bb:%\w+]] -; CHECK: [[continue_bb]] = OpLabel -; CHECK-NEXT: [[val:%\w+]] = OpUndef %float -; CHECK: [[merge_bb]] = OpLabel -; CHECK-NEXT: [[phi:%\w+]] = OpPhi %float {{%\w+}} {{%\w+}} [[val]] [[continue_bb]] -; CHECK-NOT: OpLabel -; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} [[old_merge:%\w+]] -; CHECK: [[old_merge]] = OpLabel -; CHECK-NEXT: OpConvertFToS %int [[phi]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %bool = OpTypeBool - %8 = OpUndef %bool - %2 = OpFunction %void None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %13 - %13 = OpLabel - OpLoopMerge %18 %14 None - OpBranchConditional %8 %15 %18 - %15 = OpLabel - OpReturn - %14 = OpLabel - OpBranch %13 - %18 = OpLabel - OpBranch %12 - %12 = OpLabel - %16 = OpUndef %float - OpBranchConditional %8 %10 %11 - %11 = OpLabel - %17 = OpConvertFToS %int %16 - OpReturn - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndMatch(text, true); -} - -TEST_F(MergeReturnPassTest, UnreachableMergeAndContinue) { - // Make sure that the pass can handle a single block that is both a merge and - // a continue. - const std::string text = - R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %2 = OpFunction %void None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpLoopMerge %9 %10 None - OpBranch %11 - %11 = OpLabel - OpSelectionMerge %10 None - OpBranchConditional %true %12 %13 - %12 = OpLabel - OpReturn - %13 = OpLabel - OpReturn - %10 = OpLabel - OpBranch %8 - %9 = OpLabel - OpUnreachable - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - auto result = SinglePassRunAndDisassemble(text, true, true); - - // Not looking for any particular output. Other tests do that. - // Just want to make sure the check for unreachable blocks does not emit an - // error. - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/pass_remove_duplicates_test.cpp b/3rdparty/spirv-tools/test/opt/pass_remove_duplicates_test.cpp deleted file mode 100644 index 887fdfdb4..000000000 --- a/3rdparty/spirv-tools/test/opt/pass_remove_duplicates_test.cpp +++ /dev/null @@ -1,646 +0,0 @@ -// Copyright (c) 2017 Pierre Moreau -// -// 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 "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/ir_context.h" -#include "source/opt/pass_manager.h" -#include "source/opt/remove_duplicates_pass.h" -#include "source/spirv_constant.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace opt { -namespace { - -class RemoveDuplicatesTest : public ::testing::Test { - public: - RemoveDuplicatesTest() - : tools_(SPV_ENV_UNIVERSAL_1_2), - context_(), - consumer_([this](spv_message_level_t level, const char*, - const spv_position_t& position, const char* message) { - if (!error_message_.empty()) error_message_ += "\n"; - switch (level) { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - error_message_ += "ERROR"; - break; - case SPV_MSG_WARNING: - error_message_ += "WARNING"; - break; - case SPV_MSG_INFO: - error_message_ += "INFO"; - break; - case SPV_MSG_DEBUG: - error_message_ += "DEBUG"; - break; - } - error_message_ += - ": " + std::to_string(position.index) + ": " + message; - }), - disassemble_options_(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER), - error_message_() { - tools_.SetMessageConsumer(consumer_); - } - - void TearDown() override { error_message_.clear(); } - - std::string RunPass(const std::string& text) { - context_ = spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer_, text); - if (!context_.get()) return std::string(); - - PassManager manager; - manager.SetMessageConsumer(consumer_); - manager.AddPass(); - - Pass::Status pass_res = manager.Run(context_.get()); - if (pass_res == Pass::Status::Failure) return std::string(); - - return ModuleToText(); - } - - // Disassembles |binary| and outputs the result in |text|. If |text| is a - // null pointer, SPV_ERROR_INVALID_POINTER is returned. - spv_result_t Disassemble(const std::vector& binary, - std::string* text) { - if (!text) return SPV_ERROR_INVALID_POINTER; - return tools_.Disassemble(binary, text, disassemble_options_) - ? SPV_SUCCESS - : SPV_ERROR_INVALID_BINARY; - } - - // Returns the accumulated error messages for the test. - std::string GetErrorMessage() const { return error_message_; } - - std::string ToText(const std::vector& inst) { - std::vector binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u}; - for (const Instruction* i : inst) - i->ToBinaryWithoutAttachedDebugInsts(&binary); - std::string text; - Disassemble(binary, &text); - return text; - } - - std::string ModuleToText() { - std::vector binary; - context_->module()->ToBinary(&binary, false); - std::string text; - Disassemble(binary, &text); - return text; - } - - private: - spvtools::SpirvTools - tools_; // An instance for calling SPIRV-Tools functionalities. - std::unique_ptr context_; - spvtools::MessageConsumer consumer_; - uint32_t disassemble_options_; - std::string error_message_; -}; - -TEST_F(RemoveDuplicatesTest, DuplicateCapabilities) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Shader -OpMemoryModel Logical GLSL450 -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -TEST_F(RemoveDuplicatesTest, DuplicateExtInstImports) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "OpenCL.std" -%2 = OpExtInstImport "OpenCL.std" -%3 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -%1 = OpExtInstImport "OpenCL.std" -%3 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -TEST_F(RemoveDuplicatesTest, DuplicateTypes) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %1 %2 -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%3 = OpTypeStruct %1 %1 -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -TEST_F(RemoveDuplicatesTest, SameTypeDifferentMemberDecoration) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 GLSLPacked -%2 = OpTypeInt 32 0 -%1 = OpTypeStruct %2 %2 -%3 = OpTypeStruct %2 %2 -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 GLSLPacked -%2 = OpTypeInt 32 0 -%1 = OpTypeStruct %2 %2 -%3 = OpTypeStruct %2 %2 -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -TEST_F(RemoveDuplicatesTest, SameTypeAndMemberDecoration) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 GLSLPacked -OpDecorate %2 GLSLPacked -%3 = OpTypeInt 32 0 -%1 = OpTypeStruct %3 %3 -%2 = OpTypeStruct %3 %3 -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 GLSLPacked -%3 = OpTypeInt 32 0 -%1 = OpTypeStruct %3 %3 -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -TEST_F(RemoveDuplicatesTest, SameTypeAndDifferentName) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %1 "Type1" -OpName %2 "Type2" -%3 = OpTypeInt 32 0 -%1 = OpTypeStruct %3 %3 -%2 = OpTypeStruct %3 %3 -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %1 "Type1" -%3 = OpTypeInt 32 0 -%1 = OpTypeStruct %3 %3 -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// Check that #1033 has been fixed. -TEST_F(RemoveDuplicatesTest, DoNotRemoveDifferentOpDecorationGroup) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -%1 = OpDecorationGroup -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %3 %1 %2 -%4 = OpTypeInt 32 0 -%3 = OpVariable %4 Uniform -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -%1 = OpDecorationGroup -OpDecorate %2 Restrict -%2 = OpDecorationGroup -OpGroupDecorate %3 %1 %2 -%4 = OpTypeInt 32 0 -%3 = OpVariable %4 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -TEST_F(RemoveDuplicatesTest, DifferentDecorationGroup) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %1 Restrict -%1 = OpDecorationGroup -OpDecorate %2 Constant -%2 = OpDecorationGroup -OpGroupDecorate %1 %3 -OpGroupDecorate %2 %4 -%5 = OpTypeInt 32 0 -%3 = OpVariable %5 Uniform -%4 = OpVariable %5 Uniform -)"; - const std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 Constant -OpDecorate %1 Restrict -%1 = OpDecorationGroup -OpDecorate %2 Constant -%2 = OpDecorationGroup -OpGroupDecorate %1 %3 -OpGroupDecorate %2 %4 -%5 = OpTypeInt 32 0 -%3 = OpVariable %5 Uniform -%4 = OpVariable %5 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), after); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// Test what happens when a type is a resource type. For now we are merging -// them, but, if we want to merge types and make reflection work (issue #1372), -// we will not be able to merge %2 and %3 below. -TEST_F(RemoveDuplicatesTest, DontMergeNestedResourceTypes) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %2 "NormalAdjust" -OpMemberName %2 0 "XDir" -OpMemberName %3 0 "AdjustXYZ" -OpMemberName %3 1 "AdjustDir" -OpName %4 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %2 0 Offset 0 -OpMemberDecorate %3 0 Offset 0 -OpMemberDecorate %3 1 Offset 16 -OpDecorate %3 Block -OpDecorate %4 DescriptorSet 0 -OpDecorate %4 Binding 0 -%5 = OpTypeFloat 32 -%6 = OpTypeVector %5 3 -%1 = OpTypeStruct %6 -%2 = OpTypeStruct %6 -%3 = OpTypeStruct %1 %2 -%7 = OpTypePointer Uniform %3 -%4 = OpVariable %7 Uniform -)"; - - const std::string result = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpMemberName %3 0 "AdjustXYZ" -OpMemberName %3 1 "AdjustDir" -OpName %4 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %3 0 Offset 0 -OpMemberDecorate %3 1 Offset 16 -OpDecorate %3 Block -OpDecorate %4 DescriptorSet 0 -OpDecorate %4 Binding 0 -%5 = OpTypeFloat 32 -%6 = OpTypeVector %5 3 -%1 = OpTypeStruct %6 -%3 = OpTypeStruct %1 %1 -%7 = OpTypePointer Uniform %3 -%4 = OpVariable %7 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), result); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// See comment for DontMergeNestedResourceTypes. -TEST_F(RemoveDuplicatesTest, DontMergeResourceTypes) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %2 "NormalAdjust" -OpMemberName %2 0 "XDir" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %2 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -OpDecorate %4 DescriptorSet 1 -OpDecorate %4 Binding 0 -%5 = OpTypeFloat 32 -%6 = OpTypeVector %5 3 -%1 = OpTypeStruct %6 -%2 = OpTypeStruct %6 -%7 = OpTypePointer Uniform %1 -%8 = OpTypePointer Uniform %2 -%3 = OpVariable %7 Uniform -%4 = OpVariable %8 Uniform -)"; - - const std::string result = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -OpDecorate %4 DescriptorSet 1 -OpDecorate %4 Binding 0 -%5 = OpTypeFloat 32 -%6 = OpTypeVector %5 3 -%1 = OpTypeStruct %6 -%7 = OpTypePointer Uniform %1 -%3 = OpVariable %7 Uniform -%4 = OpVariable %7 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), result); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// See comment for DontMergeNestedResourceTypes. -TEST_F(RemoveDuplicatesTest, DontMergeResourceTypesContainingArray) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %2 "NormalAdjust" -OpMemberName %2 0 "XDir" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %2 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -OpDecorate %4 DescriptorSet 1 -OpDecorate %4 Binding 0 -%5 = OpTypeFloat 32 -%6 = OpTypeVector %5 3 -%1 = OpTypeStruct %6 -%2 = OpTypeStruct %6 -%7 = OpTypeInt 32 0 -%8 = OpConstant %7 4 -%9 = OpTypeArray %1 %8 -%10 = OpTypeArray %2 %8 -%11 = OpTypePointer Uniform %9 -%12 = OpTypePointer Uniform %10 -%3 = OpVariable %11 Uniform -%4 = OpVariable %12 Uniform -)"; - - const std::string result = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -OpDecorate %4 DescriptorSet 1 -OpDecorate %4 Binding 0 -%5 = OpTypeFloat 32 -%6 = OpTypeVector %5 3 -%1 = OpTypeStruct %6 -%7 = OpTypeInt 32 0 -%8 = OpConstant %7 4 -%9 = OpTypeArray %1 %8 -%11 = OpTypePointer Uniform %9 -%3 = OpVariable %11 Uniform -%4 = OpVariable %11 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), result); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// Test that we merge the type of a resource with a type that is not the type -// a resource. The resource type appears first in this case. We must keep -// the resource type. -TEST_F(RemoveDuplicatesTest, MergeResourceTypeWithNonresourceType1) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %2 "NormalAdjust" -OpMemberName %2 0 "XDir" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %2 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -%4 = OpTypeFloat 32 -%5 = OpTypeVector %4 3 -%1 = OpTypeStruct %5 -%2 = OpTypeStruct %5 -%6 = OpTypePointer Uniform %1 -%7 = OpTypePointer Uniform %2 -%3 = OpVariable %6 Uniform -%8 = OpVariable %7 Uniform -)"; - - const std::string result = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -%4 = OpTypeFloat 32 -%5 = OpTypeVector %4 3 -%1 = OpTypeStruct %5 -%6 = OpTypePointer Uniform %1 -%3 = OpVariable %6 Uniform -%8 = OpVariable %6 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), result); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// Test that we merge the type of a resource with a type that is not the type -// a resource. The resource type appears second in this case. We must keep -// the resource type. -// -// See comment for DontMergeNestedResourceTypes. -TEST_F(RemoveDuplicatesTest, MergeResourceTypeWithNonresourceType2) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %2 "NormalAdjust" -OpMemberName %2 0 "XDir" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpMemberDecorate %2 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -%4 = OpTypeFloat 32 -%5 = OpTypeVector %4 3 -%1 = OpTypeStruct %5 -%2 = OpTypeStruct %5 -%6 = OpTypePointer Uniform %1 -%7 = OpTypePointer Uniform %2 -%8 = OpVariable %6 Uniform -%3 = OpVariable %7 Uniform -)"; - - const std::string result = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpSource HLSL 600 -OpName %1 "PositionAdjust" -OpMemberName %1 0 "XAdjust" -OpName %3 "Constants" -OpMemberDecorate %1 0 Offset 0 -OpDecorate %3 DescriptorSet 0 -OpDecorate %3 Binding 0 -%4 = OpTypeFloat 32 -%5 = OpTypeVector %4 3 -%1 = OpTypeStruct %5 -%6 = OpTypePointer Uniform %1 -%8 = OpVariable %6 Uniform -%3 = OpVariable %6 Uniform -)"; - - EXPECT_EQ(RunPass(spirv), result); - EXPECT_EQ(GetErrorMessage(), ""); -} - -// In this test, %8 and %9 are the same and only %9 is used in a resource. -// However, we cannot merge them unless we also merge %2 and %3, which cannot -// happen because both are used in resources. -// -// If we try to avoid replaces resource types, then remove duplicates should -// have not change in this case. That is not currently implemented. -TEST_F(RemoveDuplicatesTest, MergeResourceTypeWithNonresourceType3) { - const std::string spirv = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource HLSL 600 -OpName %2 "PositionAdjust" -OpMemberName %2 0 "XAdjust" -OpName %3 "NormalAdjust" -OpMemberName %3 0 "XDir" -OpName %4 "Constants" -OpMemberDecorate %2 0 Offset 0 -OpMemberDecorate %3 0 Offset 0 -OpDecorate %4 DescriptorSet 0 -OpDecorate %4 Binding 0 -OpDecorate %5 DescriptorSet 1 -OpDecorate %5 Binding 0 -%6 = OpTypeFloat 32 -%7 = OpTypeVector %6 3 -%2 = OpTypeStruct %7 -%3 = OpTypeStruct %7 -%8 = OpTypePointer Uniform %3 -%9 = OpTypePointer Uniform %2 -%10 = OpTypeStruct %3 -%11 = OpTypePointer Uniform %10 -%5 = OpVariable %9 Uniform -%4 = OpVariable %11 Uniform -%12 = OpTypeVoid -%13 = OpTypeFunction %12 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 0 -%1 = OpFunction %12 None %13 -%16 = OpLabel -%17 = OpAccessChain %8 %4 %15 -OpReturn -OpFunctionEnd -)"; - - const std::string result = R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpSource HLSL 600 -OpName %2 "PositionAdjust" -OpMemberName %2 0 "XAdjust" -OpName %4 "Constants" -OpMemberDecorate %2 0 Offset 0 -OpDecorate %4 DescriptorSet 0 -OpDecorate %4 Binding 0 -OpDecorate %5 DescriptorSet 1 -OpDecorate %5 Binding 0 -%6 = OpTypeFloat 32 -%7 = OpTypeVector %6 3 -%2 = OpTypeStruct %7 -%8 = OpTypePointer Uniform %2 -%10 = OpTypeStruct %2 -%11 = OpTypePointer Uniform %10 -%5 = OpVariable %8 Uniform -%4 = OpVariable %11 Uniform -%12 = OpTypeVoid -%13 = OpTypeFunction %12 -%14 = OpTypeInt 32 0 -%15 = OpConstant %14 0 -%1 = OpFunction %12 None %13 -%16 = OpLabel -%17 = OpAccessChain %8 %4 %15 -OpReturn -OpFunctionEnd -)"; - - EXPECT_EQ(RunPass(spirv), result); - EXPECT_EQ(GetErrorMessage(), ""); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/pass_utils.cpp b/3rdparty/spirv-tools/test/opt/pass_utils.cpp deleted file mode 100644 index 4709d0fd1..000000000 --- a/3rdparty/spirv-tools/test/opt/pass_utils.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// 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 "test/opt/pass_utils.h" - -#include -#include - -namespace spvtools { -namespace opt { -namespace { - -// Well, this is another place requiring the knowledge of the grammar and can be -// stale when SPIR-V is updated. It would be nice to automatically generate -// this, but the cost is just too high. - -const char* kDebugOpcodes[] = { - // clang-format off - "OpSourceContinued", "OpSource", "OpSourceExtension", - "OpName", "OpMemberName", "OpString", - "OpLine", "OpNoLine", "OpModuleProcessed" - // clang-format on -}; - -} // anonymous namespace - -MessageConsumer GetTestMessageConsumer( - std::vector& expected_messages) { - return [&expected_messages](spv_message_level_t level, const char* source, - const spv_position_t& position, - const char* message) { - EXPECT_TRUE(!expected_messages.empty()); - if (expected_messages.empty()) { - return; - } - - EXPECT_EQ(expected_messages[0].level, level); - EXPECT_EQ(expected_messages[0].line_number, position.line); - EXPECT_EQ(expected_messages[0].column_number, position.column); - EXPECT_STREQ(expected_messages[0].source_file, source); - EXPECT_STREQ(expected_messages[0].message, message); - - expected_messages.erase(expected_messages.begin()); - }; -} - -bool FindAndReplace(std::string* process_str, const std::string find_str, - const std::string replace_str) { - if (process_str->empty() || find_str.empty()) { - return false; - } - bool replaced = false; - // Note this algorithm has quadratic time complexity. It is OK for test cases - // with short strings, but might not fit in other contexts. - for (size_t pos = process_str->find(find_str, 0); pos != std::string::npos; - pos = process_str->find(find_str, pos)) { - process_str->replace(pos, find_str.length(), replace_str); - pos += replace_str.length(); - replaced = true; - } - return replaced; -} - -bool ContainsDebugOpcode(const char* inst) { - return std::any_of(std::begin(kDebugOpcodes), std::end(kDebugOpcodes), - [inst](const char* op) { - return std::string(inst).find(op) != std::string::npos; - }); -} - -std::string SelectiveJoin(const std::vector& strings, - const std::function& skip_dictator, - char delimiter) { - std::ostringstream oss; - for (const auto* str : strings) { - if (!skip_dictator(str)) oss << str << delimiter; - } - return oss.str(); -} - -std::string JoinAllInsts(const std::vector& insts) { - return SelectiveJoin(insts, [](const char*) { return false; }); -} - -std::string JoinNonDebugInsts(const std::vector& insts) { - return SelectiveJoin( - insts, [](const char* inst) { return ContainsDebugOpcode(inst); }); -} - -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/pass_utils.h b/3rdparty/spirv-tools/test/opt/pass_utils.h deleted file mode 100644 index 8968f8a64..000000000 --- a/3rdparty/spirv-tools/test/opt/pass_utils.h +++ /dev/null @@ -1,84 +0,0 @@ -// 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. - -#ifndef TEST_OPT_PASS_UTILS_H_ -#define TEST_OPT_PASS_UTILS_H_ - -#include -#include -#include -#include -#include - -#include "gtest/gtest.h" -#include "include/spirv-tools/libspirv.h" -#include "include/spirv-tools/libspirv.hpp" - -namespace spvtools { -namespace opt { - -struct Message { - spv_message_level_t level; - const char* source_file; - uint32_t line_number; - uint32_t column_number; - const char* message; -}; - -// Return a message consumer that can be used to check that the message produced -// are the messages in |expexted_messages|, and in the same order. -MessageConsumer GetTestMessageConsumer(std::vector& expected_messages); - -// In-place substring replacement. Finds the |find_str| in the |process_str| -// and replaces the found substring with |replace_str|. Returns true if at -// least one replacement is done successfully, returns false otherwise. The -// replaced substring won't be processed again, which means: If the -// |replace_str| has |find_str| as its substring, that newly replaced part of -// |process_str| won't be processed again. -bool FindAndReplace(std::string* process_str, const std::string find_str, - const std::string replace_str); - -// Returns true if the given string contains any debug opcode substring. -bool ContainsDebugOpcode(const char* inst); - -// Returns the concatenated string from a vector of |strings|, with postfixing -// each string with the given |delimiter|. if the |skip_dictator| returns true -// for an original string, that string will be omitted. -std::string SelectiveJoin(const std::vector& strings, - const std::function& skip_dictator, - char delimiter = '\n'); - -// Concatenates a vector of strings into one string. Each string is postfixed -// with '\n'. -std::string JoinAllInsts(const std::vector& insts); - -// Concatenates a vector of strings into one string. Each string is postfixed -// with '\n'. If a string contains opcode for debug instruction, that string -// will be ignored. -std::string JoinNonDebugInsts(const std::vector& insts); - -// Returns a vector that contains the contents of |a| followed by the contents -// of |b|. -template -std::vector Concat(const std::vector& a, const std::vector& b) { - std::vector ret; - std::copy(a.begin(), a.end(), back_inserter(ret)); - std::copy(b.begin(), b.end(), back_inserter(ret)); - return ret; -} - -} // namespace opt -} // namespace spvtools - -#endif // TEST_OPT_PASS_UTILS_H_ diff --git a/3rdparty/spirv-tools/test/opt/pch_test_opt.cpp b/3rdparty/spirv-tools/test/opt/pch_test_opt.cpp deleted file mode 100644 index f15812913..000000000 --- a/3rdparty/spirv-tools/test/opt/pch_test_opt.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "pch_test_opt.h" diff --git a/3rdparty/spirv-tools/test/opt/pch_test_opt.h b/3rdparty/spirv-tools/test/opt/pch_test_opt.h deleted file mode 100644 index 4e8106fbf..000000000 --- a/3rdparty/spirv-tools/test/opt/pch_test_opt.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_dependence.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/scalar_analysis.h" -#include "source/opt/tree_iterator.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" diff --git a/3rdparty/spirv-tools/test/opt/private_to_local_test.cpp b/3rdparty/spirv-tools/test/opt/private_to_local_test.cpp deleted file mode 100644 index 12306529a..000000000 --- a/3rdparty/spirv-tools/test/opt/private_to_local_test.cpp +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/value_number_table.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; -using PrivateToLocalTest = PassTest<::testing::Test>; - -TEST_F(PrivateToLocalTest, ChangeToLocal) { - // Change the private variable to a local, and change the types accordingly. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 -; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32 - %5 = OpTypeFloat 32 -; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]] - %6 = OpTypePointer Private %5 -; CHECK-NOT: OpVariable [[.+]] Private - %8 = OpVariable %6 Private -; CHECK: OpFunction - %2 = OpFunction %3 None %4 -; CHECK: OpLabel - %7 = OpLabel -; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function -; CHECK: OpLoad [[float]] [[newvar]] - %9 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(PrivateToLocalTest, ReuseExistingType) { - // Change the private variable to a local, and change the types accordingly. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 -; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32 - %5 = OpTypeFloat 32 - %func_ptr = OpTypePointer Function %5 -; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]] -; CHECK-NOT: [[%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]] - %6 = OpTypePointer Private %5 -; CHECK-NOT: OpVariable [[.+]] Private - %8 = OpVariable %6 Private -; CHECK: OpFunction - %2 = OpFunction %3 None %4 -; CHECK: OpLabel - %7 = OpLabel -; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function -; CHECK: OpLoad [[float]] [[newvar]] - %9 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(PrivateToLocalTest, UpdateAccessChain) { - // Change the private variable to a local, and change the AccessChain. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %void = OpTypeVoid - %6 = OpTypeFunction %void -; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat - %float = OpTypeFloat 32 -; CHECK: [[struct:%[a-zA-Z_\d]+]] = OpTypeStruct - %_struct_8 = OpTypeStruct %float -%_ptr_Private_float = OpTypePointer Private %float -; CHECK: [[new_struct_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[struct]] -; CHECK: [[new_float_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]] -%_ptr_Private__struct_8 = OpTypePointer Private %_struct_8 -; CHECK-NOT: OpVariable [[.+]] Private - %11 = OpVariable %_ptr_Private__struct_8 Private -; CHECK: OpFunction - %2 = OpFunction %void None %6 -; CHECK: OpLabel - %12 = OpLabel -; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[new_struct_type]] Function -; CHECK: [[member:%[a-zA-Z_\d]+]] = OpAccessChain [[new_float_type]] [[newvar]] - %13 = OpAccessChain %_ptr_Private_float %11 %uint_0 -; CHECK: OpLoad [[float]] [[member]] - %14 = OpLoad %float %13 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(PrivateToLocalTest, UseTexelPointer) { - // Change the private variable to a local, and change the OpImageTexelPointer. - const std::string text = R"( -OpCapability SampledBuffer - OpCapability StorageImageExtendedFormats - OpCapability ImageBuffer - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID - OpExecutionMode %2 LocalSize 64 1 1 - OpSource HLSL 600 - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %4 DescriptorSet 4 - OpDecorate %4 Binding 70 - %uint = OpTypeInt 32 0 - %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui -%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6 -%_ptr_Private_6 = OpTypePointer Private %6 - %void = OpTypeVoid - %10 = OpTypeFunction %void - %uint_0 = OpConstant %uint 0 - %uint_1 = OpConstant %uint 1 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%_ptr_Image_uint = OpTypePointer Image %uint - %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant - %16 = OpVariable %_ptr_Private_6 Private -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input - %2 = OpFunction %void None %10 - %17 = OpLabel -; Make sure the variable was moved. -; CHECK: OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpVariable %_ptr_Function_6 Function - %18 = OpLoad %6 %4 - OpStore %16 %18 - %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0 - %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(PrivateToLocalTest, UsedInTwoFunctions) { - // Should not change because it is used in multiple functions. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Private %5 - %8 = OpVariable %6 Private - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - %10 = OpFunction %3 None %4 - %11 = OpLabel - %12 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(PrivateToLocalTest, UsedInFunctionCall) { - // Should not change because it is used in a function call. Changing the - // signature of the function would require cloning the function, which is not - // worth it. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_ptr_Private_float = OpTypePointer Private %float - %7 = OpTypeFunction %void %_ptr_Private_float - %8 = OpVariable %_ptr_Private_float Private - %2 = OpFunction %void None %4 - %9 = OpLabel - %10 = OpFunctionCall %void %11 %8 - OpReturn - OpFunctionEnd - %11 = OpFunction %void None %7 - %12 = OpFunctionParameter %_ptr_Private_float - %13 = OpLabel - %14 = OpLoad %float %12 - OpReturn - OpFunctionEnd - )"; - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct1) { - // Test that the correct pointer type is picked up. - const std::string text = R"( -; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct -; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct -; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct1]] -; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]] -; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]] -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr1]] Function -; CHECK: OpLoad [[struct1]] [[newvar]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %struct1 = OpTypeStruct %5 - %struct2 = OpTypeStruct %5 - %6 = OpTypePointer Private %struct1 - %func_ptr2 = OpTypePointer Function %struct2 - %8 = OpVariable %6 Private - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %struct1 %8 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct2) { - // Test that the correct pointer type is picked up. - const std::string text = R"( -; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct -; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct -; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct2]] -; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]] -; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]] -; CHECK: OpFunction -; CHECK: OpLabel -; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr2]] Function -; CHECK: OpLoad [[struct2]] [[newvar]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %struct1 = OpTypeStruct %5 - %struct2 = OpTypeStruct %5 - %6 = OpTypePointer Private %struct2 - %func_ptr2 = OpTypePointer Function %struct1 - %8 = OpVariable %6 Private - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %struct2 %8 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -TEST_F(PrivateToLocalTest, SPV14RemoveFromInterface) { - const std::string text = R"( -; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv -; CHECK: OpEntryPoint GLCompute %foo "foo" %in -; CHECK: %priv = OpVariable {{%\w+}} Function -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %foo "foo" %in %priv -OpExecutionMode %foo LocalSize 1 1 1 -OpName %foo "foo" -OpName %in "in" -OpName %priv "priv" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_private_int = OpTypePointer Private %int -%in = OpVariable %ptr_ssbo_int StorageBuffer -%priv = OpVariable %ptr_private_int Private -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpLoad %int %in -OpStore %priv %ld -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(PrivateToLocalTest, SPV14RemoveFromInterfaceMultipleEntryPoints) { - const std::string text = R"( -; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv -; CHECK-NOT: OpEntryPoint GLCompute %foo "bar" %in %priv -; CHECK: OpEntryPoint GLCompute %foo "foo" %in -; CHECK: OpEntryPoint GLCompute %foo "bar" %in -; CHECK: %priv = OpVariable {{%\w+}} Function -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %foo "foo" %in %priv -OpEntryPoint GLCompute %foo "bar" %in %priv -OpExecutionMode %foo LocalSize 1 1 1 -OpName %foo "foo" -OpName %in "in" -OpName %priv "priv" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_private_int = OpTypePointer Private %int -%in = OpVariable %ptr_ssbo_int StorageBuffer -%priv = OpVariable %ptr_private_int Private -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpLoad %int %in -OpStore %priv %ld -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(PrivateToLocalTest, SPV14RemoveFromInterfaceMultipleVariables) { - const std::string text = R"( -; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv1 %priv2 -; CHECK: OpEntryPoint GLCompute %foo "foo" %in -; CHECK: %priv1 = OpVariable {{%\w+}} Function -; CHECK: %priv2 = OpVariable {{%\w+}} Function -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %foo "foo" %in %priv1 %priv2 -OpExecutionMode %foo LocalSize 1 1 1 -OpName %foo "foo" -OpName %in "in" -OpName %priv1 "priv1" -OpName %priv2 "priv2" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_private_int = OpTypePointer Private %int -%in = OpVariable %ptr_ssbo_int StorageBuffer -%priv1 = OpVariable %ptr_private_int Private -%priv2 = OpVariable %ptr_private_int Private -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -%1 = OpFunctionCall %void %bar1 -%2 = OpFunctionCall %void %bar2 -OpReturn -OpFunctionEnd -%bar1 = OpFunction %void None %void_fn -%3 = OpLabel -%ld1 = OpLoad %int %in -OpStore %priv1 %ld1 -OpReturn -OpFunctionEnd -%bar2 = OpFunction %void None %void_fn -%4 = OpLabel -%ld2 = OpLoad %int %in -OpStore %priv2 %ld2 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(PrivateToLocalTest, IdBoundOverflow1) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginLowerLeft - OpSource HLSL 84 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeStruct %7 - %4194302 = OpTypeStruct %8 %8 - %9 = OpTypeStruct %8 %8 - %11 = OpTypePointer Private %7 - %18 = OpTypeStruct %6 %9 - %12 = OpVariable %11 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - %13 = OpLoad %7 %12 - OpReturn - OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/process_lines_test.cpp b/3rdparty/spirv-tools/test/opt/process_lines_test.cpp deleted file mode 100644 index 33ad4be89..000000000 --- a/3rdparty/spirv-tools/test/opt/process_lines_test.cpp +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ProcessLinesTest = PassTest<::testing::Test>; - -TEST_F(ProcessLinesTest, SimplePropagation) { - // Texture2D g_tColor[128]; - // - // layout(push_constant) cbuffer PerViewConstantBuffer_t - // { - // uint g_nDataIdx; - // uint g_nDataIdx2; - // bool g_B; - // }; - // - // SamplerState g_sAniso; - // - // struct PS_INPUT - // { - // float2 vTextureCoords : TEXCOORD2; - // }; - // - // struct PS_OUTPUT - // { - // float4 vColor : SV_Target0; - // }; - // - // PS_OUTPUT MainPs(PS_INPUT i) - // { - // PS_OUTPUT ps_output; - // - // uint u; - // if (g_B) - // u = g_nDataIdx; - // else - // u = g_nDataIdx2; - // ps_output.vColor = g_tColor[u].Sample(g_sAniso, i.vTextureCoords.xy); - // return ps_output; - // } - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -%5 = OpString "foo.frag" -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %PS_INPUT "PS_INPUT" -OpMemberName %PS_INPUT 0 "vTextureCoords" -OpName %PS_OUTPUT "PS_OUTPUT" -OpMemberName %PS_OUTPUT 0 "vColor" -OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" -OpName %i "i" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpMemberName %PerViewConstantBuffer_t 1 "g_nDataIdx2" -OpMemberName %PerViewConstantBuffer_t 2 "g_B" -OpName %_ "" -OpName %u "u" -OpName %ps_output "ps_output" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_0 "i" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpName %param "param" -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 -OpMemberDecorate %PerViewConstantBuffer_t 2 Offset 8 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -)"; - - const std::string before = - R"(%void = OpTypeVoid -%19 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%PS_INPUT = OpTypeStruct %v2float -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -%v4float = OpTypeVector %float 4 -%PS_OUTPUT = OpTypeStruct %v4float -%24 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -%uint = OpTypeInt 32 0 -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%int = OpTypeInt 32 1 -%int_2 = OpConstant %int 2 -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%_ptr_Function_uint = OpTypePointer Function %uint -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -%36 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint_128 = OpConstant %uint 128 -%_arr_36_uint_128 = OpTypeArray %36 %uint_128 -%_ptr_UniformConstant__arr_36_uint_128 = OpTypePointer UniformConstant %_arr_36_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_36_uint_128 UniformConstant -%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 -%41 = OpTypeSampler -%_ptr_UniformConstant_41 = OpTypePointer UniformConstant %41 -%g_sAniso = OpVariable %_ptr_UniformConstant_41 UniformConstant -%43 = OpTypeSampledImage %36 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%MainPs = OpFunction %void None %19 -%48 = OpLabel -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %5 23 0 -%49 = OpLoad %v2float %i_vTextureCoords -%50 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpStore %50 %49 -%51 = OpLoad %PS_INPUT %i_0 -OpStore %param %51 -%52 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -%53 = OpCompositeExtract %v4float %52 0 -OpStore %_entryPointOutput_vColor %53 -OpReturn -OpFunctionEnd -%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %24 -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -%54 = OpLabel -%u = OpVariable %_ptr_Function_uint Function -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %5 27 0 -%55 = OpAccessChain %_ptr_PushConstant_uint %_ %int_2 -%56 = OpLoad %uint %55 -%57 = OpINotEqual %bool %56 %uint_0 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %60 -%59 = OpLabel -OpLine %5 28 0 -%61 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%62 = OpLoad %uint %61 -OpStore %u %62 -OpBranch %58 -%60 = OpLabel -OpLine %5 30 0 -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -%64 = OpLoad %uint %63 -OpStore %u %64 -OpBranch %58 -%58 = OpLabel -OpLine %5 31 0 -%65 = OpLoad %uint %u -%66 = OpAccessChain %_ptr_UniformConstant_36 %g_tColor %65 -%67 = OpLoad %36 %66 -%68 = OpLoad %41 %g_sAniso -%69 = OpSampledImage %43 %67 %68 -%70 = OpAccessChain %_ptr_Function_v2float %i %int_0 -%71 = OpLoad %v2float %70 -%72 = OpImageSampleImplicitLod %v4float %69 %71 -%73 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpStore %73 %72 -OpLine %5 32 0 -%74 = OpLoad %PS_OUTPUT %ps_output -OpReturnValue %74 -OpFunctionEnd -)"; - - const std::string after = - R"(OpNoLine -%void = OpTypeVoid -OpNoLine -%19 = OpTypeFunction %void -OpNoLine -%float = OpTypeFloat 32 -OpNoLine -%v2float = OpTypeVector %float 2 -OpNoLine -%PS_INPUT = OpTypeStruct %v2float -OpNoLine -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -OpNoLine -%v4float = OpTypeVector %float 4 -OpNoLine -%PS_OUTPUT = OpTypeStruct %v4float -OpNoLine -%24 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -OpNoLine -%uint = OpTypeInt 32 0 -OpNoLine -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint %uint -OpNoLine -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -OpNoLine -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -OpNoLine -%int = OpTypeInt 32 1 -OpNoLine -%int_2 = OpConstant %int 2 -OpNoLine -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -OpNoLine -%bool = OpTypeBool -OpNoLine -%uint_0 = OpConstant %uint 0 -OpNoLine -%_ptr_Function_uint = OpTypePointer Function %uint -OpNoLine -%int_0 = OpConstant %int 0 -OpNoLine -%int_1 = OpConstant %int 1 -OpNoLine -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -OpNoLine -%36 = OpTypeImage %float 2D 0 0 0 1 Unknown -OpNoLine -%uint_128 = OpConstant %uint 128 -OpNoLine -%_arr_36_uint_128 = OpTypeArray %36 %uint_128 -OpNoLine -%_ptr_UniformConstant__arr_36_uint_128 = OpTypePointer UniformConstant %_arr_36_uint_128 -OpNoLine -%g_tColor = OpVariable %_ptr_UniformConstant__arr_36_uint_128 UniformConstant -OpNoLine -%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 -OpNoLine -%41 = OpTypeSampler -OpNoLine -%_ptr_UniformConstant_41 = OpTypePointer UniformConstant %41 -OpNoLine -%g_sAniso = OpVariable %_ptr_UniformConstant_41 UniformConstant -OpNoLine -%43 = OpTypeSampledImage %36 -OpNoLine -%_ptr_Function_v2float = OpTypePointer Function %v2float -OpNoLine -%_ptr_Function_v4float = OpTypePointer Function %v4float -OpNoLine -%_ptr_Input_v2float = OpTypePointer Input %v2float -OpNoLine -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -OpNoLine -%_ptr_Output_v4float = OpTypePointer Output %v4float -OpNoLine -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -OpNoLine -%MainPs = OpFunction %void None %19 -OpNoLine -%48 = OpLabel -OpNoLine -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -OpNoLine -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %5 23 0 -%49 = OpLoad %v2float %i_vTextureCoords -OpLine %5 23 0 -%50 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpLine %5 23 0 -OpStore %50 %49 -OpLine %5 23 0 -%51 = OpLoad %PS_INPUT %i_0 -OpLine %5 23 0 -OpStore %param %51 -OpLine %5 23 0 -%52 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -OpLine %5 23 0 -%53 = OpCompositeExtract %v4float %52 0 -OpLine %5 23 0 -OpStore %_entryPointOutput_vColor %53 -OpLine %5 23 0 -OpReturn -OpNoLine -OpFunctionEnd -OpNoLine -%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %24 -OpNoLine -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -OpNoLine -%54 = OpLabel -OpNoLine -%u = OpVariable %_ptr_Function_uint Function -OpNoLine -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %5 27 0 -%55 = OpAccessChain %_ptr_PushConstant_uint %_ %int_2 -OpLine %5 27 0 -%56 = OpLoad %uint %55 -OpLine %5 27 0 -%57 = OpINotEqual %bool %56 %uint_0 -OpLine %5 27 0 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %60 -OpNoLine -%59 = OpLabel -OpLine %5 28 0 -%61 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -OpLine %5 28 0 -%62 = OpLoad %uint %61 -OpLine %5 28 0 -OpStore %u %62 -OpLine %5 28 0 -OpBranch %58 -OpNoLine -%60 = OpLabel -OpLine %5 30 0 -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -OpLine %5 30 0 -%64 = OpLoad %uint %63 -OpLine %5 30 0 -OpStore %u %64 -OpLine %5 30 0 -OpBranch %58 -OpNoLine -%58 = OpLabel -OpLine %5 31 0 -%65 = OpLoad %uint %u -OpLine %5 31 0 -%66 = OpAccessChain %_ptr_UniformConstant_36 %g_tColor %65 -OpLine %5 31 0 -%67 = OpLoad %36 %66 -OpLine %5 31 0 -%68 = OpLoad %41 %g_sAniso -OpLine %5 31 0 -%69 = OpSampledImage %43 %67 %68 -OpLine %5 31 0 -%70 = OpAccessChain %_ptr_Function_v2float %i %int_0 -OpLine %5 31 0 -%71 = OpLoad %v2float %70 -OpLine %5 31 0 -%72 = OpImageSampleImplicitLod %v4float %69 %71 -OpLine %5 31 0 -%73 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpLine %5 31 0 -OpStore %73 %72 -OpLine %5 32 0 -%74 = OpLoad %PS_OUTPUT %ps_output -OpLine %5 32 0 -OpReturnValue %74 -OpNoLine -OpFunctionEnd -)"; - - SinglePassRunAndCheck(predefs + before, predefs + after, - false, true, kLinesPropagateLines); -} - -TEST_F(ProcessLinesTest, SimpleElimination) { - // Previous test with before and after reversed - - const std::string predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor -OpExecutionMode %MainPs OriginUpperLeft -%5 = OpString "foo.frag" -OpSource HLSL 500 -OpName %MainPs "MainPs" -OpName %PS_INPUT "PS_INPUT" -OpMemberName %PS_INPUT 0 "vTextureCoords" -OpName %PS_OUTPUT "PS_OUTPUT" -OpMemberName %PS_OUTPUT 0 "vColor" -OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" -OpName %i "i" -OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" -OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" -OpMemberName %PerViewConstantBuffer_t 1 "g_nDataIdx2" -OpMemberName %PerViewConstantBuffer_t 2 "g_B" -OpName %_ "" -OpName %u "u" -OpName %ps_output "ps_output" -OpName %g_tColor "g_tColor" -OpName %g_sAniso "g_sAniso" -OpName %i_0 "i" -OpName %i_vTextureCoords "i.vTextureCoords" -OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" -OpName %param "param" -OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 -OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 -OpMemberDecorate %PerViewConstantBuffer_t 2 Offset 8 -OpDecorate %PerViewConstantBuffer_t Block -OpDecorate %g_tColor DescriptorSet 0 -OpDecorate %g_sAniso DescriptorSet 0 -OpDecorate %i_vTextureCoords Location 0 -OpDecorate %_entryPointOutput_vColor Location 0 -)"; - - const std::string before = - R"(OpNoLine -%void = OpTypeVoid -OpNoLine -%19 = OpTypeFunction %void -OpNoLine -%float = OpTypeFloat 32 -OpNoLine -%v2float = OpTypeVector %float 2 -OpNoLine -%PS_INPUT = OpTypeStruct %v2float -OpNoLine -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -OpNoLine -%v4float = OpTypeVector %float 4 -OpNoLine -%PS_OUTPUT = OpTypeStruct %v4float -OpNoLine -%24 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -OpNoLine -%uint = OpTypeInt 32 0 -OpNoLine -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint %uint -OpNoLine -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -OpNoLine -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -OpNoLine -%int = OpTypeInt 32 1 -OpNoLine -%int_2 = OpConstant %int 2 -OpNoLine -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -OpNoLine -%bool = OpTypeBool -OpNoLine -%uint_0 = OpConstant %uint 0 -OpNoLine -%_ptr_Function_uint = OpTypePointer Function %uint -OpNoLine -%int_0 = OpConstant %int 0 -OpNoLine -%int_1 = OpConstant %int 1 -OpNoLine -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -OpNoLine -%36 = OpTypeImage %float 2D 0 0 0 1 Unknown -OpNoLine -%uint_128 = OpConstant %uint 128 -OpNoLine -%_arr_36_uint_128 = OpTypeArray %36 %uint_128 -OpNoLine -%_ptr_UniformConstant__arr_36_uint_128 = OpTypePointer UniformConstant %_arr_36_uint_128 -OpNoLine -%g_tColor = OpVariable %_ptr_UniformConstant__arr_36_uint_128 UniformConstant -OpNoLine -%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 -OpNoLine -%41 = OpTypeSampler -OpNoLine -%_ptr_UniformConstant_41 = OpTypePointer UniformConstant %41 -OpNoLine -%g_sAniso = OpVariable %_ptr_UniformConstant_41 UniformConstant -OpNoLine -%43 = OpTypeSampledImage %36 -OpNoLine -%_ptr_Function_v2float = OpTypePointer Function %v2float -OpNoLine -%_ptr_Function_v4float = OpTypePointer Function %v4float -OpNoLine -%_ptr_Input_v2float = OpTypePointer Input %v2float -OpNoLine -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -OpNoLine -%_ptr_Output_v4float = OpTypePointer Output %v4float -OpNoLine -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -OpNoLine -%MainPs = OpFunction %void None %19 -OpNoLine -%48 = OpLabel -OpNoLine -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -OpNoLine -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %5 23 0 -%49 = OpLoad %v2float %i_vTextureCoords -OpLine %5 23 0 -%50 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpLine %5 23 0 -OpStore %50 %49 -OpLine %5 23 0 -%51 = OpLoad %PS_INPUT %i_0 -OpLine %5 23 0 -OpStore %param %51 -OpLine %5 23 0 -%52 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -OpLine %5 23 0 -%53 = OpCompositeExtract %v4float %52 0 -OpLine %5 23 0 -OpStore %_entryPointOutput_vColor %53 -OpLine %5 23 0 -OpReturn -OpNoLine -OpFunctionEnd -OpNoLine -%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %24 -OpNoLine -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -OpNoLine -%54 = OpLabel -OpNoLine -%u = OpVariable %_ptr_Function_uint Function -OpNoLine -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %5 27 0 -%55 = OpAccessChain %_ptr_PushConstant_uint %_ %int_2 -OpLine %5 27 0 -%56 = OpLoad %uint %55 -OpLine %5 27 0 -%57 = OpINotEqual %bool %56 %uint_0 -OpLine %5 27 0 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %60 -OpNoLine -%59 = OpLabel -OpLine %5 28 0 -%61 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -OpLine %5 28 0 -%62 = OpLoad %uint %61 -OpLine %5 28 0 -OpStore %u %62 -OpLine %5 28 0 -OpBranch %58 -OpNoLine -%60 = OpLabel -OpLine %5 30 0 -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -OpLine %5 30 0 -%64 = OpLoad %uint %63 -OpLine %5 30 0 -OpStore %u %64 -OpLine %5 30 0 -OpBranch %58 -OpNoLine -%58 = OpLabel -OpLine %5 31 0 -%65 = OpLoad %uint %u -OpLine %5 31 0 -%66 = OpAccessChain %_ptr_UniformConstant_36 %g_tColor %65 -OpLine %5 31 0 -%67 = OpLoad %36 %66 -OpLine %5 31 0 -%68 = OpLoad %41 %g_sAniso -OpLine %5 31 0 -%69 = OpSampledImage %43 %67 %68 -OpLine %5 31 0 -%70 = OpAccessChain %_ptr_Function_v2float %i %int_0 -OpLine %5 31 0 -%71 = OpLoad %v2float %70 -OpLine %5 31 0 -%72 = OpImageSampleImplicitLod %v4float %69 %71 -OpLine %5 31 0 -%73 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpLine %5 31 0 -OpStore %73 %72 -OpLine %5 32 0 -%74 = OpLoad %PS_OUTPUT %ps_output -OpLine %5 32 0 -OpReturnValue %74 -OpNoLine -OpFunctionEnd -)"; - - const std::string after = - R"(%void = OpTypeVoid -%19 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%PS_INPUT = OpTypeStruct %v2float -%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT -%v4float = OpTypeVector %float 4 -%PS_OUTPUT = OpTypeStruct %v4float -%24 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT -%uint = OpTypeInt 32 0 -%PerViewConstantBuffer_t = OpTypeStruct %uint %uint %uint -%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t -%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant -%int = OpTypeInt 32 1 -%int_2 = OpConstant %int 2 -%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%_ptr_Function_uint = OpTypePointer Function %uint -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT -%36 = OpTypeImage %float 2D 0 0 0 1 Unknown -%uint_128 = OpConstant %uint 128 -%_arr_36_uint_128 = OpTypeArray %36 %uint_128 -%_ptr_UniformConstant__arr_36_uint_128 = OpTypePointer UniformConstant %_arr_36_uint_128 -%g_tColor = OpVariable %_ptr_UniformConstant__arr_36_uint_128 UniformConstant -%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 -%41 = OpTypeSampler -%_ptr_UniformConstant_41 = OpTypePointer UniformConstant %41 -%g_sAniso = OpVariable %_ptr_UniformConstant_41 UniformConstant -%43 = OpTypeSampledImage %36 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -%MainPs = OpFunction %void None %19 -%48 = OpLabel -%i_0 = OpVariable %_ptr_Function_PS_INPUT Function -%param = OpVariable %_ptr_Function_PS_INPUT Function -OpLine %5 23 0 -%49 = OpLoad %v2float %i_vTextureCoords -%50 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 -OpStore %50 %49 -%51 = OpLoad %PS_INPUT %i_0 -OpStore %param %51 -%52 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param -%53 = OpCompositeExtract %v4float %52 0 -OpStore %_entryPointOutput_vColor %53 -OpReturn -OpFunctionEnd -%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %24 -%i = OpFunctionParameter %_ptr_Function_PS_INPUT -%54 = OpLabel -%u = OpVariable %_ptr_Function_uint Function -%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function -OpLine %5 27 0 -%55 = OpAccessChain %_ptr_PushConstant_uint %_ %int_2 -%56 = OpLoad %uint %55 -%57 = OpINotEqual %bool %56 %uint_0 -OpSelectionMerge %58 None -OpBranchConditional %57 %59 %60 -%59 = OpLabel -OpLine %5 28 0 -%61 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 -%62 = OpLoad %uint %61 -OpStore %u %62 -OpBranch %58 -%60 = OpLabel -OpLine %5 30 0 -%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 -%64 = OpLoad %uint %63 -OpStore %u %64 -OpBranch %58 -%58 = OpLabel -OpLine %5 31 0 -%65 = OpLoad %uint %u -%66 = OpAccessChain %_ptr_UniformConstant_36 %g_tColor %65 -%67 = OpLoad %36 %66 -%68 = OpLoad %41 %g_sAniso -%69 = OpSampledImage %43 %67 %68 -%70 = OpAccessChain %_ptr_Function_v2float %i %int_0 -%71 = OpLoad %v2float %70 -%72 = OpImageSampleImplicitLod %v4float %69 %71 -%73 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 -OpStore %73 %72 -OpLine %5 32 0 -%74 = OpLoad %PS_OUTPUT %ps_output -OpReturnValue %74 -OpFunctionEnd -)"; - - SinglePassRunAndCheck( - predefs + before, predefs + after, false, true, kLinesEliminateDeadLines); -} - -// TODO(greg-lunarg): Add tests to verify handling of these cases: -// -// TODO(greg-lunarg): Think about other tests :) - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/propagator_test.cpp b/3rdparty/spirv-tools/test/opt/propagator_test.cpp deleted file mode 100644 index fb8e487cc..000000000 --- a/3rdparty/spirv-tools/test/opt/propagator_test.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/cfg.h" -#include "source/opt/ir_context.h" -#include "source/opt/pass.h" -#include "source/opt/propagator.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; - -class PropagatorTest : public testing::Test { - protected: - virtual void TearDown() { - ctx_.reset(nullptr); - values_.clear(); - values_vec_.clear(); - } - - void Assemble(const std::string& input) { - ctx_ = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input); - ASSERT_NE(nullptr, ctx_) << "Assembling failed for shader:\n" - << input << "\n"; - } - - bool Propagate(const SSAPropagator::VisitFunction& visit_fn) { - SSAPropagator propagator(ctx_.get(), visit_fn); - bool retval = false; - for (auto& fn : *ctx_->module()) { - retval |= propagator.Run(&fn); - } - return retval; - } - - const std::vector& GetValues() { - values_vec_.clear(); - for (const auto& it : values_) { - values_vec_.push_back(it.second); - } - return values_vec_; - } - - std::unique_ptr ctx_; - std::map values_; - std::vector values_vec_; -}; - -TEST_F(PropagatorTest, LocalPropagate) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %x "x" - OpName %y "y" - OpName %z "z" - OpName %outparm "outparm" - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_4 = OpConstant %int 4 - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %3 - %5 = OpLabel - %x = OpVariable %_ptr_Function_int Function - %y = OpVariable %_ptr_Function_int Function - %z = OpVariable %_ptr_Function_int Function - OpStore %x %int_4 - OpStore %y %int_3 - OpStore %z %int_1 - %20 = OpLoad %int %z - OpStore %outparm %20 - OpReturn - OpFunctionEnd - )"; - Assemble(spv_asm); - - const auto visit_fn = [this](Instruction* instr, BasicBlock** dest_bb) { - *dest_bb = nullptr; - if (instr->opcode() == SpvOpStore) { - uint32_t lhs_id = instr->GetSingleWordOperand(0); - uint32_t rhs_id = instr->GetSingleWordOperand(1); - Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id); - if (rhs_def->opcode() == SpvOpConstant) { - uint32_t val = rhs_def->GetSingleWordOperand(2); - values_[lhs_id] = val; - return SSAPropagator::kInteresting; - } - } - return SSAPropagator::kVarying; - }; - - EXPECT_TRUE(Propagate(visit_fn)); - EXPECT_THAT(GetValues(), UnorderedElementsAre(4, 3, 1)); -} - -TEST_F(PropagatorTest, PropagateThroughPhis) { - const std::string spv_asm = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %x %outparm - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %x "x" - OpName %outparm "outparm" - OpDecorate %x Flat - OpDecorate %x Location 0 - OpDecorate %outparm Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %bool = OpTypeBool -%_ptr_Function_int = OpTypePointer Function %int - %int_4 = OpConstant %int 4 - %int_3 = OpConstant %int 3 - %int_1 = OpConstant %int 1 -%_ptr_Input_int = OpTypePointer Input %int - %x = OpVariable %_ptr_Input_int Input -%_ptr_Output_int = OpTypePointer Output %int - %outparm = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %3 - %4 = OpLabel - %5 = OpLoad %int %x - %6 = OpSGreaterThan %bool %5 %int_3 - OpSelectionMerge %25 None - OpBranchConditional %6 %22 %23 - %22 = OpLabel - %7 = OpLoad %int %int_4 - OpBranch %25 - %23 = OpLabel - %8 = OpLoad %int %int_4 - OpBranch %25 - %25 = OpLabel - %35 = OpPhi %int %7 %22 %8 %23 - OpStore %outparm %35 - OpReturn - OpFunctionEnd - )"; - - Assemble(spv_asm); - - Instruction* phi_instr = nullptr; - const auto visit_fn = [this, &phi_instr](Instruction* instr, - BasicBlock** dest_bb) { - *dest_bb = nullptr; - if (instr->opcode() == SpvOpLoad) { - uint32_t rhs_id = instr->GetSingleWordOperand(2); - Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id); - if (rhs_def->opcode() == SpvOpConstant) { - uint32_t val = rhs_def->GetSingleWordOperand(2); - values_[instr->result_id()] = val; - return SSAPropagator::kInteresting; - } - } else if (instr->opcode() == SpvOpPhi) { - phi_instr = instr; - SSAPropagator::PropStatus retval; - for (uint32_t i = 2; i < instr->NumOperands(); i += 2) { - uint32_t phi_arg_id = instr->GetSingleWordOperand(i); - auto it = values_.find(phi_arg_id); - if (it != values_.end()) { - EXPECT_EQ(it->second, 4u); - retval = SSAPropagator::kInteresting; - values_[instr->result_id()] = it->second; - } else { - retval = SSAPropagator::kNotInteresting; - break; - } - } - return retval; - } - - return SSAPropagator::kVarying; - }; - - EXPECT_TRUE(Propagate(visit_fn)); - - // The propagator should've concluded that the Phi instruction has a constant - // value of 4. - EXPECT_NE(phi_instr, nullptr); - EXPECT_EQ(values_[phi_instr->result_id()], 4u); - - EXPECT_THAT(GetValues(), UnorderedElementsAre(4u, 4u, 4u)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/reduce_load_size_test.cpp b/3rdparty/spirv-tools/test/opt/reduce_load_size_test.cpp deleted file mode 100644 index 50dc5017c..000000000 --- a/3rdparty/spirv-tools/test/opt/reduce_load_size_test.cpp +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ReduceLoadSizeTest = PassTest<::testing::Test>; - -TEST_F(ReduceLoadSizeTest, cbuffer_load_extract) { - // Originally from the following HLSL: - // struct S { - // uint f; - // }; - // - // - // cbuffer gBuffer { uint a[32]; }; - // - // RWStructuredBuffer gRWSBuffer; - // - // uint foo(uint p[32]) { - // return p[1]; - // } - // - // [numthreads(1,1,1)] - // void main() { - // gRWSBuffer[0].f = foo(a); - // } - const std::string test = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource HLSL 600 - OpName %type_gBuffer "type.gBuffer" - OpMemberName %type_gBuffer 0 "a" - OpName %gBuffer "gBuffer" - OpName %S "S" - OpMemberName %S 0 "f" - OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" - OpName %gRWSBuffer "gRWSBuffer" - OpName %main "main" - OpDecorate %_arr_uint_uint_32 ArrayStride 16 - OpMemberDecorate %type_gBuffer 0 Offset 0 - OpDecorate %type_gBuffer Block - OpMemberDecorate %S 0 Offset 0 - OpDecorate %_runtimearr_S ArrayStride 4 - OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 - OpDecorate %type_RWStructuredBuffer_S BufferBlock - OpDecorate %gBuffer DescriptorSet 0 - OpDecorate %gBuffer Binding 0 - OpDecorate %gRWSBuffer DescriptorSet 0 - OpDecorate %gRWSBuffer Binding 1 - %uint = OpTypeInt 32 0 - %uint_32 = OpConstant %uint 32 -%_arr_uint_uint_32 = OpTypeArray %uint %uint_32 -%type_gBuffer = OpTypeStruct %_arr_uint_uint_32 -%_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer - %S = OpTypeStruct %uint -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S - %int = OpTypeInt 32 1 - %void = OpTypeVoid - %15 = OpTypeFunction %void - %int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_uint_uint_32 = OpTypePointer Uniform %_arr_uint_uint_32 - %uint_0 = OpConstant %uint 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint - %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform - %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform - %main = OpFunction %void None %15 - %20 = OpLabel -; CHECK: [[ac1:%\w+]] = OpAccessChain {{%\w+}} %gBuffer %int_0 -; CHECK: [[ac2:%\w+]] = OpAccessChain {{%\w+}} [[ac1]] %uint_1 -; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[ac2]] -; CHECK: OpStore {{%\w+}} [[ld]] - %21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_32 %gBuffer %int_0 - %22 = OpLoad %_arr_uint_uint_32 %21 ; Load of 32-element array. - %23 = OpCompositeExtract %uint %22 1 - %24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0 - OpStore %24 %23 - OpReturn - OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndMatch(test, false); -} - -TEST_F(ReduceLoadSizeTest, cbuffer_load_extract_vector) { - // Originally from the following HLSL: - // struct S { - // uint f; - // }; - // - // - // cbuffer gBuffer { uint4 a; }; - // - // RWStructuredBuffer gRWSBuffer; - // - // uint foo(uint p[32]) { - // return p[1]; - // } - // - // [numthreads(1,1,1)] - // void main() { - // gRWSBuffer[0].f = foo(a); - // } - const std::string test = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource HLSL 600 -OpName %type_gBuffer "type.gBuffer" -OpMemberName %type_gBuffer 0 "a" -OpName %gBuffer "gBuffer" -OpName %S "S" -OpMemberName %S 0 "f" -OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" -OpName %gRWSBuffer "gRWSBuffer" -OpName %main "main" -OpMemberDecorate %type_gBuffer 0 Offset 0 -OpDecorate %type_gBuffer Block -OpMemberDecorate %S 0 Offset 0 -OpDecorate %_runtimearr_S ArrayStride 4 -OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 -OpDecorate %type_RWStructuredBuffer_S BufferBlock -OpDecorate %gBuffer DescriptorSet 0 -OpDecorate %gBuffer Binding 0 -OpDecorate %gRWSBuffer DescriptorSet 0 -OpDecorate %gRWSBuffer Binding 1 -%uint = OpTypeInt 32 0 -%uint_32 = OpConstant %uint 32 -%v4uint = OpTypeVector %uint 4 -%type_gBuffer = OpTypeStruct %v4uint -%_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer -%S = OpTypeStruct %uint -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S -%int = OpTypeInt 32 1 -%void = OpTypeVoid -%15 = OpTypeFunction %void -%int_0 = OpConstant %int 0 -%_ptr_Uniform_v4uint = OpTypePointer Uniform %v4uint -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform -%gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform -%main = OpFunction %void None %15 -%20 = OpLabel -%21 = OpAccessChain %_ptr_Uniform_v4uint %gBuffer %int_0 -%22 = OpLoad %v4uint %21 -%23 = OpCompositeExtract %uint %22 1 -%24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0 -OpStore %24 %23 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndCheck(test, test, true, false); -} - -TEST_F(ReduceLoadSizeTest, cbuffer_load_5_extract) { - // All of the elements of the value loaded are used, so we should not - // change the load. - const std::string test = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource HLSL 600 -OpName %type_gBuffer "type.gBuffer" -OpMemberName %type_gBuffer 0 "a" -OpName %gBuffer "gBuffer" -OpName %S "S" -OpMemberName %S 0 "f" -OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" -OpName %gRWSBuffer "gRWSBuffer" -OpName %main "main" -OpDecorate %_arr_uint_uint_5 ArrayStride 16 -OpMemberDecorate %type_gBuffer 0 Offset 0 -OpDecorate %type_gBuffer Block -OpMemberDecorate %S 0 Offset 0 -OpDecorate %_runtimearr_S ArrayStride 4 -OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 -OpDecorate %type_RWStructuredBuffer_S BufferBlock -OpDecorate %gBuffer DescriptorSet 0 -OpDecorate %gBuffer Binding 0 -OpDecorate %gRWSBuffer DescriptorSet 0 -OpDecorate %gRWSBuffer Binding 1 -%uint = OpTypeInt 32 0 -%uint_5 = OpConstant %uint 5 -%_arr_uint_uint_5 = OpTypeArray %uint %uint_5 -%type_gBuffer = OpTypeStruct %_arr_uint_uint_5 -%_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer -%S = OpTypeStruct %uint -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S -%int = OpTypeInt 32 1 -%void = OpTypeVoid -%15 = OpTypeFunction %void -%int_0 = OpConstant %int 0 -%_ptr_Uniform__arr_uint_uint_5 = OpTypePointer Uniform %_arr_uint_uint_5 -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform -%gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform -%main = OpFunction %void None %15 -%20 = OpLabel -%21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_5 %gBuffer %int_0 -%22 = OpLoad %_arr_uint_uint_5 %21 -%23 = OpCompositeExtract %uint %22 0 -%24 = OpCompositeExtract %uint %22 1 -%25 = OpCompositeExtract %uint %22 2 -%26 = OpCompositeExtract %uint %22 3 -%27 = OpCompositeExtract %uint %22 4 -%28 = OpIAdd %uint %23 %24 -%29 = OpIAdd %uint %28 %25 -%30 = OpIAdd %uint %29 %26 -%31 = OpIAdd %uint %20 %27 -%32 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0 -OpStore %32 %31 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndCheck(test, test, true, false); -} - -TEST_F(ReduceLoadSizeTest, cbuffer_load_fully_used) { - // The result of the load (%22) is used in an instruction that uses the whole - // load and has only 1 in operand. This trigger issue #1559. - const std::string test = - R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource HLSL 600 -OpName %type_gBuffer "type.gBuffer" -OpMemberName %type_gBuffer 0 "a" -OpName %gBuffer "gBuffer" -OpName %S "S" -OpMemberName %S 0 "f" -OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S" -OpName %gRWSBuffer "gRWSBuffer" -OpName %main "main" -OpMemberDecorate %type_gBuffer 0 Offset 0 -OpDecorate %type_gBuffer Block -OpMemberDecorate %S 0 Offset 0 -OpDecorate %_runtimearr_S ArrayStride 4 -OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0 -OpDecorate %type_RWStructuredBuffer_S BufferBlock -OpDecorate %gBuffer DescriptorSet 0 -OpDecorate %gBuffer Binding 0 -OpDecorate %gRWSBuffer DescriptorSet 0 -OpDecorate %gRWSBuffer Binding 1 -%uint = OpTypeInt 32 0 -%uint_32 = OpConstant %uint 32 -%v4uint = OpTypeVector %uint 4 -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%type_gBuffer = OpTypeStruct %v4uint -%_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer -%S = OpTypeStruct %uint -%_runtimearr_S = OpTypeRuntimeArray %S -%type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S -%_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S -%int = OpTypeInt 32 1 -%void = OpTypeVoid -%15 = OpTypeFunction %void -%int_0 = OpConstant %int 0 -%_ptr_Uniform_v4uint = OpTypePointer Uniform %v4uint -%uint_0 = OpConstant %uint 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform -%gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform -%main = OpFunction %void None %15 -%20 = OpLabel -%21 = OpAccessChain %_ptr_Uniform_v4uint %gBuffer %int_0 -%22 = OpLoad %v4uint %21 -%23 = OpCompositeExtract %uint %22 1 -%24 = OpConvertUToF %v4float %22 -%25 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0 -OpStore %25 %23 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); - SinglePassRunAndCheck(test, test, true, false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/redundancy_elimination_test.cpp b/3rdparty/spirv-tools/test/opt/redundancy_elimination_test.cpp deleted file mode 100644 index 7d2abe846..000000000 --- a/3rdparty/spirv-tools/test/opt/redundancy_elimination_test.cpp +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/value_number_table.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; -using RedundancyEliminationTest = PassTest<::testing::Test>; - -// Test that it can get a simple case of local redundancy elimination. -// The rest of the test check for extra functionality. -TEST_F(RedundancyEliminationTest, RemoveRedundantLocalAdd) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 -; CHECK: OpFAdd -; CHECK-NOT: OpFAdd - %11 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -// Remove a redundant add across basic blocks. -TEST_F(RedundancyEliminationTest, RemoveRedundantAdd) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 - OpBranch %11 - %11 = OpLabel -; CHECK: OpFAdd -; CHECK-NOT: OpFAdd - %12 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - SinglePassRunAndMatch(text, false); -} - -// Remove a redundant add going through a multiple basic blocks. -TEST_F(RedundancyEliminationTest, RemoveRedundantAddDiamond) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpVariable %6 Function - %11 = OpLoad %5 %10 - %12 = OpFAdd %5 %11 %11 -; CHECK: OpFAdd -; CHECK-NOT: OpFAdd - OpBranchConditional %8 %13 %14 - %13 = OpLabel - OpBranch %15 - %14 = OpLabel - OpBranch %15 - %15 = OpLabel - %16 = OpFAdd %5 %11 %11 - OpReturn - OpFunctionEnd - - )"; - SinglePassRunAndMatch(text, false); -} - -// Remove a redundant add in a side node. -TEST_F(RedundancyEliminationTest, RemoveRedundantAddInSideNode) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpVariable %6 Function - %11 = OpLoad %5 %10 - %12 = OpFAdd %5 %11 %11 -; CHECK: OpFAdd -; CHECK-NOT: OpFAdd - OpBranchConditional %8 %13 %14 - %13 = OpLabel - OpBranch %15 - %14 = OpLabel - %16 = OpFAdd %5 %11 %11 - OpBranch %15 - %15 = OpLabel - OpReturn - OpFunctionEnd - - )"; - SinglePassRunAndMatch(text, false); -} - -// Remove a redundant add whose value is in the result of a phi node. -TEST_F(RedundancyEliminationTest, RemoveRedundantAddWithPhi) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpVariable %6 Function - %11 = OpLoad %5 %10 - OpBranchConditional %8 %13 %14 - %13 = OpLabel - %add1 = OpFAdd %5 %11 %11 -; CHECK: OpFAdd - OpBranch %15 - %14 = OpLabel - %add2 = OpFAdd %5 %11 %11 -; CHECK: OpFAdd - OpBranch %15 - %15 = OpLabel -; CHECK: OpPhi - %phi = OpPhi %5 %add1 %13 %add2 %14 -; CHECK-NOT: OpFAdd - %16 = OpFAdd %5 %11 %11 - OpReturn - OpFunctionEnd - - )"; - SinglePassRunAndMatch(text, false); -} - -// Keep the add because it is redundant on some paths, but not all paths. -TEST_F(RedundancyEliminationTest, KeepPartiallyRedundantAdd) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpVariable %6 Function - %11 = OpLoad %5 %10 - OpBranchConditional %8 %13 %14 - %13 = OpLabel - %add = OpFAdd %5 %11 %11 - OpBranch %15 - %14 = OpLabel - OpBranch %15 - %15 = OpLabel - %16 = OpFAdd %5 %11 %11 - OpReturn - OpFunctionEnd - - )"; - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// Keep the add. Even if it is redundant on all paths, there is no single id -// whose definition dominates the add and contains the same value. -TEST_F(RedundancyEliminationTest, KeepRedundantAddWithoutPhi) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpVariable %6 Function - %11 = OpLoad %5 %10 - OpBranchConditional %8 %13 %14 - %13 = OpLabel - %add1 = OpFAdd %5 %11 %11 - OpBranch %15 - %14 = OpLabel - %add2 = OpFAdd %5 %11 %11 - OpBranch %15 - %15 = OpLabel - %16 = OpFAdd %5 %11 %11 - OpReturn - OpFunctionEnd - - )"; - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/register_liveness.cpp b/3rdparty/spirv-tools/test/opt/register_liveness.cpp deleted file mode 100644 index 7cb210f1e..000000000 --- a/3rdparty/spirv-tools/test/opt/register_liveness.cpp +++ /dev/null @@ -1,1322 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/register_pressure.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using PassClassTest = PassTest<::testing::Test>; - -void CompareSets(const std::unordered_set& computed, - const std::unordered_set& expected) { - for (Instruction* insn : computed) { - EXPECT_TRUE(expected.count(insn->result_id())) - << "Unexpected instruction in live set: " << *insn; - } - EXPECT_EQ(computed.size(), expected.size()); -} - -/* -Generated from the following GLSL - -#version 330 -in vec4 BaseColor; -flat in int Count; -void main() -{ - vec4 color = BaseColor; - vec4 acc; - if (Count == 0) { - acc = color; - } - else { - acc = color + vec4(0,1,2,0); - } - gl_FragColor = acc + color; -} -*/ -TEST_F(PassClassTest, LivenessWithIf) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %11 %15 %32 - OpExecutionMode %4 OriginLowerLeft - OpSource GLSL 330 - OpName %4 "main" - OpName %11 "BaseColor" - OpName %15 "Count" - OpName %32 "gl_FragColor" - OpDecorate %11 Location 0 - OpDecorate %15 Flat - OpDecorate %15 Location 0 - OpDecorate %32 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %10 = OpTypePointer Input %7 - %11 = OpVariable %10 Input - %13 = OpTypeInt 32 1 - %14 = OpTypePointer Input %13 - %15 = OpVariable %14 Input - %17 = OpConstant %13 0 - %18 = OpTypeBool - %26 = OpConstant %6 0 - %27 = OpConstant %6 1 - %28 = OpConstant %6 2 - %29 = OpConstantComposite %7 %26 %27 %28 %26 - %31 = OpTypePointer Output %7 - %32 = OpVariable %31 Output - %4 = OpFunction %2 None %3 - %5 = OpLabel - %12 = OpLoad %7 %11 - %16 = OpLoad %13 %15 - %19 = OpIEqual %18 %16 %17 - OpSelectionMerge %21 None - OpBranchConditional %19 %20 %24 - %20 = OpLabel - OpBranch %21 - %24 = OpLabel - %30 = OpFAdd %7 %12 %29 - OpBranch %21 - %21 = OpLabel - %36 = OpPhi %7 %12 %20 %30 %24 - %35 = OpFAdd %7 %36 %12 - OpStore %32 %35 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function* f = &*module->begin(); - LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); - const RegisterLiveness* register_liveness = liveness_analysis->Get(f); - { - SCOPED_TRACE("Block 5"); - auto live_sets = register_liveness->Get(5); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 15, // %15 = OpVariable %14 Input - 32, // %32 = OpVariable %31 Output - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 12, // %12 = OpLoad %7 %11 - 32, // %32 = OpVariable %31 Output - }; - CompareSets(live_sets->live_out_, live_out); - } - { - SCOPED_TRACE("Block 20"); - auto live_sets = register_liveness->Get(20); - std::unordered_set live_inout{ - 12, // %12 = OpLoad %7 %11 - 32, // %32 = OpVariable %31 Output - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - } - { - SCOPED_TRACE("Block 24"); - auto live_sets = register_liveness->Get(24); - std::unordered_set live_in{ - 12, // %12 = OpLoad %7 %11 - 32, // %32 = OpVariable %31 Output - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 12, // %12 = OpLoad %7 %11 - 30, // %30 = OpFAdd %7 %12 %29 - 32, // %32 = OpVariable %31 Output - }; - CompareSets(live_sets->live_out_, live_out); - } - { - SCOPED_TRACE("Block 21"); - auto live_sets = register_liveness->Get(21); - std::unordered_set live_in{ - 12, // %12 = OpLoad %7 %11 - 32, // %32 = OpVariable %31 Output - 36, // %36 = OpPhi %7 %12 %20 %30 %24 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{}; - CompareSets(live_sets->live_out_, live_out); - } -} - -/* -Generated from the following GLSL -#version 330 -in vec4 bigColor; -in vec4 BaseColor; -in float f; -flat in int Count; -flat in uvec4 v4; -void main() -{ - vec4 color = BaseColor; - for (int i = 0; i < Count; ++i) - color += bigColor; - float sum = 0.0; - for (int i = 0; i < 4; ++i) { - float acc = 0.0; - if (sum == 0.0) { - acc = v4[i]; - } - else { - acc = BaseColor[i]; - } - sum += acc + v4[i]; - } - vec4 tv4; - for (int i = 0; i < 4; ++i) - tv4[i] = v4[i] * 4u; - color += vec4(sum) + tv4; - vec4 r; - r.xyz = BaseColor.xyz; - for (int i = 0; i < Count; ++i) - r.w = f; - color.xyz += r.xyz; - for (int i = 0; i < 16; i += 4) - for (int j = 0; j < 4; j++) - color *= f; - gl_FragColor = color + tv4; -} -*/ -TEST_F(PassClassTest, RegisterLiveness) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %11 %24 %28 %55 %124 %176 - OpExecutionMode %4 OriginLowerLeft - OpSource GLSL 330 - OpName %4 "main" - OpName %11 "BaseColor" - OpName %24 "Count" - OpName %28 "bigColor" - OpName %55 "v4" - OpName %84 "tv4" - OpName %124 "f" - OpName %176 "gl_FragColor" - OpDecorate %11 Location 0 - OpDecorate %24 Flat - OpDecorate %24 Location 0 - OpDecorate %28 Location 0 - OpDecorate %55 Flat - OpDecorate %55 Location 0 - OpDecorate %124 Location 0 - OpDecorate %176 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Function %7 - %10 = OpTypePointer Input %7 - %11 = OpVariable %10 Input - %13 = OpTypeInt 32 1 - %16 = OpConstant %13 0 - %23 = OpTypePointer Input %13 - %24 = OpVariable %23 Input - %26 = OpTypeBool - %28 = OpVariable %10 Input - %33 = OpConstant %13 1 - %35 = OpTypePointer Function %6 - %37 = OpConstant %6 0 - %45 = OpConstant %13 4 - %52 = OpTypeInt 32 0 - %53 = OpTypeVector %52 4 - %54 = OpTypePointer Input %53 - %55 = OpVariable %54 Input - %57 = OpTypePointer Input %52 - %63 = OpTypePointer Input %6 - %89 = OpConstant %52 4 - %102 = OpTypeVector %6 3 - %124 = OpVariable %63 Input - %158 = OpConstant %13 16 - %175 = OpTypePointer Output %7 - %176 = OpVariable %175 Output - %195 = OpUndef %7 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %84 = OpVariable %8 Function - %12 = OpLoad %7 %11 - OpBranch %17 - %17 = OpLabel - %191 = OpPhi %7 %12 %5 %31 %18 - %184 = OpPhi %13 %16 %5 %34 %18 - %25 = OpLoad %13 %24 - %27 = OpSLessThan %26 %184 %25 - OpLoopMerge %19 %18 None - OpBranchConditional %27 %18 %19 - %18 = OpLabel - %29 = OpLoad %7 %28 - %31 = OpFAdd %7 %191 %29 - %34 = OpIAdd %13 %184 %33 - OpBranch %17 - %19 = OpLabel - OpBranch %39 - %39 = OpLabel - %188 = OpPhi %6 %37 %19 %73 %51 - %185 = OpPhi %13 %16 %19 %75 %51 - %46 = OpSLessThan %26 %185 %45 - OpLoopMerge %41 %51 None - OpBranchConditional %46 %40 %41 - %40 = OpLabel - %49 = OpFOrdEqual %26 %188 %37 - OpSelectionMerge %51 None - OpBranchConditional %49 %50 %61 - %50 = OpLabel - %58 = OpAccessChain %57 %55 %185 - %59 = OpLoad %52 %58 - %60 = OpConvertUToF %6 %59 - OpBranch %51 - %61 = OpLabel - %64 = OpAccessChain %63 %11 %185 - %65 = OpLoad %6 %64 - OpBranch %51 - %51 = OpLabel - %210 = OpPhi %6 %60 %50 %65 %61 - %68 = OpAccessChain %57 %55 %185 - %69 = OpLoad %52 %68 - %70 = OpConvertUToF %6 %69 - %71 = OpFAdd %6 %210 %70 - %73 = OpFAdd %6 %188 %71 - %75 = OpIAdd %13 %185 %33 - OpBranch %39 - %41 = OpLabel - OpBranch %77 - %77 = OpLabel - %186 = OpPhi %13 %16 %41 %94 %78 - %83 = OpSLessThan %26 %186 %45 - OpLoopMerge %79 %78 None - OpBranchConditional %83 %78 %79 - %78 = OpLabel - %87 = OpAccessChain %57 %55 %186 - %88 = OpLoad %52 %87 - %90 = OpIMul %52 %88 %89 - %91 = OpConvertUToF %6 %90 - %92 = OpAccessChain %35 %84 %186 - OpStore %92 %91 - %94 = OpIAdd %13 %186 %33 - OpBranch %77 - %79 = OpLabel - %96 = OpCompositeConstruct %7 %188 %188 %188 %188 - %97 = OpLoad %7 %84 - %98 = OpFAdd %7 %96 %97 - %100 = OpFAdd %7 %191 %98 - %104 = OpVectorShuffle %102 %12 %12 0 1 2 - %106 = OpVectorShuffle %7 %195 %104 4 5 6 3 - OpBranch %108 - %108 = OpLabel - %197 = OpPhi %7 %106 %79 %208 %133 - %196 = OpPhi %13 %16 %79 %143 %133 - %115 = OpSLessThan %26 %196 %25 - OpLoopMerge %110 %133 None - OpBranchConditional %115 %109 %110 - %109 = OpLabel - OpBranch %117 - %117 = OpLabel - %209 = OpPhi %7 %197 %109 %181 %118 - %204 = OpPhi %13 %16 %109 %129 %118 - %123 = OpSLessThan %26 %204 %45 - OpLoopMerge %119 %118 None - OpBranchConditional %123 %118 %119 - %118 = OpLabel - %125 = OpLoad %6 %124 - %181 = OpCompositeInsert %7 %125 %209 3 - %129 = OpIAdd %13 %204 %33 - OpBranch %117 - %119 = OpLabel - OpBranch %131 - %131 = OpLabel - %208 = OpPhi %7 %209 %119 %183 %132 - %205 = OpPhi %13 %16 %119 %141 %132 - %137 = OpSLessThan %26 %205 %45 - OpLoopMerge %133 %132 None - OpBranchConditional %137 %132 %133 - %132 = OpLabel - %138 = OpLoad %6 %124 - %183 = OpCompositeInsert %7 %138 %208 3 - %141 = OpIAdd %13 %205 %33 - OpBranch %131 - %133 = OpLabel - %143 = OpIAdd %13 %196 %33 - OpBranch %108 - %110 = OpLabel - %145 = OpVectorShuffle %102 %197 %197 0 1 2 - %147 = OpVectorShuffle %102 %100 %100 0 1 2 - %148 = OpFAdd %102 %147 %145 - %150 = OpVectorShuffle %7 %100 %148 4 5 6 3 - OpBranch %152 - %152 = OpLabel - %200 = OpPhi %7 %150 %110 %203 %163 - %199 = OpPhi %13 %16 %110 %174 %163 - %159 = OpSLessThan %26 %199 %158 - OpLoopMerge %154 %163 None - OpBranchConditional %159 %153 %154 - %153 = OpLabel - OpBranch %161 - %161 = OpLabel - %203 = OpPhi %7 %200 %153 %170 %162 - %201 = OpPhi %13 %16 %153 %172 %162 - %167 = OpSLessThan %26 %201 %45 - OpLoopMerge %163 %162 None - OpBranchConditional %167 %162 %163 - %162 = OpLabel - %168 = OpLoad %6 %124 - %170 = OpVectorTimesScalar %7 %203 %168 - %172 = OpIAdd %13 %201 %33 - OpBranch %161 - %163 = OpLabel - %174 = OpIAdd %13 %199 %45 - OpBranch %152 - %154 = OpLabel - %178 = OpLoad %7 %84 - %179 = OpFAdd %7 %200 %178 - OpStore %176 %179 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function* f = &*module->begin(); - LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); - const RegisterLiveness* register_liveness = liveness_analysis->Get(f); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - - { - SCOPED_TRACE("Block 5"); - auto live_sets = register_liveness->Get(5); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 24, // %24 = OpVariable %23 Input - 28, // %28 = OpVariable %10 Input - 55, // %55 = OpVariable %54 Input - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 24, // %24 = OpVariable %23 Input - 28, // %28 = OpVariable %10 Input - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 8u); - } - { - SCOPED_TRACE("Block 17"); - auto live_sets = register_liveness->Get(17); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 24, // %24 = OpVariable %23 Input - 28, // %28 = OpVariable %10 Input - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 184, // %184 = OpPhi %13 %16 %5 %34 %18 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 28, // %28 = OpVariable %10 Input - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 184, // %184 = OpPhi %13 %16 %5 %34 %18 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 11u); - } - { - SCOPED_TRACE("Block 18"); - auto live_sets = register_liveness->Get(18); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 24, // %24 = OpVariable %23 Input - 28, // %28 = OpVariable %10 Input - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 184, // %184 = OpPhi %13 %16 %5 %34 %18 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 24, // %24 = OpVariable %23 Input - 28, // %28 = OpVariable %10 Input - 31, // %31 = OpFAdd %7 %191 %29 - 34, // %34 = OpIAdd %13 %184 %33 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 12u); - } - { - SCOPED_TRACE("Block 19"); - auto live_sets = register_liveness->Get(19); - std::unordered_set live_inout{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 8u); - } - { - SCOPED_TRACE("Block 39"); - auto live_sets = register_liveness->Get(39); - std::unordered_set live_inout{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 11u); - } - { - SCOPED_TRACE("Block 40"); - auto live_sets = register_liveness->Get(40); - std::unordered_set live_inout{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 11u); - } - { - SCOPED_TRACE("Block 50"); - auto live_sets = register_liveness->Get(50); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 60, // %60 = OpConvertUToF %6 %59 - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 12u); - } - { - SCOPED_TRACE("Block 61"); - auto live_sets = register_liveness->Get(61); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 65, // %65 = OpLoad %6 %64 - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 12u); - } - { - SCOPED_TRACE("Block 51"); - auto live_sets = register_liveness->Get(51); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - 210, // %210 = OpPhi %6 %60 %50 %65 %61 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 73, // %73 = OpFAdd %6 %188 %71 - 75, // %75 = OpIAdd %13 %185 %33 - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 13u); - } - { - SCOPED_TRACE("Block 41"); - auto live_sets = register_liveness->Get(41); - std::unordered_set live_inout{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 8u); - } - { - SCOPED_TRACE("Block 77"); - auto live_sets = register_liveness->Get(77); - std::unordered_set live_inout{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 186, // %186 = OpPhi %13 %16 %41 %94 %78 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 10u); - } - { - SCOPED_TRACE("Block 78"); - auto live_sets = register_liveness->Get(78); - std::unordered_set live_in{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 186, // %186 = OpPhi %13 %16 %41 %94 %78 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 94, // %94 = OpIAdd %13 %186 %33 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 11u); - } - { - SCOPED_TRACE("Block 79"); - auto live_sets = register_liveness->Get(79); - std::unordered_set live_in{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 106, // %106 = OpVectorShuffle %7 %195 %104 4 5 6 3 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 9u); - } - { - SCOPED_TRACE("Block 108"); - auto live_sets = register_liveness->Get(108); - std::unordered_set live_in{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 197, // %197 = OpPhi %7 %106 %79 %208 %133 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 197, // %197 = OpPhi %7 %106 %79 %208 %133 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 8u); - } - { - SCOPED_TRACE("Block 109"); - auto live_sets = register_liveness->Get(109); - std::unordered_set live_inout{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 197, // %197 = OpPhi %7 %106 %79 %208 %133 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 7u); - } - { - SCOPED_TRACE("Block 117"); - auto live_sets = register_liveness->Get(117); - std::unordered_set live_inout{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 204, // %204 = OpPhi %13 %16 %109 %129 %118 - 209, // %209 = OpPhi %7 %197 %109 %181 %118 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 9u); - } - { - SCOPED_TRACE("Block 118"); - auto live_sets = register_liveness->Get(118); - std::unordered_set live_in{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 204, // %204 = OpPhi %13 %16 %109 %129 %118 - 209, // %209 = OpPhi %7 %197 %109 %181 %118 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 129, // %129 = OpIAdd %13 %204 %33 - 176, // %176 = OpVariable %175 Output - 181, // %181 = OpCompositeInsert %7 %125 %209 3 - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 10u); - } - { - SCOPED_TRACE("Block 119"); - auto live_sets = register_liveness->Get(119); - std::unordered_set live_inout{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 209, // %209 = OpPhi %7 %197 %109 %181 %118 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 7u); - } - { - SCOPED_TRACE("Block 131"); - auto live_sets = register_liveness->Get(131); - std::unordered_set live_inout{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 205, // %205 = OpPhi %13 %16 %119 %141 %132 - 208, // %208 = OpPhi %7 %209 %119 %183 %132 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 9u); - } - { - SCOPED_TRACE("Block 132"); - auto live_sets = register_liveness->Get(132); - std::unordered_set live_in{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 205, // %205 = OpPhi %13 %16 %119 %141 %132 - 208, // %208 = OpPhi %7 %209 %119 %183 %132 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 141, // %141 = OpIAdd %13 %205 %33 - 176, // %176 = OpVariable %175 Output - 183, // %183 = OpCompositeInsert %7 %138 %208 3 - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 10u); - } - { - SCOPED_TRACE("Block 133"); - auto live_sets = register_liveness->Get(133); - std::unordered_set live_in{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 196, // %196 = OpPhi %13 %16 %79 %143 %133 - 208, // %208 = OpPhi %7 %209 %119 %183 %132 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 25, // %25 = OpLoad %13 %24 - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 143, // %143 = OpIAdd %13 %196 %33 - 176, // %176 = OpVariable %175 Output - 208, // %208 = OpPhi %7 %209 %119 %183 %132 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 8u); - } - { - SCOPED_TRACE("Block 110"); - auto live_sets = register_liveness->Get(110); - std::unordered_set live_in{ - 84, // %84 = OpVariable %8 Function - 100, // %100 = OpFAdd %7 %191 %98 - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 197, // %197 = OpPhi %7 %106 %79 %208 %133 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 150, // %150 = OpVectorShuffle %7 %100 %148 4 5 6 3 - 176, // %176 = OpVariable %175 Output - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 7u); - } - { - SCOPED_TRACE("Block 152"); - auto live_sets = register_liveness->Get(152); - std::unordered_set live_inout{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 199, // %199 = OpPhi %13 %16 %110 %174 %163 - 200, // %200 = OpPhi %7 %150 %110 %203 %163 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 6u); - } - { - SCOPED_TRACE("Block 153"); - auto live_sets = register_liveness->Get(153); - std::unordered_set live_inout{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 199, // %199 = OpPhi %13 %16 %110 %174 %163 - 200, // %200 = OpPhi %7 %150 %110 %203 %163 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 5u); - } - { - SCOPED_TRACE("Block 161"); - auto live_sets = register_liveness->Get(161); - std::unordered_set live_inout{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 199, // %199 = OpPhi %13 %16 %110 %174 %163 - 201, // %201 = OpPhi %13 %16 %153 %172 %162 - 203, // %203 = OpPhi %7 %200 %153 %170 %162 - }; - CompareSets(live_sets->live_in_, live_inout); - CompareSets(live_sets->live_out_, live_inout); - - EXPECT_EQ(live_sets->used_registers_, 7u); - } - { - SCOPED_TRACE("Block 162"); - auto live_sets = register_liveness->Get(162); - std::unordered_set live_in{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 199, // %199 = OpPhi %13 %16 %110 %174 %163 - 201, // %201 = OpPhi %13 %16 %153 %172 %162 - 203, // %203 = OpPhi %7 %200 %153 %170 %162 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 170, // %170 = OpVectorTimesScalar %7 %203 %168 - 172, // %172 = OpIAdd %13 %201 %33 - 176, // %176 = OpVariable %175 Output - 199, // %199 = OpPhi %13 %16 %110 %174 %163 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 8u); - } - { - SCOPED_TRACE("Block 163"); - auto live_sets = register_liveness->Get(163); - std::unordered_set live_in{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 199, // %199 = OpPhi %13 %16 %110 %174 %163 - 203, // %203 = OpPhi %7 %200 %153 %170 %162 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{ - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 174, // %174 = OpIAdd %13 %199 %45 - 176, // %176 = OpVariable %175 Output - 203, // %203 = OpPhi %7 %200 %153 %170 %162 - }; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 6u); - } - { - SCOPED_TRACE("Block 154"); - auto live_sets = register_liveness->Get(154); - std::unordered_set live_in{ - 84, // %84 = OpVariable %8 Function - 176, // %176 = OpVariable %175 Output - 200, // %200 = OpPhi %7 %150 %110 %203 %163 - }; - CompareSets(live_sets->live_in_, live_in); - - std::unordered_set live_out{}; - CompareSets(live_sets->live_out_, live_out); - - EXPECT_EQ(live_sets->used_registers_, 4u); - } - - { - SCOPED_TRACE("Compute loop pressure"); - RegisterLiveness::RegionRegisterLiveness loop_reg_pressure; - register_liveness->ComputeLoopRegisterPressure(*ld[39], &loop_reg_pressure); - // Generate(*context->cfg()->block(39), &loop_reg_pressure); - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(loop_reg_pressure.live_in_, live_in); - - std::unordered_set live_out{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(loop_reg_pressure.live_out_, live_out); - - EXPECT_EQ(loop_reg_pressure.used_registers_, 13u); - } - - { - SCOPED_TRACE("Loop Fusion simulation"); - RegisterLiveness::RegionRegisterLiveness simulation_resut; - register_liveness->SimulateFusion(*ld[17], *ld[39], &simulation_resut); - - std::unordered_set live_in{ - 11, // %11 = OpVariable %10 Input - 12, // %12 = OpLoad %7 %11 - 24, // %24 = OpVariable %23 Input - 25, // %25 = OpLoad %13 %24 - 28, // %28 = OpVariable %10 Input - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 184, // %184 = OpPhi %13 %16 %5 %34 %18 - 185, // %185 = OpPhi %13 %16 %19 %75 %51 - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(simulation_resut.live_in_, live_in); - - std::unordered_set live_out{ - 12, // %12 = OpLoad %7 %11 - 25, // %25 = OpLoad %13 %24 - 55, // %55 = OpVariable %54 Input - 84, // %84 = OpVariable %8 Function - 124, // %124 = OpVariable %63 Input - 176, // %176 = OpVariable %175 Output - 188, // %188 = OpPhi %6 %37 %19 %73 %51 - 191, // %191 = OpPhi %7 %12 %5 %31 %18 - }; - CompareSets(simulation_resut.live_out_, live_out); - - EXPECT_EQ(simulation_resut.used_registers_, 17u); - } -} - -TEST_F(PassClassTest, FissionSimulation) { - const std::string source = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "i" - OpName %4 "A" - OpName %5 "B" - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Function %16 - %18 = OpTypePointer Function %13 - %19 = OpConstant %8 1 - %2 = OpFunction %6 None %7 - %20 = OpLabel - %3 = OpVariable %9 Function - %4 = OpVariable %17 Function - %5 = OpVariable %17 Function - OpBranch %21 - %21 = OpLabel - %22 = OpPhi %8 %10 %20 %23 %24 - OpLoopMerge %25 %24 None - OpBranch %26 - %26 = OpLabel - %27 = OpSLessThan %12 %22 %11 - OpBranchConditional %27 %28 %25 - %28 = OpLabel - %29 = OpAccessChain %18 %5 %22 - %30 = OpLoad %13 %29 - %31 = OpAccessChain %18 %4 %22 - OpStore %31 %30 - %32 = OpAccessChain %18 %4 %22 - %33 = OpLoad %13 %32 - %34 = OpAccessChain %18 %5 %22 - OpStore %34 %33 - OpBranch %24 - %24 = OpLabel - %23 = OpIAdd %8 %22 %19 - OpBranch %21 - %25 = OpLabel - OpStore %3 %22 - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << source << std::endl; - Function* f = &*module->begin(); - LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); - const RegisterLiveness* register_liveness = liveness_analysis->Get(f); - LoopDescriptor& ld = *context->GetLoopDescriptor(f); - analysis::DefUseManager& def_use_mgr = *context->get_def_use_mgr(); - - { - RegisterLiveness::RegionRegisterLiveness l1_sim_resut; - RegisterLiveness::RegionRegisterLiveness l2_sim_resut; - std::unordered_set moved_instructions{ - def_use_mgr.GetDef(29), def_use_mgr.GetDef(30), def_use_mgr.GetDef(31), - def_use_mgr.GetDef(31)->NextNode()}; - std::unordered_set copied_instructions{ - def_use_mgr.GetDef(22), def_use_mgr.GetDef(27), - def_use_mgr.GetDef(27)->NextNode(), def_use_mgr.GetDef(23)}; - - register_liveness->SimulateFission(*ld[21], moved_instructions, - copied_instructions, &l1_sim_resut, - &l2_sim_resut); - { - SCOPED_TRACE("L1 simulation"); - std::unordered_set live_in{ - 3, // %3 = OpVariable %9 Function - 4, // %4 = OpVariable %17 Function - 5, // %5 = OpVariable %17 Function - 22, // %22 = OpPhi %8 %10 %20 %23 %24 - }; - CompareSets(l1_sim_resut.live_in_, live_in); - - std::unordered_set live_out{ - 3, // %3 = OpVariable %9 Function - 4, // %4 = OpVariable %17 Function - 5, // %5 = OpVariable %17 Function - 22, // %22 = OpPhi %8 %10 %20 %23 %24 - }; - CompareSets(l1_sim_resut.live_out_, live_out); - - EXPECT_EQ(l1_sim_resut.used_registers_, 6u); - } - { - SCOPED_TRACE("L2 simulation"); - std::unordered_set live_in{ - 3, // %3 = OpVariable %9 Function - 4, // %4 = OpVariable %17 Function - 5, // %5 = OpVariable %17 Function - 22, // %22 = OpPhi %8 %10 %20 %23 %24 - }; - CompareSets(l2_sim_resut.live_in_, live_in); - - std::unordered_set live_out{ - 3, // %3 = OpVariable %9 Function - 22, // %22 = OpPhi %8 %10 %20 %23 %24 - }; - CompareSets(l2_sim_resut.live_out_, live_out); - - EXPECT_EQ(l2_sim_resut.used_registers_, 6u); - } - } -} - -// Test that register liveness does not fail when there is an unreachable block. -// We are not testing if the liveness is computed correctly because the specific -// results do not matter for unreachable blocks. -TEST_F(PassClassTest, RegisterLivenessWithUnreachableBlock) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginLowerLeft - OpSource GLSL 330 - OpSourceExtension "GL_ARB_shading_language_420pack" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %2 = OpFunction %void None %4 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %7 %8 None - OpBranch %9 - %9 = OpLabel - OpBranch %7 - %8 = OpLabel - OpBranch %6 - %7 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - Function* f = &*module->begin(); - LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); - liveness_analysis->Get(f); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/relax_float_ops_test.cpp b/3rdparty/spirv-tools/test/opt/relax_float_ops_test.cpp deleted file mode 100644 index 14cde0b94..000000000 --- a/3rdparty/spirv-tools/test/opt/relax_float_ops_test.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2019 Valve Corporation -// Copyright (c) 2019 LunarG 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. - -// Relax float ops tests - -#include -#include - -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using RelaxFloatOpsTest = PassTest<::testing::Test>; - -TEST_F(RelaxFloatOpsTest, RelaxFloatOpsBasic) { - // All float result instructions in functions should be relaxed - // clang-format off - // - // SamplerState g_sSamp : register(s0); - // uniform Texture1D g_tTex1df4 : register(t0); - // - // struct PS_INPUT - // { - // float Tex0 : TEXCOORD0; - // float Tex1 : TEXCOORD1; - // }; - // - // struct PS_OUTPUT - // { - // float4 Color : SV_Target0; - // }; - // - // PS_OUTPUT main(PS_INPUT i) - // { - // PS_OUTPUT psout; - // float4 txval10 = g_tTex1df4.Sample(g_sSamp, i.Tex0); - // float4 txval11 = g_tTex1df4.Sample(g_sSamp, i.Tex1); - // float4 t = txval10 + txval11; - // float4 t2 = t / 2.0; - // psout.Color = t2; - // return psout; - // } - // clang-format on - - const std::string defs0 = - R"(OpCapability Shader -OpCapability Sampled1D -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpName %main "main" -OpName %g_tTex1df4 "g_tTex1df4" -OpName %g_sSamp "g_sSamp" -OpName %i_Tex0 "i.Tex0" -OpName %i_Tex1 "i.Tex1" -OpName %_entryPointOutput_Color "@entryPointOutput.Color" -OpDecorate %g_tTex1df4 DescriptorSet 0 -OpDecorate %g_tTex1df4 Binding 0 -OpDecorate %g_sSamp DescriptorSet 0 -OpDecorate %g_sSamp Binding 0 -OpDecorate %i_Tex0 Location 0 -OpDecorate %i_Tex1 Location 1 -OpDecorate %_entryPointOutput_Color Location 0 -)"; - - const std::string defs1 = - R"(%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%17 = OpTypeImage %float 1D 0 0 0 1 Unknown -%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 -%g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant -%21 = OpTypeSampler -%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 -%g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant -%25 = OpTypeSampledImage %17 -%_ptr_Input_float = OpTypePointer Input %float -%i_Tex0 = OpVariable %_ptr_Input_float Input -%i_Tex1 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output -%float_0_5 = OpConstant %float 0.5 -%116 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 -)"; - - const std::string relax_decos = - R"(OpDecorate %60 RelaxedPrecision -OpDecorate %63 RelaxedPrecision -OpDecorate %82 RelaxedPrecision -OpDecorate %88 RelaxedPrecision -OpDecorate %91 RelaxedPrecision -OpDecorate %94 RelaxedPrecision -)"; - - const std::string func_orig = - R"(%main = OpFunction %void None %3 -%5 = OpLabel -%60 = OpLoad %float %i_Tex0 -%63 = OpLoad %float %i_Tex1 -%77 = OpLoad %17 %g_tTex1df4 -%78 = OpLoad %21 %g_sSamp -%79 = OpSampledImage %25 %77 %78 -%82 = OpImageSampleImplicitLod %v4float %79 %60 -%83 = OpLoad %17 %g_tTex1df4 -%84 = OpLoad %21 %g_sSamp -%85 = OpSampledImage %25 %83 %84 -%88 = OpImageSampleImplicitLod %v4float %85 %63 -%91 = OpFAdd %v4float %82 %88 -%94 = OpFMul %v4float %91 %116 -OpStore %_entryPointOutput_Color %94 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - defs0 + defs1 + func_orig, defs0 + relax_decos + defs1 + func_orig, true, - true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/replace_invalid_opc_test.cpp b/3rdparty/spirv-tools/test/opt/replace_invalid_opc_test.cpp deleted file mode 100644 index 1be904b4e..000000000 --- a/3rdparty/spirv-tools/test/opt/replace_invalid_opc_test.cpp +++ /dev/null @@ -1,566 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "pass_utils.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ReplaceInvalidOpcodeTest = PassTest<::testing::Test>; - -TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstruction) { - const std::string text = R"( -; CHECK: [[special_const:%\w+]] = OpConstant %float -6.2598534e+18 -; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]] -; CHECK-NOT: OpImageSampleImplicitLod -; CHECK: OpStore [[:%\w+]] [[constant]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_6 0 BuiltIn Position - OpDecorate %_struct_6 Block - %void = OpTypeVoid - %8 = OpTypeFunction %void - %float = OpTypeFloat 32 - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampler -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 - %14 = OpTypeSampledImage %10 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_6 = OpTypeStruct %v4float -%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6 - %5 = OpVariable %_ptr_Output__struct_6 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %23 = OpConstantComposite %v2float %float_0 %float_0 - %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant - %main = OpFunction %void None %8 - %26 = OpLabel - %27 = OpLoad %12 %25 - %28 = OpLoad %10 %24 - %29 = OpSampledImage %14 %28 %27 - %30 = OpImageSampleImplicitLod %v4float %29 %23 - %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %31 %30 - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstructionInNonEntryPoint) { - const std::string text = R"( -; CHECK: [[special_const:%\w+]] = OpConstant %float -6.2598534e+18 -; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]] -; CHECK-NOT: OpImageSampleImplicitLod -; CHECK: OpStore [[:%\w+]] [[constant]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_6 0 BuiltIn Position - OpDecorate %_struct_6 Block - %void = OpTypeVoid - %8 = OpTypeFunction %void - %float = OpTypeFloat 32 - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampler -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 - %14 = OpTypeSampledImage %10 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_6 = OpTypeStruct %v4float -%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6 - %5 = OpVariable %_ptr_Output__struct_6 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %23 = OpConstantComposite %v2float %float_0 %float_0 - %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant - %main = OpFunction %void None %8 - %26 = OpLabel - %27 = OpFunctionCall %void %28 - OpReturn - OpFunctionEnd - %28 = OpFunction %void None %8 - %29 = OpLabel - %30 = OpLoad %12 %25 - %31 = OpLoad %10 %24 - %32 = OpSampledImage %14 %31 %30 - %33 = OpImageSampleImplicitLod %v4float %32 %23 - %34 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %34 %33 - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstructionMultipleEntryPoints) { - const std::string text = R"( -; CHECK: [[special_const:%\w+]] = OpConstant %float -6.2598534e+18 -; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]] -; CHECK-NOT: OpImageSampleImplicitLod -; CHECK: OpStore [[:%\w+]] [[constant]] -; CHECK-NOT: OpImageSampleImplicitLod -; CHECK: OpStore [[:%\w+]] [[constant]] - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpEntryPoint Vertex %main2 "main2" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %main2 "main2" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_6 0 BuiltIn Position - OpDecorate %_struct_6 Block - %void = OpTypeVoid - %8 = OpTypeFunction %void - %float = OpTypeFloat 32 - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampler -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 - %14 = OpTypeSampledImage %10 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_6 = OpTypeStruct %v4float -%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6 - %5 = OpVariable %_ptr_Output__struct_6 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %23 = OpConstantComposite %v2float %float_0 %float_0 - %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant - %main = OpFunction %void None %8 - %26 = OpLabel - %27 = OpLoad %12 %25 - %28 = OpLoad %10 %24 - %29 = OpSampledImage %14 %28 %27 - %30 = OpImageSampleImplicitLod %v4float %29 %23 - %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %31 %30 - OpReturn - OpFunctionEnd - %main2 = OpFunction %void None %8 - %46 = OpLabel - %47 = OpLoad %12 %25 - %48 = OpLoad %10 %24 - %49 = OpSampledImage %14 %48 %47 - %50 = OpImageSampleImplicitLod %v4float %49 %23 - %51 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %51 %50 - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} -TEST_F(ReplaceInvalidOpcodeTest, DontReplaceInstruction) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_6 0 BuiltIn Position - OpDecorate %_struct_6 Block - %void = OpTypeVoid - %8 = OpTypeFunction %void - %float = OpTypeFloat 32 - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampler -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 - %14 = OpTypeSampledImage %10 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_6 = OpTypeStruct %v4float -%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6 - %5 = OpVariable %_ptr_Output__struct_6 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %23 = OpConstantComposite %v2float %float_0 %float_0 - %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant - %main = OpFunction %void None %8 - %26 = OpLabel - %27 = OpLoad %12 %25 - %28 = OpLoad %10 %24 - %29 = OpSampledImage %14 %28 %27 - %30 = OpImageSampleImplicitLod %v4float %29 %23 - %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %31 %30 - OpReturn - OpFunctionEnd)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(ReplaceInvalidOpcodeTest, MultipleEntryPointsDifferentStage) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpEntryPoint Fragment %main2 "main2" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %main2 "main2" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_6 0 BuiltIn Position - OpDecorate %_struct_6 Block - %void = OpTypeVoid - %8 = OpTypeFunction %void - %float = OpTypeFloat 32 - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampler -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 - %14 = OpTypeSampledImage %10 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_6 = OpTypeStruct %v4float -%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6 - %5 = OpVariable %_ptr_Output__struct_6 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %23 = OpConstantComposite %v2float %float_0 %float_0 - %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant - %main = OpFunction %void None %8 - %26 = OpLabel - %27 = OpLoad %12 %25 - %28 = OpLoad %10 %24 - %29 = OpSampledImage %14 %28 %27 - %30 = OpImageSampleImplicitLod %v4float %29 %23 - %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %31 %30 - OpReturn - OpFunctionEnd - %main2 = OpFunction %void None %8 - %46 = OpLabel - %47 = OpLoad %12 %25 - %48 = OpLoad %10 %24 - %49 = OpSampledImage %14 %48 %47 - %50 = OpImageSampleImplicitLod %v4float %49 %23 - %51 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %51 %50 - OpReturn - OpFunctionEnd)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(ReplaceInvalidOpcodeTest, DontReplaceLinkage) { - const std::string text = R"( - OpCapability Shader - OpCapability Linkage - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_6 0 BuiltIn Position - OpDecorate %_struct_6 Block - %void = OpTypeVoid - %8 = OpTypeFunction %void - %float = OpTypeFloat 32 - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampler -%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 - %14 = OpTypeSampledImage %10 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_6 = OpTypeStruct %v4float -%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6 - %5 = OpVariable %_ptr_Output__struct_6 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %23 = OpConstantComposite %v2float %float_0 %float_0 - %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant - %main = OpFunction %void None %8 - %26 = OpLabel - %27 = OpLoad %12 %25 - %28 = OpLoad %10 %24 - %29 = OpSampledImage %14 %28 %27 - %30 = OpImageSampleImplicitLod %v4float %29 %23 - %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %31 %30 - OpReturn - OpFunctionEnd)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(ReplaceInvalidOpcodeTest, BarrierDontReplace) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 450 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%uint_264 = OpConstant %uint 264 - %main = OpFunction %void None %3 - %5 = OpLabel - OpControlBarrier %uint_2 %uint_2 %uint_264 - OpReturn - OpFunctionEnd)"; - - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(ReplaceInvalidOpcodeTest, BarrierReplace) { - const std::string text = R"( -; CHECK-NOT: OpControlBarrier - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 450 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%uint_264 = OpConstant %uint 264 - %main = OpFunction %void None %3 - %5 = OpLabel - OpControlBarrier %uint_2 %uint_2 %uint_264 - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(ReplaceInvalidOpcodeTest, MessageTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - %6 = OpString "test.hlsl" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_7 0 BuiltIn Position - OpDecorate %_struct_7 Block - %void = OpTypeVoid - %9 = OpTypeFunction %void - %float = OpTypeFloat 32 - %11 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 - %13 = OpTypeSampler -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 - %15 = OpTypeSampledImage %11 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_7 = OpTypeStruct %v4float -%_ptr_Output__struct_7 = OpTypePointer Output %_struct_7 - %5 = OpVariable %_ptr_Output__struct_7 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %24 = OpConstantComposite %v2float %float_0 %float_0 - %25 = OpVariable %_ptr_UniformConstant_11 UniformConstant - %26 = OpVariable %_ptr_UniformConstant_13 UniformConstant - %main = OpFunction %void None %9 - %27 = OpLabel - OpLine %6 2 4 - %28 = OpLoad %13 %26 - %29 = OpLoad %11 %25 - %30 = OpSampledImage %15 %29 %28 - %31 = OpImageSampleImplicitLod %v4float %30 %24 - %32 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %32 %31 - OpReturn - OpFunctionEnd)"; - - std::vector messages = { - {SPV_MSG_WARNING, "test.hlsl", 2, 4, - "Removing ImageSampleImplicitLod instruction because of incompatible " - "execution model."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); -} - -TEST_F(ReplaceInvalidOpcodeTest, MultipleMessageTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5 - OpSource GLSL 400 - %6 = OpString "test.hlsl" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpDecorate %3 Location 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %_struct_7 0 BuiltIn Position - OpDecorate %_struct_7 Block - %void = OpTypeVoid - %9 = OpTypeFunction %void - %float = OpTypeFloat 32 - %11 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 - %13 = OpTypeSampler -%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 - %15 = OpTypeSampledImage %11 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %3 = OpVariable %_ptr_Output_v4float Output - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input - %_struct_7 = OpTypeStruct %v4float -%_ptr_Output__struct_7 = OpTypePointer Output %_struct_7 - %5 = OpVariable %_ptr_Output__struct_7 Output - %int_0 = OpConstant %int 0 - %float_0 = OpConstant %float 0 - %24 = OpConstantComposite %v2float %float_0 %float_0 - %25 = OpVariable %_ptr_UniformConstant_11 UniformConstant - %26 = OpVariable %_ptr_UniformConstant_13 UniformConstant - %main = OpFunction %void None %9 - %27 = OpLabel - OpLine %6 2 4 - %28 = OpLoad %13 %26 - %29 = OpLoad %11 %25 - %30 = OpSampledImage %15 %29 %28 - %31 = OpImageSampleImplicitLod %v4float %30 %24 - OpLine %6 12 4 - %41 = OpImageSampleProjImplicitLod %v4float %30 %24 - %32 = OpAccessChain %_ptr_Output_v4float %5 %int_0 - OpStore %32 %31 - OpReturn - OpFunctionEnd)"; - - std::vector messages = { - {SPV_MSG_WARNING, "test.hlsl", 2, 4, - "Removing ImageSampleImplicitLod instruction because of incompatible " - "execution model."}, - {SPV_MSG_WARNING, "test.hlsl", 12, 4, - "Removing ImageSampleProjImplicitLod instruction because of " - "incompatible " - "execution model."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/scalar_analysis.cpp b/3rdparty/spirv-tools/test/opt/scalar_analysis.cpp deleted file mode 100644 index 598d8c7b7..000000000 --- a/3rdparty/spirv-tools/test/opt/scalar_analysis.cpp +++ /dev/null @@ -1,1221 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/opt/iterator.h" -#include "source/opt/loop_descriptor.h" -#include "source/opt/pass.h" -#include "source/opt/scalar_analysis.h" -#include "source/opt/tree_iterator.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/function_utils.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::UnorderedElementsAre; -using ScalarAnalysisTest = PassTest<::testing::Test>; - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 410 core -layout (location = 1) out float array[10]; -void main() { - for (int i = 0; i < 10; ++i) { - array[i] = array[i+1]; - } -} -*/ -TEST_F(ScalarAnalysisTest, BasicEvolutionTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %24 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %24 "array" - OpDecorate %24 Location 1 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 10 - %17 = OpTypeBool - %19 = OpTypeFloat 32 - %20 = OpTypeInt 32 0 - %21 = OpConstant %20 10 - %22 = OpTypeArray %19 %21 - %23 = OpTypePointer Output %22 - %24 = OpVariable %23 Output - %27 = OpConstant %6 1 - %29 = OpTypePointer Output %19 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %35 = OpPhi %6 %9 %5 %34 %13 - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %18 = OpSLessThan %17 %35 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %28 = OpIAdd %6 %35 %27 - %30 = OpAccessChain %29 %24 %28 - %31 = OpLoad %19 %30 - %32 = OpAccessChain %29 %24 %35 - OpStore %32 %31 - OpBranch %13 - %13 = OpLabel - %34 = OpIAdd %6 %35 %27 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - ScalarEvolutionAnalysis analysis{context.get()}; - - const Instruction* store = nullptr; - const Instruction* load = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 11)) { - if (inst.opcode() == SpvOp::SpvOpStore) { - store = &inst; - } - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(load, nullptr); - EXPECT_NE(store, nullptr); - - Instruction* access_chain = - context->get_def_use_mgr()->GetDef(load->GetSingleWordInOperand(0)); - - Instruction* child = context->get_def_use_mgr()->GetDef( - access_chain->GetSingleWordInOperand(1)); - const SENode* node = analysis.AnalyzeInstruction(child); - - EXPECT_NE(node, nullptr); - - // Unsimplified node should have the form of ADD(REC(0,1), 1) - EXPECT_EQ(node->GetType(), SENode::Add); - - const SENode* child_1 = node->GetChild(0); - EXPECT_TRUE(child_1->GetType() == SENode::Constant || - child_1->GetType() == SENode::RecurrentAddExpr); - - const SENode* child_2 = node->GetChild(1); - EXPECT_TRUE(child_2->GetType() == SENode::Constant || - child_2->GetType() == SENode::RecurrentAddExpr); - - SENode* simplified = analysis.SimplifyExpression(const_cast(node)); - // Simplified should be in the form of REC(1,1) - EXPECT_EQ(simplified->GetType(), SENode::RecurrentAddExpr); - - EXPECT_EQ(simplified->GetChild(0)->GetType(), SENode::Constant); - EXPECT_EQ(simplified->GetChild(0)->AsSEConstantNode()->FoldToSingleValue(), - 1); - - EXPECT_EQ(simplified->GetChild(1)->GetType(), SENode::Constant); - EXPECT_EQ(simplified->GetChild(1)->AsSEConstantNode()->FoldToSingleValue(), - 1); - - EXPECT_EQ(simplified->GetChild(0), simplified->GetChild(1)); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 410 core -layout (location = 1) out float array[10]; -layout (location = 2) flat in int loop_invariant; -void main() { - for (int i = 0; i < 10; ++i) { - array[i] = array[i+loop_invariant]; - } -} - -*/ -TEST_F(ScalarAnalysisTest, LoadTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "array" - OpName %4 "loop_invariant" - OpDecorate %3 Location 1 - OpDecorate %4 Flat - OpDecorate %4 Location 2 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeInt 32 1 - %8 = OpTypePointer Function %7 - %9 = OpConstant %7 0 - %10 = OpConstant %7 10 - %11 = OpTypeBool - %12 = OpTypeFloat 32 - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 10 - %15 = OpTypeArray %12 %14 - %16 = OpTypePointer Output %15 - %3 = OpVariable %16 Output - %17 = OpTypePointer Input %7 - %4 = OpVariable %17 Input - %18 = OpTypePointer Output %12 - %19 = OpConstant %7 1 - %2 = OpFunction %5 None %6 - %20 = OpLabel - OpBranch %21 - %21 = OpLabel - %22 = OpPhi %7 %9 %20 %23 %24 - OpLoopMerge %25 %24 None - OpBranch %26 - %26 = OpLabel - %27 = OpSLessThan %11 %22 %10 - OpBranchConditional %27 %28 %25 - %28 = OpLabel - %29 = OpLoad %7 %4 - %30 = OpIAdd %7 %22 %29 - %31 = OpAccessChain %18 %3 %30 - %32 = OpLoad %12 %31 - %33 = OpAccessChain %18 %3 %22 - OpStore %33 %32 - OpBranch %24 - %24 = OpLabel - %23 = OpIAdd %7 %22 %19 - OpBranch %21 - %25 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - ScalarEvolutionAnalysis analysis{context.get()}; - - const Instruction* load = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 28)) { - if (inst.opcode() == SpvOp::SpvOpLoad) { - load = &inst; - } - } - - EXPECT_NE(load, nullptr); - - Instruction* access_chain = - context->get_def_use_mgr()->GetDef(load->GetSingleWordInOperand(0)); - - Instruction* child = context->get_def_use_mgr()->GetDef( - access_chain->GetSingleWordInOperand(1)); - // const SENode* node = - // analysis.GetNodeFromInstruction(child->unique_id()); - - const SENode* node = analysis.AnalyzeInstruction(child); - - EXPECT_NE(node, nullptr); - - // Unsimplified node should have the form of ADD(REC(0,1), X) - EXPECT_EQ(node->GetType(), SENode::Add); - - const SENode* child_1 = node->GetChild(0); - EXPECT_TRUE(child_1->GetType() == SENode::ValueUnknown || - child_1->GetType() == SENode::RecurrentAddExpr); - - const SENode* child_2 = node->GetChild(1); - EXPECT_TRUE(child_2->GetType() == SENode::ValueUnknown || - child_2->GetType() == SENode::RecurrentAddExpr); - - SENode* simplified = analysis.SimplifyExpression(const_cast(node)); - EXPECT_EQ(simplified->GetType(), SENode::RecurrentAddExpr); - - const SERecurrentNode* rec = simplified->AsSERecurrentNode(); - - EXPECT_NE(rec->GetChild(0), rec->GetChild(1)); - - EXPECT_EQ(rec->GetOffset()->GetType(), SENode::ValueUnknown); - - EXPECT_EQ(rec->GetCoefficient()->GetType(), SENode::Constant); - EXPECT_EQ(rec->GetCoefficient()->AsSEConstantNode()->FoldToSingleValue(), 1u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 410 core -layout (location = 1) out float array[10]; -layout (location = 2) flat in int loop_invariant; -void main() { - array[0] = array[loop_invariant * 2 + 4 + 5 - 24 - loop_invariant - -loop_invariant+ 16 * 3]; -} - -*/ -TEST_F(ScalarAnalysisTest, SimplifySimple) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %3 "array" - OpName %4 "loop_invariant" - OpDecorate %3 Location 1 - OpDecorate %4 Flat - OpDecorate %4 Location 2 - %5 = OpTypeVoid - %6 = OpTypeFunction %5 - %7 = OpTypeFloat 32 - %8 = OpTypeInt 32 0 - %9 = OpConstant %8 10 - %10 = OpTypeArray %7 %9 - %11 = OpTypePointer Output %10 - %3 = OpVariable %11 Output - %12 = OpTypeInt 32 1 - %13 = OpConstant %12 0 - %14 = OpTypePointer Input %12 - %4 = OpVariable %14 Input - %15 = OpConstant %12 2 - %16 = OpConstant %12 4 - %17 = OpConstant %12 5 - %18 = OpConstant %12 24 - %19 = OpConstant %12 48 - %20 = OpTypePointer Output %7 - %2 = OpFunction %5 None %6 - %21 = OpLabel - %22 = OpLoad %12 %4 - %23 = OpIMul %12 %22 %15 - %24 = OpIAdd %12 %23 %16 - %25 = OpIAdd %12 %24 %17 - %26 = OpISub %12 %25 %18 - %28 = OpISub %12 %26 %22 - %30 = OpISub %12 %28 %22 - %31 = OpIAdd %12 %30 %19 - %32 = OpAccessChain %20 %3 %31 - %33 = OpLoad %7 %32 - %34 = OpAccessChain %20 %3 %13 - OpStore %34 %33 - OpReturn - OpFunctionEnd - )"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - ScalarEvolutionAnalysis analysis{context.get()}; - - const Instruction* load = nullptr; - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 21)) { - if (inst.opcode() == SpvOp::SpvOpLoad && inst.result_id() == 33) { - load = &inst; - } - } - - EXPECT_NE(load, nullptr); - - Instruction* access_chain = - context->get_def_use_mgr()->GetDef(load->GetSingleWordInOperand(0)); - - Instruction* child = context->get_def_use_mgr()->GetDef( - access_chain->GetSingleWordInOperand(1)); - - const SENode* node = analysis.AnalyzeInstruction(child); - - // Unsimplified is a very large graph with an add at the top. - EXPECT_NE(node, nullptr); - EXPECT_EQ(node->GetType(), SENode::Add); - - // Simplified node should resolve down to a constant expression as the loads - // will eliminate themselves. - SENode* simplified = analysis.SimplifyExpression(const_cast(node)); - - EXPECT_EQ(simplified->GetType(), SENode::Constant); - EXPECT_EQ(simplified->AsSEConstantNode()->FoldToSingleValue(), 33u); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 410 core -layout(location = 0) in vec4 c; -layout (location = 1) out float array[10]; -void main() { - int N = int(c.x); - for (int i = 0; i < 10; ++i) { - array[i] = array[i]; - array[i] = array[i-1]; - array[i] = array[i+1]; - array[i+1] = array[i+1]; - array[i+N] = array[i+N]; - array[i] = array[i+N]; - } -} - -*/ -TEST_F(ScalarAnalysisTest, Simplify) { - const std::string text = R"( OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %12 %33 - OpExecutionMode %4 OriginUpperLeft - OpSource GLSL 410 - OpName %4 "main" - OpName %8 "N" - OpName %12 "c" - OpName %19 "i" - OpName %33 "array" - OpDecorate %12 Location 0 - OpDecorate %33 Location 1 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpTypeFloat 32 - %10 = OpTypeVector %9 4 - %11 = OpTypePointer Input %10 - %12 = OpVariable %11 Input - %13 = OpTypeInt 32 0 - %14 = OpConstant %13 0 - %15 = OpTypePointer Input %9 - %20 = OpConstant %6 0 - %27 = OpConstant %6 10 - %28 = OpTypeBool - %30 = OpConstant %13 10 - %31 = OpTypeArray %9 %30 - %32 = OpTypePointer Output %31 - %33 = OpVariable %32 Output - %36 = OpTypePointer Output %9 - %42 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %16 = OpAccessChain %15 %12 %14 - %17 = OpLoad %9 %16 - %18 = OpConvertFToS %6 %17 - OpStore %8 %18 - OpStore %19 %20 - OpBranch %21 - %21 = OpLabel - %78 = OpPhi %6 %20 %5 %77 %24 - OpLoopMerge %23 %24 None - OpBranch %25 - %25 = OpLabel - %29 = OpSLessThan %28 %78 %27 - OpBranchConditional %29 %22 %23 - %22 = OpLabel - %37 = OpAccessChain %36 %33 %78 - %38 = OpLoad %9 %37 - %39 = OpAccessChain %36 %33 %78 - OpStore %39 %38 - %43 = OpISub %6 %78 %42 - %44 = OpAccessChain %36 %33 %43 - %45 = OpLoad %9 %44 - %46 = OpAccessChain %36 %33 %78 - OpStore %46 %45 - %49 = OpIAdd %6 %78 %42 - %50 = OpAccessChain %36 %33 %49 - %51 = OpLoad %9 %50 - %52 = OpAccessChain %36 %33 %78 - OpStore %52 %51 - %54 = OpIAdd %6 %78 %42 - %56 = OpIAdd %6 %78 %42 - %57 = OpAccessChain %36 %33 %56 - %58 = OpLoad %9 %57 - %59 = OpAccessChain %36 %33 %54 - OpStore %59 %58 - %62 = OpIAdd %6 %78 %18 - %65 = OpIAdd %6 %78 %18 - %66 = OpAccessChain %36 %33 %65 - %67 = OpLoad %9 %66 - %68 = OpAccessChain %36 %33 %62 - OpStore %68 %67 - %72 = OpIAdd %6 %78 %18 - %73 = OpAccessChain %36 %33 %72 - %74 = OpLoad %9 %73 - %75 = OpAccessChain %36 %33 %78 - OpStore %75 %74 - OpBranch %24 - %24 = OpLabel - %77 = OpIAdd %6 %78 %42 - OpStore %19 %77 - OpBranch %21 - %23 = OpLabel - OpReturn - OpFunctionEnd -)"; - // clang-format on - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 4); - ScalarEvolutionAnalysis analysis{context.get()}; - - const Instruction* loads[6]; - const Instruction* stores[6]; - int load_count = 0; - int store_count = 0; - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 22)) { - if (inst.opcode() == SpvOp::SpvOpLoad) { - loads[load_count] = &inst; - ++load_count; - } - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[store_count] = &inst; - ++store_count; - } - } - - EXPECT_EQ(load_count, 6); - EXPECT_EQ(store_count, 6); - - Instruction* load_access_chain; - Instruction* store_access_chain; - Instruction* load_child; - Instruction* store_child; - SENode* load_node; - SENode* store_node; - SENode* subtract_node; - SENode* simplified_node; - - // Testing [i] - [i] == 0 - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[0]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[0]->GetSingleWordInOperand(0)); - - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - load_node = analysis.AnalyzeInstruction(load_child); - store_node = analysis.AnalyzeInstruction(store_child); - - subtract_node = analysis.CreateSubtraction(store_node, load_node); - simplified_node = analysis.SimplifyExpression(subtract_node); - EXPECT_EQ(simplified_node->GetType(), SENode::Constant); - EXPECT_EQ(simplified_node->AsSEConstantNode()->FoldToSingleValue(), 0u); - - // Testing [i] - [i-1] == 1 - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[1]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[1]->GetSingleWordInOperand(0)); - - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - load_node = analysis.AnalyzeInstruction(load_child); - store_node = analysis.AnalyzeInstruction(store_child); - - subtract_node = analysis.CreateSubtraction(store_node, load_node); - simplified_node = analysis.SimplifyExpression(subtract_node); - - EXPECT_EQ(simplified_node->GetType(), SENode::Constant); - EXPECT_EQ(simplified_node->AsSEConstantNode()->FoldToSingleValue(), 1u); - - // Testing [i] - [i+1] == -1 - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[2]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[2]->GetSingleWordInOperand(0)); - - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - load_node = analysis.AnalyzeInstruction(load_child); - store_node = analysis.AnalyzeInstruction(store_child); - - subtract_node = analysis.CreateSubtraction(store_node, load_node); - simplified_node = analysis.SimplifyExpression(subtract_node); - EXPECT_EQ(simplified_node->GetType(), SENode::Constant); - EXPECT_EQ(simplified_node->AsSEConstantNode()->FoldToSingleValue(), -1); - - // Testing [i+1] - [i+1] == 0 - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[3]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[3]->GetSingleWordInOperand(0)); - - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - load_node = analysis.AnalyzeInstruction(load_child); - store_node = analysis.AnalyzeInstruction(store_child); - - subtract_node = analysis.CreateSubtraction(store_node, load_node); - simplified_node = analysis.SimplifyExpression(subtract_node); - EXPECT_EQ(simplified_node->GetType(), SENode::Constant); - EXPECT_EQ(simplified_node->AsSEConstantNode()->FoldToSingleValue(), 0u); - - // Testing [i+N] - [i+N] == 0 - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[4]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[4]->GetSingleWordInOperand(0)); - - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - load_node = analysis.AnalyzeInstruction(load_child); - store_node = analysis.AnalyzeInstruction(store_child); - - subtract_node = analysis.CreateSubtraction(store_node, load_node); - - simplified_node = analysis.SimplifyExpression(subtract_node); - EXPECT_EQ(simplified_node->GetType(), SENode::Constant); - EXPECT_EQ(simplified_node->AsSEConstantNode()->FoldToSingleValue(), 0u); - - // Testing [i] - [i+N] == -N - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[5]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[5]->GetSingleWordInOperand(0)); - - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - load_node = analysis.AnalyzeInstruction(load_child); - store_node = analysis.AnalyzeInstruction(store_child); - - subtract_node = analysis.CreateSubtraction(store_node, load_node); - simplified_node = analysis.SimplifyExpression(subtract_node); - EXPECT_EQ(simplified_node->GetType(), SENode::Negative); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 430 -layout(location = 1) out float array[10]; -layout(location = 2) flat in int loop_invariant; -void main(void) { - for (int i = 0; i < 10; ++i) { - array[i * 2 + i * 5] = array[i * i * 2]; - array[i * 2] = array[i * 5]; - } -} - -*/ - -TEST_F(ScalarAnalysisTest, SimplifyMultiplyInductions) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %5 "i" - OpName %3 "array" - OpName %4 "loop_invariant" - OpDecorate %3 Location 1 - OpDecorate %4 Flat - OpDecorate %4 Location 2 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Output %16 - %3 = OpVariable %17 Output - %18 = OpConstant %8 2 - %19 = OpConstant %8 5 - %20 = OpTypePointer Output %13 - %21 = OpConstant %8 1 - %22 = OpTypePointer Input %8 - %4 = OpVariable %22 Input - %2 = OpFunction %6 None %7 - %23 = OpLabel - %5 = OpVariable %9 Function - OpStore %5 %10 - OpBranch %24 - %24 = OpLabel - %25 = OpPhi %8 %10 %23 %26 %27 - OpLoopMerge %28 %27 None - OpBranch %29 - %29 = OpLabel - %30 = OpSLessThan %12 %25 %11 - OpBranchConditional %30 %31 %28 - %31 = OpLabel - %32 = OpIMul %8 %25 %18 - %33 = OpIMul %8 %25 %19 - %34 = OpIAdd %8 %32 %33 - %35 = OpIMul %8 %25 %25 - %36 = OpIMul %8 %35 %18 - %37 = OpAccessChain %20 %3 %36 - %38 = OpLoad %13 %37 - %39 = OpAccessChain %20 %3 %34 - OpStore %39 %38 - %40 = OpIMul %8 %25 %18 - %41 = OpIMul %8 %25 %19 - %42 = OpAccessChain %20 %3 %41 - %43 = OpLoad %13 %42 - %44 = OpAccessChain %20 %3 %40 - OpStore %44 %43 - OpBranch %27 - %27 = OpLabel - %26 = OpIAdd %8 %25 %21 - OpStore %5 %26 - OpBranch %24 - %28 = OpLabel - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - ScalarEvolutionAnalysis analysis{context.get()}; - - const Instruction* loads[2] = {nullptr, nullptr}; - const Instruction* stores[2] = {nullptr, nullptr}; - int load_count = 0; - int store_count = 0; - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 31)) { - if (inst.opcode() == SpvOp::SpvOpLoad) { - loads[load_count] = &inst; - ++load_count; - } - if (inst.opcode() == SpvOp::SpvOpStore) { - stores[store_count] = &inst; - ++store_count; - } - } - - EXPECT_EQ(load_count, 2); - EXPECT_EQ(store_count, 2); - - Instruction* load_access_chain = - context->get_def_use_mgr()->GetDef(loads[0]->GetSingleWordInOperand(0)); - Instruction* store_access_chain = - context->get_def_use_mgr()->GetDef(stores[0]->GetSingleWordInOperand(0)); - - Instruction* load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - Instruction* store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - SENode* store_node = analysis.AnalyzeInstruction(store_child); - - SENode* store_simplified = analysis.SimplifyExpression(store_node); - - load_access_chain = - context->get_def_use_mgr()->GetDef(loads[1]->GetSingleWordInOperand(0)); - store_access_chain = - context->get_def_use_mgr()->GetDef(stores[1]->GetSingleWordInOperand(0)); - load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - SENode* second_store = - analysis.SimplifyExpression(analysis.AnalyzeInstruction(store_child)); - SENode* second_load = - analysis.SimplifyExpression(analysis.AnalyzeInstruction(load_child)); - SENode* combined_add = analysis.SimplifyExpression( - analysis.CreateAddNode(second_load, second_store)); - - // We're checking that the two recurrent expression have been correctly - // folded. In store_simplified they will have been folded as the entire - // expression was simplified as one. In combined_add the two expressions have - // been simplified one after the other which means the recurrent expressions - // aren't exactly the same but should still be folded as they are with respect - // to the same loop. - EXPECT_EQ(combined_add, store_simplified); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 430 -void main(void) { - for (int i = 0; i < 10; --i) { - array[i] = array[i]; - } -} - -*/ - -TEST_F(ScalarAnalysisTest, SimplifyNegativeSteps) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %5 "i" - OpName %3 "array" - OpName %4 "loop_invariant" - OpDecorate %3 Location 1 - OpDecorate %4 Flat - OpDecorate %4 Location 2 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Output %16 - %3 = OpVariable %17 Output - %18 = OpTypePointer Output %13 - %19 = OpConstant %8 1 - %20 = OpTypePointer Input %8 - %4 = OpVariable %20 Input - %2 = OpFunction %6 None %7 - %21 = OpLabel - %5 = OpVariable %9 Function - OpStore %5 %10 - OpBranch %22 - %22 = OpLabel - %23 = OpPhi %8 %10 %21 %24 %25 - OpLoopMerge %26 %25 None - OpBranch %27 - %27 = OpLabel - %28 = OpSLessThan %12 %23 %11 - OpBranchConditional %28 %29 %26 - %29 = OpLabel - %30 = OpAccessChain %18 %3 %23 - %31 = OpLoad %13 %30 - %32 = OpAccessChain %18 %3 %23 - OpStore %32 %31 - OpBranch %25 - %25 = OpLabel - %24 = OpISub %8 %23 %19 - OpStore %5 %24 - OpBranch %22 - %26 = OpLabel - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - ScalarEvolutionAnalysis analysis{context.get()}; - - const Instruction* loads[1] = {nullptr}; - int load_count = 0; - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) { - if (inst.opcode() == SpvOp::SpvOpLoad) { - loads[load_count] = &inst; - ++load_count; - } - } - - EXPECT_EQ(load_count, 1); - - Instruction* load_access_chain = - context->get_def_use_mgr()->GetDef(loads[0]->GetSingleWordInOperand(0)); - Instruction* load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - - SENode* load_node = analysis.AnalyzeInstruction(load_child); - - EXPECT_TRUE(load_node); - EXPECT_EQ(load_node->GetType(), SENode::RecurrentAddExpr); - EXPECT_TRUE(load_node->AsSERecurrentNode()); - - SENode* child_1 = load_node->AsSERecurrentNode()->GetCoefficient(); - SENode* child_2 = load_node->AsSERecurrentNode()->GetOffset(); - - EXPECT_EQ(child_1->GetType(), SENode::Constant); - EXPECT_EQ(child_2->GetType(), SENode::Constant); - - EXPECT_EQ(child_1->AsSEConstantNode()->FoldToSingleValue(), -1); - EXPECT_EQ(child_2->AsSEConstantNode()->FoldToSingleValue(), 0u); - - SERecurrentNode* load_simplified = - analysis.SimplifyExpression(load_node)->AsSERecurrentNode(); - - EXPECT_TRUE(load_simplified); - EXPECT_EQ(load_node, load_simplified); - - EXPECT_EQ(load_simplified->GetType(), SENode::RecurrentAddExpr); - EXPECT_TRUE(load_simplified->AsSERecurrentNode()); - - SENode* simplified_child_1 = - load_simplified->AsSERecurrentNode()->GetCoefficient(); - SENode* simplified_child_2 = - load_simplified->AsSERecurrentNode()->GetOffset(); - - EXPECT_EQ(child_1, simplified_child_1); - EXPECT_EQ(child_2, simplified_child_2); -} - -/* -Generated from the following GLSL + --eliminate-local-multi-store - -#version 430 -void main(void) { - for (int i = 0; i < 10; --i) { - array[i] = array[i]; - } -} - -*/ - -TEST_F(ScalarAnalysisTest, SimplifyInductionsAndLoads) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %5 "i" - OpName %3 "array" - OpName %4 "N" - OpDecorate %3 Location 1 - OpDecorate %4 Flat - OpDecorate %4 Location 2 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeInt 32 1 - %9 = OpTypePointer Function %8 - %10 = OpConstant %8 0 - %11 = OpConstant %8 10 - %12 = OpTypeBool - %13 = OpTypeFloat 32 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 10 - %16 = OpTypeArray %13 %15 - %17 = OpTypePointer Output %16 - %3 = OpVariable %17 Output - %18 = OpConstant %8 2 - %19 = OpTypePointer Input %8 - %4 = OpVariable %19 Input - %20 = OpTypePointer Output %13 - %21 = OpConstant %8 1 - %2 = OpFunction %6 None %7 - %22 = OpLabel - %5 = OpVariable %9 Function - OpStore %5 %10 - OpBranch %23 - %23 = OpLabel - %24 = OpPhi %8 %10 %22 %25 %26 - OpLoopMerge %27 %26 None - OpBranch %28 - %28 = OpLabel - %29 = OpSLessThan %12 %24 %11 - OpBranchConditional %29 %30 %27 - %30 = OpLabel - %31 = OpLoad %8 %4 - %32 = OpIMul %8 %18 %31 - %33 = OpIAdd %8 %24 %32 - %35 = OpIAdd %8 %24 %31 - %36 = OpAccessChain %20 %3 %35 - %37 = OpLoad %13 %36 - %38 = OpAccessChain %20 %3 %33 - OpStore %38 %37 - %39 = OpIMul %8 %18 %24 - %41 = OpIMul %8 %18 %31 - %42 = OpIAdd %8 %39 %41 - %43 = OpIAdd %8 %42 %21 - %44 = OpIMul %8 %18 %24 - %46 = OpIAdd %8 %44 %31 - %47 = OpIAdd %8 %46 %21 - %48 = OpAccessChain %20 %3 %47 - %49 = OpLoad %13 %48 - %50 = OpAccessChain %20 %3 %43 - OpStore %50 %49 - OpBranch %26 - %26 = OpLabel - %25 = OpISub %8 %24 %21 - OpStore %5 %25 - OpBranch %23 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - ScalarEvolutionAnalysis analysis{context.get()}; - - std::vector loads{}; - std::vector stores{}; - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) { - if (inst.opcode() == SpvOp::SpvOpLoad) { - loads.push_back(&inst); - } - if (inst.opcode() == SpvOp::SpvOpStore) { - stores.push_back(&inst); - } - } - - EXPECT_EQ(loads.size(), 3u); - EXPECT_EQ(stores.size(), 2u); - { - Instruction* store_access_chain = context->get_def_use_mgr()->GetDef( - stores[0]->GetSingleWordInOperand(0)); - - Instruction* store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - - SENode* store_node = analysis.AnalyzeInstruction(store_child); - - SENode* store_simplified = analysis.SimplifyExpression(store_node); - - Instruction* load_access_chain = - context->get_def_use_mgr()->GetDef(loads[1]->GetSingleWordInOperand(0)); - - Instruction* load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - - SENode* load_node = analysis.AnalyzeInstruction(load_child); - - SENode* load_simplified = analysis.SimplifyExpression(load_node); - - SENode* difference = - analysis.CreateSubtraction(store_simplified, load_simplified); - - SENode* difference_simplified = analysis.SimplifyExpression(difference); - - // Check that i+2*N - i*N, turns into just N when both sides have already - // been simplified into a single recurrent expression. - EXPECT_EQ(difference_simplified->GetType(), SENode::ValueUnknown); - - // Check that the inverse, i*N - i+2*N turns into -N. - SENode* difference_inverse = analysis.SimplifyExpression( - analysis.CreateSubtraction(load_simplified, store_simplified)); - - EXPECT_EQ(difference_inverse->GetType(), SENode::Negative); - EXPECT_EQ(difference_inverse->GetChild(0)->GetType(), SENode::ValueUnknown); - EXPECT_EQ(difference_inverse->GetChild(0), difference_simplified); - } - - { - Instruction* store_access_chain = context->get_def_use_mgr()->GetDef( - stores[1]->GetSingleWordInOperand(0)); - - Instruction* store_child = context->get_def_use_mgr()->GetDef( - store_access_chain->GetSingleWordInOperand(1)); - SENode* store_node = analysis.AnalyzeInstruction(store_child); - SENode* store_simplified = analysis.SimplifyExpression(store_node); - - Instruction* load_access_chain = - context->get_def_use_mgr()->GetDef(loads[2]->GetSingleWordInOperand(0)); - - Instruction* load_child = context->get_def_use_mgr()->GetDef( - load_access_chain->GetSingleWordInOperand(1)); - - SENode* load_node = analysis.AnalyzeInstruction(load_child); - - SENode* load_simplified = analysis.SimplifyExpression(load_node); - - SENode* difference = - analysis.CreateSubtraction(store_simplified, load_simplified); - SENode* difference_simplified = analysis.SimplifyExpression(difference); - - // Check that 2*i + 2*N + 1 - 2*i + N + 1, turns into just N when both - // sides have already been simplified into a single recurrent expression. - EXPECT_EQ(difference_simplified->GetType(), SENode::ValueUnknown); - - // Check that the inverse, (2*i + N + 1) - (2*i + 2*N + 1) turns into -N. - SENode* difference_inverse = analysis.SimplifyExpression( - analysis.CreateSubtraction(load_simplified, store_simplified)); - - EXPECT_EQ(difference_inverse->GetType(), SENode::Negative); - EXPECT_EQ(difference_inverse->GetChild(0)->GetType(), SENode::ValueUnknown); - EXPECT_EQ(difference_inverse->GetChild(0), difference_simplified); - } -} - -/* Generated from the following GLSL + --eliminate-local-multi-store - - #version 430 - layout(location = 1) out float array[10]; - layout(location = 2) flat in int N; - void main(void) { - int step = 0; - for (int i = 0; i < N; i += step) { - step++; - } - } -*/ -TEST_F(ScalarAnalysisTest, InductionWithVariantStep) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 %4 - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpName %2 "main" - OpName %5 "step" - OpName %6 "i" - OpName %3 "N" - OpName %4 "array" - OpDecorate %3 Flat - OpDecorate %3 Location 2 - OpDecorate %4 Location 1 - %7 = OpTypeVoid - %8 = OpTypeFunction %7 - %9 = OpTypeInt 32 1 - %10 = OpTypePointer Function %9 - %11 = OpConstant %9 0 - %12 = OpTypePointer Input %9 - %3 = OpVariable %12 Input - %13 = OpTypeBool - %14 = OpConstant %9 1 - %15 = OpTypeFloat 32 - %16 = OpTypeInt 32 0 - %17 = OpConstant %16 10 - %18 = OpTypeArray %15 %17 - %19 = OpTypePointer Output %18 - %4 = OpVariable %19 Output - %2 = OpFunction %7 None %8 - %20 = OpLabel - %5 = OpVariable %10 Function - %6 = OpVariable %10 Function - OpStore %5 %11 - OpStore %6 %11 - OpBranch %21 - %21 = OpLabel - %22 = OpPhi %9 %11 %20 %23 %24 - %25 = OpPhi %9 %11 %20 %26 %24 - OpLoopMerge %27 %24 None - OpBranch %28 - %28 = OpLabel - %29 = OpLoad %9 %3 - %30 = OpSLessThan %13 %25 %29 - OpBranchConditional %30 %31 %27 - %31 = OpLabel - %23 = OpIAdd %9 %22 %14 - OpStore %5 %23 - OpBranch %24 - %24 = OpLabel - %26 = OpIAdd %9 %25 %23 - OpStore %6 %26 - OpBranch %21 - %27 = OpLabel - OpReturn - OpFunctionEnd - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - Module* module = context->module(); - EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" - << text << std::endl; - const Function* f = spvtest::GetFunction(module, 2); - ScalarEvolutionAnalysis analysis{context.get()}; - - std::vector phis{}; - - for (const Instruction& inst : *spvtest::GetBasicBlock(f, 21)) { - if (inst.opcode() == SpvOp::SpvOpPhi) { - phis.push_back(&inst); - } - } - - EXPECT_EQ(phis.size(), 2u); - SENode* phi_node_1 = analysis.AnalyzeInstruction(phis[0]); - SENode* phi_node_2 = analysis.AnalyzeInstruction(phis[1]); - phi_node_1->DumpDot(std::cout, true); - EXPECT_NE(phi_node_1, nullptr); - EXPECT_NE(phi_node_2, nullptr); - - EXPECT_EQ(phi_node_1->GetType(), SENode::RecurrentAddExpr); - EXPECT_EQ(phi_node_2->GetType(), SENode::CanNotCompute); - - SENode* simplified_1 = analysis.SimplifyExpression(phi_node_1); - SENode* simplified_2 = analysis.SimplifyExpression(phi_node_2); - - EXPECT_EQ(simplified_1->GetType(), SENode::RecurrentAddExpr); - EXPECT_EQ(simplified_2->GetType(), SENode::CanNotCompute); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/scalar_replacement_test.cpp b/3rdparty/spirv-tools/test/opt/scalar_replacement_test.cpp deleted file mode 100644 index 3cf46ca13..000000000 --- a/3rdparty/spirv-tools/test/opt/scalar_replacement_test.cpp +++ /dev/null @@ -1,1904 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ScalarReplacementTest = PassTest<::testing::Test>; - -TEST_F(ScalarReplacementTest, SimpleStruct) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem:%\w+]] -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]] -; CHECK: OpConstantNull [[struct]] -; CHECK: [[null:%\w+]] = OpConstantNull [[elem]] -; CHECK-NOT: OpVariable [[struct_ptr]] -; CHECK: [[one:%\w+]] = OpVariable [[elem_ptr]] Function [[null]] -; CHECK-NEXT: [[two:%\w+]] = OpVariable [[elem_ptr]] Function [[null]] -; CHECK-NOT: OpVariable [[elem_ptr]] Function [[null]] -; CHECK-NOT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpInBoundsAccessChain -; CHECK: [[l1:%\w+]] = OpLoad [[elem]] [[two]] -; CHECK-NOT: OpAccessChain -; CHECK: [[l2:%\w+]] = OpLoad [[elem]] [[one]] -; CHECK: OpIAdd [[elem]] [[l1]] [[l2]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "simple_struct" -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %2 %2 %2 %2 -%4 = OpTypePointer Function %3 -%5 = OpTypePointer Function %2 -%6 = OpTypeFunction %2 -%7 = OpConstantNull %3 -%8 = OpConstant %2 0 -%9 = OpConstant %2 1 -%10 = OpConstant %2 2 -%11 = OpConstant %2 3 -%12 = OpFunction %2 None %6 -%13 = OpLabel -%14 = OpVariable %4 Function %7 -%15 = OpInBoundsAccessChain %5 %14 %8 -%16 = OpLoad %2 %15 -%17 = OpAccessChain %5 %14 %10 -%18 = OpLoad %2 %17 -%19 = OpIAdd %2 %16 %18 -OpReturnValue %19 -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, StructInitialization) { - const std::string text = R"( -; -; CHECK: [[elem:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem]] [[elem]] [[elem]] [[elem]] -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]] -; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0 -; CHECK: [[undef:%\w+]] = OpUndef [[elem]] -; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2 -; CHECK: [[null:%\w+]] = OpConstantNull [[elem]] -; CHECK-NOT: OpVariable [[struct_ptr]] -; CHECK: OpVariable [[elem_ptr]] Function [[null]] -; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]] -; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]] -; CHECK-NEXT: OpVariable [[elem_ptr]] Function -; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[zero]] -; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "struct_init" -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %2 %2 %2 %2 -%4 = OpTypePointer Function %3 -%20 = OpTypePointer Function %2 -%6 = OpTypeFunction %1 -%7 = OpConstant %2 0 -%8 = OpUndef %2 -%9 = OpConstant %2 2 -%30 = OpConstant %2 1 -%31 = OpConstant %2 3 -%10 = OpConstantNull %2 -%11 = OpConstantComposite %3 %7 %8 %9 %10 -%12 = OpFunction %1 None %6 -%13 = OpLabel -%14 = OpVariable %4 Function %11 -%15 = OpAccessChain %20 %14 %7 -OpStore %15 %10 -%16 = OpAccessChain %20 %14 %9 -OpStore %16 %10 -%17 = OpAccessChain %20 %14 %30 -OpStore %17 %10 -%18 = OpAccessChain %20 %14 %31 -OpStore %18 %10 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, SpecConstantInitialization) { - const std::string text = R"( -; -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct:%\w+]] = OpTypeStruct [[int]] [[int]] -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]] -; CHECK: [[spec_comp:%\w+]] = OpSpecConstantComposite [[struct]] -; CHECK: [[ex0:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 0 -; CHECK: [[ex1:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 1 -; CHECK-NOT: OpVariable [[struct]] -; CHECK: OpVariable [[int_ptr]] Function [[ex1]] -; CHECK-NEXT: OpVariable [[int_ptr]] Function [[ex0]] -; CHECK-NOT: OpVariable [[struct]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "spec_const" -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %2 %2 -%4 = OpTypePointer Function %3 -%20 = OpTypePointer Function %2 -%5 = OpTypeFunction %1 -%6 = OpConstant %2 0 -%30 = OpConstant %2 1 -%7 = OpSpecConstant %2 0 -%8 = OpSpecConstantOp %2 IAdd %7 %7 -%9 = OpSpecConstantComposite %3 %7 %8 -%10 = OpFunction %1 None %5 -%11 = OpLabel -%12 = OpVariable %4 Function %9 -%13 = OpAccessChain %20 %12 %6 -%14 = OpLoad %2 %13 -%15 = OpAccessChain %20 %12 %30 -%16 = OpLoad %2 %15 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -// TODO(alanbaker): Re-enable when vector and matrix scalarization is supported. -// TEST_F(ScalarReplacementTest, VectorInitialization) { -// const std::string text = R"( -// ; -// ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0 -// ; CHECK: [[vector:%\w+]] = OpTypeVector [[elem]] 4 -// ; CHECK: [[vector_ptr:%\w+]] = OpTypePointer Function [[vector]] -// ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]] -// ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0 -// ; CHECK: [[undef:%\w+]] = OpUndef [[elem]] -// ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2 -// ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]] -// ; CHECK-NOT: OpVariable [[vector_ptr]] -// ; CHECK: OpVariable [[elem_ptr]] Function [[zero]] -// ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]] -// ; CHECK-NEXT: OpVariable [[elem_ptr]] Function -// ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]] -// ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[null]] -// ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]] -// ; -// OpCapability Shader -// OpCapability Linkage -// OpMemoryModel Logical GLSL450 -// OpName %6 "vector_init" -// %1 = OpTypeVoid -// %2 = OpTypeInt 32 0 -// %3 = OpTypeVector %2 4 -// %4 = OpTypePointer Function %3 -// %20 = OpTypePointer Function %2 -// %6 = OpTypeFunction %1 -// %7 = OpConstant %2 0 -// %8 = OpUndef %2 -// %9 = OpConstant %2 2 -// %30 = OpConstant %2 1 -// %31 = OpConstant %2 3 -// %10 = OpConstantNull %2 -// %11 = OpConstantComposite %3 %10 %9 %8 %7 -// %12 = OpFunction %1 None %6 -// %13 = OpLabel -// %14 = OpVariable %4 Function %11 -// %15 = OpAccessChain %20 %14 %7 -// OpStore %15 %10 -// %16 = OpAccessChain %20 %14 %9 -// OpStore %16 %10 -// %17 = OpAccessChain %20 %14 %30 -// OpStore %17 %10 -// %18 = OpAccessChain %20 %14 %31 -// OpStore %18 %10 -// OpReturn -// OpFunctionEnd -// )"; -// -// SinglePassRunAndMatch(text, true); -// } -// -// TEST_F(ScalarReplacementTest, MatrixInitialization) { -// const std::string text = R"( -// ; -// ; CHECK: [[float:%\w+]] = OpTypeFloat 32 -// ; CHECK: [[vector:%\w+]] = OpTypeVector [[float]] 2 -// ; CHECK: [[matrix:%\w+]] = OpTypeMatrix [[vector]] 2 -// ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]] -// ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]] -// ; CHECK: [[vec_ptr:%\w+]] = OpTypePointer Function [[vector]] -// ; CHECK: [[zerof:%\w+]] = OpConstant [[float]] 0 -// ; CHECK: [[onef:%\w+]] = OpConstant [[float]] 1 -// ; CHECK: [[one_zero:%\w+]] = OpConstantComposite [[vector]] [[onef]] -// [[zerof]] ; CHECK: [[zero_one:%\w+]] = OpConstantComposite [[vector]] -// [[zerof]] [[onef]] ; CHECK: [[const_mat:%\w+]] = OpConstantComposite -// [[matrix]] [[one_zero]] -// [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ; CHECK-NOT: OpVariable -// [[vector]] Function [[one_zero]] ; CHECK: [[f1:%\w+]] = OpVariable -// [[float_ptr]] Function [[zerof]] ; CHECK-NEXT: [[f2:%\w+]] = OpVariable -// [[float_ptr]] Function [[onef]] ; CHECK-NEXT: [[vec_var:%\w+]] = OpVariable -// [[vec_ptr]] Function [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ; -// CHECK-NOT: OpVariable [[vector]] Function [[one_zero]] -// ; -// OpCapability Shader -// OpCapability Linkage -// OpMemoryModel Logical GLSL450 -// OpName %7 "matrix_init" -// %1 = OpTypeVoid -// %2 = OpTypeFloat 32 -// %3 = OpTypeVector %2 2 -// %4 = OpTypeMatrix %3 2 -// %5 = OpTypePointer Function %4 -// %6 = OpTypePointer Function %2 -// %30 = OpTypePointer Function %3 -// %10 = OpTypeInt 32 0 -// %7 = OpTypeFunction %1 %10 -// %8 = OpConstant %2 0.0 -// %9 = OpConstant %2 1.0 -// %11 = OpConstant %10 0 -// %12 = OpConstant %10 1 -// %13 = OpConstantComposite %3 %9 %8 -// %14 = OpConstantComposite %3 %8 %9 -// %15 = OpConstantComposite %4 %13 %14 -// %16 = OpFunction %1 None %7 -// %31 = OpFunctionParameter %10 -// %17 = OpLabel -// %18 = OpVariable %5 Function %15 -// %19 = OpAccessChain %6 %18 %11 %12 -// OpStore %19 %8 -// %20 = OpAccessChain %6 %18 %11 %11 -// OpStore %20 %8 -// %21 = OpAccessChain %30 %18 %12 -// OpStore %21 %14 -// OpReturn -// OpFunctionEnd -// )"; -// -// SinglePassRunAndMatch(text, true); -// } - -TEST_F(ScalarReplacementTest, ElideAccessChain) { - const std::string text = R"( -; -; CHECK: [[var:%\w+]] = OpVariable -; CHECK-NOT: OpAccessChain -; CHECK: OpStore [[var]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "elide_access_chain" -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %2 %2 %2 %2 -%4 = OpTypePointer Function %3 -%20 = OpTypePointer Function %2 -%6 = OpTypeFunction %1 -%7 = OpConstant %2 0 -%8 = OpUndef %2 -%9 = OpConstant %2 2 -%10 = OpConstantNull %2 -%11 = OpConstantComposite %3 %7 %8 %9 %10 -%12 = OpFunction %1 None %6 -%13 = OpLabel -%14 = OpVariable %4 Function %11 -%15 = OpAccessChain %20 %14 %7 -OpStore %15 %10 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ElideMultipleAccessChains) { - const std::string text = R"( -; -; CHECK: [[var:%\w+]] = OpVariable -; CHECK-NOT: OpInBoundsAccessChain -; CHECK OpStore [[var]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "elide_two_access_chains" -%1 = OpTypeVoid -%2 = OpTypeFloat 32 -%3 = OpTypeStruct %2 %2 -%4 = OpTypeStruct %3 %3 -%5 = OpTypePointer Function %4 -%6 = OpTypePointer Function %2 -%7 = OpTypeFunction %1 -%8 = OpConstant %2 0.0 -%9 = OpConstant %2 1.0 -%10 = OpTypeInt 32 0 -%11 = OpConstant %10 0 -%12 = OpConstant %10 1 -%13 = OpConstantComposite %3 %9 %8 -%14 = OpConstantComposite %3 %8 %9 -%15 = OpConstantComposite %4 %13 %14 -%16 = OpFunction %1 None %7 -%17 = OpLabel -%18 = OpVariable %5 Function %15 -%19 = OpInBoundsAccessChain %6 %18 %11 %12 -OpStore %19 %8 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceAccessChain) { - const std::string text = R"( -; -; CHECK: [[param:%\w+]] = OpFunctionParameter -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: [[access:%\w+]] = OpAccessChain {{%\w+}} [[var]] [[param]] -; CHECK: OpStore [[access]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %7 "replace_access_chain" -%1 = OpTypeVoid -%2 = OpTypeFloat 32 -%10 = OpTypeInt 32 0 -%uint_2 = OpConstant %10 2 -%3 = OpTypeArray %2 %uint_2 -%4 = OpTypeStruct %3 %3 -%5 = OpTypePointer Function %4 -%20 = OpTypePointer Function %3 -%6 = OpTypePointer Function %2 -%7 = OpTypeFunction %1 %10 -%8 = OpConstant %2 0.0 -%9 = OpConstant %2 1.0 -%11 = OpConstant %10 0 -%12 = OpConstant %10 1 -%13 = OpConstantComposite %3 %9 %8 -%14 = OpConstantComposite %3 %8 %9 -%15 = OpConstantComposite %4 %13 %14 -%16 = OpFunction %1 None %7 -%32 = OpFunctionParameter %10 -%17 = OpLabel -%18 = OpVariable %5 Function %15 -%19 = OpAccessChain %6 %18 %11 %32 -OpStore %19 %8 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ArrayInitialization) { - const std::string text = R"( -; -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[array:%\w+]] = OpTypeArray -; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]] -; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]] -; CHECK: [[float0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[float1:%\w+]] = OpConstant [[float]] 1 -; CHECK: [[float2:%\w+]] = OpConstant [[float]] 2 -; CHECK-NOT: OpVariable [[array_ptr]] -; CHECK: [[var0:%\w+]] = OpVariable [[float_ptr]] Function [[float0]] -; CHECK-NEXT: [[var1:%\w+]] = OpVariable [[float_ptr]] Function [[float1]] -; CHECK-NEXT: [[var2:%\w+]] = OpVariable [[float_ptr]] Function [[float2]] -; CHECK-NOT: OpVariable [[array_ptr]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "array_init" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%float_array = OpTypeArray %float %uint_3 -%array_ptr = OpTypePointer Function %float_array -%float_ptr = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%const_array = OpConstantComposite %float_array %float_2 %float_1 %float_0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%3 = OpVariable %array_ptr Function %const_array -%4 = OpInBoundsAccessChain %float_ptr %3 %uint_0 -OpStore %4 %float_0 -%5 = OpInBoundsAccessChain %float_ptr %3 %uint_1 -OpStore %5 %float_0 -%6 = OpInBoundsAccessChain %float_ptr %3 %uint_2 -OpStore %6 %float_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, NonUniformCompositeInitialization) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[long:%\w+]] = OpTypeInt 64 1 -; CHECK: [[dvector:%\w+]] = OpTypeVector -; CHECK: [[vector:%\w+]] = OpTypeVector -; CHECK: [[array:%\w+]] = OpTypeArray -; CHECK: [[matrix:%\w+]] = OpTypeMatrix -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[vector]] -; CHECK: [[struct2:%\w+]] = OpTypeStruct [[struct1]] [[matrix]] [[array]] [[uint]] -; CHECK: [[struct1_ptr:%\w+]] = OpTypePointer Function [[struct1]] -; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]] -; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[struct2_ptr:%\w+]] = OpTypePointer Function [[struct2]] -; CHECK: [[const_array:%\w+]] = OpConstantComposite [[array]] -; CHECK: [[const_matrix:%\w+]] = OpConstantNull [[matrix]] -; CHECK: [[const_struct1:%\w+]] = OpConstantComposite [[struct1]] -; CHECK: OpConstantNull [[uint]] -; CHECK: OpConstantNull [[vector]] -; CHECK: OpConstantNull [[long]] -; CHECK: OpFunction -; CHECK-NOT: OpVariable [[struct2_ptr]] Function -; CHECK: OpVariable [[uint_ptr]] Function -; CHECK-NEXT: OpVariable [[matrix_ptr]] Function [[const_matrix]] -; CHECK-NOT: OpVariable [[struct1_ptr]] Function [[const_struct1]] -; CHECK-NOT: OpVariable [[struct2_ptr]] Function -; -OpCapability Shader -OpCapability Linkage -OpCapability Int64 -OpCapability Float64 -OpMemoryModel Logical GLSL450 -OpName %func "non_uniform_composite_init" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%int64 = OpTypeInt 64 1 -%float = OpTypeFloat 32 -%double = OpTypeFloat 64 -%double2 = OpTypeVector %double 2 -%float4 = OpTypeVector %float 4 -%int64_0 = OpConstant %int64 0 -%int64_1 = OpConstant %int64 1 -%int64_2 = OpConstant %int64 2 -%int64_3 = OpConstant %int64 3 -%int64_array3 = OpTypeArray %int64 %int64_3 -%matrix_double2 = OpTypeMatrix %double2 2 -%struct1 = OpTypeStruct %uint %float4 -%struct2 = OpTypeStruct %struct1 %matrix_double2 %int64_array3 %uint -%struct1_ptr = OpTypePointer Function %struct1 -%matrix_double2_ptr = OpTypePointer Function %matrix_double2 -%int64_array_ptr = OpTypePointer Function %int64_array3 -%uint_ptr = OpTypePointer Function %uint -%struct2_ptr = OpTypePointer Function %struct2 -%const_uint = OpConstant %uint 0 -%const_int64_array = OpConstantComposite %int64_array3 %int64_0 %int64_1 %int64_2 -%const_double2 = OpConstantNull %double2 -%const_matrix_double2 = OpConstantNull %matrix_double2 -%undef_float4 = OpUndef %float4 -%const_struct1 = OpConstantComposite %struct1 %const_uint %undef_float4 -%const_struct2 = OpConstantComposite %struct2 %const_struct1 %const_matrix_double2 %const_int64_array %const_uint -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct2_ptr Function %const_struct2 -%3 = OpAccessChain %struct1_ptr %var %int64_0 -OpStore %3 %const_struct1 -%4 = OpAccessChain %matrix_double2_ptr %var %int64_1 -OpStore %4 %const_matrix_double2 -%5 = OpAccessChain %int64_array_ptr %var %int64_2 -OpStore %5 %const_int64_array -%6 = OpAccessChain %uint_ptr %var %int64_3 -OpStore %6 %const_uint -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ElideUncombinedAccessChains) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[var:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK-NOT: OpAccessChain -; CHECK: OpStore [[var]] [[const]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "elide_uncombined_access_chains" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%struct2 = OpTypeStruct %struct1 -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%struct2_ptr = OpTypePointer Function %struct2 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct2_ptr Function -%3 = OpAccessChain %struct1_ptr %var %uint_0 -%4 = OpAccessChain %uint_ptr %3 %uint_0 -OpStore %4 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ElideSingleUncombinedAccessChains) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[array:%\w+]] = OpTypeArray [[uint]] -; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[param:%\w+]] = OpFunctionParameter [[uint]] -; CHECK: [[var:%\w+]] = OpVariable [[array_ptr]] Function -; CHECK: [[access:%\w+]] = OpAccessChain {{.*}} [[var]] [[param]] -; CHECK: OpStore [[access]] [[const]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "elide_single_uncombined_access_chains" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%array = OpTypeArray %uint %uint_1 -%struct2 = OpTypeStruct %array -%uint_ptr = OpTypePointer Function %uint -%array_ptr = OpTypePointer Function %array -%struct2_ptr = OpTypePointer Function %struct2 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void %uint -%1 = OpFunction %void None %func -%param = OpFunctionParameter %uint -%2 = OpLabel -%var = OpVariable %struct2_ptr Function -%3 = OpAccessChain %array_ptr %var %uint_0 -%4 = OpAccessChain %uint_ptr %3 %param -OpStore %4 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceWholeLoad) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]] -; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] -; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[l1]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_load" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%load = OpLoad %struct1 %var -%3 = OpAccessChain %uint_ptr %var %uint_0 -OpStore %3 %uint_0 -%4 = OpAccessChain %uint_ptr %var %uint_1 -OpStore %4 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceWholeLoadCopyMemoryAccess) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[null:%\w+]] = OpConstantNull [[uint]] -; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] Nontemporal -; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[null]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_load_copy_memory_access" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%load = OpLoad %struct1 %var Nontemporal -%3 = OpAccessChain %uint_ptr %var %uint_0 -OpStore %3 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceWholeStore) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]] -; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0 -; CHECK: OpStore [[var0]] [[ex0]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_store" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%const_struct = OpConstantComposite %struct1 %uint_0 %uint_0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -OpStore %var %const_struct -%3 = OpAccessChain %uint_ptr %var %uint_0 -%4 = OpLoad %uint %3 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceWholeStoreCopyMemoryAccess) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]] -; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK-NOT: OpVariable -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0 -; CHECK: OpStore [[var0]] [[ex0]] Aligned 4 -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_store_copy_memory_access" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%const_struct = OpConstantComposite %struct1 %uint_0 %uint_0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -OpStore %var %const_struct Aligned 4 -%3 = OpAccessChain %uint_ptr %var %uint_0 -%4 = OpLoad %uint %3 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontTouchVolatileLoad) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "dont_touch_volatile_load" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpAccessChain %uint_ptr %var %uint_0 -%4 = OpLoad %uint %3 Volatile -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontTouchVolatileStore) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "dont_touch_volatile_store" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpAccessChain %uint_ptr %var %uint_0 -OpStore %3 %uint_0 Volatile -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontTouchSpecNonFunctionVariable) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Uniform [[struct]] -; CHECK: OpConstant -; CHECK-NEXT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "dont_touch_spec_constant_access_chain" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Uniform %uint -%struct1_ptr = OpTypePointer Uniform %struct1 -%uint_0 = OpConstant %uint 0 -%var = OpVariable %struct1_ptr Uniform -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%3 = OpAccessChain %uint_ptr %var %uint_0 -OpStore %3 %uint_0 Volatile -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontTouchSpecConstantAccessChain) { - const std::string text = R"( -; -; CHECK: [[array:%\w+]] = OpTypeArray -; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[array_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "dont_touch_spec_constant_access_chain" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%array = OpTypeArray %uint %uint_1 -%uint_ptr = OpTypePointer Function %uint -%array_ptr = OpTypePointer Function %array -%uint_0 = OpConstant %uint 0 -%spec_const = OpSpecConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %array_ptr Function -%3 = OpAccessChain %uint_ptr %var %spec_const -OpStore %3 %uint_0 Volatile -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, NoPartialAccesses) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: OpLabel -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "no_partial_accesses" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%const = OpConstantNull %struct1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -OpStore %var %const -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontTouchPtrAccessChain) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "dont_touch_ptr_access_chain" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpPtrAccessChain %uint_ptr %var %uint_0 %uint_0 -OpStore %3 %uint_0 -%4 = OpAccessChain %uint_ptr %var %uint_0 -OpStore %4 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(ScalarReplacementTest, DontTouchInBoundsPtrAccessChain) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "dont_touch_in_bounds_ptr_access_chain" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpInBoundsPtrAccessChain %uint_ptr %var %uint_0 %uint_0 -OpStore %3 %uint_0 -%4 = OpInBoundsAccessChain %uint_ptr %var %uint_0 -OpStore %4 %uint_0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(ScalarReplacementTest, DonTouchAliasedDecoration) { - const std::string text = R"( -; -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[struct_ptr]] -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "aliased" -OpDecorate %var Aliased -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpAccessChain %uint_ptr %var %uint_0 -%4 = OpLoad %uint %3 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, CopyRestrictDecoration) { - const std::string text = R"( -; -; CHECK: OpName -; CHECK-NEXT: OpDecorate [[var0:%\w+]] Restrict -; CHECK-NEXT: OpDecorate [[var1:%\w+]] Restrict -; CHECK: [[int:%\w+]] = OpTypeInt -; CHECK: [[struct:%\w+]] = OpTypeStruct -; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]] -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: [[var1]] = OpVariable [[int_ptr]] -; CHECK-NEXT: [[var0]] = OpVariable [[int_ptr]] -; CHECK-NOT: OpVariable [[struct_ptr]] -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "restrict" -OpDecorate %var Restrict -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpAccessChain %uint_ptr %var %uint_0 -%4 = OpLoad %uint %3 -%5 = OpAccessChain %uint_ptr %var %uint_1 -%6 = OpLoad %uint %5 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontClobberDecoratesOnSubtypes) { - const std::string text = R"( -; -; CHECK: OpDecorate [[array:%\w+]] ArrayStride 1 -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[array]] = OpTypeArray [[uint]] -; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[array_ptr]] Function -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "array_stride" -OpDecorate %array ArrayStride 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%array = OpTypeArray %uint %uint_1 -%struct1 = OpTypeStruct %array -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void %uint -%1 = OpFunction %void None %func -%param = OpFunctionParameter %uint -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpAccessChain %uint_ptr %var %uint_0 %param -%4 = OpLoad %uint %3 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, DontCopyMemberDecorate) { - const std::string text = R"( -; -; CHECK-NOT: OpDecorate -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[uint_ptr]] Function -; CHECK-NOT: OpVariable -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "member_decorate" -OpMemberDecorate %struct1 0 Offset 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%struct1 = OpTypeStruct %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%func = OpTypeFunction %void %uint -%1 = OpFunction %void None %func -%2 = OpLabel -%var = OpVariable %struct1_ptr Function -%3 = OpAccessChain %uint_ptr %var %uint_0 -%4 = OpLoad %uint %3 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, NoPartialAccesses2) { - const std::string text = R"( -; -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]] -; CHECK: OpVariable [[float_ptr]] Function -; CHECK: OpVariable [[float_ptr]] Function -; CHECK: OpVariable [[float_ptr]] Function -; CHECK: OpVariable [[float_ptr]] Function -; CHECK: OpVariable [[float_ptr]] Function -; CHECK: OpVariable [[float_ptr]] Function -; CHECK: OpVariable [[float_ptr]] Function -; CHECK-NOT: OpVariable -; -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %fo -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 430 -OpName %main "main" -OpName %S "S" -OpMemberName %S 0 "x" -OpMemberName %S 1 "y" -OpName %ts1 "ts1" -OpName %S_0 "S" -OpMemberName %S_0 0 "x" -OpMemberName %S_0 1 "y" -OpName %U_t "U_t" -OpMemberName %U_t 0 "g_s1" -OpMemberName %U_t 1 "g_s2" -OpMemberName %U_t 2 "g_s3" -OpName %_ "" -OpName %ts2 "ts2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpName %__0 "" -OpName %ts3 "ts3" -OpName %ts4 "ts4" -OpName %fo "fo" -OpMemberDecorate %S_0 0 Offset 0 -OpMemberDecorate %S_0 1 Offset 4 -OpMemberDecorate %U_t 0 Offset 0 -OpMemberDecorate %U_t 1 Offset 8 -OpMemberDecorate %U_t 2 Offset 16 -OpDecorate %U_t BufferBlock -OpDecorate %_ DescriptorSet 0 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpDecorate %_Globals_ Block -OpDecorate %__0 DescriptorSet 0 -OpDecorate %__0 Binding 0 -OpDecorate %fo Location 0 -%void = OpTypeVoid -%15 = OpTypeFunction %void -%float = OpTypeFloat 32 -%S = OpTypeStruct %float %float -%_ptr_Function_S = OpTypePointer Function %S -%S_0 = OpTypeStruct %float %float -%U_t = OpTypeStruct %S_0 %S_0 %S_0 -%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t -%_ = OpVariable %_ptr_Uniform_U_t Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_S_0 = OpTypePointer Uniform %S_0 -%_ptr_Function_float = OpTypePointer Function %float -%int_1 = OpConstant %int 1 -%uint = OpTypeInt 32 0 -%_Globals_ = OpTypeStruct %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%__0 = OpVariable %_ptr_Uniform__Globals_ Uniform -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%_ptr_Output_float = OpTypePointer Output %float -%fo = OpVariable %_ptr_Output_float Output -%main = OpFunction %void None %15 -%30 = OpLabel -%ts1 = OpVariable %_ptr_Function_S Function -%ts2 = OpVariable %_ptr_Function_S Function -%ts3 = OpVariable %_ptr_Function_S Function -%ts4 = OpVariable %_ptr_Function_S Function -%31 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_0 -%32 = OpLoad %S_0 %31 -%33 = OpCompositeExtract %float %32 0 -%34 = OpAccessChain %_ptr_Function_float %ts1 %int_0 -OpStore %34 %33 -%35 = OpCompositeExtract %float %32 1 -%36 = OpAccessChain %_ptr_Function_float %ts1 %int_1 -OpStore %36 %35 -%37 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_1 -%38 = OpLoad %S_0 %37 -%39 = OpCompositeExtract %float %38 0 -%40 = OpAccessChain %_ptr_Function_float %ts2 %int_0 -OpStore %40 %39 -%41 = OpCompositeExtract %float %38 1 -%42 = OpAccessChain %_ptr_Function_float %ts2 %int_1 -OpStore %42 %41 -%43 = OpAccessChain %_ptr_Uniform_uint %__0 %int_0 -%44 = OpLoad %uint %43 -%45 = OpINotEqual %bool %44 %uint_0 -OpSelectionMerge %46 None -OpBranchConditional %45 %47 %48 -%47 = OpLabel -%49 = OpLoad %S %ts1 -OpStore %ts3 %49 -OpBranch %46 -%48 = OpLabel -%50 = OpLoad %S %ts2 -OpStore %ts3 %50 -OpBranch %46 -%46 = OpLabel -%51 = OpLoad %S %ts3 -OpStore %ts4 %51 -%52 = OpAccessChain %_ptr_Function_float %ts4 %int_1 -%53 = OpLoad %float %52 -OpStore %fo %53 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[null:%\w+]] = OpConstantNull [[uint]] -; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK-NOT: OpVariable -; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] -; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0]] [[null]] -; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0 -; CHECK: OpStore [[var1]] [[e0]] -; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]] -; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]] -; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0 -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_load" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var2 = OpVariable %struct1_ptr Function -%var1 = OpVariable %struct1_ptr Function -%load1 = OpLoad %struct1 %var1 -OpStore %var2 %load1 -%load2 = OpLoad %struct1 %var2 -%3 = OpCompositeExtract %uint %load2 0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore2) { - // TODO: We can improve this case by ensuring that |var2| is processed first. - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[null:%\w+]] = OpConstantNull [[uint]] -; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK-NOT: OpVariable -; CHECK: [[l0a:%\w+]] = OpLoad [[uint]] [[var0a]] -; CHECK: [[l0b:%\w+]] = OpLoad [[uint]] [[var0b]] -; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0b]] [[l0a]] -; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0 -; CHECK: OpStore [[var1]] [[e0]] -; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]] -; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]] -; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0 -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_load" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct1 = OpTypeStruct %uint %uint -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var1 = OpVariable %struct1_ptr Function -%var2 = OpVariable %struct1_ptr Function -%load1 = OpLoad %struct1 %var1 -OpStore %var2 %load1 -%load2 = OpLoad %struct1 %var2 -%3 = OpCompositeExtract %uint %load2 0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant1) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[null:%\w+]] = OpConstantNull [[struct_member]] -; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK-NOT: OpVariable -; CHECK: OpStore [[var1]] -; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]] -; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]] -; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0 -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_load" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct2 = OpTypeStruct %uint -%struct3 = OpTypeStruct %uint -%struct1 = OpTypeStruct %uint %struct2 -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var1 = OpVariable %struct1_ptr Function -%var2 = OpVariable %struct1_ptr Function -%load1 = OpLoad %struct1 %var1 -OpStore %var2 %load1 -%load2 = OpLoad %struct1 %var2 -%3 = OpCompositeExtract %uint %load2 0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, SpecConstantArray) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt -; CHECK: [[spec_const:%\w+]] = OpSpecConstant [[int]] 4 -; CHECK: [[spec_op:%\w+]] = OpSpecConstantOp [[int]] IAdd [[spec_const]] [[spec_const]] -; CHECK: [[array1:%\w+]] = OpTypeArray [[int]] [[spec_const]] -; CHECK: [[array2:%\w+]] = OpTypeArray [[int]] [[spec_op]] -; CHECK: [[ptr_array1:%\w+]] = OpTypePointer Function [[array1]] -; CHECK: [[ptr_array2:%\w+]] = OpTypePointer Function [[array2]] -; CHECK: OpLabel -; CHECK-NEXT: OpVariable [[ptr_array1]] Function -; CHECK-NEXT: OpVariable [[ptr_array2]] Function -; CHECK-NOT: OpVariable -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%int = OpTypeInt 32 0 -%spec_const = OpSpecConstant %int 4 -%spec_op = OpSpecConstantOp %int IAdd %spec_const %spec_const -%array_1 = OpTypeArray %int %spec_const -%array_2 = OpTypeArray %int %spec_op -%ptr_array_1_Function = OpTypePointer Function %array_1 -%ptr_array_2_Function = OpTypePointer Function %array_2 -%func = OpFunction %void None %void_fn -%1 = OpLabel -%var_1 = OpVariable %ptr_array_1_Function Function -%var_2 = OpVariable %ptr_array_2_Function Function -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant2) { - const std::string text = R"( -; -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]] -; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]] -; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0 -; CHECK: [[null:%\w+]] = OpConstantNull [[struct_member]] -; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function -; CHECK: OpStore [[var1]] -; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]] -; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[null]] -; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0 -; -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %func "replace_whole_load" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct3 = OpTypeStruct %uint -%struct2 = OpTypeStruct %uint -%struct1 = OpTypeStruct %uint %struct2 -%uint_ptr = OpTypePointer Function %uint -%struct1_ptr = OpTypePointer Function %struct1 -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%func = OpTypeFunction %void -%1 = OpFunction %void None %func -%2 = OpLabel -%var1 = OpVariable %struct1_ptr Function -%var2 = OpVariable %struct1_ptr Function -%load1 = OpLoad %struct1 %var1 -OpStore %var2 %load1 -%load2 = OpLoad %struct1 %var2 -%3 = OpCompositeExtract %uint %load2 0 -OpReturn -OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -// Test that a struct of size 4 is not replaced when there is a limit of 2. -TEST_F(ScalarReplacementTest, TestLimit) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "simple_struct" -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %2 %2 %2 %2 -%4 = OpTypePointer Function %3 -%5 = OpTypePointer Function %2 -%6 = OpTypeFunction %2 -%7 = OpConstantNull %3 -%8 = OpConstant %2 0 -%9 = OpConstant %2 1 -%10 = OpConstant %2 2 -%11 = OpConstant %2 3 -%12 = OpFunction %2 None %6 -%13 = OpLabel -%14 = OpVariable %4 Function %7 -%15 = OpInBoundsAccessChain %5 %14 %8 -%16 = OpLoad %2 %15 -%17 = OpAccessChain %5 %14 %10 -%18 = OpLoad %2 %17 -%19 = OpIAdd %2 %16 %18 -OpReturnValue %19 -OpFunctionEnd - )"; - - auto result = - SinglePassRunAndDisassemble(text, true, false, 2); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// Test that a struct of size 4 is replaced when there is a limit of 0 (no -// limit). This is the same spir-v as a test above, so we do not check that it -// is correctly transformed. We leave that to the test above. -TEST_F(ScalarReplacementTest, TestUnimited) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %6 "simple_struct" -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeStruct %2 %2 %2 %2 -%4 = OpTypePointer Function %3 -%5 = OpTypePointer Function %2 -%6 = OpTypeFunction %2 -%7 = OpConstantNull %3 -%8 = OpConstant %2 0 -%9 = OpConstant %2 1 -%10 = OpConstant %2 2 -%11 = OpConstant %2 3 -%12 = OpFunction %2 None %6 -%13 = OpLabel -%14 = OpVariable %4 Function %7 -%15 = OpInBoundsAccessChain %5 %14 %8 -%16 = OpLoad %2 %15 -%17 = OpAccessChain %5 %14 %10 -%18 = OpLoad %2 %17 -%19 = OpIAdd %2 %16 %18 -OpReturnValue %19 -OpFunctionEnd - )"; - - auto result = - SinglePassRunAndDisassemble(text, true, false, 0); - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); -} - -TEST_F(ScalarReplacementTest, AmbigousPointer) { - const std::string text = R"( -; CHECK: [[s1:%\w+]] = OpTypeStruct %uint -; CHECK: [[s2:%\w+]] = OpTypeStruct %uint -; CHECK: [[s3:%\w+]] = OpTypeStruct [[s2]] -; CHECK: [[s3_const:%\w+]] = OpConstantComposite [[s3]] -; CHECK: [[s2_ptr:%\w+]] = OpTypePointer Function [[s2]] -; CHECK: OpCompositeExtract [[s2]] [[s3_const]] - - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %_struct_7 = OpTypeStruct %uint - %_struct_8 = OpTypeStruct %uint - %_struct_9 = OpTypeStruct %_struct_8 - %uint_1 = OpConstant %uint 1 - %11 = OpConstantComposite %_struct_8 %uint_1 - %12 = OpConstantComposite %_struct_9 %11 -%_ptr_Function__struct_9 = OpTypePointer Function %_struct_9 -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %2 = OpFunction %void None %5 - %15 = OpLabel - %var = OpVariable %_ptr_Function__struct_9 Function - OpStore %var %12 - %ld = OpLoad %_struct_9 %var - %ex = OpCompositeExtract %_struct_8 %ld 0 - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -// Test that scalar replacement does not crash when there is an OpAccessChain -// with no index. If we choose to handle this case in the future, then the -// result can change. -TEST_F(ScalarReplacementTest, TestAccessChainWithNoIndexes) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginLowerLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %_struct_5 = OpTypeStruct %float -%_ptr_Function__struct_5 = OpTypePointer Function %_struct_5 - %1 = OpFunction %void None %3 - %7 = OpLabel - %8 = OpVariable %_ptr_Function__struct_5 Function - %9 = OpAccessChain %_ptr_Function__struct_5 %8 - OpReturn - OpFunctionEnd - )"; - - auto result = - SinglePassRunAndDisassemble(text, true, false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// Test that id overflow is handled gracefully. -TEST_F(ScalarReplacementTest, IdBoundOverflow1) { - const std::string text = R"( -OpCapability ImageQuery -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" -OpExecutionMode %4 OriginUpperLeft -OpDecorate %4194302 DescriptorSet 1073495039 -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeFloat 32 -%7 = OpTypeStruct %6 %6 -%557056 = OpTypeStruct %7 -%9 = OpTypePointer Function %7 -%18 = OpTypeFunction %7 %9 -%4 = OpFunction %2 Pure|Const %3 -%1836763 = OpLabel -%4194302 = OpVariable %9 Function -%10 = OpVariable %9 Function -OpKill -%4194301 = OpLabel -%524296 = OpLoad %7 %4194302 -OpKill -OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true, false); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -// Test that id overflow is handled gracefully. -TEST_F(ScalarReplacementTest, IdBoundOverflow2) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" %17 -OpExecutionMode %4 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeFloat 32 -%7 = OpTypeVector %6 4 -%8 = OpTypeStruct %7 -%9 = OpTypePointer Function %8 -%16 = OpTypePointer Output %7 -%21 = OpTypeInt 32 1 -%22 = OpConstant %21 0 -%23 = OpTypePointer Function %7 -%17 = OpVariable %16 Output -%4 = OpFunction %2 None %3 -%5 = OpLabel -%4194300 = OpVariable %23 Function -%10 = OpVariable %9 Function -%4194301 = OpAccessChain %23 %10 %22 -%4194302 = OpLoad %7 %4194301 -OpStore %4194300 %4194302 -%15 = OpLoad %7 %4194300 -OpStore %17 %15 -OpReturn -OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true, false); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -// Test that id overflow is handled gracefully. -TEST_F(ScalarReplacementTest, IdBoundOverflow3) { - const std::string text = R"( -OpCapability InterpolationFunction -OpExtension "z" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" -OpExecutionMode %4 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeFloat 32 -%7 = OpTypeStruct %6 %6 -%9 = OpTypePointer Function %7 -%18 = OpTypeFunction %7 %9 -%21 = OpTypeInt 32 0 -%22 = OpConstant %21 4293000676 -%4194302 = OpConstantNull %6 -%4 = OpFunction %2 Inline|Pure %3 -%786464 = OpLabel -%4194298 = OpVariable %9 Function -%10 = OpVariable %9 Function -%4194299 = OpUDiv %21 %22 %22 -%4194300 = OpLoad %7 %10 -%50959 = OpLoad %7 %4194298 -OpKill -OpFunctionEnd -%1 = OpFunction %7 None %18 -%19 = OpFunctionParameter %9 -%147667 = OpLabel -%2044391 = OpUDiv %21 %22 %22 -%25 = OpLoad %7 %19 -OpReturnValue %25 -OpFunctionEnd -%4194295 = OpFunction %2 None %3 -%4194296 = OpLabel -OpKill -OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}, - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true, false); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -// Test that replacements for OpAccessChain do not go out of bounds. -// https://github.com/KhronosGroup/SPIRV-Tools/issues/2609. -TEST_F(ScalarReplacementTest, OutOfBoundOpAccessChain) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %_GLF_color - OpExecutionMode %main OriginUpperLeft - OpSource ESSL 310 - OpName %main "main" - OpName %a "a" - OpName %_GLF_color "_GLF_color" - OpDecorate %_GLF_color Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_1 = OpConstant %int 1 - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1 -%_ptr_Function_float = OpTypePointer Function %float -%_ptr_Output_float = OpTypePointer Output %float - %_GLF_color = OpVariable %_ptr_Output_float Output - %main = OpFunction %void None %3 - %5 = OpLabel - %a = OpVariable %_ptr_Function__arr_float_uint_1 Function - %21 = OpAccessChain %_ptr_Function_float %a %int_1 - %22 = OpLoad %float %21 - OpStore %_GLF_color %22 - OpReturn - OpFunctionEnd - )"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - auto result = - SinglePassRunAndDisassemble(text, true, false); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(ScalarReplacementTest, CharIndex) { - const std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer Function [[int]] -; CHECK: OpVariable [[ptr]] Function -OpCapability Shader -OpCapability Int8 -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_1024 = OpConstant %int 1024 -%char = OpTypeInt 8 0 -%char_1 = OpConstant %char 1 -%array = OpTypeArray %int %int_1024 -%ptr_func_array = OpTypePointer Function %array -%ptr_func_int = OpTypePointer Function %int -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%var = OpVariable %ptr_func_array Function -%gep = OpAccessChain %ptr_func_int %var %char_1 -OpStore %gep %int_1024 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true, 0); -} - -TEST_F(ScalarReplacementTest, OutOfBoundsOpAccessChainNegative) { - const std::string text = R"( -OpCapability Shader -OpCapability Int8 -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_1024 = OpConstant %int 1024 -%char = OpTypeInt 8 1 -%char_n1 = OpConstant %char -1 -%array = OpTypeArray %int %int_1024 -%ptr_func_array = OpTypePointer Function %array -%ptr_func_int = OpTypePointer Function %int -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%var = OpVariable %ptr_func_array Function -%gep = OpAccessChain %ptr_func_int %var %char_n1 -OpStore %gep %int_1024 -OpReturn -OpFunctionEnd -)"; - - auto result = - SinglePassRunAndDisassemble(text, true, true, 0); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(ScalarReplacementTest, RelaxedPrecisionMemberDecoration) { - const std::string text = R"( -; CHECK: OpDecorate {{%\w+}} RelaxedPrecision -; CHECK: OpDecorate [[new_var:%\w+]] RelaxedPrecision -; CHECK: [[new_var]] = OpVariable %_ptr_Function_v3float Function -; CHECK: OpLoad %v3float [[new_var]] - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "Draw2DTexCol_VS" %2 %3 - OpSource HLSL 600 - OpDecorate %2 Location 0 - OpDecorate %3 Location 1 - OpDecorate %3 RelaxedPrecision - OpMemberDecorate %_struct_4 1 RelaxedPrecision - %float = OpTypeFloat 32 - %int = OpTypeInt 32 1 - %int_1 = OpConstant %int 1 - %v3float = OpTypeVector %float 3 -%_ptr_Input_v3float = OpTypePointer Input %v3float - %void = OpTypeVoid - %11 = OpTypeFunction %void - %_struct_4 = OpTypeStruct %v3float %v3float -%_ptr_Function__struct_4 = OpTypePointer Function %_struct_4 -%_ptr_Function_v3float = OpTypePointer Function %v3float - %2 = OpVariable %_ptr_Input_v3float Input - %3 = OpVariable %_ptr_Input_v3float Input - %1 = OpFunction %void None %11 - %14 = OpLabel - %15 = OpVariable %_ptr_Function__struct_4 Function - %16 = OpLoad %v3float %2 - %17 = OpLoad %v3float %3 - %18 = OpCompositeConstruct %_struct_4 %16 %17 - OpStore %15 %18 - %19 = OpAccessChain %_ptr_Function_v3float %15 %int_1 - %20 = OpLoad %v3float %19 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/set_spec_const_default_value_test.cpp b/3rdparty/spirv-tools/test/opt/set_spec_const_default_value_test.cpp deleted file mode 100644 index 5e63862e9..000000000 --- a/3rdparty/spirv-tools/test/opt/set_spec_const_default_value_test.cpp +++ /dev/null @@ -1,1077 +0,0 @@ -// 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 "gmock/gmock.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using testing::Eq; -using SpecIdToValueStrMap = - SetSpecConstantDefaultValuePass::SpecIdToValueStrMap; -using SpecIdToValueBitPatternMap = - SetSpecConstantDefaultValuePass::SpecIdToValueBitPatternMap; - -struct DefaultValuesStringParsingTestCase { - const char* default_values_str; - bool expect_success; - SpecIdToValueStrMap expected_map; -}; - -using DefaultValuesStringParsingTest = - ::testing::TestWithParam; - -TEST_P(DefaultValuesStringParsingTest, TestCase) { - const auto& tc = GetParam(); - auto actual_map = SetSpecConstantDefaultValuePass::ParseDefaultValuesString( - tc.default_values_str); - if (tc.expect_success) { - EXPECT_NE(nullptr, actual_map); - if (actual_map) { - EXPECT_THAT(*actual_map, Eq(tc.expected_map)); - } - } else { - EXPECT_EQ(nullptr, actual_map); - } -} - -INSTANTIATE_TEST_SUITE_P( - ValidString, DefaultValuesStringParsingTest, - ::testing::ValuesIn(std::vector{ - // 0. empty map - {"", true, SpecIdToValueStrMap{}}, - // 1. one pair - {"100:1024", true, SpecIdToValueStrMap{{100, "1024"}}}, - // 2. two pairs - {"100:1024 200:2048", true, - SpecIdToValueStrMap{{100, "1024"}, {200, "2048"}}}, - // 3. spaces between entries - {"100:1024 \n \r \t \v \f 200:2048", true, - SpecIdToValueStrMap{{100, "1024"}, {200, "2048"}}}, - // 4. \t, \n, \r and spaces before spec id - {" \n \r\t \t \v \f 100:1024", true, - SpecIdToValueStrMap{{100, "1024"}}}, - // 5. \t, \n, \r and spaces after value string - {"100:1024 \n \r\t \t \v \f ", true, - SpecIdToValueStrMap{{100, "1024"}}}, - // 6. maximum spec id - {"4294967295:0", true, SpecIdToValueStrMap{{4294967295, "0"}}}, - // 7. minimum spec id - {"0:100", true, SpecIdToValueStrMap{{0, "100"}}}, - // 8. random content without spaces are allowed - {"200:random_stuff", true, SpecIdToValueStrMap{{200, "random_stuff"}}}, - // 9. support hex format spec id (just because we use the - // ParseNumber() utility) - {"0x100:1024", true, SpecIdToValueStrMap{{256, "1024"}}}, - // 10. multiple entries - {"101:1 102:2 103:3 104:4 200:201 9999:1000 0x100:333", true, - SpecIdToValueStrMap{{101, "1"}, - {102, "2"}, - {103, "3"}, - {104, "4"}, - {200, "201"}, - {9999, "1000"}, - {256, "333"}}}, - // 11. default value in hex float format - {"100:0x0.3p10", true, SpecIdToValueStrMap{{100, "0x0.3p10"}}}, - // 12. default value in decimal float format - {"100:1.5e-13", true, SpecIdToValueStrMap{{100, "1.5e-13"}}}, - })); - -INSTANTIATE_TEST_SUITE_P( - InvalidString, DefaultValuesStringParsingTest, - ::testing::ValuesIn(std::vector{ - // 0. missing default value - {"100:", false, SpecIdToValueStrMap{}}, - // 1. spec id is not an integer - {"100.0:200", false, SpecIdToValueStrMap{}}, - // 2. spec id is not a number - {"something_not_a_number:1", false, SpecIdToValueStrMap{}}, - // 3. only spec id number - {"100", false, SpecIdToValueStrMap{}}, - // 4. same spec id defined multiple times - {"100:20 100:21", false, SpecIdToValueStrMap{}}, - // 5. Multiple definition of an identical spec id in different forms - // is not allowed - {"0x100:100 256:200", false, SpecIdToValueStrMap{}}, - // 6. empty spec id - {":3", false, SpecIdToValueStrMap{}}, - // 7. only colon - {":", false, SpecIdToValueStrMap{}}, - // 8. spec id overflow - {"4294967296:200", false, SpecIdToValueStrMap{}}, - // 9. spec id less than 0 - {"-1:200", false, SpecIdToValueStrMap{}}, - // 10. nullptr - {nullptr, false, SpecIdToValueStrMap{}}, - // 11. only a number is invalid - {"1234", false, SpecIdToValueStrMap{}}, - // 12. invalid entry separator - {"12:34;23:14", false, SpecIdToValueStrMap{}}, - // 13. invalid spec id and default value separator - {"12@34", false, SpecIdToValueStrMap{}}, - // 14. spaces before colon - {"100 :1024", false, SpecIdToValueStrMap{}}, - // 15. spaces after colon - {"100: 1024", false, SpecIdToValueStrMap{}}, - // 16. spec id represented in hex float format is invalid - {"0x3p10:200", false, SpecIdToValueStrMap{}}, - })); - -struct SetSpecConstantDefaultValueInStringFormTestCase { - const char* code; - SpecIdToValueStrMap default_values; - const char* expected; -}; - -using SetSpecConstantDefaultValueInStringFormParamTest = PassTest< - ::testing::TestWithParam>; - -TEST_P(SetSpecConstantDefaultValueInStringFormParamTest, TestCase) { - const auto& tc = GetParam(); - SinglePassRunAndCheck( - tc.code, tc.expected, /* skip_nop = */ false, tc.default_values); -} - -INSTANTIATE_TEST_SUITE_P( - ValidCases, SetSpecConstantDefaultValueInStringFormParamTest, - ::testing::ValuesIn(std::vector< - SetSpecConstantDefaultValueInStringFormTestCase>{ - // 0. Empty. - {"", SpecIdToValueStrMap{}, ""}, - // 1. Empty with non-empty values to set. - {"", SpecIdToValueStrMap{{1, "100"}, {2, "200"}}, ""}, - // 2. Bool type. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n", - // default values - SpecIdToValueStrMap{{100, "false"}, {101, "true"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantFalse %bool\n" - "%2 = OpSpecConstantTrue %bool\n", - }, - // 3. 32-bit int type. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 10\n" - "%2 = OpSpecConstant %int 11\n" - "%3 = OpSpecConstant %int 11\n", - // default values - SpecIdToValueStrMap{ - {100, "2147483647"}, {101, "0xffffffff"}, {102, "-42"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 2147483647\n" - "%2 = OpSpecConstant %int -1\n" - "%3 = OpSpecConstant %int -42\n", - }, - // 4. 64-bit uint type. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %ulong 10\n" - "%2 = OpSpecConstant %ulong 11\n", - // default values - SpecIdToValueStrMap{{100, "18446744073709551614"}, {101, "0x100"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %ulong 18446744073709551614\n" - "%2 = OpSpecConstant %ulong 256\n", - }, - // 5. 32-bit float type. - { - // code - "OpDecorate %1 SpecId 101\n" - "OpDecorate %2 SpecId 102\n" - "%float = OpTypeFloat 32\n" - "%1 = OpSpecConstant %float 200\n" - "%2 = OpSpecConstant %float 201\n", - // default values - SpecIdToValueStrMap{{101, "-0x1.fffffep+128"}, {102, "2.5"}}, - // expected - "OpDecorate %1 SpecId 101\n" - "OpDecorate %2 SpecId 102\n" - "%float = OpTypeFloat 32\n" - "%1 = OpSpecConstant %float -0x1.fffffep+128\n" - "%2 = OpSpecConstant %float 2.5\n", - }, - // 6. 64-bit float type. - { - // code - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n" - "%2 = OpSpecConstant %double 0.14285\n", - // default values - SpecIdToValueStrMap{{201, "0x1.fffffffffffffp+1024"}, - {202, "-32.5"}}, - // expected - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n" - "%2 = OpSpecConstant %double -32.5\n", - }, - // 7. SpecId not found, expect no modification. - { - // code - "OpDecorate %1 SpecId 201\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n", - // default values - SpecIdToValueStrMap{{8888, "0.0"}}, - // expected - "OpDecorate %1 SpecId 201\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n", - }, - // 8. Multiple types of spec constants. - { - // code - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "OpDecorate %3 SpecId 203\n" - "%bool = OpTypeBool\n" - "%int = OpTypeInt 32 1\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n" - "%2 = OpSpecConstant %int 1024\n" - "%3 = OpSpecConstantTrue %bool\n", - // default values - SpecIdToValueStrMap{ - {201, "0x1.fffffffffffffp+1024"}, - {202, "2048"}, - {203, "false"}, - }, - // expected - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "OpDecorate %3 SpecId 203\n" - "%bool = OpTypeBool\n" - "%int = OpTypeInt 32 1\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n" - "%2 = OpSpecConstant %int 2048\n" - "%3 = OpSpecConstantFalse %bool\n", - }, - // 9. Ignore other decorations. - { - // code - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{4, "0x7fffffff"}}, - // expected - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 100\n", - }, - // 10. Distinguish from other decorations. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{4, "0x7fffffff"}, {100, "0xffffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int -1\n", - }, - // 11. Decorate through decoration group. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{100, "0x7fffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 2147483647\n", - }, - // 12. Ignore other decorations in decoration group. - { - // code - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{4, "0x7fffffff"}}, - // expected - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - }, - // 13. Distinguish from other decorations in decoration group. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{100, "0x7fffffff"}, {4, "0x00000001"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 2147483647\n", - }, - // 14. Unchanged bool default value - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n", - // default values - SpecIdToValueStrMap{{100, "true"}, {101, "false"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n", - }, - // 15. Unchanged int default values - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%int = OpTypeInt 32 1\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %int 10\n" - "%2 = OpSpecConstant %ulong 11\n", - // default values - SpecIdToValueStrMap{{100, "10"}, {101, "11"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%int = OpTypeInt 32 1\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %int 10\n" - "%2 = OpSpecConstant %ulong 11\n", - }, - // 16. Unchanged float default values - { - // code - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%float = OpTypeFloat 32\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %float 3.1415\n" - "%2 = OpSpecConstant %double 0.14285\n", - // default values - SpecIdToValueStrMap{{201, "3.1415"}, {202, "0.14285"}}, - // expected - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%float = OpTypeFloat 32\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %float 3.1415\n" - "%2 = OpSpecConstant %double 0.14285\n", - }, - // 17. OpGroupDecorate may have multiple target ids defined by the same - // eligible spec constant - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %2 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{100, "0xffffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %2 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int -1\n", - }, - })); - -INSTANTIATE_TEST_SUITE_P( - InvalidCases, SetSpecConstantDefaultValueInStringFormParamTest, - ::testing::ValuesIn(std::vector< - SetSpecConstantDefaultValueInStringFormTestCase>{ - // 0. Do not crash when decoration group is not used. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueStrMap{{100, "0x7fffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 100\n", - }, - // 1. Do not crash when target does not exist. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n", - // default values - SpecIdToValueStrMap{{100, "0x7fffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n", - }, - // 2. Do nothing when SpecId decoration is not attached to a - // non-spec-constant instruction. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%int_101 = OpConstant %int 101\n", - // default values - SpecIdToValueStrMap{{100, "0x7fffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%int_101 = OpConstant %int 101\n", - }, - // 3. Do nothing when SpecId decoration is not attached to a - // OpSpecConstant{|True|False} instruction. - { - // code - "OpDecorate %1 SpecId 100\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 101\n" - "%1 = OpSpecConstantOp %int IAdd %3 %3\n", - // default values - SpecIdToValueStrMap{{100, "0x7fffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 101\n" - "%1 = OpSpecConstantOp %int IAdd %3 %3\n", - }, - // 4. Do not crash and do nothing when SpecId decoration is applied to - // multiple spec constants. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %3 %4\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n" - "%3 = OpSpecConstant %int 200\n" - "%4 = OpSpecConstant %int 300\n", - // default values - SpecIdToValueStrMap{{100, "0xffffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %3 %4\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n" - "%3 = OpSpecConstant %int 200\n" - "%4 = OpSpecConstant %int 300\n", - }, - // 5. Do not crash and do nothing when SpecId decoration is attached to - // non-spec-constants (invalid case). - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%2 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%int_100 = OpConstant %int 100\n", - // default values - SpecIdToValueStrMap{{100, "0xffffffff"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%2 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%int_100 = OpConstant %int 100\n", - }, - // 6. Boolean type spec constant cannot be set with numeric values in - // string form. i.e. only 'true' and 'false' are acceptable for setting - // boolean type spec constants. Nothing should be done if numeric values - // in string form are provided. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "OpDecorate %4 SpecId 103\n" - "OpDecorate %5 SpecId 104\n" - "OpDecorate %6 SpecId 105\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n" - "%3 = OpSpecConstantTrue %bool\n" - "%4 = OpSpecConstantTrue %bool\n" - "%5 = OpSpecConstantTrue %bool\n" - "%6 = OpSpecConstantFalse %bool\n", - // default values - SpecIdToValueStrMap{{100, "0"}, - {101, "1"}, - {102, "0x0"}, - {103, "0.0"}, - {104, "-0.0"}, - {105, "0x12345678"}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "OpDecorate %4 SpecId 103\n" - "OpDecorate %5 SpecId 104\n" - "OpDecorate %6 SpecId 105\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n" - "%3 = OpSpecConstantTrue %bool\n" - "%4 = OpSpecConstantTrue %bool\n" - "%5 = OpSpecConstantTrue %bool\n" - "%6 = OpSpecConstantFalse %bool\n", - }, - })); - -struct SetSpecConstantDefaultValueInBitPatternFormTestCase { - const char* code; - SpecIdToValueBitPatternMap default_values; - const char* expected; -}; - -using SetSpecConstantDefaultValueInBitPatternFormParamTest = - PassTest<::testing::TestWithParam< - SetSpecConstantDefaultValueInBitPatternFormTestCase>>; - -TEST_P(SetSpecConstantDefaultValueInBitPatternFormParamTest, TestCase) { - const auto& tc = GetParam(); - SinglePassRunAndCheck( - tc.code, tc.expected, /* skip_nop = */ false, tc.default_values); -} - -INSTANTIATE_TEST_SUITE_P( - ValidCases, SetSpecConstantDefaultValueInBitPatternFormParamTest, - ::testing::ValuesIn(std::vector< - SetSpecConstantDefaultValueInBitPatternFormTestCase>{ - // 0. Empty. - {"", SpecIdToValueBitPatternMap{}, ""}, - // 1. Empty with non-empty values to set. - {"", SpecIdToValueBitPatternMap{{1, {100}}, {2, {200}}}, ""}, - // 2. Baisc bool type. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x0}}, {101, {0x1}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantFalse %bool\n" - "%2 = OpSpecConstantTrue %bool\n", - }, - // 3. 32-bit int type. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 10\n" - "%2 = OpSpecConstant %int 11\n" - "%3 = OpSpecConstant %int 11\n", - // default values - SpecIdToValueBitPatternMap{ - {100, {2147483647}}, {101, {0xffffffff}}, {102, {0xffffffd6}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 2147483647\n" - "%2 = OpSpecConstant %int -1\n" - "%3 = OpSpecConstant %int -42\n", - }, - // 4. 64-bit uint type. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %ulong 10\n" - "%2 = OpSpecConstant %ulong 11\n", - // default values - SpecIdToValueBitPatternMap{{100, {0xFFFFFFFE, 0xFFFFFFFF}}, - {101, {0x100, 0x0}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %ulong 18446744073709551614\n" - "%2 = OpSpecConstant %ulong 256\n", - }, - // 5. 32-bit float type. - { - // code - "OpDecorate %1 SpecId 101\n" - "OpDecorate %2 SpecId 102\n" - "%float = OpTypeFloat 32\n" - "%1 = OpSpecConstant %float 200\n" - "%2 = OpSpecConstant %float 201\n", - // default values - SpecIdToValueBitPatternMap{{101, {0xffffffff}}, - {102, {0x40200000}}}, - // expected - "OpDecorate %1 SpecId 101\n" - "OpDecorate %2 SpecId 102\n" - "%float = OpTypeFloat 32\n" - "%1 = OpSpecConstant %float -0x1.fffffep+128\n" - "%2 = OpSpecConstant %float 2.5\n", - }, - // 6. 64-bit float type. - { - // code - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n" - "%2 = OpSpecConstant %double 0.14285\n", - // default values - SpecIdToValueBitPatternMap{{201, {0xffffffff, 0x7fffffff}}, - {202, {0x00000000, 0xc0404000}}}, - // expected - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n" - "%2 = OpSpecConstant %double -32.5\n", - }, - // 7. SpecId not found, expect no modification. - { - // code - "OpDecorate %1 SpecId 201\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n", - // default values - SpecIdToValueBitPatternMap{{8888, {0x0}}}, - // expected - "OpDecorate %1 SpecId 201\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n", - }, - // 8. Multiple types of spec constants. - { - // code - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "OpDecorate %3 SpecId 203\n" - "%bool = OpTypeBool\n" - "%int = OpTypeInt 32 1\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 3.14159265358979\n" - "%2 = OpSpecConstant %int 1024\n" - "%3 = OpSpecConstantTrue %bool\n", - // default values - SpecIdToValueBitPatternMap{ - {201, {0xffffffff, 0x7fffffff}}, - {202, {0x00000800}}, - {203, {0x0}}, - }, - // expected - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "OpDecorate %3 SpecId 203\n" - "%bool = OpTypeBool\n" - "%int = OpTypeInt 32 1\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n" - "%2 = OpSpecConstant %int 2048\n" - "%3 = OpSpecConstantFalse %bool\n", - }, - // 9. Ignore other decorations. - { - // code - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{4, {0x7fffffff}}}, - // expected - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 100\n", - }, - // 10. Distinguish from other decorations. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{4, {0x7fffffff}}, {100, {0xffffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%int = OpTypeInt 32 1\n" - "%1 = OpSpecConstant %int -1\n", - }, - // 11. Decorate through decoration group. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x7fffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 2147483647\n", - }, - // 12. Ignore other decorations in decoration group. - { - // code - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{4, {0x7fffffff}}}, - // expected - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - }, - // 13. Distinguish from other decorations in decoration group. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x7fffffff}}, {4, {0x00000001}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %1 ArrayStride 4\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 2147483647\n", - }, - // 14. Unchanged bool default value - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x1}}, {101, {0x0}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n", - }, - // 15. Unchanged int default values - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%int = OpTypeInt 32 1\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %int 10\n" - "%2 = OpSpecConstant %ulong 11\n", - // default values - SpecIdToValueBitPatternMap{{100, {10}}, {101, {11, 0}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "%int = OpTypeInt 32 1\n" - "%ulong = OpTypeInt 64 0\n" - "%1 = OpSpecConstant %int 10\n" - "%2 = OpSpecConstant %ulong 11\n", - }, - // 16. Unchanged float default values - { - // code - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%float = OpTypeFloat 32\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %float 3.25\n" - "%2 = OpSpecConstant %double 1.25\n", - // default values - SpecIdToValueBitPatternMap{{201, {0x40500000}}, - {202, {0x00000000, 0x3ff40000}}}, - // expected - "OpDecorate %1 SpecId 201\n" - "OpDecorate %2 SpecId 202\n" - "%float = OpTypeFloat 32\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %float 3.25\n" - "%2 = OpSpecConstant %double 1.25\n", - }, - // 17. OpGroupDecorate may have multiple target ids defined by the same - // eligible spec constant - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %2 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{100, {0xffffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %2 %2\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int -1\n", - }, - // 18. For Boolean type spec constants,if any word in the bit pattern - // is not zero, it can be considered as a 'true', otherwise, it can be - // considered as a 'false'. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantTrue %bool\n" - "%2 = OpSpecConstantFalse %bool\n" - "%3 = OpSpecConstantFalse %bool\n", - // default values - SpecIdToValueBitPatternMap{ - {100, {0x0, 0x0, 0x0, 0x0}}, - {101, {0x10101010}}, - {102, {0x0, 0x0, 0x0, 0x2}}, - }, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%bool = OpTypeBool\n" - "%1 = OpSpecConstantFalse %bool\n" - "%2 = OpSpecConstantTrue %bool\n" - "%3 = OpSpecConstantTrue %bool\n", - }, - })); - -INSTANTIATE_TEST_SUITE_P( - InvalidCases, SetSpecConstantDefaultValueInBitPatternFormParamTest, - ::testing::ValuesIn(std::vector< - SetSpecConstantDefaultValueInBitPatternFormTestCase>{ - // 0. Do not crash when decoration group is not used. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x7fffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 100\n", - }, - // 1. Do not crash when target does not exist. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x7fffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n", - }, - // 2. Do nothing when SpecId decoration is not attached to a - // non-spec-constant instruction. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%int_101 = OpConstant %int 101\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x7fffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%int = OpTypeInt 32 1\n" - "%int_101 = OpConstant %int 101\n", - }, - // 3. Do nothing when SpecId decoration is not attached to a - // OpSpecConstant{|True|False} instruction. - { - // code - "OpDecorate %1 SpecId 100\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 101\n" - "%1 = OpSpecConstantOp %int IAdd %3 %3\n", - // default values - SpecIdToValueBitPatternMap{{100, {0x7fffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%int = OpTypeInt 32 1\n" - "%3 = OpSpecConstant %int 101\n" - "%1 = OpSpecConstantOp %int IAdd %3 %3\n", - }, - // 4. Do not crash and do nothing when SpecId decoration is applied to - // multiple spec constants. - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %3 %4\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n" - "%3 = OpSpecConstant %int 200\n" - "%4 = OpSpecConstant %int 300\n", - // default values - SpecIdToValueBitPatternMap{{100, {0xffffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2 %3 %4\n" - "%int = OpTypeInt 32 1\n" - "%2 = OpSpecConstant %int 100\n" - "%3 = OpSpecConstant %int 200\n" - "%4 = OpSpecConstant %int 300\n", - }, - // 5. Do not crash and do nothing when SpecId decoration is attached to - // non-spec-constants (invalid case). - { - // code - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%2 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%int_100 = OpConstant %int 100\n", - // default values - SpecIdToValueBitPatternMap{{100, {0xffffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "%1 = OpDecorationGroup\n" - "%2 = OpDecorationGroup\n" - "OpGroupDecorate %1 %2\n" - "%int = OpTypeInt 32 1\n" - "%int_100 = OpConstant %int 100\n", - }, - // 6. Incompatible input bit pattern with the type. Nothing should be - // done in such a case. - { - // code - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%int = OpTypeInt 32 1\n" - "%ulong = OpTypeInt 64 0\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %int 100\n" - "%2 = OpSpecConstant %ulong 200\n" - "%3 = OpSpecConstant %double 3.141592653\n", - // default values - SpecIdToValueBitPatternMap{ - {100, {10, 0}}, {101, {11}}, {102, {0xffffffff}}}, - // expected - "OpDecorate %1 SpecId 100\n" - "OpDecorate %2 SpecId 101\n" - "OpDecorate %3 SpecId 102\n" - "%int = OpTypeInt 32 1\n" - "%ulong = OpTypeInt 64 0\n" - "%double = OpTypeFloat 64\n" - "%1 = OpSpecConstant %int 100\n" - "%2 = OpSpecConstant %ulong 200\n" - "%3 = OpSpecConstant %double 3.141592653\n", - }, - })); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/simplification_test.cpp b/3rdparty/spirv-tools/test/opt/simplification_test.cpp deleted file mode 100644 index 7a9696eab..000000000 --- a/3rdparty/spirv-tools/test/opt/simplification_test.cpp +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" -#include "source/opt/simplification_pass.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using SimplificationTest = PassTest<::testing::Test>; - -TEST_F(SimplificationTest, StraightLineTest) { - // Testing that folding rules are combined in simple straight line code. - const std::string text = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %i %o - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %i "i" - OpName %o "o" - OpDecorate %i Flat - OpDecorate %i Location 0 - OpDecorate %o Location 0 - %void = OpTypeVoid - %8 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %v4int = OpTypeVector %int 4 - %int_0 = OpConstant %int 0 - %13 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 - %int_1 = OpConstant %int 1 -%_ptr_Input_v4int = OpTypePointer Input %v4int - %i = OpVariable %_ptr_Input_v4int Input -%_ptr_Output_int = OpTypePointer Output %int - %o = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %8 - %21 = OpLabel - %31 = OpCompositeInsert %v4int %int_1 %13 0 -; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad - %23 = OpLoad %v4int %i - %33 = OpCompositeInsert %v4int %int_0 %23 0 - %35 = OpCompositeExtract %int %31 0 -; CHECK: [[extract:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 1 - %37 = OpCompositeExtract %int %33 1 -; CHECK: [[add:%[a-zA-Z_\d]+]] = OpIAdd %int %int_1 [[extract]] - %29 = OpIAdd %int %35 %37 - OpStore %o %29 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(SimplificationTest, NewInstructionTest) { - // Testing that new instructions are simplified. Specifically, - // that the new add instruction generated by FactorAddMul is - // further simplified by MergeGenericAddSub. - const std::string text = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %_ptr_int = OpTypePointer Function %int -; CHECK: [[mul:%[a-zA-Z_\d]+]] = OpIMul %int %13 %11 - %main = OpFunction %void None %4 - %7 = OpLabel - %8 = OpVariable %_ptr_int Function - %9 = OpVariable %_ptr_int Function - %10 = OpVariable %_ptr_int Function - %11 = OpLoad %int %8 - %12 = OpLoad %int %9 - %13 = OpLoad %int %10 - %14 = OpISub %int %11 %12 - %15 = OpIMul %int %13 %11 - %16 = OpIMul %int %13 %12 - %17 = OpIAdd %int %14 %15 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(SimplificationTest, AcrossBasicBlocks) { - // Testing that folding rules are combined across basic blocks. - const std::string text = R"(OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %i %o - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %i "i" - OpName %o "o" - OpDecorate %i Flat - OpDecorate %i Location 0 - OpDecorate %o Location 0 - %void = OpTypeVoid - %8 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %v4int = OpTypeVector %int 4 - %int_0 = OpConstant %int 0 -%_ptr_Input_v4int = OpTypePointer Input %v4int - %i = OpVariable %_ptr_Input_v4int Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_int = OpTypePointer Input %int - %int_10 = OpConstant %int 10 - %bool = OpTypeBool - %int_1 = OpConstant %int 1 -%_ptr_Output_int = OpTypePointer Output %int - %o = OpVariable %_ptr_Output_int Output - %main = OpFunction %void None %8 - %24 = OpLabel -; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad %v4int %i - %25 = OpLoad %v4int %i - %41 = OpCompositeInsert %v4int %int_0 %25 0 - %27 = OpAccessChain %_ptr_Input_int %i %uint_0 - %28 = OpLoad %int %27 - %29 = OpSGreaterThan %bool %28 %int_10 - OpSelectionMerge %30 None - OpBranchConditional %29 %31 %32 - %31 = OpLabel - %43 = OpCopyObject %v4int %25 - OpBranch %30 - %32 = OpLabel - %45 = OpCopyObject %v4int %25 - OpBranch %30 - %30 = OpLabel - %50 = OpPhi %v4int %43 %31 %45 %32 -; CHECK: [[extract1:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 0 - %47 = OpCompositeExtract %int %50 0 -; CHECK: [[extract2:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 1 - %49 = OpCompositeExtract %int %41 1 -; CHECK: [[add:%[a-zA-Z_\d]+]] = OpIAdd %int [[extract1]] [[extract2]] - %39 = OpIAdd %int %47 %49 - OpStore %o %39 - OpReturn - OpFunctionEnd - -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(SimplificationTest, ThroughLoops) { - // Testing that folding rules are applied multiple times to instructions - // to be able to propagate across loop iterations. - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %o %i - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 430 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %o "o" - OpName %i "i" - OpDecorate %o Location 0 - OpDecorate %i Flat - OpDecorate %i Location 0 - %void = OpTypeVoid - %8 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %v4int = OpTypeVector %int 4 - %int_0 = OpConstant %int 0 -; CHECK: [[constant:%[a-zA-Z_\d]+]] = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 - %13 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 - %bool = OpTypeBool -%_ptr_Output_int = OpTypePointer Output %int - %o = OpVariable %_ptr_Output_int Output -%_ptr_Input_v4int = OpTypePointer Input %v4int - %i = OpVariable %_ptr_Input_v4int Input - %68 = OpUndef %v4int - %main = OpFunction %void None %8 - %23 = OpLabel -; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad %v4int %i - %load = OpLoad %v4int %i - OpBranch %24 - %24 = OpLabel - %67 = OpPhi %v4int %load %23 %64 %26 -; CHECK: OpLoopMerge [[merge_lab:%[a-zA-Z_\d]+]] - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - %48 = OpCompositeExtract %int %67 0 - %30 = OpIEqual %bool %48 %int_0 - OpBranchConditional %30 %31 %25 - %31 = OpLabel - %50 = OpCompositeExtract %int %67 0 - %54 = OpCompositeExtract %int %67 1 - %58 = OpCompositeExtract %int %67 2 - %62 = OpCompositeExtract %int %67 3 - %64 = OpCompositeConstruct %v4int %50 %54 %58 %62 - OpBranch %26 - %26 = OpLabel - OpBranch %24 - %25 = OpLabel -; CHECK: [[merge_lab]] = OpLabel -; CHECK: [[extract:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 0 - %66 = OpCompositeExtract %int %67 0 -; CHECK-NEXT: OpStore %o [[extract]] - OpStore %o %66 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(SimplificationTest, CopyObjectWithDecorations1) { - // Don't simplify OpCopyObject if the result id has a decoration that the - // operand does not. - const std::string text = R"(OpCapability Shader -OpCapability ShaderNonUniform -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpDecorate %3 NonUniform -%void = OpTypeVoid -%5 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%2 = OpFunction %void None %5 -%7 = OpLabel -%8 = OpUndef %int -%3 = OpCopyObject %int %8 -%9 = OpIAdd %int %3 %3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, false); -} - -TEST_F(SimplificationTest, CopyObjectWithDecorations2) { - // Simplify OpCopyObject if the result id is a subset of the decorations of - // the operand. - const std::string before = R"(OpCapability Shader -OpCapability ShaderNonUniform -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpDecorate %3 NonUniform -%void = OpTypeVoid -%5 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%2 = OpFunction %void None %5 -%7 = OpLabel -%3 = OpUndef %int -%8 = OpCopyObject %int %3 -%9 = OpIAdd %int %8 %8 -OpReturn -OpFunctionEnd -)"; - - const std::string after = R"(OpCapability Shader -OpCapability ShaderNonUniform -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -OpSource GLSL 430 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpDecorate %3 NonUniform -%void = OpTypeVoid -%5 = OpTypeFunction %void -%int = OpTypeInt 32 1 -%2 = OpFunction %void None %5 -%7 = OpLabel -%3 = OpUndef %int -%9 = OpIAdd %int %3 %3 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before, after, false); -} - -TEST_F(SimplificationTest, DontMoveDecorations) { - const std::string spirv = R"( -; CHECK-NOT: RelaxedPrecision -; CHECK: [[sub:%\w+]] = OpFSub -; CHECK: OpStore {{.*}} [[sub]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %add RelaxedPrecision -OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -OpMemberDecorate %block 1 Offset 4 -OpDecorate %in DescriptorSet 0 -OpDecorate %in Binding 0 -OpDecorate %out DescriptorSet 0 -OpDecorate %out Binding 1 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%void_fn = OpTypeFunction %void -%block = OpTypeStruct %float %float -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%in = OpVariable %ptr_ssbo_block StorageBuffer -%out = OpVariable %ptr_ssbo_block StorageBuffer -%ptr_ssbo_float = OpTypePointer StorageBuffer %float -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%main = OpFunction %void None %void_fn -%entry = OpLabel -%in_gep_0 = OpAccessChain %ptr_ssbo_float %in %int_0 -%in_gep_1 = OpAccessChain %ptr_ssbo_float %in %int_1 -%load_0 = OpLoad %float %in_gep_0 -%load_1 = OpLoad %float %in_gep_1 -%sub = OpFSub %float %load_0 %load_1 -%add = OpFAdd %float %float_0 %sub -%out_gep_0 = OpAccessChain %ptr_ssbo_float %out %int_0 -OpStore %out_gep_0 %add -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(spirv, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/split_invalid_unreachable_test.cpp b/3rdparty/spirv-tools/test/opt/split_invalid_unreachable_test.cpp deleted file mode 100644 index 520af0154..000000000 --- a/3rdparty/spirv-tools/test/opt/split_invalid_unreachable_test.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using SplitInvalidUnreachableTest = PassTest<::testing::Test>; - -std::string spirv_header = R"(OpCapability Shader -OpCapability VulkanMemoryModel -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical Vulkan -OpEntryPoint Vertex %1 "shader" -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%void = OpTypeVoid -%bool = OpTypeBool -%7 = OpTypeFunction %void -)"; - -std::string function_head = R"(%1 = OpFunction %void None %7 -%8 = OpLabel -OpBranch %9 -)"; - -std::string function_tail = "OpFunctionEnd\n"; - -std::string GetLoopMergeBlock(std::string block_id, std::string merge_id, - std::string continue_id, std::string body_id) { - std::string result; - result += block_id + " = OpLabel\n"; - result += "OpLoopMerge " + merge_id + " " + continue_id + " None\n"; - result += "OpBranch " + body_id + "\n"; - return result; -} - -std::string GetSelectionMergeBlock(std::string block_id, - std::string condition_id, - std::string merge_id, std::string true_id, - std::string false_id) { - std::string result; - result += block_id + " = OpLabel\n"; - result += condition_id + " = OpSLessThan %bool %uint_1 %uint_2\n"; - result += "OpSelectionMerge " + merge_id + " None\n"; - result += "OpBranchConditional " + condition_id + " " + true_id + " " + - false_id + "\n"; - - return result; -} - -std::string GetReturnBlock(std::string block_id) { - std::string result; - result += block_id + " = OpLabel\n"; - result += "OpReturn\n"; - return result; -} - -std::string GetUnreachableBlock(std::string block_id) { - std::string result; - result += block_id + " = OpLabel\n"; - result += "OpUnreachable\n"; - return result; -} - -std::string GetBranchBlock(std::string block_id, std::string target_id) { - std::string result; - result += block_id + " = OpLabel\n"; - result += "OpBranch " + target_id + "\n"; - return result; -} - -TEST_F(SplitInvalidUnreachableTest, NoInvalidBlocks) { - std::string input = spirv_header + function_head; - input += GetLoopMergeBlock("%9", "%10", "%11", "%12"); - input += GetSelectionMergeBlock("%12", "%13", "%14", "%15", "%16"); - input += GetReturnBlock("%15"); - input += GetReturnBlock("%16"); - input += GetUnreachableBlock("%10"); - input += GetBranchBlock("%11", "%9"); - input += GetUnreachableBlock("%14"); - input += function_tail; - - SinglePassRunAndCheck(input, input, - /* skip_nop = */ false); -} - -TEST_F(SplitInvalidUnreachableTest, SelectionInLoop) { - std::string input = spirv_header + function_head; - input += GetLoopMergeBlock("%9", "%10", "%11", "%12"); - input += GetSelectionMergeBlock("%12", "%13", "%11", "%15", "%16"); - input += GetReturnBlock("%15"); - input += GetReturnBlock("%16"); - input += GetUnreachableBlock("%10"); - input += GetBranchBlock("%11", "%9"); - input += function_tail; - - std::string expected = spirv_header + function_head; - expected += GetLoopMergeBlock("%9", "%10", "%11", "%12"); - expected += GetSelectionMergeBlock("%12", "%13", "%16", "%14", "%15"); - expected += GetReturnBlock("%14"); - expected += GetReturnBlock("%15"); - expected += GetUnreachableBlock("%10"); - expected += GetUnreachableBlock("%16"); - expected += GetBranchBlock("%11", "%9"); - expected += function_tail; - - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -TEST_F(SplitInvalidUnreachableTest, LoopInSelection) { - std::string input = spirv_header + function_head; - input += GetSelectionMergeBlock("%9", "%10", "%11", "%12", "%13"); - input += GetLoopMergeBlock("%12", "%14", "%11", "%15"); - input += GetReturnBlock("%13"); - input += GetUnreachableBlock("%14"); - input += GetBranchBlock("%11", "%12"); - input += GetReturnBlock("%15"); - input += function_tail; - - std::string expected = spirv_header + function_head; - expected += GetSelectionMergeBlock("%9", "%10", "%16", "%12", "%13"); - expected += GetLoopMergeBlock("%12", "%14", "%11", "%15"); - expected += GetReturnBlock("%13"); - expected += GetUnreachableBlock("%14"); - expected += GetUnreachableBlock("%16"); - expected += GetBranchBlock("%11", "%12"); - expected += GetReturnBlock("%15"); - expected += function_tail; - - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/strength_reduction_test.cpp b/3rdparty/spirv-tools/test/opt/strength_reduction_test.cpp deleted file mode 100644 index 31d050360..000000000 --- a/3rdparty/spirv-tools/test/opt/strength_reduction_test.cpp +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright (c) 2017 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 -#include - -#include "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; -using StrengthReductionBasicTest = PassTest<::testing::Test>; - -// Test to make sure we replace 5*8. -TEST_F(StrengthReductionBasicTest, BasicReplaceMulBy8) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "%void = OpTypeVoid", - "%4 = OpTypeFunction %void", - "%uint = OpTypeInt 32 0", - "%uint_5 = OpConstant %uint 5", - "%uint_8 = OpConstant %uint 8", - "%main = OpFunction %void None %4", - "%8 = OpLabel", - "%9 = OpIMul %uint %uint_5 %uint_8", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - auto result = SinglePassRunAndDisassemble( - JoinAllInsts(text), /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); - const std::string& output = std::get<0>(result); - EXPECT_THAT(output, Not(HasSubstr("OpIMul"))); - EXPECT_THAT(output, HasSubstr("OpShiftLeftLogical %uint %uint_5 %uint_3")); -} - -// TODO(dneto): Add Effcee as required dependency, and make this unconditional. -// Test to make sure we replace 16*5 -// Also demonstrate use of Effcee matching. -TEST_F(StrengthReductionBasicTest, BasicReplaceMulBy16) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void -; We know disassembly will produce %uint here, but -; CHECK: %uint = OpTypeInt 32 0 -; CHECK-DAG: [[five:%[a-zA-Z_\d]+]] = OpConstant %uint 5 - -; We have RE2 regular expressions, so \w matches [_a-zA-Z0-9]. -; This shows the preferred pattern for matching SPIR-V identifiers. -; (We could have cheated in this case since we know the disassembler will -; generate the 'nice' name of "%uint_4". -; CHECK-DAG: [[four:%\w+]] = OpConstant %uint 4 - %uint = OpTypeInt 32 0 - %uint_5 = OpConstant %uint 5 - %uint_16 = OpConstant %uint 16 - %main = OpFunction %void None %4 -; CHECK: OpLabel - %8 = OpLabel -; CHECK-NEXT: OpShiftLeftLogical %uint [[five]] [[four]] -; The multiplication disappears. -; CHECK-NOT: OpIMul - %9 = OpIMul %uint %uint_16 %uint_5 - OpReturn -; CHECK: OpFunctionEnd - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -// Test to make sure we replace a multiple of 32 and 4. -TEST_F(StrengthReductionBasicTest, BasicTwoPowersOf2) { - // In this case, we have two powers of 2. Need to make sure we replace only - // one of them for the bit shift. - // clang-format off - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%int_32 = OpConstant %int 32 - %int_4 = OpConstant %int 4 - %main = OpFunction %void None %4 - %8 = OpLabel - %9 = OpIMul %int %int_32 %int_4 - OpReturn - OpFunctionEnd -)"; - // clang-format on - auto result = SinglePassRunAndDisassemble( - text, /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); - const std::string& output = std::get<0>(result); - EXPECT_THAT(output, Not(HasSubstr("OpIMul"))); - EXPECT_THAT(output, HasSubstr("OpShiftLeftLogical %int %int_4 %uint_5")); -} - -// Test to make sure we don't replace 0*5. -TEST_F(StrengthReductionBasicTest, BasicDontReplace0) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "%void = OpTypeVoid", - "%4 = OpTypeFunction %void", - "%int = OpTypeInt 32 1", - "%int_0 = OpConstant %int 0", - "%int_5 = OpConstant %int 5", - "%main = OpFunction %void None %4", - "%8 = OpLabel", - "%9 = OpIMul %int %int_0 %int_5", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - auto result = SinglePassRunAndDisassemble( - JoinAllInsts(text), /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// Test to make sure we do not replace a multiple of 5 and 7. -TEST_F(StrengthReductionBasicTest, BasicNoChange) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %2 \"main\"", - "OpName %2 \"main\"", - "%3 = OpTypeVoid", - "%4 = OpTypeFunction %3", - "%5 = OpTypeInt 32 1", - "%6 = OpTypeInt 32 0", - "%7 = OpConstant %5 5", - "%8 = OpConstant %5 7", - "%2 = OpFunction %3 None %4", - "%9 = OpLabel", - "%10 = OpIMul %5 %7 %8", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - auto result = SinglePassRunAndDisassemble( - JoinAllInsts(text), /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -// Test to make sure constants and types are reused and not duplicated. -TEST_F(StrengthReductionBasicTest, NoDuplicateConstantsAndTypes) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "%void = OpTypeVoid", - "%4 = OpTypeFunction %void", - "%uint = OpTypeInt 32 0", - "%uint_8 = OpConstant %uint 8", - "%uint_3 = OpConstant %uint 3", - "%main = OpFunction %void None %4", - "%8 = OpLabel", - "%9 = OpIMul %uint %uint_8 %uint_3", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - - auto result = SinglePassRunAndDisassemble( - JoinAllInsts(text), /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); - const std::string& output = std::get<0>(result); - EXPECT_THAT(output, - Not(MatchesRegex(".*OpConstant %uint 3.*OpConstant %uint 3.*"))); - EXPECT_THAT(output, Not(MatchesRegex(".*OpTypeInt 32 0.*OpTypeInt 32 0.*"))); -} - -// Test to make sure we generate the constants only once -TEST_F(StrengthReductionBasicTest, BasicCreateOneConst) { - const std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %main \"main\"", - "OpName %main \"main\"", - "%void = OpTypeVoid", - "%4 = OpTypeFunction %void", - "%uint = OpTypeInt 32 0", - "%uint_5 = OpConstant %uint 5", - "%uint_9 = OpConstant %uint 9", - "%uint_128 = OpConstant %uint 128", - "%main = OpFunction %void None %4", - "%8 = OpLabel", - "%9 = OpIMul %uint %uint_5 %uint_128", - "%10 = OpIMul %uint %uint_9 %uint_128", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - auto result = SinglePassRunAndDisassemble( - JoinAllInsts(text), /* skip_nop = */ true, /* do_validation = */ false); - - EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); - const std::string& output = std::get<0>(result); - EXPECT_THAT(output, Not(HasSubstr("OpIMul"))); - EXPECT_THAT(output, HasSubstr("OpShiftLeftLogical %uint %uint_5 %uint_7")); - EXPECT_THAT(output, HasSubstr("OpShiftLeftLogical %uint %uint_9 %uint_7")); -} - -// Test to make sure we generate the instructions in the correct position and -// that the uses get replaced as well. Here we check that the use in the return -// is replaced, we also check that we can replace two OpIMuls when one feeds the -// other. -TEST_F(StrengthReductionBasicTest, BasicCheckPositionAndReplacement) { - // This is just the preamble to set up the test. - const std::vector common_text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpName %main \"main\"", - "OpName %foo_i1_ \"foo(i1;\"", - "OpName %n \"n\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "OpName %param \"param\"", - "OpDecorate %gl_FragColor Location 0", - "%void = OpTypeVoid", - "%3 = OpTypeFunction %void", - "%int = OpTypeInt 32 1", -"%_ptr_Function_int = OpTypePointer Function %int", - "%8 = OpTypeFunction %int %_ptr_Function_int", - "%int_256 = OpConstant %int 256", - "%int_2 = OpConstant %int 2", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - "%float_1 = OpConstant %float 1", - "%int_10 = OpConstant %int 10", - "%float_0_375 = OpConstant %float 0.375", - "%float_0_75 = OpConstant %float 0.75", - "%uint = OpTypeInt 32 0", - "%uint_8 = OpConstant %uint 8", - "%uint_1 = OpConstant %uint 1", - "%main = OpFunction %void None %3", - "%5 = OpLabel", - "%param = OpVariable %_ptr_Function_int Function", - "OpStore %param %int_10", - "%26 = OpFunctionCall %int %foo_i1_ %param", - "%27 = OpConvertSToF %float %26", - "%28 = OpFDiv %float %float_1 %27", - "%31 = OpCompositeConstruct %v4float %28 %float_0_375 %float_0_75 %float_1", - "OpStore %gl_FragColor %31", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - // This is the real test. The two OpIMul should be replaced. The expected - // output is in |foo_after|. - const std::vector foo_before = { - // clang-format off - "%foo_i1_ = OpFunction %int None %8", - "%n = OpFunctionParameter %_ptr_Function_int", - "%11 = OpLabel", - "%12 = OpLoad %int %n", - "%14 = OpIMul %int %12 %int_256", - "%16 = OpIMul %int %14 %int_2", - "OpReturnValue %16", - "OpFunctionEnd", - - // clang-format on - }; - - const std::vector foo_after = { - // clang-format off - "%foo_i1_ = OpFunction %int None %8", - "%n = OpFunctionParameter %_ptr_Function_int", - "%11 = OpLabel", - "%12 = OpLoad %int %n", - "%33 = OpShiftLeftLogical %int %12 %uint_8", - "%34 = OpShiftLeftLogical %int %33 %uint_1", - "OpReturnValue %34", - "OpFunctionEnd", - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - JoinAllInsts(Concat(common_text, foo_before)), - JoinAllInsts(Concat(common_text, foo_after)), - /* skip_nop = */ true, /* do_validate = */ true); -} - -// Test that, when the result of an OpIMul instruction has more than 1 use, and -// the instruction is replaced, all of the uses of the results are replace with -// the new result. -TEST_F(StrengthReductionBasicTest, BasicTestMultipleReplacements) { - // This is just the preamble to set up the test. - const std::vector common_text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Fragment %main \"main\" %gl_FragColor", - "OpExecutionMode %main OriginUpperLeft", - "OpName %main \"main\"", - "OpName %foo_i1_ \"foo(i1;\"", - "OpName %n \"n\"", - "OpName %gl_FragColor \"gl_FragColor\"", - "OpName %param \"param\"", - "OpDecorate %gl_FragColor Location 0", - "%void = OpTypeVoid", - "%3 = OpTypeFunction %void", - "%int = OpTypeInt 32 1", -"%_ptr_Function_int = OpTypePointer Function %int", - "%8 = OpTypeFunction %int %_ptr_Function_int", - "%int_256 = OpConstant %int 256", - "%int_2 = OpConstant %int 2", - "%float = OpTypeFloat 32", - "%v4float = OpTypeVector %float 4", -"%_ptr_Output_v4float = OpTypePointer Output %v4float", -"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", - "%float_1 = OpConstant %float 1", - "%int_10 = OpConstant %int 10", - "%float_0_375 = OpConstant %float 0.375", - "%float_0_75 = OpConstant %float 0.75", - "%uint = OpTypeInt 32 0", - "%uint_8 = OpConstant %uint 8", - "%uint_1 = OpConstant %uint 1", - "%main = OpFunction %void None %3", - "%5 = OpLabel", - "%param = OpVariable %_ptr_Function_int Function", - "OpStore %param %int_10", - "%26 = OpFunctionCall %int %foo_i1_ %param", - "%27 = OpConvertSToF %float %26", - "%28 = OpFDiv %float %float_1 %27", - "%31 = OpCompositeConstruct %v4float %28 %float_0_375 %float_0_75 %float_1", - "OpStore %gl_FragColor %31", - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - - // This is the real test. The two OpIMul instructions should be replaced. In - // particular, we want to be sure that both uses of %16 are changed to use the - // new result. - const std::vector foo_before = { - // clang-format off - "%foo_i1_ = OpFunction %int None %8", - "%n = OpFunctionParameter %_ptr_Function_int", - "%11 = OpLabel", - "%12 = OpLoad %int %n", - "%14 = OpIMul %int %12 %int_256", - "%16 = OpIMul %int %14 %int_2", - "%17 = OpIAdd %int %14 %16", - "OpReturnValue %17", - "OpFunctionEnd", - - // clang-format on - }; - - const std::vector foo_after = { - // clang-format off - "%foo_i1_ = OpFunction %int None %8", - "%n = OpFunctionParameter %_ptr_Function_int", - "%11 = OpLabel", - "%12 = OpLoad %int %n", - "%34 = OpShiftLeftLogical %int %12 %uint_8", - "%35 = OpShiftLeftLogical %int %34 %uint_1", - "%17 = OpIAdd %int %34 %35", - "OpReturnValue %17", - "OpFunctionEnd", - // clang-format on - }; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck( - JoinAllInsts(Concat(common_text, foo_before)), - JoinAllInsts(Concat(common_text, foo_after)), - /* skip_nop = */ true, /* do_validate = */ true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp b/3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp deleted file mode 100644 index 90daa59c1..000000000 --- a/3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp +++ /dev/null @@ -1,406 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -typedef std::tuple StripAtomicCounterMemoryParam; - -using MemorySemanticsModified = - PassTest<::testing::TestWithParam>; -using NonMemorySemanticsUnmodifiedTest = PassTest<::testing::Test>; - -void operator+=(std::vector& lhs, const char* rhs) { - lhs.push_back(rhs); -} - -std::string GetConstDecl(std::string val) { - std::string decl; - decl += "%uint_" + val + " = OpConstant %uint " + val; - return decl; -} - -std::string GetUnchangedString(std::string(generate_inst)(std::string), - std::string val) { - std::string decl = GetConstDecl(val); - std::string inst = generate_inst(val); - - std::vector result = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", -"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint", - "%4 = OpVariable %_ptr_Workgroup_uint Workgroup", - "%uint_0 = OpConstant %uint 0", - "%uint_1 = OpConstant %uint 1", - "%void = OpTypeVoid", - "%8 = OpTypeFunction %void", - decl.c_str(), - "%1 = OpFunction %void None %8", - "%10 = OpLabel", - inst.c_str(), - "OpReturn", - "OpFunctionEnd" - // clang-format on - }; - return JoinAllInsts(result); -} - -std::string GetChangedString(std::string(generate_inst)(std::string), - std::string orig, std::string changed) { - std::string orig_decl = GetConstDecl(orig); - std::string changed_decl = GetConstDecl(changed); - std::string inst = generate_inst(changed); - - std::vector result = { - // clang-format off - "OpCapability Shader", - "OpCapability VulkanMemoryModel", - "OpExtension \"SPV_KHR_vulkan_memory_model\"", - "OpMemoryModel Logical Vulkan", - "OpEntryPoint Vertex %1 \"shader\"", - "%uint = OpTypeInt 32 0", -"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint", - "%4 = OpVariable %_ptr_Workgroup_uint Workgroup", - "%uint_0 = OpConstant %uint 0", - "%uint_1 = OpConstant %uint 1", - "%void = OpTypeVoid", - "%8 = OpTypeFunction %void", - orig_decl.c_str() }; - // clang-format on - if (changed != "0") result += changed_decl.c_str(); - result += "%1 = OpFunction %void None %8"; - result += "%10 = OpLabel"; - result += inst.c_str(); - result += "OpReturn"; - result += "OpFunctionEnd"; - return JoinAllInsts(result); -} - -std::tuple GetInputAndExpected( - std::string(generate_inst)(std::string), - StripAtomicCounterMemoryParam param) { - std::string orig = std::get<0>(param); - std::string changed = std::get<1>(param); - std::string input = GetUnchangedString(generate_inst, orig); - std::string expected = orig == changed - ? GetUnchangedString(generate_inst, changed) - : GetChangedString(generate_inst, orig, changed); - return std::make_tuple(input, expected); -} - -std::string GetOpControlBarrierInst(std::string val) { - return "OpControlBarrier %uint_1 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpControlBarrier) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpControlBarrierInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpMemoryBarrierInst(std::string val) { - return "OpMemoryBarrier %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpMemoryBarrier) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpMemoryBarrierInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicLoadInst(std::string val) { - return "%11 = OpAtomicLoad %uint %4 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpAtomicLoad) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicLoadInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicStoreInst(std::string val) { - return "OpAtomicStore %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicStore) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicStoreInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicExchangeInst(std::string val) { - return "%11 = OpAtomicExchange %uint %4 %uint_1 %uint_" + val + " %uint_0"; -} - -TEST_P(MemorySemanticsModified, OpAtomicExchange) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicExchangeInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicCompareExchangeInst(std::string val) { - return "%11 = OpAtomicCompareExchange %uint %4 %uint_1 %uint_" + val + - " %uint_" + val + " %uint_0 %uint_0"; -} - -TEST_P(MemorySemanticsModified, OpAtomicCompareExchange) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicCompareExchangeInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicCompareExchangeWeakInst(std::string val) { - return "%11 = OpAtomicCompareExchangeWeak %uint %4 %uint_1 %uint_" + val + - " %uint_" + val + " %uint_0 %uint_0"; -} - -TEST_P(MemorySemanticsModified, OpAtomicCompareExchangeWeak) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicCompareExchangeWeakInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicIIncrementInst(std::string val) { - return "%11 = OpAtomicIIncrement %uint %4 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpAtomicIIncrement) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicIIncrementInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicIDecrementInst(std::string val) { - return "%11 = OpAtomicIDecrement %uint %4 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpAtomicIDecrement) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicIDecrementInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicIAddInst(std::string val) { - return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicIAdd) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicIAddInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicISubInst(std::string val) { - return "%11 = OpAtomicISub %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicISub) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicISubInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicSMinInst(std::string val) { - return "%11 = OpAtomicSMin %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicSMin) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicSMinInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicUMinInst(std::string val) { - return "%11 = OpAtomicUMin %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicUMin) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicUMinInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicSMaxInst(std::string val) { - return "%11 = OpAtomicSMax %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicSMax) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicSMaxInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicUMaxInst(std::string val) { - return "%11 = OpAtomicUMax %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicUMax) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicUMaxInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicAndInst(std::string val) { - return "%11 = OpAtomicAnd %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicAnd) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicAndInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicOrInst(std::string val) { - return "%11 = OpAtomicOr %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicOr) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicOrInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicXorInst(std::string val) { - return "%11 = OpAtomicXor %uint %4 %uint_1 %uint_" + val + " %uint_1"; -} - -TEST_P(MemorySemanticsModified, OpAtomicXor) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicXorInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicFlagTestAndSetInst(std::string val) { - return "%11 = OpAtomicFlagTestAndSet %uint %4 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpAtomicFlagTestAndSet) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicFlagTestAndSetInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpAtomicFlagClearInst(std::string val) { - return "OpAtomicFlagClear %4 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpAtomicFlagClear) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpAtomicFlagClearInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetOpMemoryNamedBarrierInst(std::string val) { - return "OpMemoryNamedBarrier %4 %uint_1 %uint_" + val; -} - -TEST_P(MemorySemanticsModified, OpMemoryNamedBarrier) { - std::string input, expected; - std::tie(input, expected) = - GetInputAndExpected(GetOpMemoryNamedBarrierInst, GetParam()); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - StripAtomicCounterMemoryTest, MemorySemanticsModified, - ::testing::ValuesIn(std::vector({ - std::make_tuple("1024", "0"), - std::make_tuple("5", "5"), - std::make_tuple("1288", "264"), - std::make_tuple("264", "264") - }))); -// clang-format on - -std::string GetNoMemorySemanticsPresentInst(std::string val) { - return "%11 = OpVariable %_ptr_Workgroup_uint Workgroup %uint_" + val; -} - -TEST_F(NonMemorySemanticsUnmodifiedTest, NoMemorySemanticsPresent) { - std::string input, expected; - StripAtomicCounterMemoryParam param = std::make_tuple("1288", "1288"); - std::tie(input, expected) = - GetInputAndExpected(GetNoMemorySemanticsPresentInst, param); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -std::string GetMemorySemanticsPresentInst(std::string val) { - return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1288"; -} - -TEST_F(NonMemorySemanticsUnmodifiedTest, MemorySemanticsPresent) { - std::string input, expected; - StripAtomicCounterMemoryParam param = std::make_tuple("1288", "264"); - std::tie(input, expected) = - GetInputAndExpected(GetMemorySemanticsPresentInst, param); - SinglePassRunAndCheck(input, expected, - /* skip_nop = */ false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/strip_debug_info_test.cpp b/3rdparty/spirv-tools/test/opt/strip_debug_info_test.cpp deleted file mode 100644 index 2f2ff4670..000000000 --- a/3rdparty/spirv-tools/test/opt/strip_debug_info_test.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using StripLineDebugInfoTest = PassTest<::testing::Test>; - -TEST_F(StripLineDebugInfoTest, LineNoLine) { - std::vector text = { - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %2 \"main\"", - "%3 = OpString \"minimal.vert\"", - "OpModuleProcessed \"42\"", - "OpModuleProcessed \"43\"", - "OpModuleProcessed \"44\"", - "OpNoLine", - "OpLine %3 10 10", - "%void = OpTypeVoid", - "OpLine %3 100 100", - "%5 = OpTypeFunction %void", - "%2 = OpFunction %void None %5", - "OpLine %3 1 1", - "OpNoLine", - "OpLine %3 2 2", - "OpLine %3 3 3", - "%6 = OpLabel", - "OpLine %3 4 4", - "OpNoLine", - "OpReturn", - "OpLine %3 4 4", - "OpNoLine", - "OpFunctionEnd", - "OpNoLine", - "OpLine %3 4 5" - // clang-format on - }; - SinglePassRunAndCheck(JoinAllInsts(text), - JoinNonDebugInsts(text), - /* skip_nop = */ false); - - // Let's add more debug instruction before the "OpString" instruction. - const std::vector more_text = { - "OpSourceContinued \"I'm a happy shader! Yay! ;)\"", - "OpSourceContinued \"wahahaha\"", - "OpSource ESSL 310", - "OpSource ESSL 310", - "OpSourceContinued \"wahahaha\"", - "OpSourceContinued \"wahahaha\"", - "OpSourceExtension \"save-the-world-extension\"", - "OpName %2 \"main\"", - }; - text.insert(text.begin() + 4, more_text.cbegin(), more_text.cend()); - SinglePassRunAndCheck(JoinAllInsts(text), - JoinNonDebugInsts(text), - /* skip_nop = */ false); -} - -using StripDebugStringTest = PassTest<::testing::Test>; - -TEST_F(StripDebugStringTest, OpDecorateRemoved) { - std::vector input{ - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %2 \"main\"", - "%3 = OpString \"minimal.vert\"", - "OpDecorate %3 Location 1337", - "%void = OpTypeVoid", - "%5 = OpTypeFunction %void", - "%2 = OpFunction %void None %5", - "%6 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - std::vector output{ - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %2 \"main\"", - "%void = OpTypeVoid", - "%5 = OpTypeFunction %void", - "%2 = OpFunction %void None %5", - "%6 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck(JoinAllInsts(input), - JoinAllInsts(output), - /* skip_nop = */ false, - /* do_validation */ true); -} - -TEST_F(StripDebugStringTest, OpNameRemoved) { - std::vector input{ - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %2 \"main\"", - "%3 = OpString \"minimal.vert\"", - "OpName %3 \"bob\"", - "%void = OpTypeVoid", - "%5 = OpTypeFunction %void", - "%2 = OpFunction %void None %5", - "%6 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - std::vector output{ - // clang-format off - "OpCapability Shader", - "%1 = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint Vertex %2 \"main\"", - "%void = OpTypeVoid", - "%5 = OpTypeFunction %void", - "%2 = OpFunction %void None %5", - "%6 = OpLabel", - "OpReturn", - "OpFunctionEnd", - // clang-format on - }; - SinglePassRunAndCheck(JoinAllInsts(input), - JoinAllInsts(output), - /* skip_nop = */ false, - /* do_validation */ true); -} - -using StripDebugInfoTest = PassTest<::testing::TestWithParam>; - -TEST_P(StripDebugInfoTest, Kind) { - std::vector text = { - "OpCapability Shader", - "OpMemoryModel Logical GLSL450", - GetParam(), - }; - SinglePassRunAndCheck(JoinAllInsts(text), - JoinNonDebugInsts(text), - /* skip_nop = */ false); -} - -// Test each possible non-line debug instruction. -// clang-format off -INSTANTIATE_TEST_SUITE_P( - SingleKindDebugInst, StripDebugInfoTest, - ::testing::ValuesIn(std::vector({ - "OpSourceContinued \"I'm a happy shader! Yay! ;)\"", - "OpSource ESSL 310", - "OpSourceExtension \"save-the-world-extension\"", - "OpName %main \"main\"", - "OpMemberName %struct 0 \"field\"", - "%1 = OpString \"name.vert\"", - "OpModuleProcessed \"42\"", - }))); -// clang-format on - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/strip_reflect_info_test.cpp b/3rdparty/spirv-tools/test/opt/strip_reflect_info_test.cpp deleted file mode 100644 index 5db34b720..000000000 --- a/3rdparty/spirv-tools/test/opt/strip_reflect_info_test.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "gmock/gmock.h" - -#include "spirv-tools/optimizer.hpp" - -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using StripLineReflectInfoTest = PassTest<::testing::Test>; - -// This test acts as an end-to-end code example on how to strip -// reflection info from a SPIR-V module. Use this code pattern -// when you have compiled HLSL code with Glslang or DXC using -// option -fhlsl_functionality1 to insert reflection information, -// but then want to filter out the extra instructions before sending -// it to a driver that does not implement VK_GOOGLE_hlsl_functionality1. -TEST_F(StripLineReflectInfoTest, StripReflectEnd2EndExample) { - // This is a non-sensical example, but exercises the instructions. - std::string before = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_decorate_string" -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpMemoryModel Logical Simple -OpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar" -OpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness" -%void = OpTypeVoid -%float = OpTypeFloat 32 -)"; - SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); - std::vector binary_in; - tools.Assemble(before, &binary_in); - - // Instantiate the optimizer, and run the strip-reflection-info - // pass over the |binary_in| module, and place the modified module - // into |binary_out|. - spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_1); - optimizer.RegisterPass(spvtools::CreateStripReflectInfoPass()); - std::vector binary_out; - optimizer.Run(binary_in.data(), binary_in.size(), &binary_out); - - // Check results - std::string disassembly; - tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly); - std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical Simple -%void = OpTypeVoid -%float = OpTypeFloat 32 -)"; - EXPECT_THAT(disassembly, testing::Eq(after)); -} - -// This test is functionally the same as the end-to-end test above, -// but uses the test SinglePassRunAndCheck test fixture instead. -TEST_F(StripLineReflectInfoTest, StripHlslSemantic) { - // This is a non-sensical example, but exercises the instructions. - std::string before = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_decorate_string" -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpMemoryModel Logical Simple -OpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar" -OpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness" -%void = OpTypeVoid -%float = OpTypeFloat 32 -)"; - std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical Simple -%void = OpTypeVoid -%float = OpTypeFloat 32 -)"; - - SinglePassRunAndCheck(before, after, false); -} - -TEST_F(StripLineReflectInfoTest, StripHlslCounterBuffer) { - std::string before = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpMemoryModel Logical Simple -OpDecorateId %void HlslCounterBufferGOOGLE %float -%void = OpTypeVoid -%float = OpTypeFloat 32 -)"; - std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical Simple -%void = OpTypeVoid -%float = OpTypeFloat 32 -)"; - - SinglePassRunAndCheck(before, after, false); -} - -TEST_F(StripLineReflectInfoTest, StripHlslSemanticOnMember) { - // This is a non-sensical example, but exercises the instructions. - std::string before = R"(OpCapability Shader -OpCapability Linkage -OpExtension "SPV_GOOGLE_decorate_string" -OpExtension "SPV_GOOGLE_hlsl_functionality1" -OpMemoryModel Logical Simple -OpMemberDecorateStringGOOGLE %struct 0 HlslSemanticGOOGLE "foobar" -%float = OpTypeFloat 32 -%_struct_3 = OpTypeStruct %float -)"; - std::string after = R"(OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical Simple -%float = OpTypeFloat 32 -%_struct_3 = OpTypeStruct %float -)"; - - SinglePassRunAndCheck(before, after, false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/struct_cfg_analysis_test.cpp b/3rdparty/spirv-tools/test/opt/struct_cfg_analysis_test.cpp deleted file mode 100644 index 0451a8b46..000000000 --- a/3rdparty/spirv-tools/test/opt/struct_cfg_analysis_test.cpp +++ /dev/null @@ -1,1374 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/opt/struct_cfg_analysis.h" - -#include - -#include "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using StructCFGAnalysisTest = PassTest<::testing::Test>; -using ::testing::UnorderedElementsAre; - -TEST_F(StructCFGAnalysisTest, BBInSelection) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The header is not in the construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // BB2 is in the construct. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The merge node is not in the construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); -} - -TEST_F(StructCFGAnalysisTest, BBInLoop) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %3 %4 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpBranch %3 -%4 = OpLabel -OpBranch %1 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The header is not in the construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // BB2 is in the construct. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 1); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 3); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The merge node is not in the construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The continue block is in the construct. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 1); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 3); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_TRUE(analysis.IsContinueBlock(4)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_TRUE(analysis.IsInContinueConstruct(4)); - EXPECT_FALSE(analysis.IsMergeBlock(4)); -} - -TEST_F(StructCFGAnalysisTest, SelectionInLoop) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %3 %4 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpSelectionMerge %6 None -OpBranchConditional %undef_bool %5 %6 -%5 = OpLabel -OpBranch %6 -%6 = OpLabel -OpBranch %3 -%4 = OpLabel -OpBranch %1 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The loop header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // Selection header is in the loop only. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 1); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 3); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The loop merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The continue block is in the loop only. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 1); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 3); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_TRUE(analysis.IsContinueBlock(4)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_TRUE(analysis.IsInContinueConstruct(4)); - EXPECT_FALSE(analysis.IsMergeBlock(4)); - - // BB5 is in the selection and the loop. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 1); - EXPECT_EQ(analysis.MergeBlock(5), 6); - EXPECT_EQ(analysis.LoopMergeBlock(5), 3); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_FALSE(analysis.IsContinueBlock(5)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_FALSE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); - - // The selection merge is in the loop only. - EXPECT_EQ(analysis.ContainingConstruct(6), 1); - EXPECT_EQ(analysis.ContainingLoop(6), 1); - EXPECT_EQ(analysis.MergeBlock(6), 3); - EXPECT_EQ(analysis.LoopMergeBlock(6), 3); - EXPECT_EQ(analysis.ContainingSwitch(6), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); - EXPECT_FALSE(analysis.IsContinueBlock(6)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); - EXPECT_FALSE(analysis.IsInContinueConstruct(6)); - EXPECT_TRUE(analysis.IsMergeBlock(6)); -} - -TEST_F(StructCFGAnalysisTest, LoopInSelection) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpLoopMerge %4 %5 None -OpBranchConditional %undef_bool %4 %6 -%5 = OpLabel -OpBranch %2 -%6 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The selection header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // Loop header is in the selection only. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The selection merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The loop merge is in the selection only. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 0); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 0); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_FALSE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // The loop continue target is in the loop. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 2); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 4); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_TRUE(analysis.IsContinueBlock(5)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_TRUE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); - - // BB6 is in the loop. - EXPECT_EQ(analysis.ContainingConstruct(6), 2); - EXPECT_EQ(analysis.ContainingLoop(6), 2); - EXPECT_EQ(analysis.MergeBlock(6), 4); - EXPECT_EQ(analysis.LoopMergeBlock(6), 4); - EXPECT_EQ(analysis.ContainingSwitch(6), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); - EXPECT_FALSE(analysis.IsContinueBlock(6)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); - EXPECT_FALSE(analysis.IsInContinueConstruct(6)); - EXPECT_FALSE(analysis.IsMergeBlock(6)); -} - -TEST_F(StructCFGAnalysisTest, SelectionInSelection) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpSelectionMerge %4 None -OpBranchConditional %undef_bool %4 %5 -%5 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The outer selection header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // The inner header is in the outer selection. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The outer merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The inner merge is in the outer selection. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 0); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 0); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_FALSE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // BB5 is in the inner selection. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 0); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 0); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_FALSE(analysis.IsContinueBlock(5)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_FALSE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); -} - -TEST_F(StructCFGAnalysisTest, LoopInLoop) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %3 %7 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpLoopMerge %4 %5 None -OpBranchConditional %undef_bool %4 %6 -%5 = OpLabel -OpBranch %2 -%6 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -%7 = OpLabel -OpBranch %1 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The outer loop header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // The inner loop header is in the outer loop. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 1); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 3); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The outer merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The inner merge is in the outer loop. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 1); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 3); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_FALSE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // The inner continue target is in the inner loop. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 2); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 4); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_TRUE(analysis.IsContinueBlock(5)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_TRUE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); - - // BB6 is in the loop. - EXPECT_EQ(analysis.ContainingConstruct(6), 2); - EXPECT_EQ(analysis.ContainingLoop(6), 2); - EXPECT_EQ(analysis.MergeBlock(6), 4); - EXPECT_EQ(analysis.LoopMergeBlock(6), 4); - EXPECT_EQ(analysis.ContainingSwitch(6), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); - EXPECT_FALSE(analysis.IsContinueBlock(6)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); - EXPECT_FALSE(analysis.IsInContinueConstruct(6)); - EXPECT_FALSE(analysis.IsMergeBlock(6)); - - // The outer continue target is in the outer loop. - EXPECT_EQ(analysis.ContainingConstruct(7), 1); - EXPECT_EQ(analysis.ContainingLoop(7), 1); - EXPECT_EQ(analysis.MergeBlock(7), 3); - EXPECT_EQ(analysis.LoopMergeBlock(7), 3); - EXPECT_EQ(analysis.ContainingSwitch(7), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(7), 0); - EXPECT_TRUE(analysis.IsContinueBlock(7)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(7)); - EXPECT_TRUE(analysis.IsInContinueConstruct(7)); - EXPECT_FALSE(analysis.IsMergeBlock(7)); -} - -TEST_F(StructCFGAnalysisTest, KernelTest) { - const std::string text = R"( -OpCapability Kernel -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%1 = OpLabel -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // No structured control flow, so none of the basic block are in any - // construct. - for (uint32_t i = 1; i <= 3; i++) { - EXPECT_EQ(analysis.ContainingConstruct(i), 0); - EXPECT_EQ(analysis.ContainingLoop(i), 0); - EXPECT_EQ(analysis.MergeBlock(i), 0); - EXPECT_EQ(analysis.LoopMergeBlock(i), 0); - EXPECT_EQ(analysis.ContainingSwitch(i), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(i), 0); - EXPECT_FALSE(analysis.IsContinueBlock(i)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(i)); - EXPECT_FALSE(analysis.IsInContinueConstruct(i)); - EXPECT_FALSE(analysis.IsMergeBlock(i)); - } -} - -TEST_F(StructCFGAnalysisTest, EmptyFunctionTest) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %func LinkageAttributes "x" Import -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - // #2451: This segfaulted on empty functions. - StructuredCFGAnalysis analysis(context.get()); -} - -TEST_F(StructCFGAnalysisTest, BBInSwitch) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%1 = OpLabel -OpSelectionMerge %3 None -OpSwitch %uint_undef %2 0 %3 -%2 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The header is not in the construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // BB2 is in the construct. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 1); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 3); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The merge node is not in the construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); -} - -TEST_F(StructCFGAnalysisTest, LoopInSwitch) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpSelectionMerge %3 None -OpSwitch %uint_undef %2 1 %3 -%2 = OpLabel -OpLoopMerge %4 %5 None -OpBranchConditional %undef_bool %4 %6 -%5 = OpLabel -OpBranch %2 -%6 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The selection header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // Loop header is in the selection only. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 1); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 3); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The selection merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The loop merge is in the selection only. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 0); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 0); - EXPECT_EQ(analysis.ContainingSwitch(4), 1); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 3); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_FALSE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // The loop continue target is in the loop. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 2); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 4); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_TRUE(analysis.IsContinueBlock(5)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_TRUE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); - - // BB6 is in the loop. - EXPECT_EQ(analysis.ContainingConstruct(6), 2); - EXPECT_EQ(analysis.ContainingLoop(6), 2); - EXPECT_EQ(analysis.MergeBlock(6), 4); - EXPECT_EQ(analysis.LoopMergeBlock(6), 4); - EXPECT_EQ(analysis.ContainingSwitch(6), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); - EXPECT_FALSE(analysis.IsContinueBlock(6)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); - EXPECT_FALSE(analysis.IsInContinueConstruct(6)); - EXPECT_FALSE(analysis.IsMergeBlock(6)); -} - -TEST_F(StructCFGAnalysisTest, SelectionInSwitch) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpSelectionMerge %3 None -OpSwitch %uint_undef %2 10 %3 -%2 = OpLabel -OpSelectionMerge %4 None -OpBranchConditional %undef_bool %4 %5 -%5 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The outer selection header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // The inner header is in the outer selection. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 1); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 3); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The outer merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The inner merge is in the outer selection. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 0); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 0); - EXPECT_EQ(analysis.ContainingSwitch(4), 1); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 3); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_FALSE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // BB5 is in the inner selection. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 0); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 0); - EXPECT_EQ(analysis.ContainingSwitch(5), 1); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 3); - EXPECT_FALSE(analysis.IsContinueBlock(5)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_FALSE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); -} - -TEST_F(StructCFGAnalysisTest, SwitchInSelection) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpSelectionMerge %3 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpSelectionMerge %4 None -OpSwitch %uint_undef %4 7 %5 -%5 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %3 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The outer selection header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // The inner header is in the outer selection. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 0); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 0); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The outer merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The inner merge is in the outer selection. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 0); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 0); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_FALSE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // BB5 is in the inner selection. - EXPECT_EQ(analysis.ContainingConstruct(5), 2); - EXPECT_EQ(analysis.ContainingLoop(5), 0); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 0); - EXPECT_EQ(analysis.ContainingSwitch(5), 2); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 4); - EXPECT_FALSE(analysis.IsContinueBlock(5)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_FALSE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); -} - -TEST_F(StructCFGAnalysisTest, SelectionInContinue) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %3 %4 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpBranch %3 -%4 = OpLabel -OpSelectionMerge %6 None -OpBranchConditional %undef_bool %5 %6 -%5 = OpLabel -OpBranch %6 -%6 = OpLabel -OpBranch %1 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The loop header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // Selection header is in the loop only. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 1); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 3); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The loop merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The continue block is in the loop only. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 1); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 3); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_TRUE(analysis.IsContinueBlock(4)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_TRUE(analysis.IsInContinueConstruct(4)); - EXPECT_FALSE(analysis.IsMergeBlock(4)); - - // BB5 is in the selection and the continue for the loop. - EXPECT_EQ(analysis.ContainingConstruct(5), 4); - EXPECT_EQ(analysis.ContainingLoop(5), 1); - EXPECT_EQ(analysis.MergeBlock(5), 6); - EXPECT_EQ(analysis.LoopMergeBlock(5), 3); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_FALSE(analysis.IsContinueBlock(5)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_TRUE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); - - // BB5 is in the continue for the loop. - EXPECT_EQ(analysis.ContainingConstruct(6), 1); - EXPECT_EQ(analysis.ContainingLoop(6), 1); - EXPECT_EQ(analysis.MergeBlock(6), 3); - EXPECT_EQ(analysis.LoopMergeBlock(6), 3); - EXPECT_EQ(analysis.ContainingSwitch(6), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); - EXPECT_FALSE(analysis.IsContinueBlock(6)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(6)); - EXPECT_TRUE(analysis.IsInContinueConstruct(6)); - EXPECT_TRUE(analysis.IsMergeBlock(6)); -} - -TEST_F(StructCFGAnalysisTest, LoopInContinue) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -%void = OpTypeVoid -%bool = OpTypeBool -%bool_undef = OpUndef %bool -%uint = OpTypeInt 32 0 -%uint_undef = OpUndef %uint -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%entry_lab = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %3 %7 None -OpBranchConditional %undef_bool %2 %3 -%2 = OpLabel -OpBranchConditional %undef_bool %3 %7 -%7 = OpLabel -OpLoopMerge %4 %5 None -OpBranchConditional %undef_bool %4 %6 -%5 = OpLabel -OpBranch %7 -%6 = OpLabel -OpBranch %4 -%4 = OpLabel -OpBranch %1 -%3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - // The outer loop header is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(1), 0); - EXPECT_EQ(analysis.ContainingLoop(1), 0); - EXPECT_EQ(analysis.MergeBlock(1), 0); - EXPECT_EQ(analysis.LoopMergeBlock(1), 0); - EXPECT_EQ(analysis.ContainingSwitch(1), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); - EXPECT_FALSE(analysis.IsContinueBlock(1)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); - EXPECT_FALSE(analysis.IsInContinueConstruct(1)); - EXPECT_FALSE(analysis.IsMergeBlock(1)); - - // BB2 is a regular block in the inner loop. - EXPECT_EQ(analysis.ContainingConstruct(2), 1); - EXPECT_EQ(analysis.ContainingLoop(2), 1); - EXPECT_EQ(analysis.MergeBlock(2), 3); - EXPECT_EQ(analysis.LoopMergeBlock(2), 3); - EXPECT_EQ(analysis.ContainingSwitch(2), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); - EXPECT_FALSE(analysis.IsContinueBlock(2)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); - EXPECT_FALSE(analysis.IsInContinueConstruct(2)); - EXPECT_FALSE(analysis.IsMergeBlock(2)); - - // The outer merge node is not in either construct. - EXPECT_EQ(analysis.ContainingConstruct(3), 0); - EXPECT_EQ(analysis.ContainingLoop(3), 0); - EXPECT_EQ(analysis.MergeBlock(3), 0); - EXPECT_EQ(analysis.LoopMergeBlock(3), 0); - EXPECT_EQ(analysis.ContainingSwitch(3), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); - EXPECT_FALSE(analysis.IsContinueBlock(3)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); - EXPECT_FALSE(analysis.IsInContinueConstruct(3)); - EXPECT_TRUE(analysis.IsMergeBlock(3)); - - // The inner merge is in the continue of the outer loop. - EXPECT_EQ(analysis.ContainingConstruct(4), 1); - EXPECT_EQ(analysis.ContainingLoop(4), 1); - EXPECT_EQ(analysis.MergeBlock(4), 3); - EXPECT_EQ(analysis.LoopMergeBlock(4), 3); - EXPECT_EQ(analysis.ContainingSwitch(4), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); - EXPECT_FALSE(analysis.IsContinueBlock(4)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); - EXPECT_TRUE(analysis.IsInContinueConstruct(4)); - EXPECT_TRUE(analysis.IsMergeBlock(4)); - - // The inner continue target is in the inner loop. - EXPECT_EQ(analysis.ContainingConstruct(5), 7); - EXPECT_EQ(analysis.ContainingLoop(5), 7); - EXPECT_EQ(analysis.MergeBlock(5), 4); - EXPECT_EQ(analysis.LoopMergeBlock(5), 4); - EXPECT_EQ(analysis.ContainingSwitch(5), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); - EXPECT_TRUE(analysis.IsContinueBlock(5)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); - EXPECT_TRUE(analysis.IsInContinueConstruct(5)); - EXPECT_FALSE(analysis.IsMergeBlock(5)); - - // BB6 is a regular block in the inner loop. - EXPECT_EQ(analysis.ContainingConstruct(6), 7); - EXPECT_EQ(analysis.ContainingLoop(6), 7); - EXPECT_EQ(analysis.MergeBlock(6), 4); - EXPECT_EQ(analysis.LoopMergeBlock(6), 4); - EXPECT_EQ(analysis.ContainingSwitch(6), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); - EXPECT_FALSE(analysis.IsContinueBlock(6)); - EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); - EXPECT_TRUE(analysis.IsInContinueConstruct(6)); - EXPECT_FALSE(analysis.IsMergeBlock(6)); - - // The outer continue target is in the outer loop. - EXPECT_EQ(analysis.ContainingConstruct(7), 1); - EXPECT_EQ(analysis.ContainingLoop(7), 1); - EXPECT_EQ(analysis.MergeBlock(7), 3); - EXPECT_EQ(analysis.LoopMergeBlock(7), 3); - EXPECT_EQ(analysis.ContainingSwitch(7), 0); - EXPECT_EQ(analysis.SwitchMergeBlock(7), 0); - EXPECT_TRUE(analysis.IsContinueBlock(7)); - EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(7)); - EXPECT_TRUE(analysis.IsInContinueConstruct(7)); - EXPECT_FALSE(analysis.IsMergeBlock(7)); -} - -TEST_F(StructCFGAnalysisTest, FuncCallInContinueDirect) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %4 = OpUndef %bool - %uint = OpTypeInt 32 0 - %6 = OpUndef %uint - %7 = OpTypeFunction %void - %1 = OpFunction %void None %7 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %10 %11 None - OpBranchConditional %12 %10 %11 - %11 = OpLabel - %13 = OpFunctionCall %void %14 - OpBranch %9 - %10 = OpLabel - %15 = OpFunctionCall %void %16 - OpReturn - OpFunctionEnd - %14 = OpFunction %void None %7 - %17 = OpLabel - OpReturn - OpFunctionEnd - %16 = OpFunction %void None %7 - %18 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - auto c = analysis.FindFuncsCalledFromContinue(); - EXPECT_THAT(c, UnorderedElementsAre(14u)); -} - -TEST_F(StructCFGAnalysisTest, FuncCallInContinueIndirect) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - %void = OpTypeVoid - %bool = OpTypeBool - %4 = OpUndef %bool - %uint = OpTypeInt 32 0 - %6 = OpUndef %uint - %7 = OpTypeFunction %void - %1 = OpFunction %void None %7 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %10 %11 None - OpBranchConditional %12 %10 %11 - %11 = OpLabel - %13 = OpFunctionCall %void %14 - OpBranch %9 - %10 = OpLabel - %15 = OpFunctionCall %void %16 - OpReturn - OpFunctionEnd - %14 = OpFunction %void None %7 - %17 = OpLabel - %19 = OpFunctionCall %void %16 - OpReturn - OpFunctionEnd - %16 = OpFunction %void None %7 - %18 = OpLabel - %20 = OpFunctionCall %void %21 - OpReturn - OpFunctionEnd - %21 = OpFunction %void None %7 - %22 = OpLabel - OpReturn - OpFunctionEnd -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - StructuredCFGAnalysis analysis(context.get()); - - auto c = analysis.FindFuncsCalledFromContinue(); - EXPECT_THAT(c, UnorderedElementsAre(14u, 16u, 21u)); -} -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/type_manager_test.cpp b/3rdparty/spirv-tools/test/opt/type_manager_test.cpp deleted file mode 100644 index 743d0b616..000000000 --- a/3rdparty/spirv-tools/test/opt/type_manager_test.cpp +++ /dev/null @@ -1,1174 +0,0 @@ -// 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 "effcee/effcee.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "source/opt/build_module.h" -#include "source/opt/instruction.h" -#include "source/opt/type_manager.h" -#include "spirv-tools/libspirv.hpp" - -namespace spvtools { -namespace opt { -namespace analysis { -namespace { - -bool Validate(const std::vector& bin) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - spv_context spvContext = spvContextCreate(target_env); - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {bin.data(), bin.size()}; - spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); - if (error != 0) spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(spvContext); - return error == 0; -} - -void Match(const std::string& original, IRContext* context, - bool do_validation = true) { - std::vector bin; - context->module()->ToBinary(&bin, true); - if (do_validation) { - EXPECT_TRUE(Validate(bin)); - } - std::string assembly; - SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); - EXPECT_TRUE( - tools.Disassemble(bin, &assembly, SpirvTools::kDefaultDisassembleOption)) - << "Disassembling failed for shader:\n" - << assembly << std::endl; - auto match_result = effcee::Match(assembly, original); - EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) - << match_result.message() << "\nChecking result:\n" - << assembly; -} - -std::vector> GenerateAllTypes() { - // Types in this test case are only equal to themselves, nothing else. - std::vector> types; - - // Void, Bool - types.emplace_back(new Void()); - auto* voidt = types.back().get(); - types.emplace_back(new Bool()); - auto* boolt = types.back().get(); - - // Integer - types.emplace_back(new Integer(32, true)); - auto* s32 = types.back().get(); - types.emplace_back(new Integer(32, false)); - types.emplace_back(new Integer(64, true)); - types.emplace_back(new Integer(64, false)); - auto* u64 = types.back().get(); - - // Float - types.emplace_back(new Float(32)); - auto* f32 = types.back().get(); - types.emplace_back(new Float(64)); - - // Vector - types.emplace_back(new Vector(s32, 2)); - types.emplace_back(new Vector(s32, 3)); - auto* v3s32 = types.back().get(); - types.emplace_back(new Vector(u64, 4)); - types.emplace_back(new Vector(f32, 3)); - auto* v3f32 = types.back().get(); - - // Matrix - types.emplace_back(new Matrix(v3s32, 3)); - types.emplace_back(new Matrix(v3s32, 4)); - types.emplace_back(new Matrix(v3f32, 4)); - - // Images - types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8, - SpvAccessQualifierReadOnly)); - auto* image1 = types.back().get(); - types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8, - SpvAccessQualifierReadOnly)); - types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8, - SpvAccessQualifierReadOnly)); - types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8, - SpvAccessQualifierReadWrite)); - auto* image2 = types.back().get(); - - // Sampler - types.emplace_back(new Sampler()); - - // Sampled Image - types.emplace_back(new SampledImage(image1)); - types.emplace_back(new SampledImage(image2)); - - // Array - types.emplace_back(new Array(f32, Array::LengthInfo{100, {0, 100u}})); - types.emplace_back(new Array(f32, Array::LengthInfo{42, {0, 42u}})); - auto* a42f32 = types.back().get(); - types.emplace_back(new Array(u64, Array::LengthInfo{24, {0, 24u}})); - - // RuntimeArray - types.emplace_back(new RuntimeArray(v3f32)); - types.emplace_back(new RuntimeArray(v3s32)); - auto* rav3s32 = types.back().get(); - - // Struct - types.emplace_back(new Struct(std::vector{s32})); - types.emplace_back(new Struct(std::vector{s32, f32})); - auto* sts32f32 = types.back().get(); - types.emplace_back( - new Struct(std::vector{u64, a42f32, rav3s32})); - - // Opaque - types.emplace_back(new Opaque("")); - types.emplace_back(new Opaque("hello")); - types.emplace_back(new Opaque("world")); - - // Pointer - types.emplace_back(new Pointer(f32, SpvStorageClassInput)); - types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction)); - types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction)); - - // Function - types.emplace_back(new Function(voidt, {})); - types.emplace_back(new Function(voidt, {boolt})); - types.emplace_back(new Function(voidt, {boolt, s32})); - types.emplace_back(new Function(s32, {boolt, s32})); - - // Event, Device Event, Reserve Id, Queue, - types.emplace_back(new Event()); - types.emplace_back(new DeviceEvent()); - types.emplace_back(new ReserveId()); - types.emplace_back(new Queue()); - - // Pipe, Forward Pointer, PipeStorage, NamedBarrier, AccelerationStructureNV, - // CooperativeMatrixNV - types.emplace_back(new Pipe(SpvAccessQualifierReadWrite)); - types.emplace_back(new Pipe(SpvAccessQualifierReadOnly)); - types.emplace_back(new ForwardPointer(1, SpvStorageClassInput)); - types.emplace_back(new ForwardPointer(2, SpvStorageClassInput)); - types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform)); - types.emplace_back(new PipeStorage()); - types.emplace_back(new NamedBarrier()); - types.emplace_back(new AccelerationStructureNV()); - types.emplace_back(new CooperativeMatrixNV(f32, 24, 24, 24)); - - return types; -} - -TEST(TypeManager, TypeStrings) { - const std::string text = R"( - OpDecorate %spec_const_with_id SpecId 99 - OpTypeForwardPointer %p Uniform - %void = OpTypeVoid - %bool = OpTypeBool - %u32 = OpTypeInt 32 0 - %id4 = OpConstant %u32 4 - %s32 = OpTypeInt 32 1 - %f64 = OpTypeFloat 64 - %v3u32 = OpTypeVector %u32 3 - %m3x3 = OpTypeMatrix %v3u32 3 - %img1 = OpTypeImage %s32 Cube 0 1 1 0 R32f ReadWrite - %img2 = OpTypeImage %s32 Cube 0 1 1 0 R32f - %sampler = OpTypeSampler - %si1 = OpTypeSampledImage %img1 - %si2 = OpTypeSampledImage %img2 - %a5u32 = OpTypeArray %u32 %id4 - %af64 = OpTypeRuntimeArray %f64 - %st1 = OpTypeStruct %u32 - %st2 = OpTypeStruct %f64 %s32 %v3u32 - %opaque1 = OpTypeOpaque "" - %opaque2 = OpTypeOpaque "opaque" - %p = OpTypePointer Uniform %st1 - %f = OpTypeFunction %void %u32 %u32 - %event = OpTypeEvent - %de = OpTypeDeviceEvent - %ri = OpTypeReserveId - %queue = OpTypeQueue - %pipe = OpTypePipe ReadOnly - %ps = OpTypePipeStorage - %nb = OpTypeNamedBarrier - %rtacc = OpTypeAccelerationStructureNV - ; Set up other kinds of OpTypeArray - %s64 = OpTypeInt 64 1 - ; ID 32 - %spec_const_without_id = OpSpecConstant %s32 44 - %spec_const_with_id = OpSpecConstant %s32 42 ;; This is ID 1 - %long_constant = OpConstant %s64 5000000000 - %spec_const_op = OpSpecConstantOp %s32 IAdd %id4 %id4 - ; ID 35 - %arr_spec_const_without_id = OpTypeArray %s32 %spec_const_without_id - %arr_spec_const_with_id = OpTypeArray %s32 %spec_const_with_id - %arr_long_constant = OpTypeArray %s32 %long_constant - %arr_spec_const_op = OpTypeArray %s32 %spec_const_op - %cm = OpTypeCooperativeMatrixNV %f64 %id4 %id4 %id4 - )"; - - std::vector> type_id_strs = { - {3, "void"}, - {4, "bool"}, - {5, "uint32"}, - // Id 6 is used by the constant. - {7, "sint32"}, - {8, "float64"}, - {9, ""}, - {10, "<, 3>"}, - {11, "image(sint32, 3, 0, 1, 1, 0, 3, 2)"}, - {12, "image(sint32, 3, 0, 1, 1, 0, 3, 0)"}, - {13, "sampler"}, - {14, "sampled_image(image(sint32, 3, 0, 1, 1, 0, 3, 2))"}, - {15, "sampled_image(image(sint32, 3, 0, 1, 1, 0, 3, 0))"}, - {16, "[uint32, id(6), words(0,4)]"}, - {17, "[float64]"}, - {18, "{uint32}"}, - {19, "{float64, sint32, }"}, - {20, "opaque('')"}, - {21, "opaque('opaque')"}, - {2, "{uint32} 2*"}, // Include storage class number - {22, "(uint32, uint32) -> void"}, - {23, "event"}, - {24, "device_event"}, - {25, "reserve_id"}, - {26, "queue"}, - {27, "pipe(0)"}, - {28, "pipe_storage"}, - {29, "named_barrier"}, - {30, "accelerationStructureNV"}, - {31, "sint64"}, - {35, "[sint32, id(32), words(0,44)]"}, - {36, "[sint32, id(1), words(1,99,42)]"}, - {37, "[sint32, id(33), words(0,705032704,1)]"}, - {38, "[sint32, id(34), words(2,34)]"}, - {39, ""}, - }; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - ASSERT_NE(nullptr, context.get()); // It assembled - TypeManager manager(nullptr, context.get()); - - EXPECT_EQ(type_id_strs.size(), manager.NumTypes()); - - for (const auto& p : type_id_strs) { - ASSERT_NE(nullptr, manager.GetType(p.first)); - EXPECT_EQ(p.second, manager.GetType(p.first)->str()) - << " id is " << p.first; - EXPECT_EQ(p.first, manager.GetId(manager.GetType(p.first))); - } -} - -TEST(TypeManager, StructWithFwdPtr) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - %1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %7 "test" - OpSource OpenCL_C 102000 - OpDecorate %11 FuncParamAttr NoCapture - %11 = OpDecorationGroup - OpGroupDecorate %11 %8 %9 - OpTypeForwardPointer %100 CrossWorkgroup - %void = OpTypeVoid - %150 = OpTypeStruct %100 -%100 = OpTypePointer CrossWorkgroup %150 - %6 = OpTypeFunction %void %100 %100 - %7 = OpFunction %void Pure %6 - %8 = OpFunctionParameter %100 - %9 = OpFunctionParameter %100 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - TypeManager manager(nullptr, context.get()); - - Type* p100 = manager.GetType(100); - Type* s150 = manager.GetType(150); - - EXPECT_TRUE(p100->AsPointer()); - EXPECT_EQ(p100->AsPointer()->pointee_type(), s150); - - EXPECT_TRUE(s150->AsStruct()); - EXPECT_EQ(s150->AsStruct()->element_types()[0], p100); -} - -TEST(TypeManager, CircularFwdPtr) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - %1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %7 "test" - OpSource OpenCL_C 102000 - OpDecorate %11 FuncParamAttr NoCapture - %11 = OpDecorationGroup - OpGroupDecorate %11 %8 %9 - OpTypeForwardPointer %100 CrossWorkgroup - OpTypeForwardPointer %200 CrossWorkgroup - %void = OpTypeVoid - %int = OpTypeInt 32 0 - %float = OpTypeFloat 32 - %150 = OpTypeStruct %200 %int - %250 = OpTypeStruct %100 %float -%100 = OpTypePointer CrossWorkgroup %150 -%200 = OpTypePointer CrossWorkgroup %250 - %6 = OpTypeFunction %void %100 %200 - %7 = OpFunction %void Pure %6 - %8 = OpFunctionParameter %100 - %9 = OpFunctionParameter %200 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - TypeManager manager(nullptr, context.get()); - - Type* p100 = manager.GetType(100); - Type* s150 = manager.GetType(150); - Type* p200 = manager.GetType(200); - Type* s250 = manager.GetType(250); - - EXPECT_TRUE(p100->AsPointer()); - EXPECT_EQ(p100->AsPointer()->pointee_type(), s150); - - EXPECT_TRUE(p200->AsPointer()); - EXPECT_EQ(p200->AsPointer()->pointee_type(), s250); - - EXPECT_TRUE(s150->AsStruct()); - EXPECT_EQ(s150->AsStruct()->element_types()[0], p200); - - EXPECT_TRUE(s250->AsStruct()); - EXPECT_EQ(s250->AsStruct()->element_types()[0], p100); -} - -TEST(TypeManager, IsomorphicStructWithFwdPtr) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - %1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %7 "test" - OpSource OpenCL_C 102000 - OpDecorate %11 FuncParamAttr NoCapture - %11 = OpDecorationGroup - OpGroupDecorate %11 %8 %9 - OpTypeForwardPointer %100 CrossWorkgroup - OpTypeForwardPointer %200 CrossWorkgroup - %void = OpTypeVoid - %_struct_1 = OpTypeStruct %100 - %_struct_2 = OpTypeStruct %200 -%100 = OpTypePointer CrossWorkgroup %_struct_1 -%200 = OpTypePointer CrossWorkgroup %_struct_2 - %6 = OpTypeFunction %void %100 %200 - %7 = OpFunction %void Pure %6 - %8 = OpFunctionParameter %100 - %9 = OpFunctionParameter %200 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - TypeManager manager(nullptr, context.get()); - - EXPECT_EQ(manager.GetType(100), manager.GetType(200)); -} - -TEST(TypeManager, IsomorphicCircularFwdPtr) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - %1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %7 "test" - OpSource OpenCL_C 102000 - OpDecorate %11 FuncParamAttr NoCapture - %11 = OpDecorationGroup - OpGroupDecorate %11 %8 %9 - OpTypeForwardPointer %100 CrossWorkgroup - OpTypeForwardPointer %200 CrossWorkgroup - OpTypeForwardPointer %300 CrossWorkgroup - OpTypeForwardPointer %400 CrossWorkgroup - %void = OpTypeVoid - %int = OpTypeInt 32 0 - %float = OpTypeFloat 32 - %150 = OpTypeStruct %200 %int - %250 = OpTypeStruct %100 %float - %350 = OpTypeStruct %400 %int - %450 = OpTypeStruct %300 %float -%100 = OpTypePointer CrossWorkgroup %150 -%200 = OpTypePointer CrossWorkgroup %250 -%300 = OpTypePointer CrossWorkgroup %350 -%400 = OpTypePointer CrossWorkgroup %450 - %6 = OpTypeFunction %void %100 %200 - %7 = OpFunction %void Pure %6 - %8 = OpFunctionParameter %100 - %9 = OpFunctionParameter %200 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - TypeManager manager(nullptr, context.get()); - - Type* p100 = manager.GetType(100); - Type* p300 = manager.GetType(300); - EXPECT_EQ(p100, p300); - Type* p200 = manager.GetType(200); - Type* p400 = manager.GetType(400); - EXPECT_EQ(p200, p400); - - Type* p150 = manager.GetType(150); - Type* p350 = manager.GetType(350); - EXPECT_EQ(p150, p350); - Type* p250 = manager.GetType(250); - Type* p450 = manager.GetType(450); - EXPECT_EQ(p250, p450); -} - -TEST(TypeManager, PartialIsomorphicFwdPtr) { - const std::string text = R"( - OpCapability Addresses - OpCapability Kernel - %1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %7 "test" - OpSource OpenCL_C 102000 - OpDecorate %11 FuncParamAttr NoCapture - %11 = OpDecorationGroup - OpGroupDecorate %11 %8 %9 - OpTypeForwardPointer %100 CrossWorkgroup - OpTypeForwardPointer %200 CrossWorkgroup - %void = OpTypeVoid - %int = OpTypeInt 32 0 - %float = OpTypeFloat 32 - %150 = OpTypeStruct %200 %int - %250 = OpTypeStruct %200 %int -%100 = OpTypePointer CrossWorkgroup %150 -%200 = OpTypePointer CrossWorkgroup %250 - %6 = OpTypeFunction %void %100 %200 - %7 = OpFunction %void Pure %6 - %8 = OpFunctionParameter %100 - %9 = OpFunctionParameter %200 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - TypeManager manager(nullptr, context.get()); - - Type* p100 = manager.GetType(100); - Type* p200 = manager.GetType(200); - EXPECT_EQ(p100->AsPointer()->pointee_type(), - p200->AsPointer()->pointee_type()); -} - -TEST(TypeManager, DecorationOnStruct) { - const std::string text = R"( - OpDecorate %struct1 Block - OpDecorate %struct2 Block - OpDecorate %struct3 Block - OpDecorate %struct4 Block - - %u32 = OpTypeInt 32 0 ; id: 5 - %f32 = OpTypeFloat 32 ; id: 6 - %struct1 = OpTypeStruct %u32 %f32 ; base - %struct2 = OpTypeStruct %f32 %u32 ; different member order - %struct3 = OpTypeStruct %f32 ; different member list - %struct4 = OpTypeStruct %u32 %f32 ; the same - %struct7 = OpTypeStruct %f32 ; no decoration - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - TypeManager manager(nullptr, context.get()); - - ASSERT_EQ(7u, manager.NumTypes()); - // Make sure we get ids correct. - ASSERT_EQ("uint32", manager.GetType(5)->str()); - ASSERT_EQ("float32", manager.GetType(6)->str()); - - // Try all combinations of pairs. Expect to be the same type only when the - // same id or (1, 4). - for (const auto id1 : {1, 2, 3, 4, 7}) { - for (const auto id2 : {1, 2, 3, 4, 7}) { - if (id1 == id2 || (id1 == 1 && id2 == 4) || (id1 == 4 && id2 == 1)) { - EXPECT_TRUE(manager.GetType(id1)->IsSame(manager.GetType(id2))) - << "%struct" << id1 << " is expected to be the same as %struct" - << id2; - } else { - EXPECT_FALSE(manager.GetType(id1)->IsSame(manager.GetType(id2))) - << "%struct" << id1 << " is expected to be different with %struct" - << id2; - } - } - } -} - -TEST(TypeManager, DecorationOnMember) { - const std::string text = R"( - OpMemberDecorate %struct1 0 Offset 0 - OpMemberDecorate %struct2 0 Offset 0 - OpMemberDecorate %struct3 0 Offset 0 - OpMemberDecorate %struct4 0 Offset 0 - OpMemberDecorate %struct5 1 Offset 0 - OpMemberDecorate %struct6 0 Offset 4 - - OpDecorate %struct7 Block - OpMemberDecorate %struct7 0 Offset 0 - - %u32 = OpTypeInt 32 0 ; id: 8 - %f32 = OpTypeFloat 32 ; id: 9 - %struct1 = OpTypeStruct %u32 %f32 ; base - %struct2 = OpTypeStruct %f32 %u32 ; different member order - %struct3 = OpTypeStruct %f32 ; different member list - %struct4 = OpTypeStruct %u32 %f32 ; the same - %struct5 = OpTypeStruct %u32 %f32 ; member decorate different field - %struct6 = OpTypeStruct %u32 %f32 ; different member decoration parameter - %struct7 = OpTypeStruct %u32 %f32 ; extra decoration on the struct - %struct10 = OpTypeStruct %u32 %f32 ; no member decoration - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - TypeManager manager(nullptr, context.get()); - - ASSERT_EQ(10u, manager.NumTypes()); - // Make sure we get ids correct. - ASSERT_EQ("uint32", manager.GetType(8)->str()); - ASSERT_EQ("float32", manager.GetType(9)->str()); - - // Try all combinations of pairs. Expect to be the same type only when the - // same id or (1, 4). - for (const auto id1 : {1, 2, 3, 4, 5, 6, 7, 10}) { - for (const auto id2 : {1, 2, 3, 4, 5, 6, 7, 10}) { - if (id1 == id2 || (id1 == 1 && id2 == 4) || (id1 == 4 && id2 == 1)) { - EXPECT_TRUE(manager.GetType(id1)->IsSame(manager.GetType(id2))) - << "%struct" << id1 << " is expected to be the same as %struct" - << id2; - } else { - EXPECT_FALSE(manager.GetType(id1)->IsSame(manager.GetType(id2))) - << "%struct" << id1 << " is expected to be different with %struct" - << id2; - } - } - } -} - -TEST(TypeManager, DecorationEmpty) { - const std::string text = R"( - OpDecorate %struct1 Block - OpMemberDecorate %struct2 0 Offset 0 - - %u32 = OpTypeInt 32 0 ; id: 3 - %f32 = OpTypeFloat 32 ; id: 4 - %struct1 = OpTypeStruct %u32 %f32 - %struct2 = OpTypeStruct %f32 %u32 - %struct5 = OpTypeStruct %f32 - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - TypeManager manager(nullptr, context.get()); - - ASSERT_EQ(5u, manager.NumTypes()); - // Make sure we get ids correct. - ASSERT_EQ("uint32", manager.GetType(3)->str()); - ASSERT_EQ("float32", manager.GetType(4)->str()); - - // %struct1 with decoration on itself - EXPECT_FALSE(manager.GetType(1)->decoration_empty()); - // %struct2 with decoration on its member - EXPECT_FALSE(manager.GetType(2)->decoration_empty()); - EXPECT_TRUE(manager.GetType(3)->decoration_empty()); - EXPECT_TRUE(manager.GetType(4)->decoration_empty()); - // %struct5 has no decorations - EXPECT_TRUE(manager.GetType(5)->decoration_empty()); -} - -TEST(TypeManager, BeginEndForEmptyModule) { - const std::string text = ""; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - TypeManager manager(nullptr, context.get()); - ASSERT_EQ(0u, manager.NumTypes()); - - EXPECT_EQ(manager.begin(), manager.end()); -} - -TEST(TypeManager, BeginEnd) { - const std::string text = R"( - %void1 = OpTypeVoid - %void2 = OpTypeVoid - %bool = OpTypeBool - %u32 = OpTypeInt 32 0 - %f64 = OpTypeFloat 64 - )"; - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); - TypeManager manager(nullptr, context.get()); - ASSERT_EQ(5u, manager.NumTypes()); - - EXPECT_NE(manager.begin(), manager.end()); - for (const auto& t : manager) { - switch (t.first) { - case 1: - case 2: - EXPECT_EQ("void", t.second->str()); - break; - case 3: - EXPECT_EQ("bool", t.second->str()); - break; - case 4: - EXPECT_EQ("uint32", t.second->str()); - break; - case 5: - EXPECT_EQ("float64", t.second->str()); - break; - default: - EXPECT_TRUE(false && "unreachable"); - break; - } - } -} - -TEST(TypeManager, LookupType) { - const std::string text = R"( -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%int = OpTypeInt 32 1 -%vec2 = OpTypeVector %int 2 -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(context, nullptr); - TypeManager manager(nullptr, context.get()); - - Void voidTy; - EXPECT_EQ(manager.GetId(&voidTy), 1u); - - Integer uintTy(32, false); - EXPECT_EQ(manager.GetId(&uintTy), 2u); - - Integer intTy(32, true); - EXPECT_EQ(manager.GetId(&intTy), 3u); - - Integer intTy2(32, true); - Vector vecTy(&intTy2, 2u); - EXPECT_EQ(manager.GetId(&vecTy), 4u); -} - -TEST(TypeManager, RemoveId) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 32 1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - context->get_type_mgr()->RemoveId(1u); - ASSERT_EQ(context->get_type_mgr()->GetType(1u), nullptr); - ASSERT_NE(context->get_type_mgr()->GetType(2u), nullptr); - - context->get_type_mgr()->RemoveId(2u); - ASSERT_EQ(context->get_type_mgr()->GetType(1u), nullptr); - ASSERT_EQ(context->get_type_mgr()->GetType(2u), nullptr); -} - -TEST(TypeManager, RemoveIdNonDuplicateAmbiguousType) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - Integer u32(32, false); - Struct st({&u32}); - ASSERT_EQ(context->get_type_mgr()->GetId(&st), 2u); - context->get_type_mgr()->RemoveId(2u); - ASSERT_EQ(context->get_type_mgr()->GetType(2u), nullptr); - ASSERT_EQ(context->get_type_mgr()->GetId(&st), 0u); -} - -TEST(TypeManager, RemoveIdDuplicateAmbiguousType) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 -%3 = OpTypeStruct %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - Integer u32(32, false); - Struct st({&u32}); - uint32_t id = context->get_type_mgr()->GetId(&st); - ASSERT_NE(id, 0u); - uint32_t toRemove = id == 2u ? 2u : 3u; - uint32_t toStay = id == 2u ? 3u : 2u; - context->get_type_mgr()->RemoveId(toRemove); - ASSERT_EQ(context->get_type_mgr()->GetType(toRemove), nullptr); - ASSERT_EQ(context->get_type_mgr()->GetId(&st), toStay); -} - -TEST(TypeManager, RemoveIdDoesntUnmapOtherTypes) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 -%3 = OpTypeStruct %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - Integer u32(32, false); - Struct st({&u32}); - - EXPECT_EQ(1u, context->get_type_mgr()->GetId(&u32)); - uint32_t id = context->get_type_mgr()->GetId(&st); - ASSERT_NE(id, 0u); - uint32_t toRemove = id == 2u ? 3u : 2u; - uint32_t toStay = id == 2u ? 2u : 3u; - context->get_type_mgr()->RemoveId(toRemove); - ASSERT_EQ(context->get_type_mgr()->GetType(toRemove), nullptr); - ASSERT_EQ(context->get_type_mgr()->GetId(&st), toStay); -} - -TEST(TypeManager, GetTypeAndPointerType) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - Integer u32(32, false); - Pointer u32Ptr(&u32, SpvStorageClassFunction); - Struct st({&u32}); - Pointer stPtr(&st, SpvStorageClassInput); - - auto pair = context->get_type_mgr()->GetTypeAndPointerType( - 3u, SpvStorageClassFunction); - ASSERT_EQ(nullptr, pair.first); - ASSERT_EQ(nullptr, pair.second); - - pair = context->get_type_mgr()->GetTypeAndPointerType( - 1u, SpvStorageClassFunction); - ASSERT_TRUE(pair.first->IsSame(&u32)); - ASSERT_TRUE(pair.second->IsSame(&u32Ptr)); - - pair = - context->get_type_mgr()->GetTypeAndPointerType(2u, SpvStorageClassInput); - ASSERT_TRUE(pair.first->IsSame(&st)); - ASSERT_TRUE(pair.second->IsSame(&stPtr)); -} - -TEST(TypeManager, DuplicateType) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 32 0 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - const Type* type1 = context->get_type_mgr()->GetType(1u); - const Type* type2 = context->get_type_mgr()->GetType(2u); - EXPECT_NE(type1, nullptr); - EXPECT_NE(type2, nullptr); - EXPECT_EQ(*type1, *type2); -} - -TEST(TypeManager, MultipleStructs) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpDecorate %3 Constant -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 -%3 = OpTypeStruct %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - const Type* type1 = context->get_type_mgr()->GetType(2u); - const Type* type2 = context->get_type_mgr()->GetType(3u); - EXPECT_NE(type1, nullptr); - EXPECT_NE(type2, nullptr); - EXPECT_FALSE(type1->IsSame(type2)); -} - -TEST(TypeManager, RemovingIdAvoidsUseAfterFree) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - Integer u32(32, false); - Struct st({&u32}); - const Type* type = context->get_type_mgr()->GetType(2u); - EXPECT_NE(type, nullptr); - context->get_type_mgr()->RemoveId(1u); - EXPECT_TRUE(type->IsSame(&st)); -} - -TEST(TypeManager, RegisterAndRemoveId) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - uint32_t id = 2u; - { - // Ensure that u32 goes out of scope. - Integer u32(32, false); - Struct st({&u32}); - context->get_type_mgr()->RegisterType(id, st); - } - - context->get_type_mgr()->RemoveId(id); - EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); -} - -TEST(TypeManager, RegisterAndRemoveIdAllTypes) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - std::vector> types = GenerateAllTypes(); - uint32_t id = 1u; - for (auto& t : types) { - context->get_type_mgr()->RegisterType(id, *t); - EXPECT_EQ(*t, *context->get_type_mgr()->GetType(id)); - } - types.clear(); - - for (; id > 0; --id) { - context->get_type_mgr()->RemoveId(id); - EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); - } -} - -TEST(TypeManager, RegisterAndRemoveIdWithDecorations) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 0 -)"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - uint32_t id = 2u; - { - Integer u32(32, false); - Struct st({&u32, &u32}); - st.AddDecoration({10}); - st.AddDecoration({11}); - st.AddMemberDecoration(0, {{35, 4}}); - st.AddMemberDecoration(1, {{35, 4}}); - st.AddMemberDecoration(1, {{36, 5}}); - context->get_type_mgr()->RegisterType(id, st); - EXPECT_EQ(st, *context->get_type_mgr()->GetType(id)); - } - - context->get_type_mgr()->RemoveId(id); - EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); -} - -TEST(TypeManager, GetTypeInstructionInt) { - const std::string text = R"( -; CHECK: OpTypeInt 32 0 -; CHECK: OpTypeInt 16 1 -OpCapability Shader -OpCapability Int16 -OpCapability Linkage -OpMemoryModel Logical GLSL450 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(context, nullptr); - - Integer uint_32(32, false); - context->get_type_mgr()->GetTypeInstruction(&uint_32); - - Integer int_16(16, true); - context->get_type_mgr()->GetTypeInstruction(&int_16); - - Match(text, context.get()); -} - -TEST(TypeManager, GetTypeInstructionDuplicateInts) { - const std::string text = R"( -; CHECK: OpTypeInt 32 0 -; CHECK-NOT: OpType -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - EXPECT_NE(context, nullptr); - - Integer uint_32(32, false); - uint32_t id = context->get_type_mgr()->GetTypeInstruction(&uint_32); - - Integer other(32, false); - EXPECT_EQ(context->get_type_mgr()->GetTypeInstruction(&other), id); - - Match(text, context.get()); -} - -TEST(TypeManager, GetTypeInstructionAllTypes) { - const std::string text = R"( -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[input_ptr:%\w+]] = OpTypePointer Input [[uint]] -; CHECK: [[uniform_ptr:%\w+]] = OpTypePointer Uniform [[uint]] -; CHECK: [[uint24:%\w+]] = OpConstant [[uint]] 24 -; CHECK: [[uint42:%\w+]] = OpConstant [[uint]] 42 -; CHECK: [[uint100:%\w+]] = OpConstant [[uint]] 100 -; CHECK: [[void:%\w+]] = OpTypeVoid -; CHECK: [[bool:%\w+]] = OpTypeBool -; CHECK: [[s32:%\w+]] = OpTypeInt 32 1 -; CHECK: OpTypeInt 64 1 -; CHECK: [[u64:%\w+]] = OpTypeInt 64 0 -; CHECK: [[f32:%\w+]] = OpTypeFloat 32 -; CHECK: OpTypeFloat 64 -; CHECK: OpTypeVector [[s32]] 2 -; CHECK: [[v3s32:%\w+]] = OpTypeVector [[s32]] 3 -; CHECK: OpTypeVector [[u64]] 4 -; CHECK: [[v3f32:%\w+]] = OpTypeVector [[f32]] 3 -; CHECK: OpTypeMatrix [[v3s32]] 3 -; CHECK: OpTypeMatrix [[v3s32]] 4 -; CHECK: OpTypeMatrix [[v3f32]] 4 -; CHECK: [[image1:%\w+]] = OpTypeImage [[s32]] 2D 0 0 0 0 Rg8 ReadOnly -; CHECK: OpTypeImage [[s32]] 2D 0 1 0 0 Rg8 ReadOnly -; CHECK: OpTypeImage [[s32]] 3D 0 1 0 0 Rg8 ReadOnly -; CHECK: [[image2:%\w+]] = OpTypeImage [[void]] 3D 0 1 0 1 Rg8 ReadWrite -; CHECK: OpTypeSampler -; CHECK: OpTypeSampledImage [[image1]] -; CHECK: OpTypeSampledImage [[image2]] -; CHECK: OpTypeArray [[f32]] [[uint100]] -; CHECK: [[a42f32:%\w+]] = OpTypeArray [[f32]] [[uint42]] -; CHECK: OpTypeArray [[u64]] [[uint24]] -; CHECK: OpTypeRuntimeArray [[v3f32]] -; CHECK: [[rav3s32:%\w+]] = OpTypeRuntimeArray [[v3s32]] -; CHECK: OpTypeStruct [[s32]] -; CHECK: [[sts32f32:%\w+]] = OpTypeStruct [[s32]] [[f32]] -; CHECK: OpTypeStruct [[u64]] [[a42f32]] [[rav3s32]] -; CHECK: OpTypeOpaque "" -; CHECK: OpTypeOpaque "hello" -; CHECK: OpTypeOpaque "world" -; CHECK: OpTypePointer Input [[f32]] -; CHECK: OpTypePointer Function [[sts32f32]] -; CHECK: OpTypePointer Function [[a42f32]] -; CHECK: OpTypeFunction [[void]] -; CHECK: OpTypeFunction [[void]] [[bool]] -; CHECK: OpTypeFunction [[void]] [[bool]] [[s32]] -; CHECK: OpTypeFunction [[s32]] [[bool]] [[s32]] -; CHECK: OpTypeEvent -; CHECK: OpTypeDeviceEvent -; CHECK: OpTypeReserveId -; CHECK: OpTypeQueue -; CHECK: OpTypePipe ReadWrite -; CHECK: OpTypePipe ReadOnly -; CHECK: OpTypeForwardPointer [[input_ptr]] Input -; CHECK: OpTypeForwardPointer [[uniform_ptr]] Input -; CHECK: OpTypeForwardPointer [[uniform_ptr]] Uniform -; CHECK: OpTypePipeStorage -; CHECK: OpTypeNamedBarrier -; CHECK: OpTypeAccelerationStructureNV -; CHECK: OpTypeCooperativeMatrixNV [[f32]] [[uint24]] [[uint24]] [[uint24]] -OpCapability Shader -OpCapability Int64 -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%uint = OpTypeInt 32 0 -%1 = OpTypePointer Input %uint -%2 = OpTypePointer Uniform %uint -%24 = OpConstant %uint 24 -%42 = OpConstant %uint 42 -%100 = OpConstant %uint 100 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - std::vector> types = GenerateAllTypes(); - for (auto& t : types) { - context->get_type_mgr()->GetTypeInstruction(t.get()); - } - - Match(text, context.get(), false); -} - -TEST(TypeManager, GetTypeInstructionWithDecorations) { - const std::string text = R"( -; CHECK: OpDecorate [[struct:%\w+]] CPacked -; CHECK: OpMemberDecorate [[struct]] 1 Offset 4 -; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 -; CHECK: [[struct]] = OpTypeStruct [[uint]] [[uint]] -OpCapability Shader -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%uint = OpTypeInt 32 0 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - Integer u32(32, false); - Struct st({&u32, &u32}); - st.AddDecoration({10}); - st.AddMemberDecoration(1, {{35, 4}}); - (void)context->get_def_use_mgr(); - context->get_type_mgr()->GetTypeInstruction(&st); - - Match(text, context.get()); -} - -TEST(TypeManager, GetPointerToAmbiguousType1) { - const std::string text = R"( -; CHECK: [[struct1:%\w+]] = OpTypeStruct -; CHECK: [[struct2:%\w+]] = OpTypeStruct -; CHECK: OpTypePointer Function [[struct2]] -; CHECK: OpTypePointer Function [[struct1]] -OpCapability Shader -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%uint = OpTypeInt 32 0 -%1 = OpTypeStruct %uint -%2 = OpTypeStruct %uint -%3 = OpTypePointer Function %2 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - context->get_type_mgr()->FindPointerToType(1, SpvStorageClassFunction); - Match(text, context.get()); -} - -TEST(TypeManager, GetPointerToAmbiguousType2) { - const std::string text = R"( -; CHECK: [[struct1:%\w+]] = OpTypeStruct -; CHECK: [[struct2:%\w+]] = OpTypeStruct -; CHECK: OpTypePointer Function [[struct1]] -; CHECK: OpTypePointer Function [[struct2]] -OpCapability Shader -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%uint = OpTypeInt 32 0 -%1 = OpTypeStruct %uint -%2 = OpTypeStruct %uint -%3 = OpTypePointer Function %1 - )"; - - std::unique_ptr context = - BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - EXPECT_NE(context, nullptr); - - context->get_type_mgr()->FindPointerToType(2, SpvStorageClassFunction); - Match(text, context.get()); -} - -} // namespace -} // namespace analysis -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/types_test.cpp b/3rdparty/spirv-tools/test/opt/types_test.cpp deleted file mode 100644 index 82e40405c..000000000 --- a/3rdparty/spirv-tools/test/opt/types_test.cpp +++ /dev/null @@ -1,389 +0,0 @@ -// 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 "source/opt/types.h" - -#include -#include -#include - -#include "gtest/gtest.h" -#include "source/util/make_unique.h" - -namespace spvtools { -namespace opt { -namespace analysis { -namespace { - -// Fixture class providing some element types. -class SameTypeTest : public ::testing::Test { - protected: - void SetUp() override { - void_t_ = MakeUnique(); - u32_t_ = MakeUnique(32, false); - f64_t_ = MakeUnique(64); - v3u32_t_ = MakeUnique(u32_t_.get(), 3); - image_t_ = - MakeUnique(f64_t_.get(), SpvDim2D, 1, 1, 0, 0, SpvImageFormatR16, - SpvAccessQualifierReadWrite); - } - - // Element types to be used for constructing other types for testing. - std::unique_ptr void_t_; - std::unique_ptr u32_t_; - std::unique_ptr f64_t_; - std::unique_ptr v3u32_t_; - std::unique_ptr image_t_; -}; - -#define TestMultipleInstancesOfTheSameTypeQualified(ty, name, ...) \ - TEST_F(SameTypeTest, MultiSame##ty##name) { \ - std::vector> types; \ - for (int i = 0; i < 10; ++i) types.emplace_back(new ty(__VA_ARGS__)); \ - for (size_t i = 0; i < types.size(); ++i) { \ - for (size_t j = 0; j < types.size(); ++j) { \ - EXPECT_TRUE(types[i]->IsSame(types[j].get())) \ - << "expected '" << types[i]->str() << "' is the same as '" \ - << types[j]->str() << "'"; \ - EXPECT_TRUE(*types[i] == *types[j]) \ - << "expected '" << types[i]->str() << "' is the same as '" \ - << types[j]->str() << "'"; \ - } \ - } \ - } -#define TestMultipleInstancesOfTheSameType(ty, ...) \ - TestMultipleInstancesOfTheSameTypeQualified(ty, Simple, __VA_ARGS__) - -// clang-format off -TestMultipleInstancesOfTheSameType(Void) -TestMultipleInstancesOfTheSameType(Bool) -TestMultipleInstancesOfTheSameType(Integer, 32, true) -TestMultipleInstancesOfTheSameType(Float, 64) -TestMultipleInstancesOfTheSameType(Vector, u32_t_.get(), 3) -TestMultipleInstancesOfTheSameType(Matrix, v3u32_t_.get(), 4) -TestMultipleInstancesOfTheSameType(Image, f64_t_.get(), SpvDimCube, 0, 0, 1, 1, - SpvImageFormatRgb10A2, - SpvAccessQualifierWriteOnly) -TestMultipleInstancesOfTheSameType(Sampler) -TestMultipleInstancesOfTheSameType(SampledImage, image_t_.get()) -// There are three classes of arrays, based on the kinds of length information -// they have. -// 1. Array length is a constant or spec constant without spec ID, with literals -// for the constant value. -TestMultipleInstancesOfTheSameTypeQualified(Array, LenConstant, u32_t_.get(), - Array::LengthInfo{42, - { - 0, - 9999, - }}) -// 2. Array length is a spec constant with a given spec id. -TestMultipleInstancesOfTheSameTypeQualified(Array, LenSpecId, u32_t_.get(), - Array::LengthInfo{42, {1, 99}}) -// 3. Array length is an OpSpecConstantOp expression -TestMultipleInstancesOfTheSameTypeQualified(Array, LenDefiningId, u32_t_.get(), - Array::LengthInfo{42, {2, 42}}) - -TestMultipleInstancesOfTheSameType(RuntimeArray, u32_t_.get()) -TestMultipleInstancesOfTheSameType(Struct, std::vector{ - u32_t_.get(), f64_t_.get()}) -TestMultipleInstancesOfTheSameType(Opaque, "testing rocks") -TestMultipleInstancesOfTheSameType(Pointer, u32_t_.get(), SpvStorageClassInput) -TestMultipleInstancesOfTheSameType(Function, u32_t_.get(), - {f64_t_.get(), f64_t_.get()}) -TestMultipleInstancesOfTheSameType(Event) -TestMultipleInstancesOfTheSameType(DeviceEvent) -TestMultipleInstancesOfTheSameType(ReserveId) -TestMultipleInstancesOfTheSameType(Queue) -TestMultipleInstancesOfTheSameType(Pipe, SpvAccessQualifierReadWrite) -TestMultipleInstancesOfTheSameType(ForwardPointer, 10, SpvStorageClassUniform) -TestMultipleInstancesOfTheSameType(PipeStorage) -TestMultipleInstancesOfTheSameType(NamedBarrier) -TestMultipleInstancesOfTheSameType(AccelerationStructureNV) -#undef TestMultipleInstanceOfTheSameType -#undef TestMultipleInstanceOfTheSameTypeQual - -std::vector> GenerateAllTypes() { - // clang-format on - // Types in this test case are only equal to themselves, nothing else. - std::vector> types; - - // Forward Pointer - types.emplace_back(new ForwardPointer(10000, SpvStorageClassInput)); - types.emplace_back(new ForwardPointer(20000, SpvStorageClassInput)); - - // Void, Bool - types.emplace_back(new Void()); - auto* voidt = types.back().get(); - types.emplace_back(new Bool()); - auto* boolt = types.back().get(); - - // Integer - types.emplace_back(new Integer(32, true)); - auto* s32 = types.back().get(); - types.emplace_back(new Integer(32, false)); - types.emplace_back(new Integer(64, true)); - types.emplace_back(new Integer(64, false)); - auto* u64 = types.back().get(); - - // Float - types.emplace_back(new Float(32)); - auto* f32 = types.back().get(); - types.emplace_back(new Float(64)); - - // Vector - types.emplace_back(new Vector(s32, 2)); - types.emplace_back(new Vector(s32, 3)); - auto* v3s32 = types.back().get(); - types.emplace_back(new Vector(u64, 4)); - types.emplace_back(new Vector(f32, 3)); - auto* v3f32 = types.back().get(); - - // Matrix - types.emplace_back(new Matrix(v3s32, 3)); - types.emplace_back(new Matrix(v3s32, 4)); - types.emplace_back(new Matrix(v3f32, 4)); - - // Images - types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8, - SpvAccessQualifierReadOnly)); - auto* image1 = types.back().get(); - types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8, - SpvAccessQualifierReadOnly)); - types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8, - SpvAccessQualifierReadOnly)); - types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8, - SpvAccessQualifierReadWrite)); - auto* image2 = types.back().get(); - - // Sampler - types.emplace_back(new Sampler()); - - // Sampled Image - types.emplace_back(new SampledImage(image1)); - types.emplace_back(new SampledImage(image2)); - - // Array - // Length is constant with integer bit representation of 42. - types.emplace_back(new Array(f32, Array::LengthInfo{99u, {0, 42u}})); - auto* a42f32 = types.back().get(); - // Differs from previous in length value only. - types.emplace_back(new Array(f32, Array::LengthInfo{99u, {0, 44u}})); - // Length is 64-bit constant integer value 42. - types.emplace_back(new Array(u64, Array::LengthInfo{100u, {0, 42u, 0u}})); - // Differs from previous in length value only. - types.emplace_back(new Array(u64, Array::LengthInfo{100u, {0, 44u, 0u}})); - - // Length is spec constant with spec id 18 and default value 44. - types.emplace_back(new Array(f32, Array::LengthInfo{99u, - { - 1, - 18u, - 44u, - }})); - // Differs from previous in spec id only. - types.emplace_back(new Array(f32, Array::LengthInfo{99u, {1, 19u, 44u}})); - // Differs from previous in literal value only. - types.emplace_back(new Array(f32, Array::LengthInfo{99u, {1, 19u, 48u}})); - // Length is spec constant op with id 42. - types.emplace_back(new Array(f32, Array::LengthInfo{42u, {2, 42}})); - // Differs from previous in result id only. - types.emplace_back(new Array(f32, Array::LengthInfo{43u, {2, 43}})); - - // RuntimeArray - types.emplace_back(new RuntimeArray(v3f32)); - types.emplace_back(new RuntimeArray(v3s32)); - auto* rav3s32 = types.back().get(); - - // Struct - types.emplace_back(new Struct(std::vector{s32})); - types.emplace_back(new Struct(std::vector{s32, f32})); - auto* sts32f32 = types.back().get(); - types.emplace_back( - new Struct(std::vector{u64, a42f32, rav3s32})); - - // Opaque - types.emplace_back(new Opaque("")); - types.emplace_back(new Opaque("hello")); - types.emplace_back(new Opaque("world")); - - // Pointer - types.emplace_back(new Pointer(f32, SpvStorageClassInput)); - types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction)); - types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction)); - types.emplace_back(new Pointer(voidt, SpvStorageClassFunction)); - - // Function - types.emplace_back(new Function(voidt, {})); - types.emplace_back(new Function(voidt, {boolt})); - types.emplace_back(new Function(voidt, {boolt, s32})); - types.emplace_back(new Function(s32, {boolt, s32})); - - // Event, Device Event, Reserve Id, Queue, - types.emplace_back(new Event()); - types.emplace_back(new DeviceEvent()); - types.emplace_back(new ReserveId()); - types.emplace_back(new Queue()); - - // Pipe, Forward Pointer, PipeStorage, NamedBarrier - types.emplace_back(new Pipe(SpvAccessQualifierReadWrite)); - types.emplace_back(new Pipe(SpvAccessQualifierReadOnly)); - types.emplace_back(new ForwardPointer(1, SpvStorageClassInput)); - types.emplace_back(new ForwardPointer(2, SpvStorageClassInput)); - types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform)); - types.emplace_back(new PipeStorage()); - types.emplace_back(new NamedBarrier()); - - return types; -} - -TEST(Types, AllTypes) { - // Types in this test case are only equal to themselves, nothing else. - std::vector> types = GenerateAllTypes(); - - for (size_t i = 0; i < types.size(); ++i) { - for (size_t j = 0; j < types.size(); ++j) { - if (i == j) { - EXPECT_TRUE(types[i]->IsSame(types[j].get())) - << "expected '" << types[i]->str() << "' is the same as '" - << types[j]->str() << "'"; - } else { - EXPECT_FALSE(types[i]->IsSame(types[j].get())) - << "entry (" << i << "," << j << ") expected '" << types[i]->str() - << "' is different to '" << types[j]->str() << "'"; - } - } - } -} - -TEST(Types, IntSignedness) { - std::vector signednesses = {true, false, false, true}; - std::vector> types; - for (bool s : signednesses) { - types.emplace_back(new Integer(32, s)); - } - for (size_t i = 0; i < signednesses.size(); i++) { - EXPECT_EQ(signednesses[i], types[i]->IsSigned()); - } -} - -TEST(Types, IntWidth) { - std::vector widths = {1, 2, 4, 8, 16, 32, 48, 64, 128}; - std::vector> types; - for (uint32_t w : widths) { - types.emplace_back(new Integer(w, true)); - } - for (size_t i = 0; i < widths.size(); i++) { - EXPECT_EQ(widths[i], types[i]->width()); - } -} - -TEST(Types, FloatWidth) { - std::vector widths = {1, 2, 4, 8, 16, 32, 48, 64, 128}; - std::vector> types; - for (uint32_t w : widths) { - types.emplace_back(new Float(w)); - } - for (size_t i = 0; i < widths.size(); i++) { - EXPECT_EQ(widths[i], types[i]->width()); - } -} - -TEST(Types, VectorElementCount) { - auto s32 = MakeUnique(32, true); - for (uint32_t c : {2, 3, 4}) { - auto s32v = MakeUnique(s32.get(), c); - EXPECT_EQ(c, s32v->element_count()); - } -} - -TEST(Types, MatrixElementCount) { - auto s32 = MakeUnique(32, true); - auto s32v4 = MakeUnique(s32.get(), 4); - for (uint32_t c : {1, 2, 3, 4, 10, 100}) { - auto s32m = MakeUnique(s32v4.get(), c); - EXPECT_EQ(c, s32m->element_count()); - } -} - -TEST(Types, IsUniqueType) { - std::vector> types = GenerateAllTypes(); - - for (auto& t : types) { - bool expectation = true; - // Disallowing variable pointers. - switch (t->kind()) { - case Type::kArray: - case Type::kRuntimeArray: - case Type::kStruct: - expectation = false; - break; - default: - break; - } - EXPECT_EQ(t->IsUniqueType(false), expectation) - << "expected '" << t->str() << "' to be a " - << (expectation ? "" : "non-") << "unique type"; - - // Allowing variables pointers. - if (t->AsPointer()) expectation = false; - EXPECT_EQ(t->IsUniqueType(true), expectation) - << "expected '" << t->str() << "' to be a " - << (expectation ? "" : "non-") << "unique type"; - } -} - -std::vector> GenerateAllTypesWithDecorations() { - std::vector> types = GenerateAllTypes(); - uint32_t elems = 1; - uint32_t decs = 1; - for (auto& t : types) { - for (uint32_t i = 0; i < (decs % 10); ++i) { - std::vector decoration; - for (uint32_t j = 0; j < (elems % 4) + 1; ++j) { - decoration.push_back(j); - } - t->AddDecoration(std::move(decoration)); - ++elems; - ++decs; - } - } - - return types; -} - -TEST(Types, Clone) { - std::vector> types = GenerateAllTypesWithDecorations(); - for (auto& t : types) { - auto clone = t->Clone(); - EXPECT_TRUE(*t == *clone); - EXPECT_TRUE(t->HasSameDecorations(clone.get())); - EXPECT_NE(clone.get(), t.get()); - } -} - -TEST(Types, RemoveDecorations) { - std::vector> types = GenerateAllTypesWithDecorations(); - for (auto& t : types) { - auto decorationless = t->RemoveDecorations(); - EXPECT_EQ(*t == *decorationless, t->decoration_empty()); - EXPECT_EQ(t->HasSameDecorations(decorationless.get()), - t->decoration_empty()); - EXPECT_NE(t.get(), decorationless.get()); - } -} - -} // namespace -} // namespace analysis -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/unify_const_test.cpp b/3rdparty/spirv-tools/test/opt/unify_const_test.cpp deleted file mode 100644 index 6ed217348..000000000 --- a/3rdparty/spirv-tools/test/opt/unify_const_test.cpp +++ /dev/null @@ -1,996 +0,0 @@ -// 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 "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -// Returns the types defining instructions commonly used in many tests. -std::vector CommonTypes() { - return std::vector{ - // clang-format off - // scalar types - "%bool = OpTypeBool", - "%uint = OpTypeInt 32 0", - "%int = OpTypeInt 32 1", - "%uint64 = OpTypeInt 64 0", - "%int64 = OpTypeInt 64 1", - "%float = OpTypeFloat 32", - "%double = OpTypeFloat 64", - // vector types - "%v2bool = OpTypeVector %bool 2", - "%v2uint = OpTypeVector %uint 2", - "%v2int = OpTypeVector %int 2", - "%v3int = OpTypeVector %int 3", - "%v4int = OpTypeVector %int 4", - "%v2float = OpTypeVector %float 2", - "%v3float = OpTypeVector %float 3", - "%v2double = OpTypeVector %double 2", - // struct types - "%inner_struct = OpTypeStruct %bool %float", - "%outer_struct = OpTypeStruct %inner_struct %int %double", - "%flat_struct = OpTypeStruct %bool %int %float %double", - // variable pointer types - "%_pf_bool = OpTypePointer Function %bool", - "%_pf_uint = OpTypePointer Function %uint", - "%_pf_int = OpTypePointer Function %int", - "%_pf_uint64 = OpTypePointer Function %uint64", - "%_pf_int64 = OpTypePointer Function %int64", - "%_pf_float = OpTypePointer Function %float", - "%_pf_double = OpTypePointer Function %double", - "%_pf_v2int = OpTypePointer Function %v2int", - "%_pf_v3int = OpTypePointer Function %v3int", - "%_pf_v4int = OpTypePointer Function %v4int", - "%_pf_v2float = OpTypePointer Function %v2float", - "%_pf_v3float = OpTypePointer Function %v3float", - "%_pf_v2double = OpTypePointer Function %v2double", - "%_pf_inner_struct = OpTypePointer Function %inner_struct", - "%_pf_outer_struct = OpTypePointer Function %outer_struct", - "%_pf_flat_struct = OpTypePointer Function %flat_struct", - // clang-format on - }; -} - -// A helper function to strip OpName instructions from the given string of -// disassembly code and put those debug instructions to a set. Returns the -// string with all OpName instruction stripped and a set of OpName -// instructions. -std::tuple> -StripOpNameInstructionsToSet(const std::string& str) { - std::stringstream ss(str); - std::ostringstream oss; - std::string inst_str; - std::unordered_set opname_instructions; - while (std::getline(ss, inst_str, '\n')) { - if (inst_str.find("OpName %") == std::string::npos) { - oss << inst_str << '\n'; - } else { - opname_instructions.insert(inst_str); - } - } - return std::make_tuple(oss.str(), std::move(opname_instructions)); -} - -// The test fixture for all tests of UnifyConstantPass. This fixture defines -// the rule of checking: all the optimized code should be exactly the same as -// the expected code, except the OpName instructions, which can be different in -// order. -template -class UnifyConstantTest : public PassTest { - protected: - // Runs UnifyConstantPass on the code built from the given |test_builder|, - // and checks whether the optimization result matches with the code built - // from |expected_builder|. - void Check(const AssemblyBuilder& expected_builder, - const AssemblyBuilder& test_builder) { - // unoptimized code - const std::string original_before_strip = test_builder.GetCode(); - std::string original_without_opnames; - std::unordered_set original_opnames; - std::tie(original_without_opnames, original_opnames) = - StripOpNameInstructionsToSet(original_before_strip); - - // expected code - std::string expected_without_opnames; - std::unordered_set expected_opnames; - std::tie(expected_without_opnames, expected_opnames) = - StripOpNameInstructionsToSet(expected_builder.GetCode()); - - // optimized code - std::string optimized_before_strip; - auto status = Pass::Status::SuccessWithoutChange; - std::tie(optimized_before_strip, status) = - this->template SinglePassRunAndDisassemble( - test_builder.GetCode(), - /* skip_nop = */ true, /* do_validation = */ false); - std::string optimized_without_opnames; - std::unordered_set optimized_opnames; - std::tie(optimized_without_opnames, optimized_opnames) = - StripOpNameInstructionsToSet(optimized_before_strip); - - // Flag "status" should be returned correctly. - EXPECT_NE(Pass::Status::Failure, status); - EXPECT_EQ(expected_without_opnames == original_without_opnames, - status == Pass::Status::SuccessWithoutChange); - // Code except OpName instructions should be exactly the same. - EXPECT_EQ(expected_without_opnames, optimized_without_opnames); - // OpName instructions can be in different order, but the content must be - // the same. - EXPECT_EQ(expected_opnames, optimized_opnames); - } -}; - -using UnifyFrontEndConstantSingleTest = - UnifyConstantTest>; - -TEST_F(UnifyFrontEndConstantSingleTest, Basic) { - AssemblyBuilder test_builder; - AssemblyBuilder expected_builder; - - test_builder - .AppendTypesConstantsGlobals({ - "%uint = OpTypeInt 32 0", "%_pf_uint = OpTypePointer Function %uint", - "%unsigned_1 = OpConstant %uint 1", - "%unsigned_1_duplicate = OpConstant %uint 1", // duplicated constant - }) - .AppendInMain({ - "%uint_var = OpVariable %_pf_uint Function", - "OpStore %uint_var %unsigned_1_duplicate", - }); - - expected_builder - .AppendTypesConstantsGlobals({ - "%uint = OpTypeInt 32 0", - "%_pf_uint = OpTypePointer Function %uint", - "%unsigned_1 = OpConstant %uint 1", - }) - .AppendInMain({ - "%uint_var = OpVariable %_pf_uint Function", - "OpStore %uint_var %unsigned_1", - }) - .AppendNames({ - "OpName %unsigned_1 \"unsigned_1_duplicate\"", // the OpName - // instruction of the - // removed duplicated - // constant won't be - // erased. - }); - Check(expected_builder, test_builder); -} - -TEST_F(UnifyFrontEndConstantSingleTest, SkipWhenResultIdHasDecorations) { - AssemblyBuilder test_builder; - AssemblyBuilder expected_builder; - - test_builder - .AppendAnnotations({ - // So far we don't have valid decorations for constants. This is - // preparing for the future updates of SPIR-V. - // TODO(qining): change to a valid decoration once they are available. - "OpDecorate %f_1 RelaxedPrecision", - "OpDecorate %f_2_dup RelaxedPrecision", - }) - .AppendTypesConstantsGlobals({ - // clang-format off - "%float = OpTypeFloat 32", - "%_pf_float = OpTypePointer Function %float", - "%f_1 = OpConstant %float 1", - // %f_1 has decoration, so %f_1 will not be used to replace %f_1_dup. - "%f_1_dup = OpConstant %float 1", - "%f_2 = OpConstant %float 2", - // %_2_dup has decoration, so %f_2 will not replace %f_2_dup. - "%f_2_dup = OpConstant %float 2", - // no decoration for %f_3 or %f_3_dup, %f_3_dup should be replaced. - "%f_3 = OpConstant %float 3", - "%f_3_dup = OpConstant %float 3", - // clang-format on - }) - .AppendInMain({ - // clang-format off - "%f_var = OpVariable %_pf_float Function", - "OpStore %f_var %f_1_dup", - "OpStore %f_var %f_2_dup", - "OpStore %f_var %f_3_dup", - // clang-format on - }); - - expected_builder - .AppendAnnotations({ - "OpDecorate %f_1 RelaxedPrecision", - "OpDecorate %f_2_dup RelaxedPrecision", - }) - .AppendTypesConstantsGlobals({ - // clang-format off - "%float = OpTypeFloat 32", - "%_pf_float = OpTypePointer Function %float", - "%f_1 = OpConstant %float 1", - "%f_1_dup = OpConstant %float 1", - "%f_2 = OpConstant %float 2", - "%f_2_dup = OpConstant %float 2", - "%f_3 = OpConstant %float 3", - // clang-format on - }) - .AppendInMain({ - // clang-format off - "%f_var = OpVariable %_pf_float Function", - "OpStore %f_var %f_1_dup", - "OpStore %f_var %f_2_dup", - "OpStore %f_var %f_3", - // clang-format on - }) - .AppendNames({ - "OpName %f_3 \"f_3_dup\"", - }); - - Check(expected_builder, test_builder); -} - -TEST_F(UnifyFrontEndConstantSingleTest, UnifyWithDecorationOnTypes) { - AssemblyBuilder test_builder; - AssemblyBuilder expected_builder; - - test_builder - .AppendAnnotations({ - "OpMemberDecorate %flat_d 1 RelaxedPrecision", - }) - .AppendTypesConstantsGlobals({ - // clang-format off - "%int = OpTypeInt 32 1", - "%float = OpTypeFloat 32", - "%flat = OpTypeStruct %int %float", - "%_pf_flat = OpTypePointer Function %flat", - // decorated flat struct - "%flat_d = OpTypeStruct %int %float", - "%_pf_flat_d = OpTypePointer Function %flat_d", - // perserved contants. %flat_1 and %flat_d has same members, but - // their type are different in decorations, so they should not be - // used to replace each other. - "%int_1 = OpConstant %int 1", - "%float_1 = OpConstant %float 1", - "%flat_1 = OpConstantComposite %flat %int_1 %float_1", - "%flat_d_1 = OpConstantComposite %flat_d %int_1 %float_1", - // duplicated constants. - "%flat_1_dup = OpConstantComposite %flat %int_1 %float_1", - "%flat_d_1_dup = OpConstantComposite %flat_d %int_1 %float_1", - // clang-format on - }) - .AppendInMain({ - "%flat_var = OpVariable %_pf_flat Function", - "OpStore %flat_var %flat_1_dup", - "%flat_d_var = OpVariable %_pf_flat_d Function", - "OpStore %flat_d_var %flat_d_1_dup", - }); - - expected_builder - .AppendAnnotations({ - "OpMemberDecorate %flat_d 1 RelaxedPrecision", - }) - .AppendTypesConstantsGlobals({ - // clang-format off - "%int = OpTypeInt 32 1", - "%float = OpTypeFloat 32", - "%flat = OpTypeStruct %int %float", - "%_pf_flat = OpTypePointer Function %flat", - // decorated flat struct - "%flat_d = OpTypeStruct %int %float", - "%_pf_flat_d = OpTypePointer Function %flat_d", - "%int_1 = OpConstant %int 1", - "%float_1 = OpConstant %float 1", - "%flat_1 = OpConstantComposite %flat %int_1 %float_1", - "%flat_d_1 = OpConstantComposite %flat_d %int_1 %float_1", - // clang-format on - }) - .AppendInMain({ - "%flat_var = OpVariable %_pf_flat Function", - "OpStore %flat_var %flat_1", - "%flat_d_var = OpVariable %_pf_flat_d Function", - "OpStore %flat_d_var %flat_d_1", - }) - .AppendNames({ - "OpName %flat_1 \"flat_1_dup\"", - "OpName %flat_d_1 \"flat_d_1_dup\"", - }); - - Check(expected_builder, test_builder); -} - -struct UnifyConstantTestCase { - // preserved constants. - std::vector preserved_consts; - // expected uses of the preserved constants. - std::vector use_preserved_consts; - // duplicated constants of the preserved constants. - std::vector duplicate_consts; - // uses of the duplicated constants, expected to be updated to use the - // preserved constants. - std::vector use_duplicate_consts; - // The updated OpName instructions that originally refer to duplicated - // constants. - std::vector remapped_names; -}; - -using UnifyFrontEndConstantParamTest = UnifyConstantTest< - PassTest<::testing::TestWithParam>>; - -TEST_P(UnifyFrontEndConstantParamTest, TestCase) { - auto& tc = GetParam(); - AssemblyBuilder test_builder; - AssemblyBuilder expected_builder; - test_builder.AppendTypesConstantsGlobals(CommonTypes()); - expected_builder.AppendTypesConstantsGlobals(CommonTypes()); - - test_builder.AppendTypesConstantsGlobals(tc.preserved_consts) - .AppendTypesConstantsGlobals(tc.duplicate_consts) - .AppendInMain(tc.use_duplicate_consts); - - // Duplicated constants are killed in the expected output, and the debug - // instructions attached to those duplicated instructions will be migrated to - // the corresponding preserved constants. - expected_builder.AppendTypesConstantsGlobals(tc.preserved_consts) - .AppendInMain(tc.use_preserved_consts) - .AppendNames(tc.remapped_names); - - Check(expected_builder, test_builder); -} - -INSTANTIATE_TEST_SUITE_P( - Case, UnifyFrontEndConstantParamTest, - :: - testing:: - ValuesIn( - std:: - vector( - { - // clang-format off - // basic tests for scalar constants - { - // preserved constants - { - "%bool_true = OpConstantTrue %bool", - "%signed_1 = OpConstant %int 1", - "%signed_minus_1 = OpConstant %int64 -1", - "%unsigned_max = OpConstant %uint64 18446744073709551615", - "%float_1 = OpConstant %float 1", - "%double_1 = OpConstant %double 1", - }, - // use preserved constants in main - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %bool_true", - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %signed_1", - "%int64_var = OpVariable %_pf_int64 Function", - "OpStore %int64_var %signed_minus_1", - "%uint64_var = OpVariable %_pf_uint64 Function", - "OpStore %uint64_var %unsigned_max", - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %float_1", - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %double_1", - }, - // duplicated constants - { - "%bool_true_duplicate = OpConstantTrue %bool", - "%signed_1_duplicate = OpConstant %int 1", - "%signed_minus_1_duplicate = OpConstant %int64 -1", - "%unsigned_max_duplicate = OpConstant %uint64 18446744073709551615", - "%float_1_duplicate = OpConstant %float 1", - "%double_1_duplicate = OpConstant %double 1", - }, - // use duplicated constants in main - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %bool_true_duplicate", - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %signed_1_duplicate", - "%int64_var = OpVariable %_pf_int64 Function", - "OpStore %int64_var %signed_minus_1_duplicate", - "%uint64_var = OpVariable %_pf_uint64 Function", - "OpStore %uint64_var %unsigned_max_duplicate", - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %float_1_duplicate", - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %double_1_duplicate", - }, - // remapped names - { - "OpName %bool_true \"bool_true_duplicate\"", - "OpName %signed_1 \"signed_1_duplicate\"", - "OpName %signed_minus_1 \"signed_minus_1_duplicate\"", - "OpName %unsigned_max \"unsigned_max_duplicate\"", - "OpName %float_1 \"float_1_duplicate\"", - "OpName %double_1 \"double_1_duplicate\"", - }, - }, - // NaN in different bit patterns should not be unified, but the ones - // using same bit pattern should be unified. - { - // preserved constants - { - "%float_nan_1 = OpConstant %float 0x1.8p+128", // !2143289344, 7FC00000 - "%float_nan_2 = OpConstant %float 0x1.800002p+128",// !2143289345 7FC00001 - }, - // use preserved constants in main - { - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %float_nan_1", - "OpStore %float_var %float_nan_2", - }, - // duplicated constants - { - "%float_nan_1_duplicate = OpConstant %float 0x1.8p+128", // !2143289344, 7FC00000 - "%float_nan_2_duplicate = OpConstant %float 0x1.800002p+128",// !2143289345, 7FC00001 - }, - // use duplicated constants in main - { - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %float_nan_1_duplicate", - "OpStore %float_var %float_nan_2_duplicate", - }, - // remapped names - { - "OpName %float_nan_1 \"float_nan_1_duplicate\"", - "OpName %float_nan_2 \"float_nan_2_duplicate\"", - }, - }, - // null values - { - // preserved constants - { - "%bool_null = OpConstantNull %bool", - "%signed_null = OpConstantNull %int", - "%signed_64_null = OpConstantNull %int64", - "%float_null = OpConstantNull %float", - "%double_null = OpConstantNull %double", - // zero-valued constants will not be unified with the equivalent - // null constants. - "%signed_zero = OpConstant %int 0", - }, - // use preserved constants in main - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %bool_null", - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %signed_null", - "%int64_var = OpVariable %_pf_int64 Function", - "OpStore %int64_var %signed_64_null", - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %float_null", - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %double_null", - }, - // duplicated constants - { - "%bool_null_duplicate = OpConstantNull %bool", - "%signed_null_duplicate = OpConstantNull %int", - "%signed_64_null_duplicate = OpConstantNull %int64", - "%float_null_duplicate = OpConstantNull %float", - "%double_null_duplicate = OpConstantNull %double", - }, - // use duplicated constants in main - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %bool_null_duplicate", - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %signed_null_duplicate", - "%int64_var = OpVariable %_pf_int64 Function", - "OpStore %int64_var %signed_64_null_duplicate", - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %float_null_duplicate", - "%double_var = OpVariable %_pf_double Function", - "OpStore %double_var %double_null_duplicate", - }, - // remapped names - { - "OpName %bool_null \"bool_null_duplicate\"", - "OpName %signed_null \"signed_null_duplicate\"", - "OpName %signed_64_null \"signed_64_null_duplicate\"", - "OpName %float_null \"float_null_duplicate\"", - "OpName %double_null \"double_null_duplicate\"", - }, - }, - // constant sampler - { - // preserved constants - { - "%sampler = OpTypeSampler", - "%_pf_sampler = OpTypePointer Function %sampler", - "%sampler_1 = OpConstantSampler %sampler Repeat 0 Linear", - }, - // use preserved constants in main - { - "%sampler_var = OpVariable %_pf_sampler Function", - "OpStore %sampler_var %sampler_1", - }, - // duplicated constants - { - "%sampler_1_duplicate = OpConstantSampler %sampler Repeat 0 Linear", - }, - // use duplicated constants in main - { - "%sampler_var = OpVariable %_pf_sampler Function", - "OpStore %sampler_var %sampler_1_duplicate", - }, - // remapped names - { - "OpName %sampler_1 \"sampler_1_duplicate\"", - }, - }, - // duplicate vector built from same ids. - { - // preserved constants - { - "%signed_1 = OpConstant %int 1", - "%signed_2 = OpConstant %int 2", - "%signed_3 = OpConstant %int 3", - "%signed_4 = OpConstant %int 4", - "%vec = OpConstantComposite %v4int %signed_1 %signed_2 %signed_3 %signed_4", - }, - // use preserved constants in main - { - "%vec_var = OpVariable %_pf_v4int Function", - "OpStore %vec_var %vec", - }, - // duplicated constants - { - "%vec_duplicate = OpConstantComposite %v4int %signed_1 %signed_2 %signed_3 %signed_4", - }, - // use duplicated constants in main - { - "%vec_var = OpVariable %_pf_v4int Function", - "OpStore %vec_var %vec_duplicate", - }, - // remapped names - { - "OpName %vec \"vec_duplicate\"", - } - }, - // duplicate vector built from duplicated ids. - { - // preserved constants - { - "%signed_1 = OpConstant %int 1", - "%signed_2 = OpConstant %int 2", - "%signed_3 = OpConstant %int 3", - "%signed_4 = OpConstant %int 4", - "%vec = OpConstantComposite %v4int %signed_1 %signed_2 %signed_3 %signed_4", - }, - // use preserved constants in main - { - "%vec_var = OpVariable %_pf_v4int Function", - "OpStore %vec_var %vec", - }, - // duplicated constants - { - "%signed_3_duplicate = OpConstant %int 3", - "%signed_4_duplicate = OpConstant %int 4", - "%vec_duplicate = OpConstantComposite %v4int %signed_1 %signed_2 %signed_3_duplicate %signed_4_duplicate", - }, - // use duplicated constants in main - { - "%vec_var = OpVariable %_pf_v4int Function", - "OpStore %vec_var %vec_duplicate", - }, - // remapped names - { - "OpName %signed_3 \"signed_3_duplicate\"", - "OpName %signed_4 \"signed_4_duplicate\"", - "OpName %vec \"vec_duplicate\"", - }, - }, - // flat struct - { - // preserved constants - { - "%bool_true = OpConstantTrue %bool", - "%signed_1 = OpConstant %int 1", - "%float_1 = OpConstant %float 1", - "%double_1 = OpConstant %double 1", - "%s = OpConstantComposite %flat_struct %bool_true %signed_1 %float_1 %double_1", - }, - // use preserved constants in main - { - "%s_var = OpVariable %_pf_flat_struct Function", - "OpStore %s_var %s", - }, - // duplicated constants - { - "%float_1_duplicate = OpConstant %float 1", - "%double_1_duplicate = OpConstant %double 1", - "%s_duplicate = OpConstantComposite %flat_struct %bool_true %signed_1 %float_1_duplicate %double_1_duplicate", - }, - // use duplicated constants in main - { - "%s_var = OpVariable %_pf_flat_struct Function", - "OpStore %s_var %s_duplicate", - }, - // remapped names - { - "OpName %float_1 \"float_1_duplicate\"", - "OpName %double_1 \"double_1_duplicate\"", - "OpName %s \"s_duplicate\"", - }, - }, - // nested struct - { - // preserved constants - { - "%bool_true = OpConstantTrue %bool", - "%signed_1 = OpConstant %int 1", - "%float_1 = OpConstant %float 1", - "%double_1 = OpConstant %double 1", - "%inner = OpConstantComposite %inner_struct %bool_true %float_1", - "%outer = OpConstantComposite %outer_struct %inner %signed_1 %double_1", - }, - // use preserved constants in main - { - "%outer_var = OpVariable %_pf_outer_struct Function", - "OpStore %outer_var %outer", - }, - // duplicated constants - { - "%float_1_duplicate = OpConstant %float 1", - "%double_1_duplicate = OpConstant %double 1", - "%inner_duplicate = OpConstantComposite %inner_struct %bool_true %float_1_duplicate", - "%outer_duplicate = OpConstantComposite %outer_struct %inner_duplicate %signed_1 %double_1_duplicate", - }, - // use duplicated constants in main - { - "%outer_var = OpVariable %_pf_outer_struct Function", - "OpStore %outer_var %outer_duplicate", - }, - // remapped names - { - "OpName %float_1 \"float_1_duplicate\"", - "OpName %double_1 \"double_1_duplicate\"", - "OpName %inner \"inner_duplicate\"", - "OpName %outer \"outer_duplicate\"", - }, - }, - // composite type null constants. Null constants and zero-valued - // constants should not be used to replace each other. - { - // preserved constants - { - "%bool_zero = OpConstantFalse %bool", - "%float_zero = OpConstant %float 0", - "%int_null = OpConstantNull %int", - "%double_null = OpConstantNull %double", - // inner_struct type null constant. - "%null_inner = OpConstantNull %inner_struct", - // zero-valued composite constant built from zero-valued constant - // component. inner_zero should not be replace by null_inner. - "%inner_zero = OpConstantComposite %inner_struct %bool_zero %float_zero", - // zero-valued composite contant built from zero-valued constants - // and null constants. - "%outer_zero = OpConstantComposite %outer_struct %inner_zero %int_null %double_null", - // outer_struct type null constant, it should not be replaced by - // outer_zero. - "%null_outer = OpConstantNull %outer_struct", - }, - // use preserved constants in main - { - "%inner_var = OpVariable %_pf_inner_struct Function", - "OpStore %inner_var %inner_zero", - "OpStore %inner_var %null_inner", - "%outer_var = OpVariable %_pf_outer_struct Function", - "OpStore %outer_var %outer_zero", - "OpStore %outer_var %null_outer", - }, - // duplicated constants - { - "%null_inner_dup = OpConstantNull %inner_struct", - "%null_outer_dup = OpConstantNull %outer_struct", - "%inner_zero_dup = OpConstantComposite %inner_struct %bool_zero %float_zero", - "%outer_zero_dup = OpConstantComposite %outer_struct %inner_zero_dup %int_null %double_null", - }, - // use duplicated constants in main - { - "%inner_var = OpVariable %_pf_inner_struct Function", - "OpStore %inner_var %inner_zero_dup", - "OpStore %inner_var %null_inner_dup", - "%outer_var = OpVariable %_pf_outer_struct Function", - "OpStore %outer_var %outer_zero_dup", - "OpStore %outer_var %null_outer_dup", - }, - // remapped names - { - "OpName %null_inner \"null_inner_dup\"", - "OpName %null_outer \"null_outer_dup\"", - "OpName %inner_zero \"inner_zero_dup\"", - "OpName %outer_zero \"outer_zero_dup\"", - }, - }, - // Spec Constants with SpecId decoration should be skipped. - { - // preserved constants - { - // Assembly builder will add OpDecorate SpecId instruction for the - // following spec constant instructions automatically. - "%spec_bool_1 = OpSpecConstantTrue %bool", - "%spec_bool_2 = OpSpecConstantTrue %bool", - "%spec_int_1 = OpSpecConstant %int 1", - "%spec_int_2 = OpSpecConstant %int 1", - }, - // use preserved constants in main - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %spec_bool_1", - "OpStore %bool_var %spec_bool_2", - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %spec_int_1", - "OpStore %int_var %spec_int_2", - }, - // duplicated constants. No duplicated instruction to remove in this - // case. - {}, - // use duplicated constants in main. Same as the above 'use preserved - // constants in main' defined above, as no instruction should be - // removed in this case. - { - "%bool_var = OpVariable %_pf_bool Function", - "OpStore %bool_var %spec_bool_1", - "OpStore %bool_var %spec_bool_2", - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %spec_int_1", - "OpStore %int_var %spec_int_2", - }, - // remapped names. No duplicated instruction removed, so this is - // empty. - {} - }, - // spec constant composite - { - // preserved constants - { - "%spec_bool_true = OpSpecConstantTrue %bool", - "%spec_signed_1 = OpSpecConstant %int 1", - "%float_1 = OpConstant %float 1", - "%double_1 = OpConstant %double 1", - "%spec_inner = OpSpecConstantComposite %inner_struct %spec_bool_true %float_1", - "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %spec_signed_1 %double_1", - "%spec_vec2 = OpSpecConstantComposite %v2float %float_1 %float_1", - }, - // use preserved constants in main - { - "%outer_var = OpVariable %_pf_outer_struct Function", - "OpStore %outer_var %spec_outer", - "%v2float_var = OpVariable %_pf_v2float Function", - "OpStore %v2float_var %spec_vec2", - }, - // duplicated constants - { - "%float_1_duplicate = OpConstant %float 1", - "%double_1_duplicate = OpConstant %double 1", - "%spec_inner_duplicate = OpSpecConstantComposite %inner_struct %spec_bool_true %float_1_duplicate", - "%spec_outer_duplicate = OpSpecConstantComposite %outer_struct %spec_inner_duplicate %spec_signed_1 %double_1_duplicate", - "%spec_vec2_duplicate = OpSpecConstantComposite %v2float %float_1 %float_1_duplicate", - }, - // use duplicated constants in main - { - "%outer_var = OpVariable %_pf_outer_struct Function", - "OpStore %outer_var %spec_outer_duplicate", - "%v2float_var = OpVariable %_pf_v2float Function", - "OpStore %v2float_var %spec_vec2_duplicate", - }, - // remapped names - { - "OpName %float_1 \"float_1_duplicate\"", - "OpName %double_1 \"double_1_duplicate\"", - "OpName %spec_inner \"spec_inner_duplicate\"", - "OpName %spec_outer \"spec_outer_duplicate\"", - "OpName %spec_vec2 \"spec_vec2_duplicate\"", - }, - }, - // spec constant op with int scalar - { - // preserved constants - { - "%spec_signed_1 = OpSpecConstant %int 1", - "%spec_signed_2 = OpSpecConstant %int 2", - "%spec_signed_add = OpSpecConstantOp %int IAdd %spec_signed_1 %spec_signed_2", - }, - // use preserved constants in main - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %spec_signed_add", - }, - // duplicated constants - { - "%spec_signed_add_duplicate = OpSpecConstantOp %int IAdd %spec_signed_1 %spec_signed_2", - }, - // use duplicated contants in main - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %spec_signed_add_duplicate", - }, - // remapped names - { - "OpName %spec_signed_add \"spec_signed_add_duplicate\"", - }, - }, - // spec constant op composite extract - { - // preserved constants - { - "%float_1 = OpConstant %float 1", - "%spec_vec2 = OpSpecConstantComposite %v2float %float_1 %float_1", - "%spec_extract = OpSpecConstantOp %float CompositeExtract %spec_vec2 1", - }, - // use preserved constants in main - { - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %spec_extract", - }, - // duplicated constants - { - "%spec_extract_duplicate = OpSpecConstantOp %float CompositeExtract %spec_vec2 1", - }, - // use duplicated constants in main - { - "%float_var = OpVariable %_pf_float Function", - "OpStore %float_var %spec_extract_duplicate", - }, - // remapped names - { - "OpName %spec_extract \"spec_extract_duplicate\"", - }, - }, - // spec constant op vector shuffle - { - // preserved constants - { - "%float_1 = OpConstant %float 1", - "%float_2 = OpConstant %float 2", - "%spec_vec2_1 = OpSpecConstantComposite %v2float %float_1 %float_1", - "%spec_vec2_2 = OpSpecConstantComposite %v2float %float_2 %float_2", - "%spec_vector_shuffle = OpSpecConstantOp %v2float VectorShuffle %spec_vec2_1 %spec_vec2_2 1 2", - }, - // use preserved constants in main - { - "%v2float_var = OpVariable %_pf_v2float Function", - "OpStore %v2float_var %spec_vector_shuffle", - }, - // duplicated constants - { - "%spec_vector_shuffle_duplicate = OpSpecConstantOp %v2float VectorShuffle %spec_vec2_1 %spec_vec2_2 1 2", - }, - // use duplicated constants in main - { - "%v2float_var = OpVariable %_pf_v2float Function", - "OpStore %v2float_var %spec_vector_shuffle_duplicate", - }, - // remapped names - { - "OpName %spec_vector_shuffle \"spec_vector_shuffle_duplicate\"", - }, - }, - // long dependency chain - { - // preserved constants - { - "%array_size = OpConstant %int 4", - "%type_arr_int_4 = OpTypeArray %int %array_size", - "%signed_0 = OpConstant %int 100", - "%signed_1 = OpConstant %int 1", - "%signed_2 = OpSpecConstantOp %int IAdd %signed_0 %signed_1", - "%signed_3 = OpSpecConstantOp %int ISub %signed_0 %signed_2", - "%signed_4 = OpSpecConstantOp %int IAdd %signed_0 %signed_3", - "%signed_5 = OpSpecConstantOp %int ISub %signed_0 %signed_4", - "%signed_6 = OpSpecConstantOp %int IAdd %signed_0 %signed_5", - "%signed_7 = OpSpecConstantOp %int ISub %signed_0 %signed_6", - "%signed_8 = OpSpecConstantOp %int IAdd %signed_0 %signed_7", - "%signed_9 = OpSpecConstantOp %int ISub %signed_0 %signed_8", - "%signed_10 = OpSpecConstantOp %int IAdd %signed_0 %signed_9", - "%signed_11 = OpSpecConstantOp %int ISub %signed_0 %signed_10", - "%signed_12 = OpSpecConstantOp %int IAdd %signed_0 %signed_11", - "%signed_13 = OpSpecConstantOp %int ISub %signed_0 %signed_12", - "%signed_14 = OpSpecConstantOp %int IAdd %signed_0 %signed_13", - "%signed_15 = OpSpecConstantOp %int ISub %signed_0 %signed_14", - "%signed_16 = OpSpecConstantOp %int ISub %signed_0 %signed_15", - "%signed_17 = OpSpecConstantOp %int IAdd %signed_0 %signed_16", - "%signed_18 = OpSpecConstantOp %int ISub %signed_0 %signed_17", - "%signed_19 = OpSpecConstantOp %int IAdd %signed_0 %signed_18", - "%signed_20 = OpSpecConstantOp %int ISub %signed_0 %signed_19", - "%signed_vec_a = OpSpecConstantComposite %v2int %signed_18 %signed_19", - "%signed_vec_b = OpSpecConstantOp %v2int IMul %signed_vec_a %signed_vec_a", - "%signed_21 = OpSpecConstantOp %int CompositeExtract %signed_vec_b 0", - "%signed_array = OpConstantComposite %type_arr_int_4 %signed_20 %signed_20 %signed_21 %signed_21", - "%signed_22 = OpSpecConstantOp %int CompositeExtract %signed_array 0", - }, - // use preserved constants in main - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %signed_22", - }, - // duplicated constants - { - "%signed_0_dup = OpConstant %int 100", - "%signed_1_dup = OpConstant %int 1", - "%signed_2_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_1_dup", - "%signed_3_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_2_dup", - "%signed_4_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_3_dup", - "%signed_5_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_4_dup", - "%signed_6_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_5_dup", - "%signed_7_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_6_dup", - "%signed_8_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_7_dup", - "%signed_9_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_8_dup", - "%signed_10_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_9_dup", - "%signed_11_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_10_dup", - "%signed_12_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_11_dup", - "%signed_13_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_12_dup", - "%signed_14_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_13_dup", - "%signed_15_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_14_dup", - "%signed_16_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_15_dup", - "%signed_17_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_16_dup", - "%signed_18_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_17_dup", - "%signed_19_dup = OpSpecConstantOp %int IAdd %signed_0_dup %signed_18_dup", - "%signed_20_dup = OpSpecConstantOp %int ISub %signed_0_dup %signed_19_dup", - "%signed_vec_a_dup = OpSpecConstantComposite %v2int %signed_18_dup %signed_19_dup", - "%signed_vec_b_dup = OpSpecConstantOp %v2int IMul %signed_vec_a_dup %signed_vec_a_dup", - "%signed_21_dup = OpSpecConstantOp %int CompositeExtract %signed_vec_b_dup 0", - "%signed_array_dup = OpConstantComposite %type_arr_int_4 %signed_20_dup %signed_20_dup %signed_21_dup %signed_21_dup", - "%signed_22_dup = OpSpecConstantOp %int CompositeExtract %signed_array_dup 0", - }, - // use duplicated constants in main - { - "%int_var = OpVariable %_pf_int Function", - "OpStore %int_var %signed_22_dup", - }, - // remapped names - { - "OpName %signed_0 \"signed_0_dup\"", - "OpName %signed_1 \"signed_1_dup\"", - "OpName %signed_2 \"signed_2_dup\"", - "OpName %signed_3 \"signed_3_dup\"", - "OpName %signed_4 \"signed_4_dup\"", - "OpName %signed_5 \"signed_5_dup\"", - "OpName %signed_6 \"signed_6_dup\"", - "OpName %signed_7 \"signed_7_dup\"", - "OpName %signed_8 \"signed_8_dup\"", - "OpName %signed_9 \"signed_9_dup\"", - "OpName %signed_10 \"signed_10_dup\"", - "OpName %signed_11 \"signed_11_dup\"", - "OpName %signed_12 \"signed_12_dup\"", - "OpName %signed_13 \"signed_13_dup\"", - "OpName %signed_14 \"signed_14_dup\"", - "OpName %signed_15 \"signed_15_dup\"", - "OpName %signed_16 \"signed_16_dup\"", - "OpName %signed_17 \"signed_17_dup\"", - "OpName %signed_18 \"signed_18_dup\"", - "OpName %signed_19 \"signed_19_dup\"", - "OpName %signed_20 \"signed_20_dup\"", - "OpName %signed_vec_a \"signed_vec_a_dup\"", - "OpName %signed_vec_b \"signed_vec_b_dup\"", - "OpName %signed_21 \"signed_21_dup\"", - "OpName %signed_array \"signed_array_dup\"", - "OpName %signed_22 \"signed_22_dup\"", - }, - }, - // clang-format on - }))); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/upgrade_memory_model_test.cpp b/3rdparty/spirv-tools/test/opt/upgrade_memory_model_test.cpp deleted file mode 100644 index 7f64ffd7c..000000000 --- a/3rdparty/spirv-tools/test/opt/upgrade_memory_model_test.cpp +++ /dev/null @@ -1,2272 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "assembly_builder.h" -#include "gmock/gmock.h" -#include "pass_fixture.h" -#include "pass_utils.h" - -namespace { - -using namespace spvtools; - -using UpgradeMemoryModelTest = opt::PassTest<::testing::Test>; - -TEST_F(UpgradeMemoryModelTest, InvalidMemoryModelOpenCL) { - const std::string text = R"( -; CHECK: OpMemoryModel Logical OpenCL -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, InvalidMemoryModelVulkan) { - const std::string text = R"( -; CHECK: OpMemoryModel Logical Vulkan -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModel -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical Vulkan -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, JustMemoryModel) { - const std::string text = R"( -; CHECK: OpCapability VulkanMemoryModel -; CHECK: OpExtension "SPV_KHR_vulkan_memory_model" -; CHECK: OpMemoryModel Logical Vulkan -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, RemoveDecorations) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %var Volatile -OpDecorate %var Coherent -%int = OpTypeInt 32 0 -%ptr_int_Uniform = OpTypePointer Uniform %int -%var = OpVariable %ptr_int_Uniform Uniform -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, WorkgroupVariable) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_Workgroup Workgroup -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, WorkgroupFunctionParameter) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Workgroup = OpTypePointer Workgroup %int -%func_ty = OpTypeFunction %void %ptr_int_Workgroup -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_int_Workgroup -%1 = OpLabel -%ld = OpLoad %int %param -OpStore %param %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformVariable) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Uniform = OpTypePointer Uniform %int -%var = OpVariable %ptr_int_Uniform Uniform -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameter) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %param Coherent -OpDecorate %param Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Uniform = OpTypePointer Uniform %int -%func_ty = OpTypeFunction %void %ptr_int_Uniform -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_int_Uniform -%1 = OpLabel -%ld = OpLoad %int %param -OpStore %param %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableOnlyVolatile) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK-NOT: OpConstant -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Uniform = OpTypePointer Uniform %int -%var = OpVariable %ptr_int_Uniform Uniform -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableCopied) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Uniform = OpTypePointer Uniform %int -%var = OpVariable %ptr_int_Uniform Uniform -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%copy = OpCopyObject %ptr_int_Uniform %var -%ld = OpLoad %int %copy -OpStore %copy %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameterCopied) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %param Coherent -OpDecorate %param Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Uniform = OpTypePointer Uniform %int -%func_ty = OpTypeFunction %void %ptr_int_Uniform -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_int_Uniform -%1 = OpLabel -%copy = OpCopyObject %ptr_int_Uniform %param -%ld = OpLoad %int %copy -%copy2 = OpCopyObject %ptr_int_Uniform %param -OpStore %copy2 %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableAccessChain) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int3 = OpConstant %int 3 -%int_array_3 = OpTypeArray %int %int3 -%ptr_intarray_Uniform = OpTypePointer Uniform %int_array_3 -%ptr_int_Uniform = OpTypePointer Uniform %int -%var = OpVariable %ptr_intarray_Uniform Uniform -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%gep = OpAccessChain %ptr_int_Uniform %var %int0 -%ld = OpLoad %int %gep -OpStore %gep %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameterAccessChain) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %param Coherent -OpDecorate %param Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int3 = OpConstant %int 3 -%int_array_3 = OpTypeArray %int %int3 -%ptr_intarray_Uniform = OpTypePointer Uniform %int_array_3 -%ptr_int_Uniform = OpTypePointer Uniform %int -%func_ty = OpTypeFunction %void %ptr_intarray_Uniform -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_intarray_Uniform -%1 = OpLabel -%ld_gep = OpAccessChain %ptr_int_Uniform %param %int0 -%ld = OpLoad %int %ld_gep -%st_gep = OpAccessChain %ptr_int_Uniform %param %int0 -OpStore %st_gep %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VariablePointerSelect) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%null = OpConstantNull %ptr_int_StorageBuffer -%var = OpVariable %ptr_int_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%select = OpSelect %ptr_int_StorageBuffer %true %var %null -%ld = OpLoad %int %select -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VariablePointerSelectConservative) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpDecorate %var1 Coherent -OpDecorate %var2 Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%var1 = OpVariable %ptr_int_StorageBuffer StorageBuffer -%var2 = OpVariable %ptr_int_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%select = OpSelect %ptr_int_StorageBuffer %true %var1 %var2 -%ld = OpLoad %int %select -OpStore %select %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VariablePointerIncrement) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{%\w+}} Coherent -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -OpDecorate %param Coherent -OpDecorate %param ArrayStride 4 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%int10 = OpConstant %int 10 -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_int_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_int_StorageBuffer -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -%phi = OpPhi %ptr_int_StorageBuffer %param %1 %ptr_next %2 -%iv = OpPhi %int %int0 %1 %inc %2 -%inc = OpIAdd %int %iv %int1 -%ptr_next = OpPtrAccessChain %ptr_int_StorageBuffer %phi %int1 -%cmp = OpIEqual %bool %iv %int10 -OpLoopMerge %3 %2 None -OpBranchConditional %cmp %3 %2 -%3 = OpLabel -%ld = OpLoad %int %phi -OpStore %phi %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentStructElement) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %struct 0 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%struct = OpTypeStruct %int -%ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_struct_StorageBuffer -%1 = OpLabel -%gep = OpAccessChain %ptr_int_StorageBuffer %param %int0 -%ld = OpLoad %int %gep -OpStore %gep %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentElementFullStructAccess) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %struct 0 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%struct = OpTypeStruct %int -%ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct -%func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_struct_StorageBuffer -%1 = OpLabel -%ld = OpLoad %struct %param -OpStore %param %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentElementNotAccessed) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK-NOT: MakePointerAvailable -; CHECK-NOT: NonPrivatePointer -; CHECK-NOT: MakePointerVisible -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %struct 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%struct = OpTypeStruct %int %int -%ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_struct_StorageBuffer -%1 = OpLabel -%gep = OpAccessChain %ptr_int_StorageBuffer %param %int0 -%ld = OpLoad %int %gep -OpStore %gep %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, MultiIndexAccessCoherent) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %inner 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%inner = OpTypeStruct %int %int -%middle = OpTypeStruct %inner -%outer = OpTypeStruct %middle %middle -%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_outer_StorageBuffer -%1 = OpLabel -%ld_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int0 %int0 %int1 -%ld = OpLoad %int %ld_gep -%st_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int1 %int0 %int1 -OpStore %st_gep %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, MultiIndexAccessNonCoherent) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK-NOT: MakePointerAvailable -; CHECK-NOT: NonPrivatePointer -; CHECK-NOT: MakePointerVisible -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %inner 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%inner = OpTypeStruct %int %int -%middle = OpTypeStruct %inner -%outer = OpTypeStruct %middle %middle -%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_outer_StorageBuffer -%1 = OpLabel -%ld_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int0 %int0 %int0 -%ld = OpLoad %int %ld_gep -%st_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int1 %int0 %int0 -OpStore %st_gep %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, ConsecutiveAccessChainCoherent) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %inner 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%inner = OpTypeStruct %int %int -%middle = OpTypeStruct %inner -%outer = OpTypeStruct %middle %middle -%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer -%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle -%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_outer_StorageBuffer -%1 = OpLabel -%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 -%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 -%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1 -%ld = OpLoad %int %ld_gep3 -%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 -%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 -%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1 -OpStore %st_gep3 %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, ConsecutiveAccessChainNonCoherent) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK-NOT: MakePointerAvailable -; CHECK-NOT: NonPrivatePointer -; CHECK-NOT: MakePointerVisible -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %inner 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%inner = OpTypeStruct %int %int -%middle = OpTypeStruct %inner -%outer = OpTypeStruct %middle %middle -%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer -%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle -%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_outer_StorageBuffer -%1 = OpLabel -%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 -%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 -%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int0 -%ld = OpLoad %int %ld_gep3 -%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 -%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 -%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int0 -OpStore %st_gep3 %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentStructElementAccess) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %middle 0 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%inner = OpTypeStruct %int %int -%middle = OpTypeStruct %inner -%outer = OpTypeStruct %middle %middle -%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer -%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle -%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_outer_StorageBuffer -%1 = OpLabel -%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 -%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 -%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1 -%ld = OpLoad %int %ld_gep3 -%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 -%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 -%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1 -OpStore %st_gep3 %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, NonCoherentLoadCoherentStore) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK-NOT: MakePointerVisible -; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpMemberDecorate %outer 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%int1 = OpConstant %int 1 -%inner = OpTypeStruct %int %int -%middle = OpTypeStruct %inner -%outer = OpTypeStruct %middle %middle -%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer -%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle -%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_outer_StorageBuffer -%1 = OpLabel -%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0 -%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0 -%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1 -%ld = OpLoad %int %ld_gep3 -%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1 -%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0 -%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1 -OpStore %st_gep3 %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CopyMemory) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[queuefamily]] -; CHECK-NOT: [[queuefamily]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %in_var Coherent -OpDecorate %out_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%in_var = OpVariable %ptr_int_StorageBuffer StorageBuffer -%out_var = OpVariable %ptr_int_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpCopyMemory %out_var %in_var -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CopyMemorySized) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemorySized {{%\w+}} {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[queuefamily]] -; CHECK-NOT: [[queuefamily]] -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %out_param Coherent -OpDecorate %in_param Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int4 = OpConstant %int 4 -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%func_ty = OpTypeFunction %void %ptr_int_StorageBuffer %ptr_int_StorageBuffer -%func = OpFunction %void None %func_ty -%in_param = OpFunctionParameter %ptr_int_StorageBuffer -%out_param = OpFunctionParameter %ptr_int_StorageBuffer -%1 = OpLabel -OpCopyMemorySized %out_param %in_param %int4 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CopyMemoryTwoScopes) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK-DAG: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK-DAG: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|MakePointerVisible|NonPrivatePointer [[workgroup]] [[queuefamily]] -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %in_var Coherent -OpDecorate %out_var Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Workgroup = OpTypePointer Workgroup %int -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%in_var = OpVariable %ptr_int_StorageBuffer StorageBuffer -%out_var = OpVariable %ptr_int_Workgroup Workgroup -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpCopyMemory %out_var %in_var -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileImageRead) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile -; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageReadWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%int0 = OpConstant %int 0 -%v2int_0 = OpConstantComposite %v2int %int0 %int0 -%image = OpTypeImage %float 2D 0 0 0 2 Unknown -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%var = OpVariable %ptr_image_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %image %var -%rd = OpImageRead %float %ld %v2int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentImageRead) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageReadWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%int0 = OpConstant %int 0 -%v2int_0 = OpConstantComposite %v2int %int0 %int0 -%image = OpTypeImage %float 2D 0 0 0 2 Unknown -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%var = OpVariable %ptr_image_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %image %var -%rd = OpImageRead %float %ld %v2int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentImageReadExtractedFromSampledImage) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[image:%\w+]] = OpTypeImage -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad [[image]] {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK-NOT: NonPrivatePointer -; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageReadWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%int0 = OpConstant %int 0 -%v2int_0 = OpConstantComposite %v2int %int0 %int0 -%image = OpTypeImage %float 2D 0 0 0 0 Unknown -%sampled_image = OpTypeSampledImage %image -%sampler = OpTypeSampler -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler -%var = OpVariable %ptr_image_StorageBuffer StorageBuffer -%sampler_var = OpVariable %ptr_sampler_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %image %var -%ld_sampler = OpLoad %sampler %sampler_var -%sample = OpSampledImage %sampled_image %ld %ld_sampler -%extract = OpImage %image %sample -%rd = OpImageRead %float %extract %v2int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileImageWrite) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile -; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageWriteWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %param Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%float0 = OpConstant %float 0 -%v2int_null = OpConstantNull %v2int -%image = OpTypeImage %float 2D 0 0 0 0 Unknown -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%func_ty = OpTypeFunction %void %ptr_image_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_image_StorageBuffer -%1 = OpLabel -%ld = OpLoad %image %param -OpImageWrite %ld %v2int_null %float0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentImageWrite) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer -; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailable|NonPrivateTexel [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageWriteWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %param Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%float0 = OpConstant %float 0 -%v2int_null = OpConstantNull %v2int -%image = OpTypeImage %float 2D 0 0 0 0 Unknown -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%func_ty = OpTypeFunction %void %ptr_image_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_image_StorageBuffer -%1 = OpLabel -%ld = OpLoad %image %param -OpImageWrite %ld %v2int_null %float0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentImageWriteExtractFromSampledImage) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer -; CHECK-NOT: NonPrivatePointer -; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailable|NonPrivateTexel [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageWriteWithoutFormat -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %param Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%float0 = OpConstant %float 0 -%v2int_null = OpConstantNull %v2int -%image = OpTypeImage %float 2D 0 0 0 0 Unknown -%sampled_image = OpTypeSampledImage %image -%sampler = OpTypeSampler -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler -%func_ty = OpTypeFunction %void %ptr_image_StorageBuffer %ptr_sampler_StorageBuffer -%func = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr_image_StorageBuffer -%sampler_param = OpFunctionParameter %ptr_sampler_StorageBuffer -%1 = OpLabel -%ld = OpLoad %image %param -%ld_sampler = OpLoad %sampler %sampler_param -%sample = OpSampledImage %sampled_image %ld %ld_sampler -%extract = OpImage %image %sample -OpImageWrite %extract %v2int_null %float0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileImageSparseRead) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile -; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageReadWithoutFormat -OpCapability SparseResidency -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%int0 = OpConstant %int 0 -%v2int_0 = OpConstantComposite %v2int %int0 %int0 -%image = OpTypeImage %float 2D 0 0 0 2 Unknown -%struct = OpTypeStruct %int %float -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%var = OpVariable %ptr_image_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %image %var -%rd = OpImageSparseRead %struct %ld %v2int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentImageSparseRead) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageReadWithoutFormat -OpCapability SparseResidency -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%int0 = OpConstant %int 0 -%v2int_0 = OpConstantComposite %v2int %int0 %int0 -%image = OpTypeImage %float 2D 0 0 0 2 Unknown -%struct = OpTypeStruct %int %float -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%var = OpVariable %ptr_image_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %image %var -%rd = OpImageSparseRead %struct %ld %v2int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, - CoherentImageSparseReadExtractedFromSampledImage) { - const std::string text = R"( -; CHECK-NOT: OpDecorate -; CHECK: [[image:%\w+]] = OpTypeImage -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpLoad [[image]] {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]] -; CHECK-NOT: NonPrivatePointer -; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]] -OpCapability Shader -OpCapability Linkage -OpCapability StorageImageReadWithoutFormat -OpCapability SparseResidency -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpDecorate %var Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%v2int = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%int0 = OpConstant %int 0 -%v2int_0 = OpConstantComposite %v2int %int0 %int0 -%image = OpTypeImage %float 2D 0 0 0 0 Unknown -%struct = OpTypeStruct %int %float -%sampled_image = OpTypeSampledImage %image -%sampler = OpTypeSampler -%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image -%ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler -%var = OpVariable %ptr_image_StorageBuffer StorageBuffer -%sampler_var = OpVariable %ptr_sampler_StorageBuffer StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %image %var -%ld_sampler = OpLoad %sampler %sampler_var -%sample = OpSampledImage %sampled_image %ld %ld_sampler -%extract = OpImage %image %sample -%rd = OpImageSparseRead %struct %extract %v2int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierNoChange) { - const std::string text = R"( -; CHECK: [[none:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[none]] -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %func "func" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%workgroup = OpConstant %int 2 -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpControlBarrier %workgroup %workgroup %none -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierAddOutput) { - const std::string text = R"( -; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096 -; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]] -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %func "func" %var -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%workgroup = OpConstant %int 2 -%ptr_int_Output = OpTypePointer Output %int -%var = OpVariable %ptr_int_Output Output -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -OpControlBarrier %workgroup %workgroup %none -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, TessellationMemoryBarrierNoChange) { - const std::string text = R"( -; CHECK: [[none:%\w+]] = OpConstant {{%\w+}} 0 -; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpMemoryBarrier [[workgroup]] [[none]] -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %func "func" %var -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%workgroup = OpConstant %int 2 -%ptr_int_Output = OpTypePointer Output %int -%var = OpVariable %ptr_int_Output Output -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -OpMemoryBarrier %workgroup %none -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierAddOutputSubFunction) { - const std::string text = R"( -; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096 -; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]] -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %func "func" %var -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%workgroup = OpConstant %int 2 -%ptr_int_Output = OpTypePointer Output %int -%var = OpVariable %ptr_int_Output Output -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%call = OpFunctionCall %void %sub_func -OpReturn -OpFunctionEnd -%sub_func = OpFunction %void None %func_ty -%2 = OpLabel -%ld = OpLoad %int %var -OpControlBarrier %workgroup %workgroup %none -OpStore %var %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, - TessellationControlBarrierAddOutputDifferentFunctions) { - const std::string text = R"( -; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096 -; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]] -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %func "func" %var -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%workgroup = OpConstant %int 2 -%ptr_int_Output = OpTypePointer Output %int -%var = OpVariable %ptr_int_Output Output -%func_ty = OpTypeFunction %void -%ld_func_ty = OpTypeFunction %int -%st_func_ty = OpTypeFunction %void %int -%func = OpFunction %void None %func_ty -%1 = OpLabel -%call_ld = OpFunctionCall %int %ld_func -%call_barrier = OpFunctionCall %void %barrier_func -%call_st = OpFunctionCall %void %st_func %call_ld -OpReturn -OpFunctionEnd -%ld_func = OpFunction %int None %ld_func_ty -%2 = OpLabel -%ld = OpLoad %int %var -OpReturnValue %ld -OpFunctionEnd -%barrier_func = OpFunction %void None %func_ty -%3 = OpLabel -OpControlBarrier %workgroup %workgroup %none -OpReturn -OpFunctionEnd -%st_func = OpFunction %void None %st_func_ty -%param = OpFunctionParameter %int -%4 = OpLabel -OpStore %var %param -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, ChangeControlBarrierMemoryScope) { - std::string text = R"( -; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpControlBarrier [[workgroup]] [[queuefamily]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpControlBarrier %workgroup %device %none -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, ChangeMemoryBarrierMemoryScope) { - std::string text = R"( -; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpMemoryBarrier [[queuefamily]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%device = OpConstant %int 1 -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpMemoryBarrier %device %none -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, ChangeAtomicMemoryScope) { - std::string text = R"( -; CHECK: [[int:%\w+]] = OpTypeInt -; CHECK: [[var:%\w+]] = OpVariable -; CHECK: [[qf:%\w+]] = OpConstant [[int]] 5 -; CHECK: OpAtomicLoad [[int]] [[var]] [[qf]] -; CHECK: OpAtomicStore [[var]] [[qf]] -; CHECK: OpAtomicExchange [[int]] [[var]] [[qf]] -; CHECK: OpAtomicCompareExchange [[int]] [[var]] [[qf]] -; CHECK: OpAtomicIIncrement [[int]] [[var]] [[qf]] -; CHECK: OpAtomicIDecrement [[int]] [[var]] [[qf]] -; CHECK: OpAtomicIAdd [[int]] [[var]] [[qf]] -; CHECK: OpAtomicISub [[int]] [[var]] [[qf]] -; CHECK: OpAtomicSMin [[int]] [[var]] [[qf]] -; CHECK: OpAtomicSMax [[int]] [[var]] [[qf]] -; CHECK: OpAtomicUMin [[int]] [[var]] [[qf]] -; CHECK: OpAtomicUMax [[int]] [[var]] [[qf]] -; CHECK: OpAtomicAnd [[int]] [[var]] [[qf]] -; CHECK: OpAtomicOr [[int]] [[var]] [[qf]] -; CHECK: OpAtomicXor [[int]] [[var]] [[qf]] -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%none = OpConstant %int 0 -%device = OpConstant %int 1 -%func_ty = OpTypeFunction %void -%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int -%var = OpVariable %ptr_int_StorageBuffer StorageBuffer -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpAtomicLoad %int %var %device %none -OpAtomicStore %var %device %none %ld -%ex = OpAtomicExchange %int %var %device %none %ld -%cmp_ex = OpAtomicCompareExchange %int %var %device %none %none %ld %ld -%inc = OpAtomicIIncrement %int %var %device %none -%dec = OpAtomicIDecrement %int %var %device %none -%add = OpAtomicIAdd %int %var %device %none %ld -%sub = OpAtomicISub %int %var %device %none %ld -%smin = OpAtomicSMin %int %var %device %none %ld -%smax = OpAtomicSMax %int %var %device %none %ld -%umin = OpAtomicUMin %int %var %device %none %ld -%umax = OpAtomicUMax %int %var %device %none %ld -%and = OpAtomicAnd %int %var %device %none %ld -%or = OpAtomicOr %int %var %device %none %ld -%xor = OpAtomicXor %int %var %device %none %ld -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeModfNoFlags) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] -; CHECK-NOT: NonPrivatePointer -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%ptr_ssbo_float = OpTypePointer StorageBuffer %float -%ssbo_var = OpVariable %ptr_ssbo_float StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Modf %float_0 %ssbo_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeModfWorkgroupCoherent) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer Workgroup [[float]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] Workgroup -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] -; CHECK: [[wg_scope:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[wg_scope]] -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -OpDecorate %wg_var Coherent -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%ptr_wg_float = OpTypePointer Workgroup %float -%wg_var = OpVariable %ptr_wg_float Workgroup -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Modf %float_0 %wg_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeModfSSBOCoherent) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] -; CHECK: [[qf_scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[qf_scope]] -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -OpDecorate %ssbo_var Coherent -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%ptr_ssbo_float = OpTypePointer StorageBuffer %float -%ssbo_var = OpVariable %ptr_ssbo_float StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Modf %float_0 %ssbo_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeModfSSBOVolatile) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]] -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] Volatile -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -OpDecorate %wg_var Volatile -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%ptr_ssbo_float = OpTypePointer StorageBuffer %float -%wg_var = OpVariable %ptr_ssbo_float StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Modf %float_0 %wg_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeFrexpNoFlags) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] -; CHECK-NOT: NonPrivatePointer -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Frexp %float_0 %ssbo_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeFrexpWorkgroupCoherent) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer Workgroup [[int]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] Workgroup -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] -; CHECK: [[wg_scope:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[wg_scope]] -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -OpDecorate %wg_var Coherent -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 0 -%ptr_wg_int = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Frexp %float_0 %wg_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeFrexpSSBOCoherent) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] -; CHECK: [[qf_scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[qf_scope]] -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -OpDecorate %ssbo_var Coherent -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Frexp %float_0 %ssbo_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, UpgradeFrexpSSBOVolatile) { - const std::string text = R"( -; CHECK: [[float:%\w+]] = OpTypeFloat 32 -; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0 -; CHECK: [[int:%\w+]] = OpTypeInt 32 0 -; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]] -; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer -; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]] -; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]] -; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0 -; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1 -; CHECK: OpStore [[var]] [[ex1]] Volatile -; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -%import = OpExtInstImport "GLSL.std.450" -OpEntryPoint GLCompute %func "func" -OpDecorate %wg_var Volatile -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%wg_var = OpVariable %ptr_ssbo_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%2 = OpExtInst %float %import Frexp %float_0 %wg_var -%3 = OpFAdd %float %float_0 %2 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryAddOperands) { - const std::string text = R"( -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} None None -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryDuplicateOperand) { - const std::string text = R"( -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Nontemporal Nontemporal -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Nontemporal -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryDuplicateOperands) { - const std::string text = R"( -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned 4 Aligned 4 -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Aligned 4 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherent) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] None -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %dst Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherentPreviousArgs) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[scope]] Aligned 4 -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %dst Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Aligned 4 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemorySrcCoherent) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} None MakePointerVisible|NonPrivatePointer [[scope]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %src Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemorySrcCoherentPreviousArgs) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned 4 Aligned|MakePointerVisible|NonPrivatePointer 4 [[scope]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %src Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Aligned 4 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothCoherent) { - const std::string text = R"( -; CHECK-DAG: [[queue:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK-DAG: [[wg:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[wg]] MakePointerVisible|NonPrivatePointer [[queue]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %src Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_wg_int = OpTypePointer Workgroup %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_wg_int Workgroup -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothCoherentPreviousArgs) { - const std::string text = R"( -; CHECK-DAG: [[queue:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK-DAG: [[wg:%\w+]] = OpConstant {{%\w+}} 2 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[queue]] Aligned|MakePointerVisible|NonPrivatePointer 4 [[wg]] -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %dst Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_wg_int = OpTypePointer Workgroup %int -%src = OpVariable %ptr_wg_int Workgroup -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Aligned 4 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothVolatile) { - const std::string text = R"( -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile Volatile -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %src Volatile -OpDecorate %dst Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothVolatilePreviousArgs) { - const std::string text = R"( -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile|Aligned 4 Volatile|Aligned 4 -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %src Volatile -OpDecorate %dst Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Aligned 4 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherentTwoOperands) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] None -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %dst Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src None None -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, - SPV14CopyMemoryDstCoherentPreviousArgsTwoOperands) { - const std::string text = R"( -; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5 -; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[scope]] Aligned 8 -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %func "func" %src %dst -OpDecorate %dst Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%src = OpVariable %ptr_ssbo_int StorageBuffer -%dst = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %dst %src Aligned 4 Aligned 8 -OpReturn -OpFunctionEnd -)"; - - SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoad) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{.*}} Volatile -; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768 -; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %ssbo_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%relaxed = OpConstant %int 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpAtomicLoad %int %ssbo_var %device %relaxed -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoadPreviousFlags) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{.*}} Volatile -; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32834 -; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %ssbo_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%acquire_ssbo = OpConstant %int 66 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpAtomicLoad %int %ssbo_var %device %acquire_ssbo -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicStore) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{.*}} Volatile -; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 32768 -; CHECK: OpAtomicStore {{.*}} {{.*}} [[volatile]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %ssbo_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%device = OpConstant %int 1 -%relaxed = OpConstant %int 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpAtomicStore %ssbo_var %device %relaxed %int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicStorePreviousFlags) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{.*}} Volatile -; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 32836 -; CHECK: OpAtomicStore {{.*}} {{.*}} [[volatile]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %ssbo_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%device = OpConstant %int 1 -%release_ssbo = OpConstant %int 68 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpAtomicStore %ssbo_var %device %release_ssbo %int_0 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicCompareExchange) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{.*}} Volatile -; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768 -; CHECK: OpAtomicCompareExchange [[int]] {{.*}} {{.*}} [[volatile]] [[volatile]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %ssbo_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%device = OpConstant %int 1 -%relaxed = OpConstant %int 0 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpAtomicCompareExchange %int %ssbo_var %device %relaxed %relaxed %int_0 %int_1 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicCompareExchangePreviousFlags) { - const std::string text = R"( -; CHECK-NOT: OpDecorate {{.*}} Volatile -; CHECK: [[volatile_acq_rel:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32840 -; CHECK: [[volatile_acq:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32834 -; CHECK: OpAtomicCompareExchange [[int]] {{.*}} {{.*}} [[volatile_acq_rel]] [[volatile_acq]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %ssbo_var Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%device = OpConstant %int 1 -%acq_ssbo = OpConstant %int 66 -%acq_rel_ssbo = OpConstant %int 72 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpAtomicCompareExchange %int %ssbo_var %device %acq_rel_ssbo %acq_ssbo %int_0 %int_1 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoadMemberDecoration) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate {{.*}} {{.*}} Volatile -; CHECK: [[relaxed:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 0 -; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768 -; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[relaxed]] -; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]] -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %struct 1 Volatile -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%relaxed = OpConstant %int 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%struct = OpTypeStruct %int %int -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%gep0 = OpAccessChain %ptr_ssbo_int %ssbo_var %int_0 -%ld0 = OpAtomicLoad %int %gep0 %device %relaxed -%gep1 = OpAccessChain %ptr_ssbo_int %ssbo_var %int_1 -%ld1 = OpAtomicLoad %int %gep1 %device %relaxed -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(UpgradeMemoryModelTest, CoherentStructMemberInArray) { - const std::string text = R"( -; CHECK-NOT: OpMemberDecorate -; CHECK: [[int:%[a-zA-Z0-9_]+]] = OpTypeInt 32 0 -; CHECK: [[device:%[a-zA-Z0-9_]+]] = OpConstant [[int]] 1 -; CHECK: OpLoad [[int]] {{.*}} MakePointerVisible|NonPrivatePointer -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpMemberDecorate %inner 1 Coherent -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int_4 = OpConstant %int 4 -%inner = OpTypeStruct %int %int -%array = OpTypeArray %inner %int_4 -%struct = OpTypeStruct %array -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%gep = OpAccessChain %ptr_ssbo_int %ssbo_var %int_0 %int_0 %int_1 -%ld = OpLoad %int %gep -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(text, true); -} - -} // namespace diff --git a/3rdparty/spirv-tools/test/opt/utils_test.cpp b/3rdparty/spirv-tools/test/opt/utils_test.cpp deleted file mode 100644 index 5ce146bbb..000000000 --- a/3rdparty/spirv-tools/test/opt/utils_test.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// 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 "gtest/gtest.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -TEST(JoinAllInsts, Cases) { - EXPECT_EQ("", JoinAllInsts({})); - EXPECT_EQ("a\n", JoinAllInsts({"a"})); - EXPECT_EQ("a\nb\n", JoinAllInsts({"a", "b"})); - EXPECT_EQ("a\nb\nc\n", JoinAllInsts({"a", "b", "c"})); - EXPECT_EQ("hello,\nworld!\n\n\n", JoinAllInsts({"hello,", "world!", "\n"})); -} - -TEST(JoinNonDebugInsts, Cases) { - EXPECT_EQ("", JoinNonDebugInsts({})); - EXPECT_EQ("a\n", JoinNonDebugInsts({"a"})); - EXPECT_EQ("", JoinNonDebugInsts({"OpName"})); - EXPECT_EQ("a\nb\n", JoinNonDebugInsts({"a", "b"})); - EXPECT_EQ("", JoinNonDebugInsts({"OpName", "%1 = OpString \"42\""})); - EXPECT_EQ("Opstring\n", JoinNonDebugInsts({"OpName", "Opstring"})); - EXPECT_EQ("the only remaining string\n", - JoinNonDebugInsts( - {"OpSourceContinued", "OpSource", "OpSourceExtension", - "lgtm OpName", "hello OpMemberName", "this is a OpString", - "lonely OpLine", "happy OpNoLine", "OpModuleProcessed", - "the only remaining string"})); -} - -struct SubstringReplacementTestCase { - const char* orig_str; - const char* find_substr; - const char* replace_substr; - const char* expected_str; - bool replace_should_succeed; -}; - -using FindAndReplaceTest = - ::testing::TestWithParam; - -TEST_P(FindAndReplaceTest, SubstringReplacement) { - auto process = std::string(GetParam().orig_str); - EXPECT_EQ(GetParam().replace_should_succeed, - FindAndReplace(&process, GetParam().find_substr, - GetParam().replace_substr)) - << "Original string: " << GetParam().orig_str - << " replace: " << GetParam().find_substr - << " to: " << GetParam().replace_substr - << " should returns: " << GetParam().replace_should_succeed; - EXPECT_STREQ(GetParam().expected_str, process.c_str()) - << "Original string: " << GetParam().orig_str - << " replace: " << GetParam().find_substr - << " to: " << GetParam().replace_substr - << " expected string: " << GetParam().expected_str; -} - -INSTANTIATE_TEST_SUITE_P( - SubstringReplacement, FindAndReplaceTest, - ::testing::ValuesIn(std::vector({ - // orig string, find substring, replace substring, expected string, - // replacement happened - {"", "", "", "", false}, - {"", "b", "", "", false}, - {"", "", "c", "", false}, - {"", "a", "b", "", false}, - - {"a", "", "c", "a", false}, - {"a", "b", "c", "a", false}, - {"a", "b", "", "a", false}, - {"a", "a", "", "", true}, - {"a", "a", "b", "b", true}, - - {"ab", "a", "b", "bb", true}, - {"ab", "a", "", "b", true}, - {"ab", "b", "", "a", true}, - {"ab", "ab", "", "", true}, - {"ab", "ab", "cd", "cd", true}, - {"bc", "abc", "efg", "bc", false}, - - {"abc", "ab", "bc", "bcc", true}, - {"abc", "ab", "", "c", true}, - {"abc", "bc", "", "a", true}, - {"abc", "bc", "d", "ad", true}, - {"abc", "a", "123", "123bc", true}, - {"abc", "ab", "a", "ac", true}, - {"abc", "a", "aab", "aabbc", true}, - {"abc", "abcd", "efg", "abc", false}, - }))); - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/value_table_test.cpp b/3rdparty/spirv-tools/test/opt/value_table_test.cpp deleted file mode 100644 index a0942ccdc..000000000 --- a/3rdparty/spirv-tools/test/opt/value_table_test.cpp +++ /dev/null @@ -1,689 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/opt/build_module.h" -#include "source/opt/value_number_table.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" - -namespace spvtools { -namespace opt { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; -using ValueTableTest = PassTest<::testing::Test>; - -TEST_F(ValueTableTest, SameInstructionSameValue) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst)); -} - -TEST_F(ValueTableTest, DifferentInstructionSameValue) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 - %11 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(10); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(11); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, SameValueDifferentBlock) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 - OpBranch %11 - %11 = OpLabel - %12 = OpFAdd %5 %9 %9 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(10); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(12); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, DifferentValue) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 - %11 = OpFAdd %5 %9 %10 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(10); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(11); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, DifferentValueDifferentBlock) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpFAdd %5 %9 %9 - OpBranch %11 - %11 = OpLabel - %12 = OpFAdd %5 %9 %10 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(10); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(12); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, SameLoad) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst = context->get_def_use_mgr()->GetDef(9); - EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst)); -} - -// Two different loads, even from the same memory, must given different value -// numbers if the memory is not read-only. -TEST_F(ValueTableTest, DifferentFunctionLoad) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(9); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(10); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, DifferentUniformLoad) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Uniform %5 - %8 = OpVariable %6 Uniform - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %5 %8 - %10 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(9); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, DifferentInputLoad) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Input %5 - %8 = OpVariable %6 Input - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %5 %8 - %10 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(9); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, DifferentUniformConstantLoad) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer UniformConstant %5 - %8 = OpVariable %6 UniformConstant - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %5 %8 - %10 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(9); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, DifferentPushConstantLoad) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer PushConstant %5 - %8 = OpVariable %6 PushConstant - %2 = OpFunction %3 None %4 - %7 = OpLabel - %9 = OpLoad %5 %8 - %10 = OpLoad %5 %8 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(9); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, SameCall) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypeFunction %5 - %7 = OpTypePointer Function %5 - %8 = OpVariable %7 Private - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpFunctionCall %5 %11 - OpReturn - OpFunctionEnd - %11 = OpFunction %5 None %6 - %12 = OpLabel - %13 = OpLoad %5 %8 - OpReturnValue %13 - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst)); -} - -// Function calls should be given a new value number, even if they are the same. -TEST_F(ValueTableTest, DifferentCall) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypeFunction %5 - %7 = OpTypePointer Function %5 - %8 = OpVariable %7 Private - %2 = OpFunction %3 None %4 - %9 = OpLabel - %10 = OpFunctionCall %5 %11 - %12 = OpFunctionCall %5 %11 - OpReturn - OpFunctionEnd - %11 = OpFunction %5 None %6 - %13 = OpLabel - %14 = OpLoad %5 %8 - OpReturnValue %14 - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(10); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(12); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -// It is possible to have two instruction that compute the same numerical value, -// but with different types. They should have different value numbers. -TEST_F(ValueTableTest, DifferentTypes) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 0 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %8 = OpLabel - %9 = OpVariable %7 Function - %10 = OpLoad %5 %9 - %11 = OpIAdd %5 %10 %10 - %12 = OpIAdd %6 %10 %10 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(11); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(12); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, CopyObject) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Function %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - %8 = OpVariable %6 Function - %9 = OpLoad %5 %8 - %10 = OpCopyObject %5 %9 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(9); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(10); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -TEST_F(ValueTableTest, CopyObjectWitDecoration) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpDecorate %3 NonUniformEXT - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Function %6 - %2 = OpFunction %4 None %5 - %8 = OpLabel - %9 = OpVariable %7 Function - %10 = OpLoad %6 %9 - %3 = OpCopyObject %6 %10 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(10); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(3); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); -} - -// Test that a phi where the operands have the same value assigned that value -// to the result of the phi. -TEST_F(ValueTableTest, PhiTest1) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Uniform %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %9 = OpVariable %6 Uniform - %2 = OpFunction %3 None %4 - %10 = OpLabel - OpBranchConditional %8 %11 %12 - %11 = OpLabel - %13 = OpLoad %5 %9 - OpBranch %14 - %12 = OpLabel - %15 = OpLoad %5 %9 - OpBranch %14 - %14 = OpLabel - %16 = OpPhi %5 %13 %11 %15 %12 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(13); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(15); - Instruction* phi = context->get_def_use_mgr()->GetDef(16); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi)); -} - -TEST_F(ValueTableTest, PhiTest1WithDecoration) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - OpDecorate %3 NonUniformEXT - %4 = OpTypeVoid - %5 = OpTypeFunction %5 - %6 = OpTypeFloat 32 - %7 = OpTypePointer Uniform %6 - %8 = OpTypeBool - %9 = OpConstantTrue %8 - %10 = OpVariable %7 Uniform - %2 = OpFunction %4 None %5 - %11 = OpLabel - OpBranchConditional %9 %12 %13 - %12 = OpLabel - %14 = OpLoad %6 %10 - OpBranch %15 - %13 = OpLabel - %16 = OpLoad %6 %10 - OpBranch %15 - %15 = OpLabel - %3 = OpPhi %6 %14 %12 %16 %13 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(14); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(16); - Instruction* phi = context->get_def_use_mgr()->GetDef(3); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi)); -} - -// When the values for the inputs to a phi do not match, then the phi should -// have its own value number. -TEST_F(ValueTableTest, PhiTest2) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Uniform %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %9 = OpVariable %6 Uniform - %10 = OpVariable %6 Uniform - %2 = OpFunction %3 None %4 - %11 = OpLabel - OpBranchConditional %8 %12 %13 - %12 = OpLabel - %14 = OpLoad %5 %9 - OpBranch %15 - %13 = OpLabel - %16 = OpLoad %5 %10 - OpBranch %15 - %15 = OpLabel - %17 = OpPhi %14 %12 %16 %13 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(14); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(16); - Instruction* phi = context->get_def_use_mgr()->GetDef(17); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi)); - EXPECT_NE(vtable.GetValueNumber(inst2), vtable.GetValueNumber(phi)); -} - -// Test that a phi node in a loop header gets a new value because one of its -// inputs comes from later in the loop. -TEST_F(ValueTableTest, PhiLoopTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeFloat 32 - %6 = OpTypePointer Uniform %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %9 = OpVariable %6 Uniform - %10 = OpVariable %6 Uniform - %2 = OpFunction %3 None %4 - %11 = OpLabel - %12 = OpLoad %5 %9 - OpSelectionMerge %13 None - OpBranchConditional %8 %14 %13 - %14 = OpLabel - %15 = OpPhi %5 %12 %11 %16 %14 - %16 = OpLoad %5 %9 - OpLoopMerge %17 %14 None - OpBranchConditional %8 %14 %17 - %17 = OpLabel - OpBranch %13 - %13 = OpLabel - %18 = OpPhi %5 %12 %11 %16 %17 - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst1 = context->get_def_use_mgr()->GetDef(12); - Instruction* inst2 = context->get_def_use_mgr()->GetDef(16); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2)); - - Instruction* phi1 = context->get_def_use_mgr()->GetDef(15); - EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi1)); - - Instruction* phi2 = context->get_def_use_mgr()->GetDef(18); - EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi2)); - EXPECT_NE(vtable.GetValueNumber(phi1), vtable.GetValueNumber(phi2)); -} - -// Test to make sure that OpPhi instructions with no in operands are handled -// correctly. -TEST_F(ValueTableTest, EmptyPhiTest) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource GLSL 430 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %2 = OpFunction %void None %4 - %7 = OpLabel - OpSelectionMerge %8 None - OpBranchConditional %true %9 %8 - %9 = OpLabel - OpKill - %8 = OpLabel - %10 = OpPhi %bool - OpReturn - OpFunctionEnd - )"; - auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); - ValueNumberTable vtable(context.get()); - Instruction* inst = context->get_def_use_mgr()->GetDef(10); - vtable.GetValueNumber(inst); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/vector_dce_test.cpp b/3rdparty/spirv-tools/test/opt/vector_dce_test.cpp deleted file mode 100644 index 594995c16..000000000 --- a/3rdparty/spirv-tools/test/opt/vector_dce_test.cpp +++ /dev/null @@ -1,1163 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using VectorDCETest = PassTest<::testing::Test>; - -TEST_F(VectorDCETest, InsertAfterInsertElim) { - // With two insertions to the same offset, the first is dead. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in float In0; - // layout (location=1) in float In1; - // layout (location=2) in vec2 In2; - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec2 v = In2; - // v.x = In0 + In1; // dead - // v.x = 0.0; - // OutColor = v.xyxy; - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In2 "In2" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %OutColor "OutColor" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_n" -OpName %_ "" -OpDecorate %In2 Location 2 -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %OutColor Location 0 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%In2 = OpVariable %_ptr_Input_v2float Input -%_ptr_Input_float = OpTypePointer Input %float -%In0 = OpVariable %_ptr_Input_float Input -%In1 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%int = OpTypeInt 32 1 -%_Globals_ = OpTypeStruct %uint %int -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In2 "In2" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %OutColor "OutColor" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_n" -OpName %_ "" -OpDecorate %In2 Location 2 -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %OutColor Location 0 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%_ptr_Input_v2float = OpTypePointer Input %v2float -%In2 = OpVariable %_ptr_Input_v2float Input -%_ptr_Input_float = OpTypePointer Input %float -%In0 = OpVariable %_ptr_Input_float Input -%In1 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%float_0 = OpConstant %float 0 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%int = OpTypeInt 32 1 -%_Globals_ = OpTypeStruct %uint %int -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -)"; - - const std::string before = - R"(%main = OpFunction %void None %11 -%25 = OpLabel -%26 = OpLoad %v2float %In2 -%27 = OpLoad %float %In0 -%28 = OpLoad %float %In1 -%29 = OpFAdd %float %27 %28 -%35 = OpCompositeInsert %v2float %29 %26 0 -%37 = OpCompositeInsert %v2float %float_0 %35 0 -%33 = OpVectorShuffle %v4float %37 %37 0 1 0 1 -OpStore %OutColor %33 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%23 = OpLabel -%24 = OpLoad %v2float %In2 -%25 = OpLoad %float %In0 -%26 = OpLoad %float %In1 -%27 = OpFAdd %float %25 %26 -%28 = OpCompositeInsert %v2float %27 %24 0 -%29 = OpCompositeInsert %v2float %float_0 %24 0 -%30 = OpVectorShuffle %v4float %29 %29 0 1 0 1 -OpStore %OutColor %30 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -TEST_F(VectorDCETest, DeadInsertInChainWithPhi) { - // Dead insert eliminated with phi in insertion chain. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in vec4 In0; - // layout (location=1) in float In1; - // layout (location=2) in float In2; - // layout (location=0) out vec4 OutColor; - // - // layout(std140, binding = 0 ) uniform _Globals_ - // { - // bool g_b; - // }; - // - // void main() - // { - // vec4 v = In0; - // v.z = In1 + In2; - // if (g_b) v.w = 1.0; - // OutColor = vec4(v.x,v.y,0.0,v.w); - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%11 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%_Globals_ = OpTypeStruct %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_ptr_Function_float = OpTypePointer Function %float -%_Globals_ = OpTypeStruct %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%float_0 = OpConstant %float 0 -)"; - - const std::string before = - R"(%main = OpFunction %void None %11 -%31 = OpLabel -%32 = OpLoad %v4float %In0 -%33 = OpLoad %float %In1 -%34 = OpLoad %float %In2 -%35 = OpFAdd %float %33 %34 -%51 = OpCompositeInsert %v4float %35 %32 2 -%37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%38 = OpLoad %uint %37 -%39 = OpINotEqual %bool %38 %uint_0 -OpSelectionMerge %40 None -OpBranchConditional %39 %41 %40 -%41 = OpLabel -%53 = OpCompositeInsert %v4float %float_1 %51 3 -OpBranch %40 -%40 = OpLabel -%60 = OpPhi %v4float %51 %31 %53 %41 -%55 = OpCompositeExtract %float %60 0 -%57 = OpCompositeExtract %float %60 1 -%59 = OpCompositeExtract %float %60 3 -%49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59 -OpStore %OutColor %49 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%27 = OpLabel -%28 = OpLoad %v4float %In0 -%29 = OpLoad %float %In1 -%30 = OpLoad %float %In2 -%31 = OpFAdd %float %29 %30 -%32 = OpCompositeInsert %v4float %31 %28 2 -%33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%34 = OpLoad %uint %33 -%35 = OpINotEqual %bool %34 %uint_0 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %36 -%37 = OpLabel -%38 = OpCompositeInsert %v4float %float_1 %28 3 -OpBranch %36 -%36 = OpLabel -%39 = OpPhi %v4float %28 %27 %38 %37 -%40 = OpCompositeExtract %float %39 0 -%41 = OpCompositeExtract %float %39 1 -%42 = OpCompositeExtract %float %39 3 -%43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42 -OpStore %OutColor %43 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -TEST_F(VectorDCETest, DeadInsertWithScalars) { - // Dead insert which requires two passes to eliminate - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in vec4 In0; - // layout (location=1) in float In1; - // layout (location=2) in float In2; - // layout (location=0) out vec4 OutColor; - // - // layout(std140, binding = 0 ) uniform _Globals_ - // { - // bool g_b; - // bool g_b2; - // }; - // - // void main() - // { - // vec4 v1, v2; - // v1 = In0; - // v1.y = In1 + In2; // dead, second pass - // if (g_b) v1.x = 1.0; - // v2.x = v1.x; - // v2.y = v1.y; // dead, first pass - // if (g_b2) v2.x = 0.0; - // OutColor = vec4(v2.x,v2.x,0.0,1.0); - // } - - const std::string before_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_b2" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_Globals_ = OpTypeStruct %uint %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%27 = OpUndef %v4float -)"; - - const std::string after_predefs = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_b" -OpMemberName %_Globals_ 1 "g_b2" -OpName %_ "" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -OpMemberDecorate %_Globals_ 0 Offset 0 -OpMemberDecorate %_Globals_ 1 Offset 4 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%uint = OpTypeInt 32 0 -%_Globals_ = OpTypeStruct %uint %uint -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%_ptr_Uniform_uint = OpTypePointer Uniform %uint -%bool = OpTypeBool -%uint_0 = OpConstant %uint 0 -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%float_0 = OpConstant %float 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%27 = OpUndef %v4float -%55 = OpUndef %v4float -)"; - - const std::string before = - R"(%main = OpFunction %void None %10 -%28 = OpLabel -%29 = OpLoad %v4float %In0 -%30 = OpLoad %float %In1 -%31 = OpLoad %float %In2 -%32 = OpFAdd %float %30 %31 -%33 = OpCompositeInsert %v4float %32 %29 1 -%34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%35 = OpLoad %uint %34 -%36 = OpINotEqual %bool %35 %uint_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %37 -%38 = OpLabel -%39 = OpCompositeInsert %v4float %float_1 %33 0 -OpBranch %37 -%37 = OpLabel -%40 = OpPhi %v4float %33 %28 %39 %38 -%41 = OpCompositeExtract %float %40 0 -%42 = OpCompositeInsert %v4float %41 %27 0 -%43 = OpCompositeExtract %float %40 1 -%44 = OpCompositeInsert %v4float %43 %42 1 -%45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1 -%46 = OpLoad %uint %45 -%47 = OpINotEqual %bool %46 %uint_0 -OpSelectionMerge %48 None -OpBranchConditional %47 %49 %48 -%49 = OpLabel -%50 = OpCompositeInsert %v4float %float_0 %44 0 -OpBranch %48 -%48 = OpLabel -%51 = OpPhi %v4float %44 %37 %50 %49 -%52 = OpCompositeExtract %float %51 0 -%53 = OpCompositeExtract %float %51 0 -%54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1 -OpStore %OutColor %54 -OpReturn -OpFunctionEnd -)"; - - const std::string after = - R"(%main = OpFunction %void None %10 -%28 = OpLabel -%29 = OpLoad %v4float %In0 -%30 = OpLoad %float %In1 -%31 = OpLoad %float %In2 -%32 = OpFAdd %float %30 %31 -%33 = OpCompositeInsert %v4float %32 %29 1 -%34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 -%35 = OpLoad %uint %34 -%36 = OpINotEqual %bool %35 %uint_0 -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %37 -%38 = OpLabel -%39 = OpCompositeInsert %v4float %float_1 %55 0 -OpBranch %37 -%37 = OpLabel -%40 = OpPhi %v4float %29 %28 %39 %38 -%41 = OpCompositeExtract %float %40 0 -%42 = OpCompositeInsert %v4float %41 %55 0 -%43 = OpCompositeExtract %float %40 1 -%44 = OpCompositeInsert %v4float %43 %42 1 -%45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1 -%46 = OpLoad %uint %45 -%47 = OpINotEqual %bool %46 %uint_0 -OpSelectionMerge %48 None -OpBranchConditional %47 %49 %48 -%49 = OpLabel -%50 = OpCompositeInsert %v4float %float_0 %55 0 -OpBranch %48 -%48 = OpLabel -%51 = OpPhi %v4float %42 %37 %50 %49 -%52 = OpCompositeExtract %float %51 0 -%53 = OpCompositeExtract %float %51 0 -%54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1 -OpStore %OutColor %54 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(before_predefs + before, - after_predefs + after, true, true); -} - -TEST_F(VectorDCETest, InsertObjectLive) { - // Make sure that the object being inserted in an OpCompositeInsert - // is not removed when it is uses later on. - const std::string before = - R"(OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %In1 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %10 -%28 = OpLabel -%29 = OpLoad %v4float %In0 -%30 = OpLoad %float %In1 -%33 = OpCompositeInsert %v4float %30 %29 1 -OpStore %OutColor %33 -OpReturn -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - SinglePassRunAndCheck(before, before, true, true); -} - -TEST_F(VectorDCETest, DeadInsertInCycle) { - // Dead insert in chain with cycle. Demonstrates analysis can handle - // cycles in chains going through scalars intermediate values. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) in vec4 In0; - // layout (location=1) in float In1; - // layout (location=2) in float In2; - // layout (location=0) out vec4 OutColor; - // - // layout(std140, binding = 0 ) uniform _Globals_ - // { - // int g_n ; - // }; - // - // void main() - // { - // vec2 v = vec2(0.0, 1.0); - // for (int i = 0; i < g_n; i++) { - // v.x = v.x + 1; - // v.y = v.y * 0.9; // dead - // } - // OutColor = vec4(v.x); - // } - - const std::string assembly = - R"( -; CHECK: [[init_val:%\w+]] = OpConstantComposite %v2float %float_0 %float_1 -; CHECK: [[undef:%\w+]] = OpUndef %v2float -; CHECK: OpFunction -; CHECK: [[entry_lab:%\w+]] = OpLabel -; CHECK: [[loop_header:%\w+]] = OpLabel -; CHECK: OpPhi %v2float [[init_val]] [[entry_lab]] [[x_insert:%\w+]] {{%\w+}} -; CHECK: [[x_insert:%\w+]] = OpCompositeInsert %v2float %43 [[undef]] 0 -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %OutColor %In0 %In1 %In2 -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpName %main "main" -OpName %_Globals_ "_Globals_" -OpMemberName %_Globals_ 0 "g_n" -OpName %_ "" -OpName %OutColor "OutColor" -OpName %In0 "In0" -OpName %In1 "In1" -OpName %In2 "In2" -OpMemberDecorate %_Globals_ 0 Offset 0 -OpDecorate %_Globals_ Block -OpDecorate %_ DescriptorSet 0 -OpDecorate %_ Binding 0 -OpDecorate %OutColor Location 0 -OpDecorate %In0 Location 0 -OpDecorate %In1 Location 1 -OpDecorate %In2 Location 2 -%void = OpTypeVoid -%10 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%16 = OpConstantComposite %v2float %float_0 %float_1 -%int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int -%int_0 = OpConstant %int 0 -%_Globals_ = OpTypeStruct %int -%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ -%_ = OpVariable %_ptr_Uniform__Globals_ Uniform -%_ptr_Uniform_int = OpTypePointer Uniform %int -%bool = OpTypeBool -%float_0_75 = OpConstant %float 0.75 -%int_1 = OpConstant %int 1 -%v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float -%In1 = OpVariable %_ptr_Input_float Input -%In2 = OpVariable %_ptr_Input_float Input -%main = OpFunction %void None %10 -%29 = OpLabel -OpBranch %30 -%30 = OpLabel -%31 = OpPhi %v2float %16 %29 %32 %33 -%34 = OpPhi %int %int_0 %29 %35 %33 -OpLoopMerge %36 %33 None -OpBranch %37 -%37 = OpLabel -%38 = OpAccessChain %_ptr_Uniform_int %_ %int_0 -%39 = OpLoad %int %38 -%40 = OpSLessThan %bool %34 %39 -OpBranchConditional %40 %41 %36 -%41 = OpLabel -%42 = OpCompositeExtract %float %31 0 -%43 = OpFAdd %float %42 %float_1 -%44 = OpCompositeInsert %v2float %43 %31 0 -%45 = OpCompositeExtract %float %44 1 -%46 = OpFMul %float %45 %float_0_75 -%32 = OpCompositeInsert %v2float %46 %44 1 -OpBranch %33 -%33 = OpLabel -%35 = OpIAdd %int %34 %int_1 -OpBranch %30 -%36 = OpLabel -%47 = OpCompositeExtract %float %31 0 -%48 = OpCompositeConstruct %v4float %47 %47 %47 %47 -OpStore %OutColor %48 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(assembly, true); -} - -TEST_F(VectorDCETest, DeadLoadFeedingCompositeConstruct) { - // Detach the loads feeding the CompositeConstruct for the unused elements. - // TODO: Implement the rewrite for CompositeConstruct. - - const std::string assembly = - R"( -; CHECK: [[undef:%\w+]] = OpUndef %float -; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Input_float %In0 %uint_2 -; CHECK: [[load:%\w+]] = OpLoad %float [[ac]] -; CHECK: OpCompositeConstruct %v3float [[load]] [[undef]] [[undef]] -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %In0 %OutColor -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" -OpSourceExtension "GL_GOOGLE_include_directive" -OpName %main "main" -OpName %In0 "In0" -OpName %OutColor "OutColor" -OpDecorate %In0 Location 0 -OpDecorate %OutColor Location 0 -%void = OpTypeVoid -%6 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%In0 = OpVariable %_ptr_Input_v4float Input -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%v3float = OpTypeVector %float 3 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%int_20 = OpConstant %int 20 -%bool = OpTypeBool -%float_1 = OpConstant %float 1 -%int_1 = OpConstant %int 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%OutColor = OpVariable %_ptr_Output_v4float Output -%23 = OpUndef %v3float -%main = OpFunction %void None %6 -%24 = OpLabel -%25 = OpAccessChain %_ptr_Input_float %In0 %uint_0 -%26 = OpLoad %float %25 -%27 = OpAccessChain %_ptr_Input_float %In0 %uint_1 -%28 = OpLoad %float %27 -%29 = OpAccessChain %_ptr_Input_float %In0 %uint_2 -%30 = OpLoad %float %29 -%31 = OpCompositeConstruct %v3float %30 %28 %26 -OpBranch %32 -%32 = OpLabel -%33 = OpPhi %v3float %31 %24 %34 %35 -%36 = OpPhi %int %int_0 %24 %37 %35 -OpLoopMerge %38 %35 None -OpBranch %39 -%39 = OpLabel -%40 = OpSLessThan %bool %36 %int_20 -OpBranchConditional %40 %41 %38 -%41 = OpLabel -%42 = OpCompositeExtract %float %33 0 -%43 = OpFAdd %float %42 %float_1 -%34 = OpCompositeInsert %v3float %43 %33 0 -OpBranch %35 -%35 = OpLabel -%37 = OpIAdd %int %36 %int_1 -OpBranch %32 -%38 = OpLabel -%44 = OpCompositeExtract %float %33 0 -%45 = OpCompositeConstruct %v4float %44 %44 %44 %44 -OpStore %OutColor %45 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndMatch(assembly, true); -} - -TEST_F(VectorDCETest, DeadLoadFeedingVectorShuffle) { - // Detach the loads feeding the CompositeConstruct for the unused elements. - // TODO: Implement the rewrite for CompositeConstruct. - - const std::string assembly = - R"( -; MemPass Type2Undef does not reuse and already existing undef. -; CHECK: {{%\w+}} = OpUndef %v3float -; CHECK: [[undef:%\w+]] = OpUndef %v3float -; CHECK: OpFunction -; CHECK: OpVectorShuffle %v3float {{%\w+}} [[undef]] 0 4 5 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %In0 %OutColor - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %In0 "In0" - OpName %OutColor "OutColor" - OpDecorate %In0 Location 0 - OpDecorate %OutColor Location 0 - %void = OpTypeVoid - %6 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %In0 = OpVariable %_ptr_Input_v4float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_20 = OpConstant %int 20 - %bool = OpTypeBool - %float_1 = OpConstant %float 1 - %vec_const = OpConstantComposite %v3float %float_1 %float_1 %float_1 - %int_1 = OpConstant %int 1 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %OutColor = OpVariable %_ptr_Output_v4float Output - %23 = OpUndef %v3float - %main = OpFunction %void None %6 - %24 = OpLabel - %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0 - %26 = OpLoad %float %25 - %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1 - %28 = OpLoad %float %27 - %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2 - %30 = OpLoad %float %29 - %31 = OpCompositeConstruct %v3float %30 %28 %26 - %sh = OpVectorShuffle %v3float %vec_const %31 0 4 5 - OpBranch %32 - %32 = OpLabel - %33 = OpPhi %v3float %sh %24 %34 %35 - %36 = OpPhi %int %int_0 %24 %37 %35 - OpLoopMerge %38 %35 None - OpBranch %39 - %39 = OpLabel - %40 = OpSLessThan %bool %36 %int_20 - OpBranchConditional %40 %41 %38 - %41 = OpLabel - %42 = OpCompositeExtract %float %33 0 - %43 = OpFAdd %float %42 %float_1 - %34 = OpCompositeInsert %v3float %43 %33 0 - OpBranch %35 - %35 = OpLabel - %37 = OpIAdd %int %36 %int_1 - OpBranch %32 - %38 = OpLabel - %44 = OpCompositeExtract %float %33 0 - %45 = OpCompositeConstruct %v4float %44 %44 %44 %44 - OpStore %OutColor %45 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(assembly, true); -} - -TEST_F(VectorDCETest, DeadInstThroughShuffle) { - // Dead insert in chain with cycle. Demonstrates analysis can handle - // cycles in chains. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec2 v; - // v.x = 0.0; - // v.y = 0.1; // dead - // for (int i = 0; i < 20; i++) { - // v.x = v.x + 1; - // v = v * 0.9; - // } - // OutColor = vec4(v.x); - // } - - const std::string assembly = - R"( -; CHECK: OpFunction -; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1 -; CHECK: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %OutColor - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %OutColor "OutColor" - OpDecorate %OutColor Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %float_0 = OpConstant %float 0 -%float_0_100000001 = OpConstant %float 0.100000001 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_20 = OpConstant %int 20 - %bool = OpTypeBool - %float_1 = OpConstant %float 1 -%float_0_899999976 = OpConstant %float 0.899999976 - %int_1 = OpConstant %int 1 - %v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %OutColor = OpVariable %_ptr_Output_v4float Output - %58 = OpUndef %v2float - %main = OpFunction %void None %3 - %5 = OpLabel - %49 = OpCompositeInsert %v2float %float_0 %58 0 - %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1 - OpBranch %22 - %22 = OpLabel - %60 = OpPhi %v2float %51 %5 %38 %25 - %59 = OpPhi %int %int_0 %5 %41 %25 - OpLoopMerge %24 %25 None - OpBranch %26 - %26 = OpLabel - %30 = OpSLessThan %bool %59 %int_20 - OpBranchConditional %30 %23 %24 - %23 = OpLabel - %53 = OpCompositeExtract %float %60 0 - %34 = OpFAdd %float %53 %float_1 - %55 = OpCompositeInsert %v2float %34 %60 0 - %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976 - OpBranch %25 - %25 = OpLabel - %41 = OpIAdd %int %59 %int_1 - OpBranch %22 - %24 = OpLabel - %57 = OpCompositeExtract %float %60 0 - %47 = OpCompositeConstruct %v4float %57 %57 %57 %57 - OpStore %OutColor %47 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(assembly, true); -} - -TEST_F(VectorDCETest, DeadInsertThroughOtherInst) { - // Dead insert in chain with cycle. Demonstrates analysis can handle - // cycles in chains. - // - // Note: The SPIR-V assembly has had store/load elimination - // performed to allow the inserts and extracts to directly - // reference each other. - // - // #version 450 - // - // layout (location=0) out vec4 OutColor; - // - // void main() - // { - // vec2 v; - // v.x = 0.0; - // v.y = 0.1; // dead - // for (int i = 0; i < 20; i++) { - // v.x = v.x + 1; - // v = v * 0.9; - // } - // OutColor = vec4(v.x); - // } - - const std::string assembly = - R"( -; CHECK: OpFunction -; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1 -; CHECK: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %OutColor - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" - OpSourceExtension "GL_GOOGLE_include_directive" - OpName %main "main" - OpName %OutColor "OutColor" - OpDecorate %OutColor Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %float_0 = OpConstant %float 0 -%float_0_100000001 = OpConstant %float 0.100000001 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_20 = OpConstant %int 20 - %bool = OpTypeBool - %float_1 = OpConstant %float 1 -%float_0_899999976 = OpConstant %float 0.899999976 - %int_1 = OpConstant %int 1 - %v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %OutColor = OpVariable %_ptr_Output_v4float Output - %58 = OpUndef %v2float - %main = OpFunction %void None %3 - %5 = OpLabel - %49 = OpCompositeInsert %v2float %float_0 %58 0 - %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1 - OpBranch %22 - %22 = OpLabel - %60 = OpPhi %v2float %51 %5 %38 %25 - %59 = OpPhi %int %int_0 %5 %41 %25 - OpLoopMerge %24 %25 None - OpBranch %26 - %26 = OpLabel - %30 = OpSLessThan %bool %59 %int_20 - OpBranchConditional %30 %23 %24 - %23 = OpLabel - %53 = OpCompositeExtract %float %60 0 - %34 = OpFAdd %float %53 %float_1 - %55 = OpCompositeInsert %v2float %34 %60 0 - %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976 - OpBranch %25 - %25 = OpLabel - %41 = OpIAdd %int %59 %int_1 - OpBranch %22 - %24 = OpLabel - %57 = OpCompositeExtract %float %60 0 - %47 = OpCompositeConstruct %v4float %57 %57 %57 %57 - OpStore %OutColor %47 - OpReturn - OpFunctionEnd -)"; - - SinglePassRunAndMatch(assembly, true); -} - -TEST_F(VectorDCETest, VectorIntoCompositeConstruct) { - const std::string text = R"(OpCapability Linkage -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "EntryPoint_Main" %2 %3 -OpExecutionMode %1 OriginUpperLeft -OpDecorate %2 Location 0 -OpDecorate %_struct_4 Block -OpDecorate %3 Location 0 -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float -%mat4v4float = OpTypeMatrix %v4float 4 -%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float -%v3float = OpTypeVector %float 3 -%_ptr_Function_v3float = OpTypePointer Function %v3float -%_struct_14 = OpTypeStruct %v2float %mat4v4float %v3float %v2float %v4float -%_ptr_Function__struct_14 = OpTypePointer Function %_struct_14 -%void = OpTypeVoid -%int = OpTypeInt 32 1 -%int_2 = OpConstant %int 2 -%int_1 = OpConstant %int 1 -%int_4 = OpConstant %int 4 -%int_0 = OpConstant %int 0 -%int_3 = OpConstant %int 3 -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 -%_ptr_Input_v2float = OpTypePointer Input %v2float -%2 = OpVariable %_ptr_Input_v2float Input -%_ptr_Output_v2float = OpTypePointer Output %v2float -%_struct_4 = OpTypeStruct %v2float -%_ptr_Output__struct_4 = OpTypePointer Output %_struct_4 -%3 = OpVariable %_ptr_Output__struct_4 Output -%28 = OpTypeFunction %void -%29 = OpConstantComposite %v2float %float_0 %float_0 -%30 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%31 = OpConstantComposite %mat4v4float %30 %30 %30 %30 -%32 = OpConstantComposite %v3float %float_0 %float_0 %float_0 -%1 = OpFunction %void None %28 -%33 = OpLabel -%34 = OpVariable %_ptr_Function_v4float Function -%35 = OpVariable %_ptr_Function__struct_14 Function -%36 = OpAccessChain %_ptr_Function_v2float %35 %int_0 -OpStore %36 %29 -%37 = OpAccessChain %_ptr_Function_mat4v4float %35 %int_1 -OpStore %37 %31 -%38 = OpAccessChain %_ptr_Function_v3float %35 %int_2 -OpStore %38 %32 -%39 = OpAccessChain %_ptr_Function_v2float %35 %int_3 -OpStore %39 %29 -%40 = OpAccessChain %_ptr_Function_v4float %35 %int_4 -OpStore %40 %30 -%41 = OpLoad %v2float %2 -OpStore %36 %41 -%42 = OpLoad %v3float %38 -%43 = OpCompositeConstruct %v4float %42 %float_1 -%44 = OpLoad %mat4v4float %37 -%45 = OpVectorTimesMatrix %v4float %43 %44 -OpStore %34 %45 -OpCopyMemory %40 %34 -OpCopyMemory %36 %39 -%46 = OpAccessChain %_ptr_Output_v2float %3 %int_0 -%47 = OpLoad %v2float %36 -OpStore %46 %47 -OpReturn -OpFunctionEnd -)"; - - SinglePassRunAndCheck(text, text, true, true); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/workaround1209_test.cpp b/3rdparty/spirv-tools/test/opt/workaround1209_test.cpp deleted file mode 100644 index 50d3c0915..000000000 --- a/3rdparty/spirv-tools/test/opt/workaround1209_test.cpp +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright (c) 2017 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 - -#include "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using Workaround1209Test = PassTest<::testing::Test>; - -TEST_F(Workaround1209Test, RemoveOpUnreachableInLoop) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_ - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %texcoord "texcoord" - OpName %buf "buf" - OpMemberName %buf 0 "MVP" - OpMemberName %buf 1 "position" - OpMemberName %buf 2 "attr" - OpName %ubuf "ubuf" - OpName %gl_VertexIndex "gl_VertexIndex" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpName %_ "" - OpDecorate %texcoord Location 0 - OpDecorate %_arr_v4float_uint_72 ArrayStride 16 - OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16 - OpMemberDecorate %buf 0 ColMajor - OpMemberDecorate %buf 0 Offset 0 - OpMemberDecorate %buf 0 MatrixStride 16 - OpMemberDecorate %buf 1 Offset 64 - OpMemberDecorate %buf 2 Offset 1216 - OpDecorate %buf Block - OpDecorate %ubuf DescriptorSet 0 - OpDecorate %ubuf Binding 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpDecorate %gl_PerVertex Block - %void = OpTypeVoid - %12 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %texcoord = OpVariable %_ptr_Output_v4float Output -%mat4v4float = OpTypeMatrix %v4float 4 - %uint = OpTypeInt 32 0 - %uint_72 = OpConstant %uint 72 -%_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72 -%_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72 - %buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0 -%_ptr_Uniform_buf = OpTypePointer Uniform %buf - %ubuf = OpVariable %_ptr_Uniform_buf Uniform - %int = OpTypeInt 32 1 - %int_2 = OpConstant %int 2 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%gl_PerVertex = OpTypeStruct %v4float -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex - %_ = OpVariable %_ptr_Output_gl_PerVertex Output - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %float_1 = OpConstant %float 1 - %28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 - %main = OpFunction %void None %12 - %29 = OpLabel - OpBranch %30 - %30 = OpLabel -; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]] - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel -; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]] - OpSelectionMerge %34 None - OpSwitch %int_1 %35 - %35 = OpLabel - %36 = OpLoad %int %gl_VertexIndex - %37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36 - %38 = OpLoad %v4float %37 - OpStore %texcoord %38 - %39 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %39 %28 - OpBranch %31 -; CHECK: [[sel_merge]] = OpLabel - %34 = OpLabel -; CHECK-NEXT: OpBranch [[merge]] - OpUnreachable - %32 = OpLabel - OpBranch %30 - %31 = OpLabel - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(Workaround1209Test, RemoveOpUnreachableInNestedLoop) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %2 "main" %3 %4 %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %2 "main" - OpName %3 "texcoord" - OpName %6 "buf" - OpMemberName %6 0 "MVP" - OpMemberName %6 1 "position" - OpMemberName %6 2 "attr" - OpName %7 "ubuf" - OpName %4 "gl_VertexIndex" - OpName %8 "gl_PerVertex" - OpMemberName %8 0 "gl_Position" - OpName %5 "" - OpDecorate %3 Location 0 - OpDecorate %9 ArrayStride 16 - OpDecorate %10 ArrayStride 16 - OpMemberDecorate %6 0 ColMajor - OpMemberDecorate %6 0 Offset 0 - OpMemberDecorate %6 0 MatrixStride 16 - OpMemberDecorate %6 1 Offset 64 - OpMemberDecorate %6 2 Offset 1216 - OpDecorate %6 Block - OpDecorate %7 DescriptorSet 0 - OpDecorate %7 Binding 0 - OpDecorate %4 BuiltIn VertexIndex - OpMemberDecorate %8 0 BuiltIn Position - OpDecorate %8 Block - %11 = OpTypeVoid - %12 = OpTypeFunction %11 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Output %14 - %3 = OpVariable %15 Output - %16 = OpTypeMatrix %14 4 - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 72 - %9 = OpTypeArray %14 %18 - %10 = OpTypeArray %14 %18 - %6 = OpTypeStruct %16 %9 %10 - %19 = OpTypePointer Uniform %6 - %7 = OpVariable %19 Uniform - %20 = OpTypeInt 32 1 - %21 = OpConstant %20 2 - %22 = OpTypePointer Input %20 - %4 = OpVariable %22 Input - %23 = OpTypePointer Uniform %14 - %8 = OpTypeStruct %14 - %24 = OpTypePointer Output %8 - %5 = OpVariable %24 Output - %25 = OpConstant %20 0 - %26 = OpConstant %20 1 - %27 = OpConstant %13 1 - %28 = OpConstantComposite %14 %27 %27 %27 %27 - %2 = OpFunction %11 None %12 - %29 = OpLabel - OpBranch %31 - %31 = OpLabel -; CHECK: OpLoopMerge - OpLoopMerge %32 %33 None - OpBranch %30 - %30 = OpLabel -; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]] - OpLoopMerge %34 %35 None - OpBranch %36 - %36 = OpLabel -; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]] - OpSelectionMerge %37 None - OpSwitch %26 %38 - %38 = OpLabel - %39 = OpLoad %20 %4 - %40 = OpAccessChain %23 %7 %21 %39 - %41 = OpLoad %14 %40 - OpStore %3 %41 - %42 = OpAccessChain %15 %5 %25 - OpStore %42 %28 - OpBranch %34 -; CHECK: [[sel_merge]] = OpLabel - %37 = OpLabel -; CHECK-NEXT: OpBranch [[merge]] - OpUnreachable - %35 = OpLabel - OpBranch %30 - %34 = OpLabel - OpBranch %32 - %33 = OpLabel - OpBranch %31 - %32 = OpLabel - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(Workaround1209Test, RemoveOpUnreachableInAdjacentLoops) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %2 "main" %3 %4 %5 - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %2 "main" - OpName %3 "texcoord" - OpName %6 "buf" - OpMemberName %6 0 "MVP" - OpMemberName %6 1 "position" - OpMemberName %6 2 "attr" - OpName %7 "ubuf" - OpName %4 "gl_VertexIndex" - OpName %8 "gl_PerVertex" - OpMemberName %8 0 "gl_Position" - OpName %5 "" - OpDecorate %3 Location 0 - OpDecorate %9 ArrayStride 16 - OpDecorate %10 ArrayStride 16 - OpMemberDecorate %6 0 ColMajor - OpMemberDecorate %6 0 Offset 0 - OpMemberDecorate %6 0 MatrixStride 16 - OpMemberDecorate %6 1 Offset 64 - OpMemberDecorate %6 2 Offset 1216 - OpDecorate %6 Block - OpDecorate %7 DescriptorSet 0 - OpDecorate %7 Binding 0 - OpDecorate %4 BuiltIn VertexIndex - OpMemberDecorate %8 0 BuiltIn Position - OpDecorate %8 Block - %11 = OpTypeVoid - %12 = OpTypeFunction %11 - %13 = OpTypeFloat 32 - %14 = OpTypeVector %13 4 - %15 = OpTypePointer Output %14 - %3 = OpVariable %15 Output - %16 = OpTypeMatrix %14 4 - %17 = OpTypeInt 32 0 - %18 = OpConstant %17 72 - %9 = OpTypeArray %14 %18 - %10 = OpTypeArray %14 %18 - %6 = OpTypeStruct %16 %9 %10 - %19 = OpTypePointer Uniform %6 - %7 = OpVariable %19 Uniform - %20 = OpTypeInt 32 1 - %21 = OpConstant %20 2 - %22 = OpTypePointer Input %20 - %4 = OpVariable %22 Input - %23 = OpTypePointer Uniform %14 - %8 = OpTypeStruct %14 - %24 = OpTypePointer Output %8 - %5 = OpVariable %24 Output - %25 = OpConstant %20 0 - %26 = OpConstant %20 1 - %27 = OpConstant %13 1 - %28 = OpConstantComposite %14 %27 %27 %27 %27 - %2 = OpFunction %11 None %12 - %29 = OpLabel - OpBranch %30 - %30 = OpLabel -; CHECK: OpLoopMerge [[merge1:%[a-zA-Z_\d]+]] - OpLoopMerge %31 %32 None - OpBranch %33 - %33 = OpLabel -; CHECK: OpSelectionMerge [[sel_merge1:%[a-zA-Z_\d]+]] - OpSelectionMerge %34 None - OpSwitch %26 %35 - %35 = OpLabel - %36 = OpLoad %20 %4 - %37 = OpAccessChain %23 %7 %21 %36 - %38 = OpLoad %14 %37 - OpStore %3 %38 - %39 = OpAccessChain %15 %5 %25 - OpStore %39 %28 - OpBranch %31 -; CHECK: [[sel_merge1]] = OpLabel - %34 = OpLabel -; CHECK-NEXT: OpBranch [[merge1]] - OpUnreachable - %32 = OpLabel - OpBranch %30 - %31 = OpLabel -; CHECK: OpLoopMerge [[merge2:%[a-zA-Z_\d]+]] - OpLoopMerge %40 %41 None - OpBranch %42 - %42 = OpLabel -; CHECK: OpSelectionMerge [[sel_merge2:%[a-zA-Z_\d]+]] - OpSelectionMerge %43 None - OpSwitch %26 %44 - %44 = OpLabel - %45 = OpLoad %20 %4 - %46 = OpAccessChain %23 %7 %21 %45 - %47 = OpLoad %14 %46 - OpStore %3 %47 - %48 = OpAccessChain %15 %5 %25 - OpStore %48 %28 - OpBranch %40 -; CHECK: [[sel_merge2]] = OpLabel - %43 = OpLabel -; CHECK-NEXT: OpBranch [[merge2]] - OpUnreachable - %41 = OpLabel - OpBranch %31 - %40 = OpLabel - OpReturn - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -TEST_F(Workaround1209Test, LeaveUnreachableNotInLoop) { - const std::string text = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_ - OpSource GLSL 400 - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %texcoord "texcoord" - OpName %buf "buf" - OpMemberName %buf 0 "MVP" - OpMemberName %buf 1 "position" - OpMemberName %buf 2 "attr" - OpName %ubuf "ubuf" - OpName %gl_VertexIndex "gl_VertexIndex" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpName %_ "" - OpDecorate %texcoord Location 0 - OpDecorate %_arr_v4float_uint_72 ArrayStride 16 - OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16 - OpMemberDecorate %buf 0 ColMajor - OpMemberDecorate %buf 0 Offset 0 - OpMemberDecorate %buf 0 MatrixStride 16 - OpMemberDecorate %buf 1 Offset 64 - OpMemberDecorate %buf 2 Offset 1216 - OpDecorate %buf Block - OpDecorate %ubuf DescriptorSet 0 - OpDecorate %ubuf Binding 0 - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpDecorate %gl_PerVertex Block - %void = OpTypeVoid - %12 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %texcoord = OpVariable %_ptr_Output_v4float Output -%mat4v4float = OpTypeMatrix %v4float 4 - %uint = OpTypeInt 32 0 - %uint_72 = OpConstant %uint 72 -%_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72 -%_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72 - %buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0 -%_ptr_Uniform_buf = OpTypePointer Uniform %buf - %ubuf = OpVariable %_ptr_Uniform_buf Uniform - %int = OpTypeInt 32 1 - %int_2 = OpConstant %int 2 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input -%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float -%gl_PerVertex = OpTypeStruct %v4float -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex - %_ = OpVariable %_ptr_Output_gl_PerVertex Output - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %float_1 = OpConstant %float 1 - %28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 - %main = OpFunction %void None %12 - %29 = OpLabel - OpBranch %30 - %30 = OpLabel - OpSelectionMerge %34 None - OpSwitch %int_1 %35 - %35 = OpLabel - %36 = OpLoad %int %gl_VertexIndex - %37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36 - %38 = OpLoad %v4float %37 - OpStore %texcoord %38 - %39 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %39 %28 - OpReturn - %34 = OpLabel -; CHECK: OpUnreachable - OpUnreachable - OpFunctionEnd)"; - - SinglePassRunAndMatch(text, false); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/opt/wrap_opkill_test.cpp b/3rdparty/spirv-tools/test/opt/wrap_opkill_test.cpp deleted file mode 100644 index d50af28a1..000000000 --- a/3rdparty/spirv-tools/test/opt/wrap_opkill_test.cpp +++ /dev/null @@ -1,518 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "gmock/gmock.h" -#include "test/opt/assembly_builder.h" -#include "test/opt/pass_fixture.h" -#include "test/opt/pass_utils.h" - -namespace spvtools { -namespace opt { -namespace { - -using WrapOpKillTest = PassTest<::testing::Test>; - -TEST_F(WrapOpKillTest, SingleOpKill) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment [[main:%\w+]] -; CHECK: [[main]] = OpFunction -; CHECK: OpFunctionCall %void [[orig_kill:%\w+]] -; CHECK: [[orig_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]] -; CHECK-NEXT: OpReturn -; CHECK: [[new_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpKill -; CHECK-NEXT: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %5 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %main = OpFunction %void None %5 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %10 %11 None - OpBranch %12 - %12 = OpLabel - OpBranchConditional %true %13 %10 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - %14 = OpFunctionCall %void %kill_ - OpBranch %9 - %10 = OpLabel - OpReturn - OpFunctionEnd - %kill_ = OpFunction %void None %5 - %15 = OpLabel - OpKill - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(WrapOpKillTest, MultipleOpKillInSameFunc) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment [[main:%\w+]] -; CHECK: [[main]] = OpFunction -; CHECK: OpFunctionCall %void [[orig_kill:%\w+]] -; CHECK: [[orig_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpSelectionMerge -; CHECK-NEXT: OpBranchConditional -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]] -; CHECK-NEXT: OpReturn -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpFunctionCall %void [[new_kill]] -; CHECK-NEXT: OpReturn -; CHECK: [[new_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpKill -; CHECK-NEXT: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %5 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %main = OpFunction %void None %5 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %10 %11 None - OpBranch %12 - %12 = OpLabel - OpBranchConditional %true %13 %10 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - %14 = OpFunctionCall %void %kill_ - OpBranch %9 - %10 = OpLabel - OpReturn - OpFunctionEnd - %kill_ = OpFunction %void None %5 - %15 = OpLabel - OpSelectionMerge %16 None - OpBranchConditional %true %17 %18 - %17 = OpLabel - OpKill - %18 = OpLabel - OpKill - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(WrapOpKillTest, MultipleOpKillInDifferentFunc) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment [[main:%\w+]] -; CHECK: [[main]] = OpFunction -; CHECK: OpFunctionCall %void [[orig_kill1:%\w+]] -; CHECK-NEXT: OpFunctionCall %void [[orig_kill2:%\w+]] -; CHECK: [[orig_kill1]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]] -; CHECK-NEXT: OpReturn -; CHECK: [[orig_kill2]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpFunctionCall %void [[new_kill]] -; CHECK-NEXT: OpReturn -; CHECK: [[new_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpKill -; CHECK-NEXT: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %4 = OpTypeFunction %void - %bool = OpTypeBool - %true = OpConstantTrue %bool - %main = OpFunction %void None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpLoopMerge %9 %10 None - OpBranch %11 - %11 = OpLabel - OpBranchConditional %true %12 %9 - %12 = OpLabel - OpBranch %10 - %10 = OpLabel - %13 = OpFunctionCall %void %14 - %15 = OpFunctionCall %void %16 - OpBranch %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - %14 = OpFunction %void None %4 - %17 = OpLabel - OpKill - OpFunctionEnd - %16 = OpFunction %void None %4 - %18 = OpLabel - OpKill - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(WrapOpKillTest, FuncWithReturnValue) { - const std::string text = R"( -; CHECK: OpEntryPoint Fragment [[main:%\w+]] -; CHECK: [[main]] = OpFunction -; CHECK: OpFunctionCall %int [[orig_kill:%\w+]] -; CHECK: [[orig_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]] -; CHECK-NEXT: [[undef:%\w+]] = OpUndef %int -; CHECK-NEXT: OpReturnValue [[undef]] -; CHECK: [[new_kill]] = OpFunction -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpKill -; CHECK-NEXT: OpFunctionEnd - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 330 - OpName %main "main" - %void = OpTypeVoid - %5 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %func_type = OpTypeFunction %int - %bool = OpTypeBool - %true = OpConstantTrue %bool - %main = OpFunction %void None %5 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %10 %11 None - OpBranch %12 - %12 = OpLabel - OpBranchConditional %true %13 %10 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - %14 = OpFunctionCall %int %kill_ - OpBranch %9 - %10 = OpLabel - OpReturn - OpFunctionEnd - %kill_ = OpFunction %int None %func_type - %15 = OpLabel - OpKill - OpFunctionEnd - )"; - - SinglePassRunAndMatch(text, true); -} - -TEST_F(WrapOpKillTest, IdBoundOverflow1) { - const std::string text = R"( -OpCapability GeometryStreams -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %2 None %3 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %10 %11 None -OpBranch %12 -%12 = OpLabel -OpBranchConditional %true %13 %10 -%13 = OpLabel -OpBranch %11 -%11 = OpLabel -%14 = OpFunctionCall %void %kill_ -OpBranch %9 -%10 = OpLabel -OpReturn -OpFunctionEnd -%kill_ = OpFunction %2 Pure|Const %3 -%4194302 = OpLabel -OpKill -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(WrapOpKillTest, IdBoundOverflow2) { - const std::string text = R"( -OpCapability GeometryStreams -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %2 None %3 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %10 %11 None -OpBranch %12 -%12 = OpLabel -OpBranchConditional %true %13 %10 -%13 = OpLabel -OpBranch %11 -%11 = OpLabel -%14 = OpFunctionCall %void %kill_ -OpBranch %9 -%10 = OpLabel -OpReturn -OpFunctionEnd -%kill_ = OpFunction %2 Pure|Const %3 -%4194301 = OpLabel -OpKill -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(WrapOpKillTest, IdBoundOverflow3) { - const std::string text = R"( -OpCapability GeometryStreams -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %2 None %3 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %10 %11 None -OpBranch %12 -%12 = OpLabel -OpBranchConditional %true %13 %10 -%13 = OpLabel -OpBranch %11 -%11 = OpLabel -%14 = OpFunctionCall %void %kill_ -OpBranch %9 -%10 = OpLabel -OpReturn -OpFunctionEnd -%kill_ = OpFunction %2 Pure|Const %3 -%4194300 = OpLabel -OpKill -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(WrapOpKillTest, IdBoundOverflow4) { - const std::string text = R"( -OpCapability DerivativeControl -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %2 Location 539091968 -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %2 None %3 -%8 = OpLabel -OpBranch %9 -%9 = OpLabel -OpLoopMerge %10 %11 None -OpBranch %12 -%12 = OpLabel -OpBranchConditional %true %13 %10 -%13 = OpLabel -OpBranch %11 -%11 = OpLabel -%14 = OpFunctionCall %void %kill_ -OpBranch %9 -%10 = OpLabel -OpReturn -OpFunctionEnd -%kill_ = OpFunction %2 Inline|Pure|Const %3 -%4194302 = OpLabel -OpKill -OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(WrapOpKillTest, IdBoundOverflow5) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - OpDecorate %void Location 539091968 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %_struct_5 = OpTypeStruct %float %float - %_struct_6 = OpTypeStruct %_struct_5 -%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6 -%_ptr_Output_float = OpTypePointer Output %float - %9 = OpTypeFunction %_struct_5 %_ptr_Function__struct_6 - %bool = OpTypeBool - %true = OpConstantTrue %bool - %1 = OpFunction %void None %3 - %12 = OpLabel - %13 = OpVariable %_ptr_Function__struct_6 Function - OpBranch %14 - %14 = OpLabel - OpLoopMerge %15 %16 None - OpBranch %17 - %17 = OpLabel - OpBranchConditional %true %18 %15 - %18 = OpLabel - OpBranch %16 - %16 = OpLabel - %19 = OpFunctionCall %void %20 - %21 = OpFunctionCall %_struct_5 %22 %13 - OpBranch %14 - %15 = OpLabel - OpReturn - OpFunctionEnd - %20 = OpFunction %void Inline|Pure|Const %3 - %23 = OpLabel - %24 = OpVariable %_ptr_Function__struct_6 Function - %25 = OpFunctionCall %_struct_5 %26 %24 - OpKill - OpFunctionEnd - %26 = OpFunction %_struct_5 None %9 - %27 = OpLabel - OpUnreachable - OpFunctionEnd - %22 = OpFunction %_struct_5 Inline %9 - %4194295 = OpLabel - OpKill - OpFunctionEnd -)"; - - SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); - - std::vector messages = { - {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}}; - SetMessageConsumer(GetTestMessageConsumer(messages)); - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::Failure, std::get<1>(result)); -} - -TEST_F(WrapOpKillTest, SkipEntryPoint) { - const std::string text = R"( -OpCapability GeometryStreams -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" -OpExecutionMode %4 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%4 = OpFunction %2 Pure|Const %3 -%5 = OpLabel -OpKill -OpFunctionEnd -)"; - - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -TEST_F(WrapOpKillTest, SkipFunctionNotInContinue) { - const std::string text = R"( -OpCapability GeometryStreams -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%main = OpFunction %2 None %3 -%6 = OpLabel -%7 = OpFunctionCall %void %4 -OpReturn -OpFunctionEnd -%4 = OpFunction %2 Pure|Const %3 -%5 = OpLabel -OpKill -OpFunctionEnd -)"; - - auto result = SinglePassRunToBinary(text, true); - EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); -} - -} // namespace -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/parse_number_test.cpp b/3rdparty/spirv-tools/test/parse_number_test.cpp deleted file mode 100644 index c99205cf5..000000000 --- a/3rdparty/spirv-tools/test/parse_number_test.cpp +++ /dev/null @@ -1,970 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/util/parse_number.h" -#include "spirv-tools/libspirv.h" - -namespace spvtools { -namespace utils { -namespace { - -using testing::Eq; -using testing::IsNull; -using testing::NotNull; - -TEST(ParseNarrowSignedIntegers, Sample) { - int16_t i16; - - EXPECT_FALSE(ParseNumber(nullptr, &i16)); - EXPECT_FALSE(ParseNumber("", &i16)); - EXPECT_FALSE(ParseNumber("0=", &i16)); - - EXPECT_TRUE(ParseNumber("0", &i16)); - EXPECT_EQ(0, i16); - EXPECT_TRUE(ParseNumber("32767", &i16)); - EXPECT_EQ(32767, i16); - EXPECT_TRUE(ParseNumber("-32768", &i16)); - EXPECT_EQ(-32768, i16); - EXPECT_TRUE(ParseNumber("-0", &i16)); - EXPECT_EQ(0, i16); - - // These are out of range, so they should return an error. - // The error code depends on whether this is an optional value. - EXPECT_FALSE(ParseNumber("32768", &i16)); - EXPECT_FALSE(ParseNumber("65535", &i16)); - - // Check hex parsing. - EXPECT_TRUE(ParseNumber("0x7fff", &i16)); - EXPECT_EQ(32767, i16); - // This is out of range. - EXPECT_FALSE(ParseNumber("0xffff", &i16)); -} - -TEST(ParseNarrowUnsignedIntegers, Sample) { - uint16_t u16; - - EXPECT_FALSE(ParseNumber(nullptr, &u16)); - EXPECT_FALSE(ParseNumber("", &u16)); - EXPECT_FALSE(ParseNumber("0=", &u16)); - - EXPECT_TRUE(ParseNumber("0", &u16)); - EXPECT_EQ(0, u16); - EXPECT_TRUE(ParseNumber("65535", &u16)); - EXPECT_EQ(65535, u16); - EXPECT_FALSE(ParseNumber("65536", &u16)); - - // We don't care about -0 since it's rejected at a higher level. - EXPECT_FALSE(ParseNumber("-1", &u16)); - EXPECT_TRUE(ParseNumber("0xffff", &u16)); - EXPECT_EQ(0xffff, u16); - EXPECT_FALSE(ParseNumber("0x10000", &u16)); -} - -TEST(ParseSignedIntegers, Sample) { - int32_t i32; - - // Invalid parse. - EXPECT_FALSE(ParseNumber(nullptr, &i32)); - EXPECT_FALSE(ParseNumber("", &i32)); - EXPECT_FALSE(ParseNumber("0=", &i32)); - - // Decimal values. - EXPECT_TRUE(ParseNumber("0", &i32)); - EXPECT_EQ(0, i32); - EXPECT_TRUE(ParseNumber("2147483647", &i32)); - EXPECT_EQ(std::numeric_limits::max(), i32); - EXPECT_FALSE(ParseNumber("2147483648", &i32)); - EXPECT_TRUE(ParseNumber("-0", &i32)); - EXPECT_EQ(0, i32); - EXPECT_TRUE(ParseNumber("-1", &i32)); - EXPECT_EQ(-1, i32); - EXPECT_TRUE(ParseNumber("-2147483648", &i32)); - EXPECT_EQ(std::numeric_limits::min(), i32); - - // Hex values. - EXPECT_TRUE(ParseNumber("0x7fffffff", &i32)); - EXPECT_EQ(std::numeric_limits::max(), i32); - EXPECT_FALSE(ParseNumber("0x80000000", &i32)); - EXPECT_TRUE(ParseNumber("-0x000", &i32)); - EXPECT_EQ(0, i32); - EXPECT_TRUE(ParseNumber("-0x001", &i32)); - EXPECT_EQ(-1, i32); - EXPECT_TRUE(ParseNumber("-0x80000000", &i32)); - EXPECT_EQ(std::numeric_limits::min(), i32); -} - -TEST(ParseUnsignedIntegers, Sample) { - uint32_t u32; - - // Invalid parse. - EXPECT_FALSE(ParseNumber(nullptr, &u32)); - EXPECT_FALSE(ParseNumber("", &u32)); - EXPECT_FALSE(ParseNumber("0=", &u32)); - - // Valid values. - EXPECT_TRUE(ParseNumber("0", &u32)); - EXPECT_EQ(0u, u32); - EXPECT_TRUE(ParseNumber("4294967295", &u32)); - EXPECT_EQ(std::numeric_limits::max(), u32); - EXPECT_FALSE(ParseNumber("4294967296", &u32)); - - // Hex values. - EXPECT_TRUE(ParseNumber("0xffffffff", &u32)); - EXPECT_EQ(std::numeric_limits::max(), u32); - - // We don't care about -0 since it's rejected at a higher level. - EXPECT_FALSE(ParseNumber("-1", &u32)); -} - -TEST(ParseWideSignedIntegers, Sample) { - int64_t i64; - EXPECT_FALSE(ParseNumber(nullptr, &i64)); - EXPECT_FALSE(ParseNumber("", &i64)); - EXPECT_FALSE(ParseNumber("0=", &i64)); - EXPECT_TRUE(ParseNumber("0", &i64)); - EXPECT_EQ(0, i64); - EXPECT_TRUE(ParseNumber("0x7fffffffffffffff", &i64)); - EXPECT_EQ(0x7fffffffffffffff, i64); - EXPECT_TRUE(ParseNumber("-0", &i64)); - EXPECT_EQ(0, i64); - EXPECT_TRUE(ParseNumber("-1", &i64)); - EXPECT_EQ(-1, i64); -} - -TEST(ParseWideUnsignedIntegers, Sample) { - uint64_t u64; - EXPECT_FALSE(ParseNumber(nullptr, &u64)); - EXPECT_FALSE(ParseNumber("", &u64)); - EXPECT_FALSE(ParseNumber("0=", &u64)); - EXPECT_TRUE(ParseNumber("0", &u64)); - EXPECT_EQ(0u, u64); - EXPECT_TRUE(ParseNumber("0xffffffffffffffff", &u64)); - EXPECT_EQ(0xffffffffffffffffULL, u64); - - // We don't care about -0 since it's rejected at a higher level. - EXPECT_FALSE(ParseNumber("-1", &u64)); -} - -TEST(ParseFloat, Sample) { - float f; - - EXPECT_FALSE(ParseNumber(nullptr, &f)); - EXPECT_FALSE(ParseNumber("", &f)); - EXPECT_FALSE(ParseNumber("0=", &f)); - - // These values are exactly representatble. - EXPECT_TRUE(ParseNumber("0", &f)); - EXPECT_EQ(0.0f, f); - EXPECT_TRUE(ParseNumber("42", &f)); - EXPECT_EQ(42.0f, f); - EXPECT_TRUE(ParseNumber("2.5", &f)); - EXPECT_EQ(2.5f, f); - EXPECT_TRUE(ParseNumber("-32.5", &f)); - EXPECT_EQ(-32.5f, f); - EXPECT_TRUE(ParseNumber("1e38", &f)); - EXPECT_EQ(1e38f, f); - EXPECT_TRUE(ParseNumber("-1e38", &f)); - EXPECT_EQ(-1e38f, f); -} - -TEST(ParseFloat, Overflow) { - // The assembler parses using HexFloat>. Make - // sure that succeeds for in-range values, and fails for out of - // range values. When it does overflow, the value is set to the - // nearest finite value, matching C++11 behavior for operator>> - // on floating point. - HexFloat> f(0.0f); - - EXPECT_TRUE(ParseNumber("1e38", &f)); - EXPECT_EQ(1e38f, f.value().getAsFloat()); - EXPECT_TRUE(ParseNumber("-1e38", &f)); - EXPECT_EQ(-1e38f, f.value().getAsFloat()); - EXPECT_FALSE(ParseNumber("1e40", &f)); - EXPECT_FALSE(ParseNumber("-1e40", &f)); - EXPECT_FALSE(ParseNumber("1e400", &f)); - EXPECT_FALSE(ParseNumber("-1e400", &f)); -} - -TEST(ParseDouble, Sample) { - double f; - - EXPECT_FALSE(ParseNumber(nullptr, &f)); - EXPECT_FALSE(ParseNumber("", &f)); - EXPECT_FALSE(ParseNumber("0=", &f)); - - // These values are exactly representatble. - EXPECT_TRUE(ParseNumber("0", &f)); - EXPECT_EQ(0.0, f); - EXPECT_TRUE(ParseNumber("42", &f)); - EXPECT_EQ(42.0, f); - EXPECT_TRUE(ParseNumber("2.5", &f)); - EXPECT_EQ(2.5, f); - EXPECT_TRUE(ParseNumber("-32.5", &f)); - EXPECT_EQ(-32.5, f); - EXPECT_TRUE(ParseNumber("1e38", &f)); - EXPECT_EQ(1e38, f); - EXPECT_TRUE(ParseNumber("-1e38", &f)); - EXPECT_EQ(-1e38, f); - // These are out of range for 32-bit float, but in range for 64-bit float. - EXPECT_TRUE(ParseNumber("1e40", &f)); - EXPECT_EQ(1e40, f); - EXPECT_TRUE(ParseNumber("-1e40", &f)); - EXPECT_EQ(-1e40, f); -} - -TEST(ParseDouble, Overflow) { - // The assembler parses using HexFloat>. Make - // sure that succeeds for in-range values, and fails for out of - // range values. When it does overflow, the value is set to the - // nearest finite value, matching C++11 behavior for operator>> - // on floating point. - HexFloat> f(0.0); - - EXPECT_TRUE(ParseNumber("1e38", &f)); - EXPECT_EQ(1e38, f.value().getAsFloat()); - EXPECT_TRUE(ParseNumber("-1e38", &f)); - EXPECT_EQ(-1e38, f.value().getAsFloat()); - EXPECT_TRUE(ParseNumber("1e40", &f)); - EXPECT_EQ(1e40, f.value().getAsFloat()); - EXPECT_TRUE(ParseNumber("-1e40", &f)); - EXPECT_EQ(-1e40, f.value().getAsFloat()); - EXPECT_FALSE(ParseNumber("1e400", &f)); - EXPECT_FALSE(ParseNumber("-1e400", &f)); -} - -TEST(ParseFloat16, Overflow) { - // The assembler parses using HexFloat>. Make - // sure that succeeds for in-range values, and fails for out of - // range values. When it does overflow, the value is set to the - // nearest finite value, matching C++11 behavior for operator>> - // on floating point. - HexFloat> f(0); - - EXPECT_FALSE(ParseNumber(nullptr, &f)); - EXPECT_TRUE(ParseNumber("-0.0", &f)); - EXPECT_EQ(uint16_t{0x8000}, f.value().getAsFloat().get_value()); - EXPECT_TRUE(ParseNumber("1.0", &f)); - EXPECT_EQ(uint16_t{0x3c00}, f.value().getAsFloat().get_value()); - - // Overflows 16-bit but not 32-bit - EXPECT_FALSE(ParseNumber("1e38", &f)); - EXPECT_FALSE(ParseNumber("-1e38", &f)); - - // Overflows 32-bit but not 64-bit - EXPECT_FALSE(ParseNumber("1e40", &f)); - EXPECT_FALSE(ParseNumber("-1e40", &f)); - - // Overflows 64-bit - EXPECT_FALSE(ParseNumber("1e400", &f)); - EXPECT_FALSE(ParseNumber("-1e400", &f)); -} - -void AssertEmitFunc(uint32_t) { - ASSERT_FALSE(true) - << "Should not call emit() function when the number can not be parsed."; - return; -} - -TEST(ParseAndEncodeNarrowSignedIntegers, Invalid) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {16, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("The given text is a nullptr", err_msg); - rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); - rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: =", err_msg); - rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid signed integer literal: -", err_msg); - rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg); -} - -TEST(ParseAndEncodeNarrowSignedIntegers, Overflow) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {16, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber("32768", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Integer 32768 does not fit in a 16-bit signed integer", err_msg); - rc = ParseAndEncodeIntegerNumber("-32769", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Integer -32769 does not fit in a 16-bit signed integer", err_msg); -} - -TEST(ParseAndEncodeNarrowSignedIntegers, Success) { - // Don't care the error message in this case. - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - NumberType type = {16, SPV_NUMBER_SIGNED_INT}; - - // Zero, maximum, and minimum value - rc = ParseAndEncodeIntegerNumber( - "0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "-0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "32767", type, [](uint32_t word) { EXPECT_EQ(0x00007fffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "-32768", type, [](uint32_t word) { EXPECT_EQ(0xffff8000u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Hex parsing - rc = ParseAndEncodeIntegerNumber( - "0x7fff", type, [](uint32_t word) { EXPECT_EQ(0x00007fffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "0xffff", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); -} - -TEST(ParseAndEncodeNarrowUnsignedIntegers, Invalid) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {16, SPV_NUMBER_UNSIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("The given text is a nullptr", err_msg); - rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); - rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: =", err_msg); - rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); - rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg); - rc = ParseAndEncodeIntegerNumber("-0", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); - rc = ParseAndEncodeIntegerNumber("-1", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); -} - -TEST(ParseAndEncodeNarrowUnsignedIntegers, Overflow) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg("random content"); - NumberType type = {16, SPV_NUMBER_UNSIGNED_INT}; - - // Overflow - rc = ParseAndEncodeIntegerNumber("65536", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Integer 65536 does not fit in a 16-bit unsigned integer", err_msg); -} - -TEST(ParseAndEncodeNarrowUnsignedIntegers, Success) { - // Don't care the error message in this case. - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - NumberType type = {16, SPV_NUMBER_UNSIGNED_INT}; - - // Zero, maximum, and minimum value - rc = ParseAndEncodeIntegerNumber( - "0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "65535", type, [](uint32_t word) { EXPECT_EQ(0x0000ffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Hex parsing - rc = ParseAndEncodeIntegerNumber( - "0xffff", type, [](uint32_t word) { EXPECT_EQ(0x0000ffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); -} - -TEST(ParseAndEncodeSignedIntegers, Invalid) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("The given text is a nullptr", err_msg); - rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); - rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: =", err_msg); - rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid signed integer literal: -", err_msg); - rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg); -} - -TEST(ParseAndEncodeSignedIntegers, Overflow) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_SIGNED_INT}; - - rc = - ParseAndEncodeIntegerNumber("2147483648", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Integer 2147483648 does not fit in a 32-bit signed integer", - err_msg); - rc = ParseAndEncodeIntegerNumber("-2147483649", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Integer -2147483649 does not fit in a 32-bit signed integer", - err_msg); -} - -TEST(ParseAndEncodeSignedIntegers, Success) { - // Don't care the error message in this case. - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - NumberType type = {32, SPV_NUMBER_SIGNED_INT}; - - // Zero, maximum, and minimum value - rc = ParseAndEncodeIntegerNumber( - "0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "-0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "2147483647", type, [](uint32_t word) { EXPECT_EQ(0x7fffffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "-2147483648", type, [](uint32_t word) { EXPECT_EQ(0x80000000u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Hex parsing - rc = ParseAndEncodeIntegerNumber( - "0x7fffffff", type, [](uint32_t word) { EXPECT_EQ(0x7fffffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "0xffffffff", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); -} - -TEST(ParseAndEncodeUnsignedIntegers, Invalid) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_UNSIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("The given text is a nullptr", err_msg); - rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); - rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: =", err_msg); - rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); - rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg); - rc = ParseAndEncodeIntegerNumber("-0", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); - rc = ParseAndEncodeIntegerNumber("-1", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); -} - -TEST(ParseAndEncodeUnsignedIntegers, Overflow) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg("random content"); - NumberType type = {32, SPV_NUMBER_UNSIGNED_INT}; - - // Overflow - rc = - ParseAndEncodeIntegerNumber("4294967296", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Integer 4294967296 does not fit in a 32-bit unsigned integer", - err_msg); -} - -TEST(ParseAndEncodeUnsignedIntegers, Success) { - // Don't care the error message in this case. - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - NumberType type = {32, SPV_NUMBER_UNSIGNED_INT}; - - // Zero, maximum, and minimum value - rc = ParseAndEncodeIntegerNumber( - "0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeIntegerNumber( - "4294967295", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Hex parsing - rc = ParseAndEncodeIntegerNumber( - "0xffffffff", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); -} - -TEST(ParseAndEncodeWideSignedIntegers, Invalid) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {64, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("The given text is a nullptr", err_msg); - rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); - rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: =", err_msg); - rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid signed integer literal: -", err_msg); - rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg); -} - -TEST(ParseAndEncodeWideSignedIntegers, Overflow) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {64, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber("9223372036854775808", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ( - "Integer 9223372036854775808 does not fit in a 64-bit signed integer", - err_msg); - rc = ParseAndEncodeIntegerNumber("-9223372036854775809", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid signed integer literal: -9223372036854775809", err_msg); -} - -TEST(ParseAndEncodeWideSignedIntegers, Success) { - // Don't care the error message in this case. - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - NumberType type = {64, SPV_NUMBER_SIGNED_INT}; - std::vector word_buffer; - auto emit = [&word_buffer](uint32_t word) { - if (word_buffer.size() == 2) word_buffer.clear(); - word_buffer.push_back(word); - }; - - // Zero, maximum, and minimum value - rc = ParseAndEncodeIntegerNumber("0", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0u})); - rc = ParseAndEncodeIntegerNumber("-0", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0u})); - rc = ParseAndEncodeIntegerNumber("9223372036854775807", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xffffffffu, 0x7fffffffu})); - rc = ParseAndEncodeIntegerNumber("-9223372036854775808", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0x80000000u})); - rc = ParseAndEncodeIntegerNumber("-1", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xffffffffu, 0xffffffffu})); - - // Hex parsing - rc = ParseAndEncodeIntegerNumber("0x7fffffffffffffff", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xffffffffu, 0x7fffffffu})); - rc = ParseAndEncodeIntegerNumber("0xffffffffffffffff", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xffffffffu, 0xffffffffu})); -} - -TEST(ParseAndEncodeWideUnsignedIntegers, Invalid) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {64, SPV_NUMBER_UNSIGNED_INT}; - - // Invalid - rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("The given text is a nullptr", err_msg); - rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); - rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: =", err_msg); - rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); - rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg); - rc = ParseAndEncodeIntegerNumber("-0", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); - rc = ParseAndEncodeIntegerNumber("-1", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg); -} - -TEST(ParseAndEncodeWideUnsignedIntegers, Overflow) { - // The error message should be overwritten after each parsing call. - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {64, SPV_NUMBER_UNSIGNED_INT}; - - // Overflow - rc = ParseAndEncodeIntegerNumber("18446744073709551616", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: 18446744073709551616", err_msg); -} - -TEST(ParseAndEncodeWideUnsignedIntegers, Success) { - // Don't care the error message in this case. - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - NumberType type = {64, SPV_NUMBER_UNSIGNED_INT}; - std::vector word_buffer; - auto emit = [&word_buffer](uint32_t word) { - if (word_buffer.size() == 2) word_buffer.clear(); - word_buffer.push_back(word); - }; - - // Zero, maximum, and minimum value - rc = ParseAndEncodeIntegerNumber("0", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0u})); - rc = ParseAndEncodeIntegerNumber("18446744073709551615", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xffffffffu, 0xffffffffu})); - - // Hex parsing - rc = ParseAndEncodeIntegerNumber("0xffffffffffffffff", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xffffffffu, 0xffffffffu})); -} - -TEST(ParseAndEncodeIntegerNumber, TypeNone) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_NONE}; - - rc = ParseAndEncodeIntegerNumber( - "0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("The expected type is not a integer type", err_msg); -} - -TEST(ParseAndEncodeIntegerNumber, InvalidCaseWithoutErrorMessageString) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - NumberType type = {32, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber("invalid", type, AssertEmitFunc, nullptr); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); -} - -TEST(ParseAndEncodeIntegerNumber, DoNotTouchErrorMessageStringOnSuccess) { - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - std::string err_msg("random content"); - NumberType type = {32, SPV_NUMBER_SIGNED_INT}; - - rc = ParseAndEncodeIntegerNumber( - "100", type, [](uint32_t word) { EXPECT_EQ(100u, word); }, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_EQ("random content", err_msg); -} - -TEST(ParseAndEncodeFloat, Sample) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_FLOATING}; - - // Invalid - rc = ParseAndEncodeFloatingPointNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 32-bit float literal: ", err_msg); - rc = ParseAndEncodeFloatingPointNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 32-bit float literal: 0=", err_msg); - - // Representative samples - rc = ParseAndEncodeFloatingPointNumber( - "0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "-0.0", type, [](uint32_t word) { EXPECT_EQ(0x80000000u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "42", type, [](uint32_t word) { EXPECT_EQ(0x42280000u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "2.5", type, [](uint32_t word) { EXPECT_EQ(0x40200000u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "-32.5", type, [](uint32_t word) { EXPECT_EQ(0xc2020000u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "1e38", type, [](uint32_t word) { EXPECT_EQ(0x7e967699u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "-1e38", type, [](uint32_t word) { EXPECT_EQ(0xfe967699u, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Overflow - rc = - ParseAndEncodeFloatingPointNumber("1e40", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 32-bit float literal: 1e40", err_msg); - rc = ParseAndEncodeFloatingPointNumber("-1e40", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 32-bit float literal: -1e40", err_msg); - rc = ParseAndEncodeFloatingPointNumber("1e400", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 32-bit float literal: 1e400", err_msg); - rc = ParseAndEncodeFloatingPointNumber("-1e400", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 32-bit float literal: -1e400", err_msg); -} - -TEST(ParseAndEncodeDouble, Sample) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {64, SPV_NUMBER_FLOATING}; - std::vector word_buffer; - auto emit = [&word_buffer](uint32_t word) { - if (word_buffer.size() == 2) word_buffer.clear(); - word_buffer.push_back(word); - }; - - // Invalid - rc = ParseAndEncodeFloatingPointNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 64-bit float literal: ", err_msg); - rc = ParseAndEncodeFloatingPointNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 64-bit float literal: 0=", err_msg); - - // Representative samples - rc = ParseAndEncodeFloatingPointNumber("0.0", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0u})); - rc = ParseAndEncodeFloatingPointNumber("-0.0", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0x80000000u})); - rc = ParseAndEncodeFloatingPointNumber("42", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0x40450000u})); - rc = ParseAndEncodeFloatingPointNumber("2.5", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0x40040000u})); - rc = ParseAndEncodeFloatingPointNumber("32.5", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0u, 0x40404000u})); - rc = ParseAndEncodeFloatingPointNumber("1e38", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0x2a16a1b1u, 0x47d2ced3u})); - rc = ParseAndEncodeFloatingPointNumber("-1e38", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0x2a16a1b1u, 0xc7d2ced3u})); - rc = ParseAndEncodeFloatingPointNumber("1e40", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xf1c35ca5u, 0x483d6329u})); - rc = ParseAndEncodeFloatingPointNumber("-1e40", type, emit, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_THAT(word_buffer, Eq(std::vector{0xf1c35ca5u, 0xc83d6329u})); - - // Overflow - rc = ParseAndEncodeFloatingPointNumber("1e400", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 64-bit float literal: 1e400", err_msg); - rc = ParseAndEncodeFloatingPointNumber("-1e400", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 64-bit float literal: -1e400", err_msg); -} - -TEST(ParseAndEncodeFloat16, Sample) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {16, SPV_NUMBER_FLOATING}; - - // Invalid - rc = ParseAndEncodeFloatingPointNumber("", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: ", err_msg); - rc = ParseAndEncodeFloatingPointNumber("0=", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: 0=", err_msg); - - // Representative samples - rc = ParseAndEncodeFloatingPointNumber( - "0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "-0.0", type, [](uint32_t word) { EXPECT_EQ(0x8000u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "1.0", type, [](uint32_t word) { EXPECT_EQ(0x3c00u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "2.5", type, [](uint32_t word) { EXPECT_EQ(0x4100u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - rc = ParseAndEncodeFloatingPointNumber( - "32.5", type, [](uint32_t word) { EXPECT_EQ(0x5010u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Overflow - rc = - ParseAndEncodeFloatingPointNumber("1e38", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: 1e38", err_msg); - rc = ParseAndEncodeFloatingPointNumber("-1e38", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: -1e38", err_msg); - rc = - ParseAndEncodeFloatingPointNumber("1e40", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: 1e40", err_msg); - rc = ParseAndEncodeFloatingPointNumber("-1e40", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: -1e40", err_msg); - rc = ParseAndEncodeFloatingPointNumber("1e400", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: 1e400", err_msg); - rc = ParseAndEncodeFloatingPointNumber("-1e400", type, AssertEmitFunc, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid 16-bit float literal: -1e400", err_msg); -} - -TEST(ParseAndEncodeFloatingPointNumber, TypeNone) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_NONE}; - - rc = ParseAndEncodeFloatingPointNumber( - "0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc); - EXPECT_EQ("The expected type is not a float type", err_msg); -} - -TEST(ParseAndEncodeFloatingPointNumber, InvalidCaseWithoutErrorMessageString) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - NumberType type = {32, SPV_NUMBER_FLOATING}; - - rc = ParseAndEncodeFloatingPointNumber("invalid", type, AssertEmitFunc, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); -} - -TEST(ParseAndEncodeFloatingPointNumber, DoNotTouchErrorMessageStringOnSuccess) { - EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText; - std::string err_msg("random content"); - NumberType type = {32, SPV_NUMBER_FLOATING}; - - rc = ParseAndEncodeFloatingPointNumber( - "0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_EQ("random content", err_msg); -} - -TEST(ParseAndEncodeNumber, Sample) { - EncodeNumberStatus rc = EncodeNumberStatus::kSuccess; - std::string err_msg; - NumberType type = {32, SPV_NUMBER_SIGNED_INT}; - - // Invalid with error message string - rc = ParseAndEncodeNumber("something wrong", type, AssertEmitFunc, &err_msg); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - EXPECT_EQ("Invalid unsigned integer literal: something wrong", err_msg); - - // Invalid without error message string - rc = ParseAndEncodeNumber("something wrong", type, AssertEmitFunc, nullptr); - EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); - - // Signed integer, should not touch the error message string. - err_msg = "random content"; - rc = ParseAndEncodeNumber("-1", type, - [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); }, - &err_msg); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - EXPECT_EQ("random content", err_msg); - - // Unsigned integer - type = {32, SPV_NUMBER_UNSIGNED_INT}; - rc = ParseAndEncodeNumber( - "1", type, [](uint32_t word) { EXPECT_EQ(1u, word); }, nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); - - // Float - type = {32, SPV_NUMBER_FLOATING}; - rc = ParseAndEncodeNumber("-1.0", type, - [](uint32_t word) { EXPECT_EQ(0xbf800000, word); }, - nullptr); - EXPECT_EQ(EncodeNumberStatus::kSuccess, rc); -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/pch_test.cpp b/3rdparty/spirv-tools/test/pch_test.cpp deleted file mode 100644 index 3b06a0aa2..000000000 --- a/3rdparty/spirv-tools/test/pch_test.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "pch_test.h" diff --git a/3rdparty/spirv-tools/test/pch_test.h b/3rdparty/spirv-tools/test/pch_test.h deleted file mode 100644 index 7dac06acf..000000000 --- a/3rdparty/spirv-tools/test/pch_test.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "gmock/gmock.h" -#include "source/spirv_constant.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" diff --git a/3rdparty/spirv-tools/test/preserve_numeric_ids_test.cpp b/3rdparty/spirv-tools/test/preserve_numeric_ids_test.cpp deleted file mode 100644 index 1c3354d55..000000000 --- a/3rdparty/spirv-tools/test/preserve_numeric_ids_test.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include - -#include "source/text.h" -#include "source/text_handler.h" -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using spvtest::ScopedContext; - -// Converts code to binary and then back to text. -spv_result_t ToBinaryAndBack( - const std::string& before, std::string* after, - uint32_t text_to_binary_options = SPV_TEXT_TO_BINARY_OPTION_NONE, - uint32_t binary_to_text_options = SPV_BINARY_TO_TEXT_OPTION_NONE, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0) { - ScopedContext ctx(env); - spv_binary binary; - spv_text text; - - spv_result_t result = - spvTextToBinaryWithOptions(ctx.context, before.c_str(), before.size(), - text_to_binary_options, &binary, nullptr); - if (result != SPV_SUCCESS) { - return result; - } - - result = spvBinaryToText(ctx.context, binary->code, binary->wordCount, - binary_to_text_options, &text, nullptr); - if (result != SPV_SUCCESS) { - return result; - } - - *after = std::string(text->str, text->length); - - spvBinaryDestroy(binary); - spvTextDestroy(text); - - return SPV_SUCCESS; -} - -TEST(ToBinaryAndBack, DontPreserveNumericIds) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -%i32 = OpTypeInt 32 1 -%u32 = OpTypeInt 32 0 -%f32 = OpTypeFloat 32 -%200 = OpTypeVoid -%300 = OpTypeFunction %200 -%main = OpFunction %200 None %300 -%entry = OpLabel -%100 = OpConstant %u32 100 -%1 = OpConstant %u32 200 -%2 = OpConstant %u32 300 -OpReturn -OpFunctionEnd -)"; - - const std::string expected = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -%1 = OpTypeInt 32 1 -%2 = OpTypeInt 32 0 -%3 = OpTypeFloat 32 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -%8 = OpConstant %2 100 -%9 = OpConstant %2 200 -%10 = OpConstant %2 300 -OpReturn -OpFunctionEnd -)"; - - std::string after; - EXPECT_EQ(SPV_SUCCESS, - ToBinaryAndBack(before, &after, SPV_TEXT_TO_BINARY_OPTION_NONE, - SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)); - - EXPECT_EQ(expected, after); -} - -TEST(TextHandler, PreserveNumericIds) { - const std::string before = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -%i32 = OpTypeInt 32 1 -%u32 = OpTypeInt 32 0 -%f32 = OpTypeFloat 32 -%200 = OpTypeVoid -%300 = OpTypeFunction %200 -%main = OpFunction %200 None %300 -%entry = OpLabel -%100 = OpConstant %u32 100 -%1 = OpConstant %u32 200 -%2 = OpConstant %u32 300 -OpReturn -OpFunctionEnd -)"; - - const std::string expected = - R"(OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -%3 = OpTypeInt 32 1 -%4 = OpTypeInt 32 0 -%5 = OpTypeFloat 32 -%200 = OpTypeVoid -%300 = OpTypeFunction %200 -%6 = OpFunction %200 None %300 -%7 = OpLabel -%100 = OpConstant %4 100 -%1 = OpConstant %4 200 -%2 = OpConstant %4 300 -OpReturn -OpFunctionEnd -)"; - - std::string after; - EXPECT_EQ(SPV_SUCCESS, - ToBinaryAndBack(before, &after, - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS, - SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)); - - EXPECT_EQ(expected, after); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/CMakeLists.txt b/3rdparty/spirv-tools/test/reduce/CMakeLists.txt deleted file mode 100644 index b19bba453..000000000 --- a/3rdparty/spirv-tools/test/reduce/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2018 Google LLC -# -# 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. - -add_spvtools_unittest(TARGET reduce - SRCS - merge_blocks_test.cpp - operand_to_constant_test.cpp - operand_to_undef_test.cpp - operand_to_dominating_id_test.cpp - reduce_test_util.cpp - reduce_test_util.h - reducer_test.cpp - remove_block_test.cpp - remove_function_test.cpp - remove_selection_test.cpp - remove_unreferenced_instruction_test.cpp - structured_loop_to_selection_test.cpp - validation_during_reduction_test.cpp - conditional_branch_to_simple_conditional_branch_test.cpp - simple_conditional_branch_to_branch_test.cpp - LIBS SPIRV-Tools-reduce - ) - diff --git a/3rdparty/spirv-tools/test/reduce/conditional_branch_to_simple_conditional_branch_test.cpp b/3rdparty/spirv-tools/test/reduce/conditional_branch_to_simple_conditional_branch_test.cpp deleted file mode 100644 index 69ef1f48b..000000000 --- a/3rdparty/spirv-tools/test/reduce/conditional_branch_to_simple_conditional_branch_test.cpp +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "source/reduce/reduction_pass.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3; - -TEST(ConditionalBranchToSimpleConditionalBranchTest, Diamond) { - // A test with the following structure. - // - // selection header - // OpBranchConditional - // | | - // b b - // | | - // selection merge - // - // There should be two opportunities for redirecting the OpBranchConditional - // targets: redirecting the true to false, and vice-versa. E.g. false to true: - // - // selection header - // OpBranchConditional - // || - // b b - // | | - // selection merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %8 %12 %13 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - - )"; - - auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(2, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[0]->TryToApply(); - // The other opportunity should now be disabled. - ASSERT_FALSE(ops[1]->PreconditionHolds()); - - CheckValid(kEnv, context.get()); - - { - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %8 %12 %12 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - } - - ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); - - // Start again, and apply the other op. - context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(2, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - // The other opportunity should now be disabled. - ASSERT_FALSE(ops[0]->PreconditionHolds()); - - CheckValid(kEnv, context.get()); - - { - std::string after2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %8 %13 %13 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after2, context.get()); - } -} - -TEST(ConditionalBranchToSimpleConditionalBranchTest, AlreadySimplified) { - // A test with the following structure. - // - // selection header - // OpBranchConditional - // || - // b b - // | | - // selection merge - // - // There should be no opportunities for redirecting the OpBranchConditional - // as it is already simplified. - // - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %8 %12 %12 - %12 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - - )"; - - auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(0, ops.size()); -} - -TEST(ConditionalBranchToSimpleConditionalBranchTest, DontRemoveBackEdge) { - // A test with the following structure. The loop has a continue construct that - // ends with OpBranchConditional. The OpBranchConditional can be simplified, - // but only to point to the loop header, otherwise we have removed the - // back-edge. Thus, there should be one opportunity instead of two. - // - // loop header - // | - // loop continue target and back-edge block - // OpBranchConditional - // | | - // loop merge (to loop header^) - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %12 - %12 = OpLabel - OpBranchConditional %8 %11 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto context = - BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %12 - %12 = OpLabel - OpBranchConditional %8 %10 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - - ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(ConditionalBranchToSimpleConditionalBranchTest, - DontRemoveBackEdgeCombinedHeaderContinue) { - // A test with the following structure. - // - // loop header and continue target and back-edge block - // OpBranchConditional - // | | - // loop merge (to loop header^) - // - // The OpBranchConditional-to-header edge must not be removed, so there should - // only be one opportunity. It should change both targets to be to the loop - // header. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %10 None - OpBranchConditional %8 %11 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto context = - BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %10 None - OpBranchConditional %8 %10 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - - ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(ConditionalBranchToSimpleConditionalBranchTest, BackEdgeUnreachable) { - // A test with the following structure. I.e. a loop with an unreachable - // continue construct that ends with OpBranchConditional. - // - // loop header - // | - // | loop continue target (unreachable) - // | | - // | back-edge block (unreachable) - // | OpBranchConditional - // | | | - // loop merge (to loop header^) - // - // The branch to the loop header must not be removed, even though the continue - // construct is unreachable. So there should only be one opportunity to make - // the true and false targets of the OpBranchConditional to point to the loop - // header. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %11 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranchConditional %8 %11 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto context = - BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %11 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranchConditional %8 %10 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - - ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/merge_blocks_test.cpp b/3rdparty/spirv-tools/test/reduce/merge_blocks_test.cpp deleted file mode 100644 index dfb614ef5..000000000 --- a/3rdparty/spirv-tools/test/reduce/merge_blocks_test.cpp +++ /dev/null @@ -1,652 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/reduce/merge_blocks_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(MergeBlocksReductionPassTest, BasicCheck) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %13 - %13 = OpLabel - OpStore %8 %9 - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpBranch %15 - %15 = OpLabel - OpStore %8 %11 - OpBranch %16 - %16 = OpLabel - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(5, ops.size()); - - // Try order 3, 0, 2, 4, 1 - - ASSERT_TRUE(ops[3]->PreconditionHolds()); - ops[3]->TryToApply(); - - std::string after_op_3 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %13 - %13 = OpLabel - OpStore %8 %9 - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpBranch %15 - %15 = OpLabel - OpStore %8 %11 - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_3, context.get()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpBranch %15 - %15 = OpLabel - OpStore %8 %11 - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[2]->PreconditionHolds()); - ops[2]->TryToApply(); - - std::string after_op_2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpStore %8 %11 - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_2, context.get()); - - ASSERT_TRUE(ops[4]->PreconditionHolds()); - ops[4]->TryToApply(); - - std::string after_op_4 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpStore %8 %11 - OpStore %8 %12 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_4, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpStore %8 %10 - OpStore %8 %11 - OpStore %8 %12 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_1, context.get()); -} - -TEST(MergeBlocksReductionPassTest, Loops) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "i" - OpName %29 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %11 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %29 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %45 - %45 = OpLabel - OpStore %10 %11 - OpBranch %12 - %12 = OpLabel - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - %17 = OpLoad %6 %10 - OpBranch %46 - %46 = OpLabel - %20 = OpSLessThan %19 %17 %18 - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %21 = OpLoad %6 %10 - OpBranch %47 - %47 = OpLabel - %22 = OpLoad %6 %8 - %23 = OpIAdd %6 %22 %21 - OpStore %8 %23 - %24 = OpLoad %6 %10 - %25 = OpLoad %6 %8 - %26 = OpIAdd %6 %25 %24 - OpStore %8 %26 - OpBranch %48 - %48 = OpLabel - OpBranch %15 - %15 = OpLabel - %27 = OpLoad %6 %10 - %28 = OpIAdd %6 %27 %9 - OpStore %10 %28 - OpBranch %12 - %14 = OpLabel - OpStore %29 %11 - OpBranch %49 - %49 = OpLabel - OpBranch %30 - %30 = OpLabel - OpLoopMerge %32 %33 None - OpBranch %34 - %34 = OpLabel - %35 = OpLoad %6 %29 - %36 = OpSLessThan %19 %35 %18 - OpBranch %50 - %50 = OpLabel - OpBranchConditional %36 %31 %32 - %31 = OpLabel - %37 = OpLoad %6 %29 - %38 = OpLoad %6 %8 - %39 = OpIAdd %6 %38 %37 - OpStore %8 %39 - %40 = OpLoad %6 %29 - %41 = OpLoad %6 %8 - %42 = OpIAdd %6 %41 %40 - OpStore %8 %42 - OpBranch %33 - %33 = OpLabel - %43 = OpLoad %6 %29 - %44 = OpIAdd %6 %43 %9 - OpBranch %51 - %51 = OpLabel - OpStore %29 %44 - OpBranch %30 - %32 = OpLabel - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(11, ops.size()); - - for (auto& ri : ops) { - ASSERT_TRUE(ri->PreconditionHolds()); - ri->TryToApply(); - } - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "i" - OpName %29 "i" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %11 = OpConstant %6 0 - %18 = OpConstant %6 10 - %19 = OpTypeBool - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %29 = OpVariable %7 Function - OpStore %8 %9 - OpStore %10 %11 - OpBranch %12 - %12 = OpLabel - %17 = OpLoad %6 %10 - %20 = OpSLessThan %19 %17 %18 - OpLoopMerge %14 %13 None - OpBranchConditional %20 %13 %14 - %13 = OpLabel - %21 = OpLoad %6 %10 - %22 = OpLoad %6 %8 - %23 = OpIAdd %6 %22 %21 - OpStore %8 %23 - %24 = OpLoad %6 %10 - %25 = OpLoad %6 %8 - %26 = OpIAdd %6 %25 %24 - OpStore %8 %26 - %27 = OpLoad %6 %10 - %28 = OpIAdd %6 %27 %9 - OpStore %10 %28 - OpBranch %12 - %14 = OpLabel - OpStore %29 %11 - OpBranch %30 - %30 = OpLabel - %35 = OpLoad %6 %29 - %36 = OpSLessThan %19 %35 %18 - OpLoopMerge %32 %31 None - OpBranchConditional %36 %31 %32 - %31 = OpLabel - %37 = OpLoad %6 %29 - %38 = OpLoad %6 %8 - %39 = OpIAdd %6 %38 %37 - OpStore %8 %39 - %40 = OpLoad %6 %29 - %41 = OpLoad %6 %8 - %42 = OpIAdd %6 %41 %40 - OpStore %8 %42 - %43 = OpLoad %6 %29 - %44 = OpIAdd %6 %43 %9 - OpStore %29 %44 - OpBranch %30 - %32 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after, context.get()); -} - -TEST(MergeBlocksReductionPassTest, MergeWithOpPhi) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpBranch %12 - %12 = OpLabel - %13 = OpPhi %6 %11 %5 - OpStore %10 %13 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - OpName %10 "y" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - OpStore %10 %11 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after, context.get()); -} - -void MergeBlocksReductionPassTest_LoopReturn_Helper(bool reverse) { - // A merge block opportunity stores a block that can be merged with its - // predecessor. - // Given blocks A -> B -> C: - // This test demonstrates how merging B->C can invalidate - // the opportunity of merging A->B, and vice-versa. E.g. - // B->C are merged: B is now terminated with OpReturn. - // A->B can now no longer be merged because A is a loop header, which - // cannot be terminated with OpReturn. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantFalse %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel ; A (loop header) - OpLoopMerge %13 %12 None - OpBranch %11 - %12 = OpLabel ; (unreachable continue block) - OpBranch %10 - %11 = OpLabel ; B - OpBranch %15 - %15 = OpLabel ; C - OpReturn - %13 = OpLabel ; (unreachable merge block) - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - ASSERT_NE(context.get(), nullptr); - auto opportunities = - MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - // A->B and B->C - ASSERT_EQ(opportunities.size(), 2); - - // Test applying opportunities in both orders. - if (reverse) { - std::reverse(opportunities.begin(), opportunities.end()); - } - - size_t num_applied = 0; - for (auto& ri : opportunities) { - if (ri->PreconditionHolds()) { - ri->TryToApply(); - ++num_applied; - } - } - - // Only 1 opportunity can be applied, as both disable each other. - ASSERT_EQ(num_applied, 1); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantFalse %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel ; A-B (loop header) - OpLoopMerge %13 %12 None - OpBranch %15 - %12 = OpLabel ; (unreachable continue block) - OpBranch %10 - %15 = OpLabel ; C - OpReturn - %13 = OpLabel ; (unreachable merge block) - OpReturn - OpFunctionEnd - )"; - - // The only difference is the labels. - std::string after_reversed = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantFalse %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel ; A (loop header) - OpLoopMerge %13 %12 None - OpBranch %11 - %12 = OpLabel ; (unreachable continue block) - OpBranch %10 - %11 = OpLabel ; B-C - OpReturn - %13 = OpLabel ; (unreachable merge block) - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, reverse ? after_reversed : after, context.get()); -} - -TEST(MergeBlocksReductionPassTest, LoopReturn) { - MergeBlocksReductionPassTest_LoopReturn_Helper(false); -} - -TEST(MergeBlocksReductionPassTest, LoopReturnReverse) { - MergeBlocksReductionPassTest_LoopReturn_Helper(true); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/operand_to_constant_test.cpp b/3rdparty/spirv-tools/test/reduce/operand_to_constant_test.cpp deleted file mode 100644 index b2f67ee11..000000000 --- a/3rdparty/spirv-tools/test/reduce/operand_to_constant_test.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/reduce/operand_to_const_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(OperandToConstantReductionPassTest, BasicCheck) { - std::string prologue = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %37 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "buf1" - OpMemberName %9 0 "f" - OpName %11 "" - OpName %24 "buf2" - OpMemberName %24 0 "i" - OpName %26 "" - OpName %37 "_GLF_color" - OpMemberDecorate %9 0 Offset 0 - OpDecorate %9 Block - OpDecorate %11 DescriptorSet 0 - OpDecorate %11 Binding 1 - OpMemberDecorate %24 0 Offset 0 - OpDecorate %24 Block - OpDecorate %26 DescriptorSet 0 - OpDecorate %26 Binding 2 - OpDecorate %37 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %9 = OpTypeStruct %6 - %10 = OpTypePointer Uniform %9 - %11 = OpVariable %10 Uniform - %12 = OpTypeInt 32 1 - %13 = OpConstant %12 0 - %14 = OpTypePointer Uniform %6 - %20 = OpConstant %6 2 - %24 = OpTypeStruct %12 - %25 = OpTypePointer Uniform %24 - %26 = OpVariable %25 Uniform - %27 = OpTypePointer Uniform %12 - %33 = OpConstant %12 3 - %35 = OpTypeVector %6 4 - %36 = OpTypePointer Output %35 - %37 = OpVariable %36 Output - %4 = OpFunction %2 None %3 - %5 = OpLabel - %15 = OpAccessChain %14 %11 %13 - %16 = OpLoad %6 %15 - %19 = OpFAdd %6 %16 %16 - %21 = OpFAdd %6 %19 %20 - %28 = OpAccessChain %27 %26 %13 - %29 = OpLoad %12 %28 - )"; - - std::string epilogue = R"( - %45 = OpConvertSToF %6 %34 - %46 = OpCompositeConstruct %35 %16 %21 %43 %45 - OpStore %37 %46 - OpReturn - OpFunctionEnd - )"; - - std::string original = prologue + R"( - %32 = OpIAdd %12 %29 %29 - %34 = OpIAdd %12 %32 %33 - %43 = OpConvertSToF %6 %29 - )" + epilogue; - - std::string expected = prologue + R"( - %32 = OpIAdd %12 %13 %13 ; %29 -> %13 x 2 - %34 = OpIAdd %12 %13 %33 ; %32 -> %13 - %43 = OpConvertSToF %6 %13 ; %29 -> %13 - )" + epilogue; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, original, kReduceAssembleOption); - const auto ops = - OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(17, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - ASSERT_TRUE(ops[2]->PreconditionHolds()); - ops[2]->TryToApply(); - ASSERT_TRUE(ops[3]->PreconditionHolds()); - ops[3]->TryToApply(); - - CheckEqual(env, expected, context.get()); -} - -TEST(OperandToConstantReductionPassTest, WithCalledFunction) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %10 %12 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeFunction %7 - %9 = OpTypePointer Output %7 - %10 = OpVariable %9 Output - %11 = OpTypePointer Input %7 - %12 = OpVariable %11 Input - %13 = OpConstant %6 0 - %14 = OpConstantComposite %7 %13 %13 %13 %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %15 = OpFunctionCall %7 %16 - OpReturn - OpFunctionEnd - %16 = OpFunction %7 None %8 - %17 = OpLabel - OpReturnValue %14 - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/operand_to_dominating_id_test.cpp b/3rdparty/spirv-tools/test/reduce/operand_to_dominating_id_test.cpp deleted file mode 100644 index cd5b2c689..000000000 --- a/3rdparty/spirv-tools/test/reduce/operand_to_dominating_id_test.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2018 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 "source/reduce/operand_to_dominating_id_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(OperandToDominatingIdReductionPassTest, BasicCheck) { - std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - %12 = OpLoad %6 %8 - %13 = OpIAdd %6 %11 %12 - OpStore %10 %13 - %15 = OpLoad %6 %10 - OpStore %14 %15 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, original, kReduceAssembleOption); - const auto ops = OperandToDominatingIdReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(10, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - %12 = OpLoad %6 %8 - %13 = OpIAdd %6 %11 %12 - OpStore %8 %13 ; %10 -> %8 - %15 = OpLoad %6 %10 - OpStore %14 %15 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - %12 = OpLoad %6 %8 - %13 = OpIAdd %6 %11 %12 - OpStore %8 %13 ; %10 -> %8 - %15 = OpLoad %6 %8 ; %10 -> %8 - OpStore %14 %15 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_1, context.get()); - - ASSERT_TRUE(ops[2]->PreconditionHolds()); - ops[2]->TryToApply(); - - std::string after_op_2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - %12 = OpLoad %6 %8 - %13 = OpIAdd %6 %11 %12 - OpStore %8 %13 ; %10 -> %8 - %15 = OpLoad %6 %8 ; %10 -> %8 - OpStore %8 %15 ; %14 -> %8 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_2, context.get()); - - // The precondition has been disabled by an earlier opportunity's application. - ASSERT_FALSE(ops[3]->PreconditionHolds()); - - ASSERT_TRUE(ops[4]->PreconditionHolds()); - ops[4]->TryToApply(); - - std::string after_op_4 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %8 %9 - %11 = OpLoad %6 %8 - %12 = OpLoad %6 %8 - %13 = OpIAdd %6 %11 %11 ; %12 -> %11 - OpStore %8 %13 ; %10 -> %8 - %15 = OpLoad %6 %8 ; %10 -> %8 - OpStore %8 %15 ; %14 -> %8 - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_4, context.get()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/operand_to_undef_test.cpp b/3rdparty/spirv-tools/test/reduce/operand_to_undef_test.cpp deleted file mode 100644 index fa64bd53d..000000000 --- a/3rdparty/spirv-tools/test/reduce/operand_to_undef_test.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/reduce/operand_to_undef_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(OperandToUndefReductionPassTest, BasicCheck) { - // The following shader has 10 opportunities for replacing with undef. - - // #version 310 es - // - // precision highp float; - // - // layout(location=0) out vec4 _GLF_color; - // - // layout(set = 0, binding = 0) uniform buf0 { - // vec2 uniform1; - // }; - // - // void main() - // { - // _GLF_color = - // vec4( // opportunity - // uniform1.x / 2.0, // opportunity x2 (2.0 is const) - // uniform1.y / uniform1.x, // opportunity x3 - // uniform1.x + uniform1.x, // opportunity x3 - // uniform1.y); // opportunity - // } - - std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "_GLF_color" - OpName %11 "buf0" - OpMemberName %11 0 "uniform1" - OpName %13 "" - OpDecorate %9 Location 0 - OpMemberDecorate %11 0 Offset 0 - OpDecorate %11 Block - OpDecorate %13 DescriptorSet 0 - OpDecorate %13 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Output %7 - %9 = OpVariable %8 Output - %10 = OpTypeVector %6 2 - %11 = OpTypeStruct %10 - %12 = OpTypePointer Uniform %11 - %13 = OpVariable %12 Uniform - %14 = OpTypeInt 32 1 - %15 = OpConstant %14 0 - %16 = OpTypeInt 32 0 - %17 = OpConstant %16 0 - %18 = OpTypePointer Uniform %6 - %21 = OpConstant %6 2 - %23 = OpConstant %16 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %19 = OpAccessChain %18 %13 %15 %17 - %20 = OpLoad %6 %19 - %22 = OpFDiv %6 %20 %21 ; opportunity %20 (%21 is const) - %24 = OpAccessChain %18 %13 %15 %23 - %25 = OpLoad %6 %24 - %26 = OpAccessChain %18 %13 %15 %17 - %27 = OpLoad %6 %26 - %28 = OpFDiv %6 %25 %27 ; opportunity %25 %27 - %29 = OpAccessChain %18 %13 %15 %17 - %30 = OpLoad %6 %29 - %31 = OpAccessChain %18 %13 %15 %17 - %32 = OpLoad %6 %31 - %33 = OpFAdd %6 %30 %32 ; opportunity %30 %32 - %34 = OpAccessChain %18 %13 %15 %23 - %35 = OpLoad %6 %34 - %36 = OpCompositeConstruct %7 %22 %28 %33 %35 ; opportunity %22 %28 %33 %35 - OpStore %9 %36 ; opportunity %36 - OpReturn - OpFunctionEnd - )"; - - // This is the same as original, except where noted. - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "_GLF_color" - OpName %11 "buf0" - OpMemberName %11 0 "uniform1" - OpName %13 "" - OpDecorate %9 Location 0 - OpMemberDecorate %11 0 Offset 0 - OpDecorate %11 Block - OpDecorate %13 DescriptorSet 0 - OpDecorate %13 Binding 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Output %7 - %9 = OpVariable %8 Output - %10 = OpTypeVector %6 2 - %11 = OpTypeStruct %10 - %12 = OpTypePointer Uniform %11 - %13 = OpVariable %12 Uniform - %14 = OpTypeInt 32 1 - %15 = OpConstant %14 0 - %16 = OpTypeInt 32 0 - %17 = OpConstant %16 0 - %18 = OpTypePointer Uniform %6 - %21 = OpConstant %6 2 - %23 = OpConstant %16 1 - %37 = OpUndef %6 ; Added undef float as %37 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %19 = OpAccessChain %18 %13 %15 %17 - %20 = OpLoad %6 %19 - %22 = OpFDiv %6 %37 %21 ; Replaced with %37 - %24 = OpAccessChain %18 %13 %15 %23 - %25 = OpLoad %6 %24 - %26 = OpAccessChain %18 %13 %15 %17 - %27 = OpLoad %6 %26 - %28 = OpFDiv %6 %37 %37 ; Replaced with %37 twice - %29 = OpAccessChain %18 %13 %15 %17 - %30 = OpLoad %6 %29 - %31 = OpAccessChain %18 %13 %15 %17 - %32 = OpLoad %6 %31 - %33 = OpFAdd %6 %30 %32 - %34 = OpAccessChain %18 %13 %15 %23 - %35 = OpLoad %6 %34 - %36 = OpCompositeConstruct %7 %22 %28 %33 %35 - OpStore %9 %36 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, original, kReduceAssembleOption); - const auto ops = - OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(10, ops.size()); - - // Apply first three opportunities. - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - ASSERT_TRUE(ops[2]->PreconditionHolds()); - ops[2]->TryToApply(); - - CheckEqual(env, expected, context.get()); -} - -TEST(OperandToUndefReductionPassTest, WithCalledFunction) { - // The following shader has no opportunities. - // Most importantly, the noted function operand is not changed. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %10 %12 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypeFunction %7 - %9 = OpTypePointer Output %7 - %10 = OpVariable %9 Output - %11 = OpTypePointer Input %7 - %12 = OpVariable %11 Input - %13 = OpConstant %6 0 - %14 = OpConstantComposite %7 %13 %13 %13 %13 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %15 = OpFunctionCall %7 %16 ; do not replace %16 with undef - OpReturn - OpFunctionEnd - %16 = OpFunction %7 None %8 - %17 = OpLabel - OpReturnValue %14 - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/reduce_test_util.cpp b/3rdparty/spirv-tools/test/reduce/reduce_test_util.cpp deleted file mode 100644 index 0c2341112..000000000 --- a/3rdparty/spirv-tools/test/reduce/reduce_test_util.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "test/reduce/reduce_test_util.h" - -#include - -#include "tools/io.h" - -namespace spvtools { -namespace reduce { - -void CheckEqual(const spv_target_env env, - const std::vector& expected_binary, - const std::vector& actual_binary) { - if (expected_binary != actual_binary) { - SpirvTools t(env); - std::string expected_disassembled; - std::string actual_disassembled; - ASSERT_TRUE(t.Disassemble(expected_binary, &expected_disassembled, - kReduceDisassembleOption)); - ASSERT_TRUE(t.Disassemble(actual_binary, &actual_disassembled, - kReduceDisassembleOption)); - ASSERT_EQ(expected_disassembled, actual_disassembled); - } -} - -void CheckEqual(const spv_target_env env, const std::string& expected_text, - const std::vector& actual_binary) { - std::vector expected_binary; - SpirvTools t(env); - ASSERT_TRUE( - t.Assemble(expected_text, &expected_binary, kReduceAssembleOption)); - CheckEqual(env, expected_binary, actual_binary); -} - -void CheckEqual(const spv_target_env env, const std::string& expected_text, - const opt::IRContext* actual_ir) { - std::vector actual_binary; - actual_ir->module()->ToBinary(&actual_binary, false); - CheckEqual(env, expected_text, actual_binary); -} - -void CheckValid(spv_target_env env, const opt::IRContext* ir) { - std::vector binary; - ir->module()->ToBinary(&binary, false); - SpirvTools t(env); - ASSERT_TRUE(t.Validate(binary)); -} - -std::string ToString(spv_target_env env, const opt::IRContext* ir) { - std::vector binary; - ir->module()->ToBinary(&binary, false); - SpirvTools t(env); - std::string result; - t.Disassemble(binary, &result, kReduceDisassembleOption); - return result; -} - -void NopDiagnostic(spv_message_level_t /*level*/, const char* /*source*/, - const spv_position_t& /*position*/, - const char* /*message*/) {} - -void CLIMessageConsumer(spv_message_level_t level, const char*, - const spv_position_t& position, const char* message) { - switch (level) { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - std::cerr << "error: line " << position.index << ": " << message - << std::endl; - break; - case SPV_MSG_WARNING: - std::cout << "warning: line " << position.index << ": " << message - << std::endl; - break; - case SPV_MSG_INFO: - std::cout << "info: line " << position.index << ": " << message - << std::endl; - break; - default: - break; - } -} - -void DumpShader(opt::IRContext* context, const char* filename) { - std::vector binary; - context->module()->ToBinary(&binary, false); - DumpShader(binary, filename); -} - -void DumpShader(const std::vector& binary, const char* filename) { - auto write_file_succeeded = - WriteFile(filename, "wb", &binary[0], binary.size()); - if (!write_file_succeeded) { - std::cerr << "Failed to dump shader" << std::endl; - } -} - -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/reduce_test_util.h b/3rdparty/spirv-tools/test/reduce/reduce_test_util.h deleted file mode 100644 index b9ad12f4c..000000000 --- a/3rdparty/spirv-tools/test/reduce/reduce_test_util.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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. - -#ifndef TEST_REDUCE_REDUCE_TEST_UTIL_H_ -#define TEST_REDUCE_REDUCE_TEST_UTIL_H_ - -#include "gtest/gtest.h" -#include "source/opt/ir_context.h" -#include "source/reduce/reduction_opportunity.h" -#include "spirv-tools/libspirv.h" - -namespace spvtools { -namespace reduce { - -// Checks whether the given binaries are bit-wise equal. -void CheckEqual(spv_target_env env, - const std::vector& expected_binary, - const std::vector& actual_binary); - -// Assembles the given text and check whether the resulting binary is bit-wise -// equal to the given binary. -void CheckEqual(spv_target_env env, const std::string& expected_text, - const std::vector& actual_binary); - -// Assembles the given text and turns the given IR into binary, then checks -// whether the resulting binaries are bit-wise equal. -void CheckEqual(spv_target_env env, const std::string& expected_text, - const opt::IRContext* actual_ir); - -// Assembles the given IR context and checks whether the resulting binary is -// valid. -void CheckValid(spv_target_env env, const opt::IRContext* ir); - -// Assembles the given IR context, then returns its disassembly as a string. -// Useful for debugging. -std::string ToString(spv_target_env env, const opt::IRContext* ir); - -// Assembly options for writing reduction tests. It simplifies matters if -// numeric ids do not change. -const uint32_t kReduceAssembleOption = - SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS; -// Disassembly options for writing reduction tests. -const uint32_t kReduceDisassembleOption = - SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | SPV_BINARY_TO_TEXT_OPTION_INDENT; - -// Don't print reducer info during testing. -void NopDiagnostic(spv_message_level_t /*level*/, const char* /*source*/, - const spv_position_t& /*position*/, const char* /*message*/); - -// Prints reducer messages (for debugging). -void CLIMessageConsumer(spv_message_level_t level, const char*, - const spv_position_t& position, const char* message); - -// Dumps the SPIRV-V module in |context| to file |filename|. Useful for -// interactive debugging. -void DumpShader(opt::IRContext* context, const char* filename); - -// Dumps |binary| to file |filename|. Useful for interactive debugging. -void DumpShader(const std::vector& binary, const char* filename); - -} // namespace reduce -} // namespace spvtools - -#endif // TEST_REDUCE_REDUCE_TEST_UTIL_H_ diff --git a/3rdparty/spirv-tools/test/reduce/reducer_test.cpp b/3rdparty/spirv-tools/test/reduce/reducer_test.cpp deleted file mode 100644 index 59f280369..000000000 --- a/3rdparty/spirv-tools/test/reduce/reducer_test.cpp +++ /dev/null @@ -1,441 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/reduce/reducer.h" - -#include "source/opt/build_module.h" -#include "source/reduce/operand_to_const_reduction_opportunity_finder.h" -#include "source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -using opt::BasicBlock; -using opt::IRContext; - -const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3; -const MessageConsumer kMessageConsumer = CLIMessageConsumer; - -// This changes its mind each time IsInteresting is invoked as to whether the -// binary is interesting, until some limit is reached after which the binary is -// always deemed interesting. This is useful to test that reduction passes -// interleave in interesting ways for a while, and then always succeed after -// some point; the latter is important to end up with a predictable final -// reduced binary for tests. -class PingPongInteresting { - public: - explicit PingPongInteresting(uint32_t always_interesting_after) - : is_interesting_(true), - always_interesting_after_(always_interesting_after), - count_(0) {} - - bool IsInteresting(const std::vector&) { - bool result; - if (count_ > always_interesting_after_) { - result = true; - } else { - result = is_interesting_; - is_interesting_ = !is_interesting_; - } - count_++; - return result; - } - - private: - bool is_interesting_; - const uint32_t always_interesting_after_; - uint32_t count_; -}; - -TEST(ReducerTest, ExprToConstantAndRemoveUnreferenced) { - // Check that ExprToConstant and RemoveUnreferenced work together; once some - // ID uses have been changed to constants, those IDs can be removed. - std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %60 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %16 "buf2" - OpMemberName %16 0 "i" - OpName %18 "" - OpName %25 "buf1" - OpMemberName %25 0 "f" - OpName %27 "" - OpName %60 "_GLF_color" - OpMemberDecorate %16 0 Offset 0 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 2 - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 1 - OpDecorate %60 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpTypeStruct %6 - %17 = OpTypePointer Uniform %16 - %18 = OpVariable %17 Uniform - %19 = OpTypePointer Uniform %6 - %22 = OpTypeBool - %100 = OpConstantTrue %22 - %24 = OpTypeFloat 32 - %25 = OpTypeStruct %24 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %28 = OpTypePointer Uniform %24 - %31 = OpConstant %24 2 - %56 = OpConstant %6 1 - %58 = OpTypeVector %24 4 - %59 = OpTypePointer Output %58 - %60 = OpVariable %59 Output - %72 = OpUndef %24 - %74 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %73 = OpPhi %6 %74 %5 %77 %34 - %71 = OpPhi %24 %72 %5 %76 %34 - %70 = OpPhi %6 %9 %5 %57 %34 - %20 = OpAccessChain %19 %18 %9 - %21 = OpLoad %6 %20 - %23 = OpSLessThan %22 %70 %21 - OpLoopMerge %12 %34 None - OpBranchConditional %23 %11 %12 - %11 = OpLabel - %29 = OpAccessChain %28 %27 %9 - %30 = OpLoad %24 %29 - %32 = OpFOrdGreaterThan %22 %30 %31 - OpSelectionMerge %90 None - OpBranchConditional %32 %33 %46 - %33 = OpLabel - %40 = OpFAdd %24 %71 %30 - %45 = OpISub %6 %73 %21 - OpBranch %90 - %46 = OpLabel - %50 = OpFMul %24 %71 %30 - %54 = OpSDiv %6 %73 %21 - OpBranch %90 - %90 = OpLabel - %77 = OpPhi %6 %45 %33 %54 %46 - %76 = OpPhi %24 %40 %33 %50 %46 - OpBranch %34 - %34 = OpLabel - %57 = OpIAdd %6 %70 %56 - OpBranch %10 - %12 = OpLabel - %61 = OpAccessChain %28 %27 %9 - %62 = OpLoad %24 %61 - %66 = OpConvertSToF %24 %21 - %68 = OpConvertSToF %24 %73 - %69 = OpCompositeConstruct %58 %62 %71 %66 %68 - OpStore %60 %69 - OpReturn - OpFunctionEnd - )"; - - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %60 - OpExecutionMode %4 OriginUpperLeft - OpMemberDecorate %16 0 Offset 0 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 2 - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 1 - OpDecorate %60 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpTypeStruct %6 - %17 = OpTypePointer Uniform %16 - %18 = OpVariable %17 Uniform - %22 = OpTypeBool - %100 = OpConstantTrue %22 - %24 = OpTypeFloat 32 - %25 = OpTypeStruct %24 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %31 = OpConstant %24 2 - %56 = OpConstant %6 1 - %58 = OpTypeVector %24 4 - %59 = OpTypePointer Output %58 - %60 = OpVariable %59 Output - %72 = OpUndef %24 - %74 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %34 None - OpBranchConditional %100 %11 %12 - %11 = OpLabel - OpSelectionMerge %90 None - OpBranchConditional %100 %33 %46 - %33 = OpLabel - OpBranch %90 - %46 = OpLabel - OpBranch %90 - %90 = OpLabel - OpBranch %34 - %34 = OpLabel - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - Reducer reducer(kEnv); - PingPongInteresting ping_pong_interesting(10); - reducer.SetMessageConsumer(NopDiagnostic); - reducer.SetInterestingnessFunction( - [&](const std::vector& binary, uint32_t) -> bool { - return ping_pong_interesting.IsInteresting(binary); - }); - reducer.AddReductionPass( - MakeUnique( - false)); - reducer.AddReductionPass( - MakeUnique()); - - std::vector binary_in; - SpirvTools t(kEnv); - - ASSERT_TRUE(t.Assemble(original, &binary_in, kReduceAssembleOption)); - std::vector binary_out; - spvtools::ReducerOptions reducer_options; - reducer_options.set_step_limit(500); - reducer_options.set_fail_on_validation_error(true); - spvtools::ValidatorOptions validator_options; - - Reducer::ReductionResultStatus status = reducer.Run( - std::move(binary_in), &binary_out, reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete); - - CheckEqual(kEnv, expected, binary_out); -} - -bool InterestingWhileOpcodeExists(const std::vector& binary, - uint32_t opcode, uint32_t count, bool dump) { - if (dump) { - std::stringstream ss; - ss << "temp_" << count << ".spv"; - DumpShader(binary, ss.str().c_str()); - } - - std::unique_ptr context = - BuildModule(kEnv, kMessageConsumer, binary.data(), binary.size()); - assert(context); - bool interesting = false; - for (auto& function : *context->module()) { - context->cfg()->ForEachBlockInPostOrder( - &*function.begin(), [opcode, &interesting](BasicBlock* block) -> void { - for (auto& inst : *block) { - if (inst.opcode() == opcode) { - interesting = true; - break; - } - } - }); - if (interesting) { - break; - } - } - return interesting; -} - -bool InterestingWhileIMulReachable(const std::vector& binary, - uint32_t count) { - return InterestingWhileOpcodeExists(binary, SpvOpIMul, count, false); -} - -bool InterestingWhileSDivReachable(const std::vector& binary, - uint32_t count) { - return InterestingWhileOpcodeExists(binary, SpvOpSDiv, count, false); -} - -// The shader below was derived from the following GLSL, and optimized. -// #version 310 es -// precision highp float; -// layout(location = 0) out vec4 _GLF_color; -// int foo() { -// int x = 1; -// int y; -// x = y / x; // SDiv -// return x; -// } -// void main() { -// int c; -// while (bool(c)) { -// do { -// if (bool(c)) { -// if (bool(c)) { -// ++c; -// } else { -// _GLF_color.x = float(c*c); // IMul -// } -// return; -// } -// } while(bool(foo())); -// return; -// } -// } -const std::string kShaderWithLoopsDivAndMul = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %49 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %49 "_GLF_color" - OpDecorate %49 Location 0 - OpDecorate %52 RelaxedPrecision - OpDecorate %77 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %12 = OpConstant %6 1 - %27 = OpTypeBool - %28 = OpTypeInt 32 0 - %29 = OpConstant %28 0 - %46 = OpTypeFloat 32 - %47 = OpTypeVector %46 4 - %48 = OpTypePointer Output %47 - %49 = OpVariable %48 Output - %54 = OpTypePointer Output %46 - %64 = OpConstantFalse %27 - %67 = OpConstantTrue %27 - %81 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %61 - %61 = OpLabel - OpLoopMerge %60 %63 None - OpBranch %20 - %20 = OpLabel - %30 = OpINotEqual %27 %81 %29 - OpLoopMerge %22 %23 None - OpBranchConditional %30 %21 %22 - %21 = OpLabel - OpBranch %31 - %31 = OpLabel - OpLoopMerge %33 %38 None - OpBranch %32 - %32 = OpLabel - OpBranchConditional %30 %37 %38 - %37 = OpLabel - OpSelectionMerge %42 None - OpBranchConditional %30 %41 %45 - %41 = OpLabel - OpBranch %42 - %45 = OpLabel - %52 = OpIMul %6 %81 %81 - %53 = OpConvertSToF %46 %52 - %55 = OpAccessChain %54 %49 %29 - OpStore %55 %53 - OpBranch %42 - %42 = OpLabel - OpBranch %33 - %38 = OpLabel - %77 = OpSDiv %6 %81 %12 - %58 = OpINotEqual %27 %77 %29 - OpBranchConditional %58 %31 %33 - %33 = OpLabel - %86 = OpPhi %27 %67 %42 %64 %38 - OpSelectionMerge %68 None - OpBranchConditional %86 %22 %68 - %68 = OpLabel - OpBranch %22 - %23 = OpLabel - OpBranch %20 - %22 = OpLabel - %90 = OpPhi %27 %64 %20 %86 %33 %67 %68 - OpSelectionMerge %70 None - OpBranchConditional %90 %60 %70 - %70 = OpLabel - OpBranch %60 - %63 = OpLabel - OpBranch %61 - %60 = OpLabel - OpReturn - OpFunctionEnd - )"; - -TEST(ReducerTest, ShaderReduceWhileMulReachable) { - Reducer reducer(kEnv); - - reducer.SetInterestingnessFunction(InterestingWhileIMulReachable); - reducer.AddDefaultReductionPasses(); - reducer.SetMessageConsumer(kMessageConsumer); - - std::vector binary_in; - SpirvTools t(kEnv); - - ASSERT_TRUE( - t.Assemble(kShaderWithLoopsDivAndMul, &binary_in, kReduceAssembleOption)); - std::vector binary_out; - spvtools::ReducerOptions reducer_options; - reducer_options.set_step_limit(500); - reducer_options.set_fail_on_validation_error(true); - spvtools::ValidatorOptions validator_options; - - Reducer::ReductionResultStatus status = reducer.Run( - std::move(binary_in), &binary_out, reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete); -} - -TEST(ReducerTest, ShaderReduceWhileDivReachable) { - Reducer reducer(kEnv); - - reducer.SetInterestingnessFunction(InterestingWhileSDivReachable); - reducer.AddDefaultReductionPasses(); - reducer.SetMessageConsumer(kMessageConsumer); - - std::vector binary_in; - SpirvTools t(kEnv); - - ASSERT_TRUE( - t.Assemble(kShaderWithLoopsDivAndMul, &binary_in, kReduceAssembleOption)); - std::vector binary_out; - spvtools::ReducerOptions reducer_options; - reducer_options.set_step_limit(500); - reducer_options.set_fail_on_validation_error(true); - spvtools::ValidatorOptions validator_options; - - Reducer::ReductionResultStatus status = reducer.Run( - std::move(binary_in), &binary_out, reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/remove_block_test.cpp b/3rdparty/spirv-tools/test/reduce/remove_block_test.cpp deleted file mode 100644 index f31cc9da3..000000000 --- a/3rdparty/spirv-tools/test/reduce/remove_block_test.cpp +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/reduce/remove_block_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(RemoveBlockReductionPassTest, BasicCheck) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %14 - %13 = OpLabel ; unreachable - OpStore %8 %9 - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpBranch %16 - %15 = OpLabel ; unreachable - OpStore %8 %11 - OpBranch %16 - %16 = OpLabel - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(2, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpBranch %16 - %15 = OpLabel - OpStore %8 %11 - OpBranch %16 - %16 = OpLabel - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %8 "x" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 1 - %10 = OpConstant %6 2 - %11 = OpConstant %6 3 - %12 = OpConstant %6 4 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpBranch %14 - %14 = OpLabel - OpStore %8 %10 - OpBranch %16 - %16 = OpLabel - OpStore %8 %12 - OpBranch %17 - %17 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_1, context.get()); -} - -TEST(RemoveBlockReductionPassTest, UnreachableContinueAndMerge) { - // Loop with unreachable merge and continue target. There should be no - // opportunities. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %13 - %13 = OpLabel - OpLoopMerge %16 %15 None - OpBranch %14 - %14 = OpLabel - OpReturn - %15 = OpLabel - OpBranch %13 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveBlockReductionPassTest, OneBlock) { - // Function with just one block. There should be no opportunities. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveBlockReductionPassTest, UnreachableBlocksWithOutsideIdUses) { - // A function with two unreachable blocks A -> B. A defines ID %9 and B uses - // %9. There are no references to A, but removing A would be invalid because - // of B's use of %9, so there should be no opportunities. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeInt 32 1 - %5 = OpTypeFunction %3 - %6 = OpConstant %4 1 - %2 = OpFunction %3 None %5 - %7 = OpLabel - OpReturn - %8 = OpLabel ; A - %9 = OpUndef %4 - OpBranch %10 - %10 = OpLabel ; B - %11 = OpIAdd %4 %6 %9 ; uses %9 from A, so A cannot be removed - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - const auto ops = - RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveBlockReductionPassTest, UnreachableBlocksWithInsideIdUses) { - // Similar to the above test. - - // A function with two unreachable blocks A -> B. Both blocks create and use - // IDs, but the uses are contained within each block, so A should be removed. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeInt 32 1 - %5 = OpTypeFunction %3 - %6 = OpConstant %4 1 - %2 = OpFunction %3 None %5 - %7 = OpLabel - OpReturn - %8 = OpLabel ; A - %9 = OpUndef %4 ; define %9 - %10 = OpIAdd %4 %6 %9 ; use %9 - OpBranch %11 - %11 = OpLabel ; B - %12 = OpUndef %4 ; define %12 - %13 = OpIAdd %4 %6 %12 ; use %12 - OpReturn - OpFunctionEnd - )"; - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - auto ops = RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - - ops[0]->TryToApply(); - - // Same as above, but block A is removed. - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeInt 32 1 - %5 = OpTypeFunction %3 - %6 = OpConstant %4 1 - %2 = OpFunction %3 None %5 - %7 = OpLabel - OpReturn - %11 = OpLabel - %12 = OpUndef %4 - %13 = OpIAdd %4 %6 %12 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_0, context.get()); - - // Find opportunities again. There are no reference to B. B should now be - // removed. - - ops = RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - - ops[0]->TryToApply(); - - // Same as above, but block B is removed. - std::string after_op_0_again = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeInt 32 1 - %5 = OpTypeFunction %3 - %6 = OpConstant %4 1 - %2 = OpFunction %3 None %5 - %7 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_op_0_again, context.get()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/remove_function_test.cpp b/3rdparty/spirv-tools/test/reduce/remove_function_test.cpp deleted file mode 100644 index 576b60316..000000000 --- a/3rdparty/spirv-tools/test/reduce/remove_function_test.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/reduce/remove_function_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -// Helper to count the number of functions in the module. -// Remove if there turns out to be a more direct way to do this. -uint32_t count_functions(opt::IRContext* context) { - uint32_t result = 0; - for (auto& function : *context->module()) { - (void)(function); - ++result; - } - return result; -} - -TEST(RemoveFunctionTest, BasicCheck) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %10 = OpFunctionCall %2 %6 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - - ASSERT_EQ(3, count_functions(context.get())); - - auto ops = - RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - ASSERT_EQ(2, count_functions(context.get())); - - std::string after_first = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_first, context.get()); - - ops = RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - ASSERT_EQ(1, count_functions(context.get())); - - std::string after_second = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after_second, context.get()); -} - -TEST(RemoveFunctionTest, NothingToRemove) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %11 = OpFunctionCall %2 %8 - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - %10 = OpFunctionCall %2 %6 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - auto ops = - RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveFunctionTest, TwoRemovableFunctions) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - - ASSERT_EQ(3, count_functions(context.get())); - - auto ops = - RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(2, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - ASSERT_EQ(2, count_functions(context.get())); - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - ASSERT_EQ(1, count_functions(context.get())); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(env, after, context.get()); -} - -TEST(RemoveFunctionTest, NoRemovalsDueToOpName) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %6 "foo(" - OpName %8 "bar(" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - %6 = OpFunction %2 None %3 - %7 = OpLabel - OpReturn - OpFunctionEnd - %8 = OpFunction %2 None %3 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - auto ops = - RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveFunctionTest, NoRemovalDueToLinkageDecoration) { - // The non-entry point function is not removable because it is referenced by a - // linkage decoration. Thus no function can be removed. - std::string shader = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpName %1 "main" - OpDecorate %2 LinkageAttributes "ExportedFunc" Export - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %1 = OpFunction %4 None %5 - %6 = OpLabel - OpReturn - OpFunctionEnd - %2 = OpFunction %4 None %5 - %7 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto consumer = nullptr; - const auto context = - BuildModule(env, consumer, shader, kReduceAssembleOption); - auto ops = - RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/remove_selection_test.cpp b/3rdparty/spirv-tools/test/reduce/remove_selection_test.cpp deleted file mode 100644 index f8acd5d45..000000000 --- a/3rdparty/spirv-tools/test/reduce/remove_selection_test.cpp +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/reduce/remove_selection_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlock) { - // A test with the following structure. The OpSelectionMerge instruction - // should be removed. - // - // header - // || - // block - // | - // merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpSelectionMerge %10 None - OpBranchConditional %8 %11 %11 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranchConditional %8 %11 %11 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after, context.get()); - - ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlockMerge) { - // A test with the following structure. The OpSelectionMerge instruction - // should be removed. - // - // header - // || - // merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpSelectionMerge %10 None - OpBranchConditional %8 %10 %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranchConditional %8 %10 %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after, context.get()); - - ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocksOneMerge) { - // A test with the following structure. The OpSelectionMerge instruction - // should NOT be removed. - // - // header - // | | - // | block - // | | - // merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpSelectionMerge %10 None - OpBranchConditional %8 %10 %11 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocks) { - // A test with the following structure. The OpSelectionMerge instruction - // should NOT be removed. - // - // header - // | | - // b b - // | | - // merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpSelectionMerge %10 None - OpBranchConditional %8 %11 %12 - %11 = OpLabel - OpBranch %10 - %12 = OpLabel - OpBranch %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveSelectionTest, NoOpportunityBecauseMergeUsed) { - // A test with the following structure. The OpSelectionMerge instruction - // should NOT be removed. - // - // header - // || - // block - // | | - // | block - // | | - // merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpSelectionMerge %10 None - OpBranchConditional %8 %11 %12 - %11 = OpLabel - OpBranchConditional %8 %10 %12 - %12 = OpLabel - OpBranch %10 - %10 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveSelectionTest, OpportunityBecauseLoopMergeUsed) { - // A test with the following structure. The OpSelectionMerge instruction - // should be removed. - // - // loop header - // | - // | - // s.header - // || - // block - // | | - // | | - // | | ^ (to loop header) - // s.merge | | - // | / loop continue target (unreachable) - // loop merge - // - // - // which becomes: - // - // loop header - // | - // | - // block - // || - // block - // | | - // | | - // | | ^ (to loop header) - // block | | - // | / loop continue target (unreachable) - // loop merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %13 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %8 %15 %15 - %15 = OpLabel - OpBranchConditional %8 %14 %11 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - CheckValid(env, context.get()); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %13 - %13 = OpLabel - OpBranchConditional %8 %15 %15 - %15 = OpLabel - OpBranchConditional %8 %14 %11 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after, context.get()); - - ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveSelectionTest, OpportunityBecauseLoopContinueUsed) { - // A test with the following structure. The OpSelectionMerge instruction - // should be removed. - // - // loop header - // | - // | - // s.header - // || - // block - // | | - // | | - // | | ^ (to loop header) - // s.merge | | - // | loop continue target - // loop merge - // - // - // which becomes: - // - // loop header - // | - // | - // block - // || - // block - // | | - // | | - // | | ^ (to loop header) - // block | | - // | loop continue target - // loop merge - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %13 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %8 %15 %15 - %15 = OpLabel - OpBranchConditional %8 %14 %12 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - - CheckValid(env, context.get()); - - auto ops = - RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %13 - %13 = OpLabel - OpBranchConditional %8 %15 %15 - %15 = OpLabel - OpBranchConditional %8 %14 %12 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after, context.get()); - - ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities( - context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/remove_unreferenced_instruction_test.cpp b/3rdparty/spirv-tools/test/reduce/remove_unreferenced_instruction_test.cpp deleted file mode 100644 index 3caf88cfe..000000000 --- a/3rdparty/spirv-tools/test/reduce/remove_unreferenced_instruction_test.cpp +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "source/util/make_unique.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3; - -TEST(RemoveUnreferencedInstructionReductionPassTest, RemoveStores) { - // A module with some unused instructions, including some unused OpStore - // instructions. - - RemoveUnreferencedInstructionReductionOpportunityFinder finder(true); - - const std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 ; 0 - OpName %4 "main" ; 1 - OpName %8 "a" ; 2 - OpName %10 "b" ; 3 - OpName %12 "c" ; 4 - OpName %14 "d" ; 5 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 10 - %11 = OpConstant %6 20 - %13 = OpConstant %6 30 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function - %12 = OpVariable %7 Function - %14 = OpVariable %7 Function - OpStore %8 %9 ; 6 - OpStore %10 %11 ; 7 - OpStore %12 %13 ; 8 - %15 = OpLoad %6 %8 - OpStore %14 %15 ; 9 - OpReturn - OpFunctionEnd - - )"; - - const MessageConsumer consumer = nullptr; - const auto context = - BuildModule(kEnv, consumer, original, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(10, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - const std::string step_2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 10 ; 0 - %11 = OpConstant %6 20 ; 1 - %13 = OpConstant %6 30 ; 2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %10 = OpVariable %7 Function ; 3 - %12 = OpVariable %7 Function ; 4 - %14 = OpVariable %7 Function ; 5 - %15 = OpLoad %6 %8 ; 6 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, step_2, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(7, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - const std::string step_3 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function ; 0 - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, step_3, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - const std::string step_4 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 ; 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, step_4, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - const std::string step_5 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 ; 0 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, step_5, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - const std::string step_6 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, step_6, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(0, ops.size()); -} - -TEST(RemoveUnreferencedInstructionReductionPassTest, Referenced) { - // A module with some unused global variables, constants, and types. Some will - // not be removed initially because of the OpDecorate instructions. - - RemoveUnreferencedInstructionReductionOpportunityFinder finder(true); - - const std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 ; 1 - OpName %4 "main" ; 2 - OpName %12 "a" ; 3 - OpDecorate %12 RelaxedPrecision ; 4 - OpDecorate %13 RelaxedPrecision ; 5 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %7 = OpConstantTrue %6 ; 6 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Private %10 - %12 = OpVariable %11 Private - %13 = OpConstant %10 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(6, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool ; 1 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Private %10 - %12 = OpVariable %11 Private ; 2 - %13 = OpConstant %10 1 ; 3 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, after, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(3, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - std::string after_2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 - %11 = OpTypePointer Private %10 ; 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, after_2, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - std::string after_3 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeInt 32 1 ; 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, after_3, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - for (auto& op : ops) { - ASSERT_TRUE(op->PreconditionHolds()); - op->TryToApply(); - CheckValid(kEnv, context.get()); - } - - std::string after_4 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, after_4, context.get()); - - ops = finder.GetAvailableOpportunities(context.get()); - - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/simple_conditional_branch_to_branch_test.cpp b/3rdparty/spirv-tools/test/reduce/simple_conditional_branch_to_branch_test.cpp deleted file mode 100644 index d55e69103..000000000 --- a/3rdparty/spirv-tools/test/reduce/simple_conditional_branch_to_branch_test.cpp +++ /dev/null @@ -1,486 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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 "source/reduce/simple_conditional_branch_to_branch_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "source/reduce/reduction_pass.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3; - -TEST(SimpleConditionalBranchToBranchTest, Diamond) { - // A test with the following structure. - // - // selection header - // OpBranchConditional - // || - // b b - // | | - // selection merge - // - // The conditional branch cannot be simplified because selection headers - // cannot end with OpBranch. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %8 %12 %12 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - - )"; - - auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(0, ops.size()); -} - -TEST(SimpleConditionalBranchToBranchTest, DiamondNoSelection) { - // A test with the following structure. - // - // OpBranchConditional - // || - // b b - // | / - // b - // - // The conditional branch can be simplified. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpBranchConditional %8 %12 %12 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpBranch %12 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CheckEqual(kEnv, after, context.get()); - - ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(SimpleConditionalBranchToBranchTest, ConditionalBranchesButNotSimple) { - // A test with the following structure. - // - // selection header - // OpBranchConditional - // | | - // b OpBranchConditional - // | | | - // | b | - // | | | - // selection merge - // - // None of the conditional branches can be simplified; the first is not simple - // AND part of a selection header; the second is just not simple (where - // "simple" means it only has one target). - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %11 None - OpBranchConditional %8 %12 %13 - %12 = OpLabel - OpBranch %11 - %13 = OpLabel - OpBranchConditional %8 %14 %11 - %14 = OpLabel - OpBranch %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(0, ops.size()); -} - -TEST(SimpleConditionalBranchToBranchTest, SimplifyBackEdge) { - // A test with the following structure. The loop has a continue construct that - // ends with OpBranchConditional. The OpBranchConditional can be simplified. - // - // loop header - // | - // loop continue target and back-edge block - // OpBranchConditional - // || - // loop merge (to loop header^) - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %12 - %12 = OpLabel - OpBranchConditional %8 %10 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto context = - BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %12 - %12 = OpLabel - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - - ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(SimpleConditionalBranchToBranchTest, - DontRemoveBackEdgeCombinedHeaderContinue) { - // A test with the following structure. - // - // loop header and continue target and back-edge block - // OpBranchConditional - // || - // loop merge (to loop header^) - // - // The conditional branch can be simplified. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %10 None - OpBranchConditional %8 %10 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto context = - BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %10 None - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - - ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(SimpleConditionalBranchToBranchTest, BackEdgeUnreachable) { - // A test with the following structure. I.e. a loop with an unreachable - // continue construct that ends with OpBranchConditional. - // - // loop header - // | - // | loop continue target (unreachable) - // | | - // | back-edge block (unreachable) - // | OpBranchConditional - // | || - // loop merge (to loop header^) - // - // The conditional branch can be simplified. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %11 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranchConditional %8 %10 %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto context = - BuildModule(kEnv, nullptr, shader, kReduceAssembleOption); - - CheckValid(kEnv, context.get()); - - auto ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(kEnv, context.get()); - - std::string after = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpName %2 "main" - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypePointer Function %5 - %7 = OpTypeBool - %8 = OpConstantTrue %7 - %2 = OpFunction %3 None %4 - %9 = OpLabel - OpBranch %10 - %10 = OpLabel - OpLoopMerge %11 %12 None - OpBranch %11 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %10 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(kEnv, after, context.get()); - - ops = SimpleConditionalBranchToBranchOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/structured_loop_to_selection_test.cpp b/3rdparty/spirv-tools/test/reduce/structured_loop_to_selection_test.cpp deleted file mode 100644 index 95b5f4f15..000000000 --- a/3rdparty/spirv-tools/test/reduce/structured_loop_to_selection_test.cpp +++ /dev/null @@ -1,3628 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/reduce/structured_loop_to_selection_reduction_opportunity_finder.h" - -#include "source/opt/build_module.h" -#include "source/reduce/reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader1) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %13 - %13 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpIAdd %6 %19 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %22 = OpConstantTrue %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %22 %14 %12 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpBranch %12 - %13 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpIAdd %6 %19 %20 - OpStore %8 %21 - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader2) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %28 = OpConstant %6 1 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %7 Function - %40 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %25 = OpLoad %6 %19 - %26 = OpSLessThan %17 %25 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - OpBranch %23 - %23 = OpLabel - %27 = OpLoad %6 %19 - %29 = OpIAdd %6 %27 %28 - OpStore %19 %29 - OpBranch %20 - %22 = OpLabel - OpBranch %13 - %13 = OpLabel - %30 = OpLoad %6 %8 - %31 = OpIAdd %6 %30 %28 - OpStore %8 %31 - OpBranch %10 - %12 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpLoad %6 %32 - %39 = OpSLessThan %17 %38 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpStore %40 %9 - OpBranch %41 - %41 = OpLabel - OpLoopMerge %43 %44 None - OpBranch %45 - %45 = OpLabel - %46 = OpLoad %6 %40 - %47 = OpSLessThan %17 %46 %16 - OpBranchConditional %47 %42 %43 - %42 = OpLabel - OpBranch %44 - %44 = OpLabel - %48 = OpLoad %6 %40 - %49 = OpIAdd %6 %48 %28 - OpStore %40 %49 - OpBranch %41 - %43 = OpLabel - OpBranch %36 - %36 = OpLabel - %50 = OpLoad %6 %32 - %51 = OpIAdd %6 %50 %28 - OpStore %32 %51 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(4, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %28 = OpConstant %6 1 - %52 = OpConstantTrue %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %7 Function - %40 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %52 %14 %12 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - OpLoopMerge %22 %23 None - OpBranch %24 - %24 = OpLabel - %25 = OpLoad %6 %19 - %26 = OpSLessThan %17 %25 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - OpBranch %23 - %23 = OpLabel - %27 = OpLoad %6 %19 - %29 = OpIAdd %6 %27 %28 - OpStore %19 %29 - OpBranch %20 - %22 = OpLabel - OpBranch %12 - %13 = OpLabel - %30 = OpLoad %6 %8 - %31 = OpIAdd %6 %30 %28 - OpStore %8 %31 - OpBranch %10 - %12 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpLoad %6 %32 - %39 = OpSLessThan %17 %38 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpStore %40 %9 - OpBranch %41 - %41 = OpLabel - OpLoopMerge %43 %44 None - OpBranch %45 - %45 = OpLabel - %46 = OpLoad %6 %40 - %47 = OpSLessThan %17 %46 %16 - OpBranchConditional %47 %42 %43 - %42 = OpLabel - OpBranch %44 - %44 = OpLabel - %48 = OpLoad %6 %40 - %49 = OpIAdd %6 %48 %28 - OpStore %40 %49 - OpBranch %41 - %43 = OpLabel - OpBranch %36 - %36 = OpLabel - %50 = OpLoad %6 %32 - %51 = OpIAdd %6 %50 %28 - OpStore %32 %51 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %28 = OpConstant %6 1 - %52 = OpConstantTrue %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %7 Function - %40 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %52 %14 %12 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - OpSelectionMerge %22 None - OpBranchConditional %52 %24 %22 - %24 = OpLabel - %25 = OpLoad %6 %19 - %26 = OpSLessThan %17 %25 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - OpBranch %22 - %23 = OpLabel - %27 = OpLoad %6 %19 - %29 = OpIAdd %6 %27 %28 - OpStore %19 %29 - OpBranch %20 - %22 = OpLabel - OpBranch %12 - %13 = OpLabel - %30 = OpLoad %6 %8 - %31 = OpIAdd %6 %30 %28 - OpStore %8 %31 - OpBranch %10 - %12 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpLoad %6 %32 - %39 = OpSLessThan %17 %38 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpStore %40 %9 - OpBranch %41 - %41 = OpLabel - OpLoopMerge %43 %44 None - OpBranch %45 - %45 = OpLabel - %46 = OpLoad %6 %40 - %47 = OpSLessThan %17 %46 %16 - OpBranchConditional %47 %42 %43 - %42 = OpLabel - OpBranch %44 - %44 = OpLabel - %48 = OpLoad %6 %40 - %49 = OpIAdd %6 %48 %28 - OpStore %40 %49 - OpBranch %41 - %43 = OpLabel - OpBranch %36 - %36 = OpLabel - %50 = OpLoad %6 %32 - %51 = OpIAdd %6 %50 %28 - OpStore %32 %51 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_1, context.get()); - - ASSERT_TRUE(ops[2]->PreconditionHolds()); - ops[2]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_2 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %28 = OpConstant %6 1 - %52 = OpConstantTrue %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %7 Function - %40 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %52 %14 %12 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - OpSelectionMerge %22 None - OpBranchConditional %52 %24 %22 - %24 = OpLabel - %25 = OpLoad %6 %19 - %26 = OpSLessThan %17 %25 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - OpBranch %22 - %23 = OpLabel - %27 = OpLoad %6 %19 - %29 = OpIAdd %6 %27 %28 - OpStore %19 %29 - OpBranch %20 - %22 = OpLabel - OpBranch %12 - %13 = OpLabel - %30 = OpLoad %6 %8 - %31 = OpIAdd %6 %30 %28 - OpStore %8 %31 - OpBranch %10 - %12 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - OpSelectionMerge %35 None - OpBranchConditional %52 %37 %35 - %37 = OpLabel - %38 = OpLoad %6 %32 - %39 = OpSLessThan %17 %38 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpStore %40 %9 - OpBranch %41 - %41 = OpLabel - OpLoopMerge %43 %44 None - OpBranch %45 - %45 = OpLabel - %46 = OpLoad %6 %40 - %47 = OpSLessThan %17 %46 %16 - OpBranchConditional %47 %42 %43 - %42 = OpLabel - OpBranch %44 - %44 = OpLabel - %48 = OpLoad %6 %40 - %49 = OpIAdd %6 %48 %28 - OpStore %40 %49 - OpBranch %41 - %43 = OpLabel - OpBranch %35 - %36 = OpLabel - %50 = OpLoad %6 %32 - %51 = OpIAdd %6 %50 %28 - OpStore %32 %51 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_2, context.get()); - - ASSERT_TRUE(ops[3]->PreconditionHolds()); - ops[3]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_3 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 0 - %16 = OpConstant %6 100 - %17 = OpTypeBool - %28 = OpConstant %6 1 - %52 = OpConstantTrue %17 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - %19 = OpVariable %7 Function - %32 = OpVariable %7 Function - %40 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %52 %14 %12 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSLessThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %19 %9 - OpBranch %20 - %20 = OpLabel - OpSelectionMerge %22 None - OpBranchConditional %52 %24 %22 - %24 = OpLabel - %25 = OpLoad %6 %19 - %26 = OpSLessThan %17 %25 %16 - OpBranchConditional %26 %21 %22 - %21 = OpLabel - OpBranch %22 - %23 = OpLabel - %27 = OpLoad %6 %19 - %29 = OpIAdd %6 %27 %28 - OpStore %19 %29 - OpBranch %20 - %22 = OpLabel - OpBranch %12 - %13 = OpLabel - %30 = OpLoad %6 %8 - %31 = OpIAdd %6 %30 %28 - OpStore %8 %31 - OpBranch %10 - %12 = OpLabel - OpStore %32 %9 - OpBranch %33 - %33 = OpLabel - OpSelectionMerge %35 None - OpBranchConditional %52 %37 %35 - %37 = OpLabel - %38 = OpLoad %6 %32 - %39 = OpSLessThan %17 %38 %16 - OpBranchConditional %39 %34 %35 - %34 = OpLabel - OpStore %40 %9 - OpBranch %41 - %41 = OpLabel - OpSelectionMerge %43 None - OpBranchConditional %52 %45 %43 - %45 = OpLabel - %46 = OpLoad %6 %40 - %47 = OpSLessThan %17 %46 %16 - OpBranchConditional %47 %42 %43 - %42 = OpLabel - OpBranch %43 - %44 = OpLabel - %48 = OpLoad %6 %40 - %49 = OpIAdd %6 %48 %28 - OpStore %40 %49 - OpBranch %41 - %43 = OpLabel - OpBranch %35 - %36 = OpLabel - %50 = OpLoad %6 %32 - %51 = OpIAdd %6 %50 %28 - OpStore %32 %51 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_3, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader3) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %9 = OpConstant %6 10 - %16 = OpConstant %6 0 - %17 = OpTypeBool - %20 = OpConstant %6 1 - %23 = OpConstant %6 3 - %40 = OpConstant %6 5 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %8 = OpVariable %7 Function - OpStore %8 %9 - OpBranch %10 - %10 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %14 - %14 = OpLabel - %15 = OpLoad %6 %8 - %18 = OpSGreaterThan %17 %15 %16 - OpBranchConditional %18 %11 %12 - %11 = OpLabel - %19 = OpLoad %6 %8 - %21 = OpISub %6 %19 %20 - OpStore %8 %21 - %22 = OpLoad %6 %8 - %24 = OpSLessThan %17 %22 %23 - OpSelectionMerge %26 None - OpBranchConditional %24 %25 %26 - %25 = OpLabel - OpBranch %13 - %26 = OpLabel - OpBranch %28 - %28 = OpLabel - OpLoopMerge %30 %31 None - OpBranch %29 - %29 = OpLabel - %32 = OpLoad %6 %8 - %33 = OpISub %6 %32 %20 - OpStore %8 %33 - %34 = OpLoad %6 %8 - %35 = OpIEqual %17 %34 %20 - OpSelectionMerge %37 None - OpBranchConditional %35 %36 %37 - %36 = OpLabel - OpReturn ; This return spoils everything: it means the merge does not post-dominate the header. - %37 = OpLabel - OpBranch %31 - %31 = OpLabel - %39 = OpLoad %6 %8 - %41 = OpSGreaterThan %17 %39 %40 - OpBranchConditional %41 %28 %30 - %30 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %10 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader4) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %6 %7 - %13 = OpConstant %6 0 - %22 = OpTypeBool - %25 = OpConstant %6 1 - %39 = OpConstant %6 100 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %45 = OpVariable %7 Function - %46 = OpVariable %7 Function - %47 = OpVariable %7 Function - %32 = OpVariable %7 Function - %42 = OpVariable %7 Function - OpStore %32 %13 - OpBranch %33 - %33 = OpLabel - OpLoopMerge %35 %36 None - OpBranch %37 - %37 = OpLabel - %38 = OpLoad %6 %32 - %40 = OpSLessThan %22 %38 %39 - OpBranchConditional %40 %34 %35 - %34 = OpLabel - OpBranch %36 - %36 = OpLabel - %41 = OpLoad %6 %32 - OpStore %42 %25 - OpStore %45 %13 - OpStore %46 %13 - OpBranch %48 - %48 = OpLabel - OpLoopMerge %49 %50 None - OpBranch %51 - %51 = OpLabel - %52 = OpLoad %6 %46 - %53 = OpLoad %6 %42 - %54 = OpSLessThan %22 %52 %53 - OpBranchConditional %54 %55 %49 - %55 = OpLabel - %56 = OpLoad %6 %45 - %57 = OpIAdd %6 %56 %25 - OpStore %45 %57 - OpBranch %50 - %50 = OpLabel - %58 = OpLoad %6 %46 - %59 = OpIAdd %6 %58 %25 - OpStore %46 %59 - OpBranch %48 - %49 = OpLabel - %60 = OpLoad %6 %45 - OpStore %47 %60 - %43 = OpLoad %6 %47 - %44 = OpIAdd %6 %41 %43 - OpStore %32 %44 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - // Initially there are two opportunities. - ASSERT_EQ(2, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypePointer Function %6 - %8 = OpTypeFunction %6 %7 - %13 = OpConstant %6 0 - %22 = OpTypeBool - %25 = OpConstant %6 1 - %39 = OpConstant %6 100 - %61 = OpConstantTrue %22 - %62 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %45 = OpVariable %7 Function - %46 = OpVariable %7 Function - %47 = OpVariable %7 Function - %32 = OpVariable %7 Function - %42 = OpVariable %7 Function - OpStore %32 %13 - OpBranch %33 - %33 = OpLabel - OpSelectionMerge %35 None - OpBranchConditional %61 %37 %35 - %37 = OpLabel - %38 = OpLoad %6 %32 - %40 = OpSLessThan %22 %38 %39 - OpBranchConditional %40 %34 %35 - %34 = OpLabel - OpBranch %35 - %36 = OpLabel - %41 = OpLoad %6 %32 - OpStore %42 %25 - OpStore %45 %13 - OpStore %46 %13 - OpBranch %48 - %48 = OpLabel - OpLoopMerge %49 %50 None - OpBranch %51 - %51 = OpLabel - %52 = OpLoad %6 %46 - %53 = OpLoad %6 %42 - %54 = OpSLessThan %22 %52 %53 - OpBranchConditional %54 %55 %49 - %55 = OpLabel - %56 = OpLoad %6 %45 - %57 = OpIAdd %6 %56 %25 - OpStore %45 %57 - OpBranch %50 - %50 = OpLabel - %58 = OpLoad %6 %46 - %59 = OpIAdd %6 %58 %25 - OpStore %46 %59 - OpBranch %48 - %49 = OpLabel - %60 = OpLoad %6 %45 - OpStore %47 %60 - %43 = OpLoad %6 %47 - %44 = OpIAdd %6 %62 %43 - OpStore %32 %44 - OpBranch %33 - %35 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - - // Applying the first opportunity has killed the second opportunity, because - // there was a loop embedded in the continue target of the loop we have just - // eliminated; the continue-embedded loop is now unreachable. - ASSERT_FALSE(ops[1]->PreconditionHolds()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, ConditionalBreak1) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - OpSelectionMerge %13 None - OpBranchConditional %11 %12 %13 - %12 = OpLabel - OpBranch %8 - %13 = OpLabel - OpBranch %9 - %9 = OpLabel - OpBranchConditional %11 %6 %8 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %14 = OpConstantTrue %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpSelectionMerge %8 None - OpBranchConditional %14 %7 %8 - %7 = OpLabel - OpSelectionMerge %13 None - OpBranchConditional %11 %12 %13 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %8 - %9 = OpLabel - OpBranchConditional %11 %6 %8 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, ConditionalBreak2) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - OpSelectionMerge %13 None - OpBranchConditional %11 %8 %13 - %13 = OpLabel - OpBranch %9 - %9 = OpLabel - OpBranchConditional %11 %6 %8 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantFalse %10 - %14 = OpConstantTrue %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpSelectionMerge %8 None - OpBranchConditional %14 %7 %8 - %7 = OpLabel - OpSelectionMerge %13 None - OpBranchConditional %11 %13 %13 - %13 = OpLabel - OpBranch %8 - %9 = OpLabel - OpBranchConditional %11 %6 %8 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, UnconditionalBreak) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %7 - %7 = OpLabel - OpBranch %8 - %9 = OpLabel - OpBranch %6 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %10 = OpTypeBool - %11 = OpConstantTrue %10 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpSelectionMerge %8 None - OpBranchConditional %11 %7 %8 - %7 = OpLabel - OpBranch %8 - %9 = OpLabel - OpBranch %6 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, Complex) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 4 - OpMemberDecorate %4 2 Offset 8 - OpMemberDecorate %4 3 Offset 12 - OpDecorate %4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeBool - %9 = OpTypePointer Function %8 - %10 = OpTypeInt 32 1 - %4 = OpTypeStruct %10 %10 %10 %10 - %11 = OpTypePointer Uniform %4 - %5 = OpVariable %11 Uniform - %12 = OpConstant %10 0 - %13 = OpTypePointer Uniform %10 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpConstant %10 1 - %17 = OpConstant %10 2 - %18 = OpConstant %10 3 - %19 = OpTypePointer Function %10 - %20 = OpConstantFalse %8 - %21 = OpTypeFloat 32 - %22 = OpTypeVector %21 4 - %23 = OpTypePointer Output %22 - %3 = OpVariable %23 Output - %2 = OpFunction %6 None %7 - %24 = OpLabel - %25 = OpVariable %9 Function - %26 = OpVariable %9 Function - %27 = OpVariable %9 Function - %28 = OpVariable %9 Function - %29 = OpVariable %9 Function - %30 = OpVariable %19 Function - %31 = OpAccessChain %13 %5 %12 - %32 = OpLoad %10 %31 - %33 = OpINotEqual %8 %32 %15 - OpStore %25 %33 - %34 = OpAccessChain %13 %5 %16 - %35 = OpLoad %10 %34 - %36 = OpINotEqual %8 %35 %15 - OpStore %26 %36 - %37 = OpAccessChain %13 %5 %17 - %38 = OpLoad %10 %37 - %39 = OpINotEqual %8 %38 %15 - OpStore %27 %39 - %40 = OpAccessChain %13 %5 %18 - %41 = OpLoad %10 %40 - %42 = OpINotEqual %8 %41 %15 - OpStore %28 %42 - %43 = OpLoad %8 %25 - OpStore %29 %43 - OpStore %30 %12 - OpBranch %44 - %44 = OpLabel - OpLoopMerge %45 %46 None - OpBranch %47 - %47 = OpLabel - %48 = OpLoad %8 %29 - OpBranchConditional %48 %49 %45 - %49 = OpLabel - %50 = OpLoad %8 %25 - OpSelectionMerge %51 None - OpBranchConditional %50 %52 %51 - %52 = OpLabel - %53 = OpLoad %8 %26 - OpStore %29 %53 - %54 = OpLoad %10 %30 - %55 = OpIAdd %10 %54 %16 - OpStore %30 %55 - OpBranch %51 - %51 = OpLabel - %56 = OpLoad %8 %26 - OpSelectionMerge %57 None - OpBranchConditional %56 %58 %57 - %58 = OpLabel - %59 = OpLoad %10 %30 - %60 = OpIAdd %10 %59 %16 - OpStore %30 %60 - %61 = OpLoad %8 %29 - %62 = OpLoad %8 %25 - %63 = OpLogicalOr %8 %61 %62 - OpStore %29 %63 - %64 = OpLoad %8 %27 - OpSelectionMerge %65 None - OpBranchConditional %64 %66 %65 - %66 = OpLabel - %67 = OpLoad %10 %30 - %68 = OpIAdd %10 %67 %17 - OpStore %30 %68 - %69 = OpLoad %8 %29 - %70 = OpLogicalNot %8 %69 - OpStore %29 %70 - OpBranch %46 - %65 = OpLabel - %71 = OpLoad %8 %29 - %72 = OpLogicalOr %8 %71 %20 - OpStore %29 %72 - OpBranch %46 - %57 = OpLabel - OpBranch %73 - %73 = OpLabel - OpLoopMerge %74 %75 None - OpBranch %76 - %76 = OpLabel - %77 = OpLoad %8 %28 - OpSelectionMerge %78 None - OpBranchConditional %77 %79 %80 - %79 = OpLabel - %81 = OpLoad %10 %30 - OpSelectionMerge %82 None - OpSwitch %81 %83 1 %84 2 %85 - %83 = OpLabel - OpBranch %82 - %84 = OpLabel - %86 = OpLoad %8 %29 - %87 = OpSelect %10 %86 %16 %17 - %88 = OpLoad %10 %30 - %89 = OpIAdd %10 %88 %87 - OpStore %30 %89 - OpBranch %82 - %85 = OpLabel - OpBranch %75 - %82 = OpLabel - %90 = OpLoad %8 %27 - OpSelectionMerge %91 None - OpBranchConditional %90 %92 %91 - %92 = OpLabel - OpBranch %75 - %91 = OpLabel - OpBranch %78 - %80 = OpLabel - OpBranch %74 - %78 = OpLabel - OpBranch %75 - %75 = OpLabel - %93 = OpLoad %8 %29 - OpBranchConditional %93 %73 %74 - %74 = OpLabel - OpBranch %46 - %46 = OpLabel - OpBranch %44 - %45 = OpLabel - %94 = OpLoad %10 %30 - %95 = OpConvertSToF %21 %94 - %96 = OpCompositeConstruct %22 %95 %95 %95 %95 - OpStore %3 %96 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(2, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 4 - OpMemberDecorate %4 2 Offset 8 - OpMemberDecorate %4 3 Offset 12 - OpDecorate %4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeBool - %9 = OpTypePointer Function %8 - %10 = OpTypeInt 32 1 - %4 = OpTypeStruct %10 %10 %10 %10 - %11 = OpTypePointer Uniform %4 - %5 = OpVariable %11 Uniform - %12 = OpConstant %10 0 - %13 = OpTypePointer Uniform %10 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpConstant %10 1 - %17 = OpConstant %10 2 - %18 = OpConstant %10 3 - %19 = OpTypePointer Function %10 - %20 = OpConstantFalse %8 - %21 = OpTypeFloat 32 - %22 = OpTypeVector %21 4 - %23 = OpTypePointer Output %22 - %3 = OpVariable %23 Output - %97 = OpConstantTrue %8 - %2 = OpFunction %6 None %7 - %24 = OpLabel - %25 = OpVariable %9 Function - %26 = OpVariable %9 Function - %27 = OpVariable %9 Function - %28 = OpVariable %9 Function - %29 = OpVariable %9 Function - %30 = OpVariable %19 Function - %31 = OpAccessChain %13 %5 %12 - %32 = OpLoad %10 %31 - %33 = OpINotEqual %8 %32 %15 - OpStore %25 %33 - %34 = OpAccessChain %13 %5 %16 - %35 = OpLoad %10 %34 - %36 = OpINotEqual %8 %35 %15 - OpStore %26 %36 - %37 = OpAccessChain %13 %5 %17 - %38 = OpLoad %10 %37 - %39 = OpINotEqual %8 %38 %15 - OpStore %27 %39 - %40 = OpAccessChain %13 %5 %18 - %41 = OpLoad %10 %40 - %42 = OpINotEqual %8 %41 %15 - OpStore %28 %42 - %43 = OpLoad %8 %25 - OpStore %29 %43 - OpStore %30 %12 - OpBranch %44 - %44 = OpLabel - OpSelectionMerge %45 None ; Was OpLoopMerge %45 %46 None - OpBranchConditional %97 %47 %45 ; Was OpBranch %47 - %47 = OpLabel - %48 = OpLoad %8 %29 - OpBranchConditional %48 %49 %45 - %49 = OpLabel - %50 = OpLoad %8 %25 - OpSelectionMerge %51 None - OpBranchConditional %50 %52 %51 - %52 = OpLabel - %53 = OpLoad %8 %26 - OpStore %29 %53 - %54 = OpLoad %10 %30 - %55 = OpIAdd %10 %54 %16 - OpStore %30 %55 - OpBranch %51 - %51 = OpLabel - %56 = OpLoad %8 %26 - OpSelectionMerge %57 None - OpBranchConditional %56 %58 %57 - %58 = OpLabel - %59 = OpLoad %10 %30 - %60 = OpIAdd %10 %59 %16 - OpStore %30 %60 - %61 = OpLoad %8 %29 - %62 = OpLoad %8 %25 - %63 = OpLogicalOr %8 %61 %62 - OpStore %29 %63 - %64 = OpLoad %8 %27 - OpSelectionMerge %65 None - OpBranchConditional %64 %66 %65 - %66 = OpLabel - %67 = OpLoad %10 %30 - %68 = OpIAdd %10 %67 %17 - OpStore %30 %68 - %69 = OpLoad %8 %29 - %70 = OpLogicalNot %8 %69 - OpStore %29 %70 - OpBranch %65 ; Was OpBranch %46 - %65 = OpLabel - %71 = OpLoad %8 %29 - %72 = OpLogicalOr %8 %71 %20 - OpStore %29 %72 - OpBranch %57 ; Was OpBranch %46 - %57 = OpLabel - OpBranch %73 - %73 = OpLabel - OpLoopMerge %74 %75 None - OpBranch %76 - %76 = OpLabel - %77 = OpLoad %8 %28 - OpSelectionMerge %78 None - OpBranchConditional %77 %79 %80 - %79 = OpLabel - %81 = OpLoad %10 %30 - OpSelectionMerge %82 None - OpSwitch %81 %83 1 %84 2 %85 - %83 = OpLabel - OpBranch %82 - %84 = OpLabel - %86 = OpLoad %8 %29 - %87 = OpSelect %10 %86 %16 %17 - %88 = OpLoad %10 %30 - %89 = OpIAdd %10 %88 %87 - OpStore %30 %89 - OpBranch %82 - %85 = OpLabel - OpBranch %75 - %82 = OpLabel - %90 = OpLoad %8 %27 - OpSelectionMerge %91 None - OpBranchConditional %90 %92 %91 - %92 = OpLabel - OpBranch %75 - %91 = OpLabel - OpBranch %78 - %80 = OpLabel - OpBranch %74 - %78 = OpLabel - OpBranch %75 - %75 = OpLabel - %93 = OpLoad %8 %29 - OpBranchConditional %93 %73 %74 - %74 = OpLabel - OpBranch %45 ; Was OpBranch %46 - %46 = OpLabel - OpBranch %44 - %45 = OpLabel - %94 = OpLoad %10 %30 - %95 = OpConvertSToF %21 %94 - %96 = OpCompositeConstruct %22 %95 %95 %95 %95 - OpStore %3 %96 - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - CheckValid(env, context.get()); - - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 4 - OpMemberDecorate %4 2 Offset 8 - OpMemberDecorate %4 3 Offset 12 - OpDecorate %4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeBool - %9 = OpTypePointer Function %8 - %10 = OpTypeInt 32 1 - %4 = OpTypeStruct %10 %10 %10 %10 - %11 = OpTypePointer Uniform %4 - %5 = OpVariable %11 Uniform - %12 = OpConstant %10 0 - %13 = OpTypePointer Uniform %10 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpConstant %10 1 - %17 = OpConstant %10 2 - %18 = OpConstant %10 3 - %19 = OpTypePointer Function %10 - %20 = OpConstantFalse %8 - %21 = OpTypeFloat 32 - %22 = OpTypeVector %21 4 - %23 = OpTypePointer Output %22 - %3 = OpVariable %23 Output - %97 = OpConstantTrue %8 - %2 = OpFunction %6 None %7 - %24 = OpLabel - %25 = OpVariable %9 Function - %26 = OpVariable %9 Function - %27 = OpVariable %9 Function - %28 = OpVariable %9 Function - %29 = OpVariable %9 Function - %30 = OpVariable %19 Function - %31 = OpAccessChain %13 %5 %12 - %32 = OpLoad %10 %31 - %33 = OpINotEqual %8 %32 %15 - OpStore %25 %33 - %34 = OpAccessChain %13 %5 %16 - %35 = OpLoad %10 %34 - %36 = OpINotEqual %8 %35 %15 - OpStore %26 %36 - %37 = OpAccessChain %13 %5 %17 - %38 = OpLoad %10 %37 - %39 = OpINotEqual %8 %38 %15 - OpStore %27 %39 - %40 = OpAccessChain %13 %5 %18 - %41 = OpLoad %10 %40 - %42 = OpINotEqual %8 %41 %15 - OpStore %28 %42 - %43 = OpLoad %8 %25 - OpStore %29 %43 - OpStore %30 %12 - OpBranch %44 - %44 = OpLabel - OpSelectionMerge %45 None ; Was OpLoopMerge %45 %46 None - OpBranchConditional %97 %47 %45 ; Was OpBranch %47 - %47 = OpLabel - %48 = OpLoad %8 %29 - OpBranchConditional %48 %49 %45 - %49 = OpLabel - %50 = OpLoad %8 %25 - OpSelectionMerge %51 None - OpBranchConditional %50 %52 %51 - %52 = OpLabel - %53 = OpLoad %8 %26 - OpStore %29 %53 - %54 = OpLoad %10 %30 - %55 = OpIAdd %10 %54 %16 - OpStore %30 %55 - OpBranch %51 - %51 = OpLabel - %56 = OpLoad %8 %26 - OpSelectionMerge %57 None - OpBranchConditional %56 %58 %57 - %58 = OpLabel - %59 = OpLoad %10 %30 - %60 = OpIAdd %10 %59 %16 - OpStore %30 %60 - %61 = OpLoad %8 %29 - %62 = OpLoad %8 %25 - %63 = OpLogicalOr %8 %61 %62 - OpStore %29 %63 - %64 = OpLoad %8 %27 - OpSelectionMerge %65 None - OpBranchConditional %64 %66 %65 - %66 = OpLabel - %67 = OpLoad %10 %30 - %68 = OpIAdd %10 %67 %17 - OpStore %30 %68 - %69 = OpLoad %8 %29 - %70 = OpLogicalNot %8 %69 - OpStore %29 %70 - OpBranch %65 ; Was OpBranch %46 - %65 = OpLabel - %71 = OpLoad %8 %29 - %72 = OpLogicalOr %8 %71 %20 - OpStore %29 %72 - OpBranch %57 ; Was OpBranch %46 - %57 = OpLabel - OpBranch %73 - %73 = OpLabel - OpSelectionMerge %74 None ; Was OpLoopMerge %74 %75 None - OpBranchConditional %97 %76 %74 ; Was OpBranch %76 - %76 = OpLabel - %77 = OpLoad %8 %28 - OpSelectionMerge %78 None - OpBranchConditional %77 %79 %80 - %79 = OpLabel - %81 = OpLoad %10 %30 - OpSelectionMerge %82 None - OpSwitch %81 %83 1 %84 2 %85 - %83 = OpLabel - OpBranch %82 - %84 = OpLabel - %86 = OpLoad %8 %29 - %87 = OpSelect %10 %86 %16 %17 - %88 = OpLoad %10 %30 - %89 = OpIAdd %10 %88 %87 - OpStore %30 %89 - OpBranch %82 - %85 = OpLabel - OpBranch %82 - %82 = OpLabel - %90 = OpLoad %8 %27 - OpSelectionMerge %91 None - OpBranchConditional %90 %92 %91 - %92 = OpLabel - OpBranch %91 - %91 = OpLabel - OpBranch %78 - %80 = OpLabel - OpBranch %78 ; Was OpBranch %74 - %78 = OpLabel - OpBranch %74 - %75 = OpLabel - %93 = OpLoad %8 %29 - OpBranchConditional %93 %73 %74 - %74 = OpLabel - OpBranch %45 ; Was OpBranch %46 - %46 = OpLabel - OpBranch %44 - %45 = OpLabel - %94 = OpLoad %10 %30 - %95 = OpConvertSToF %21 %94 - %96 = OpCompositeConstruct %22 %95 %95 %95 %95 - OpStore %3 %96 - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_1, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, ComplexOptimized) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 4 - OpMemberDecorate %4 2 Offset 8 - OpMemberDecorate %4 3 Offset 12 - OpDecorate %4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeBool - %10 = OpTypeInt 32 1 - %4 = OpTypeStruct %10 %10 %10 %10 - %11 = OpTypePointer Uniform %4 - %5 = OpVariable %11 Uniform - %12 = OpConstant %10 0 - %13 = OpTypePointer Uniform %10 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpConstant %10 1 - %17 = OpConstant %10 2 - %18 = OpConstant %10 3 - %20 = OpConstantFalse %8 - %21 = OpTypeFloat 32 - %22 = OpTypeVector %21 4 - %23 = OpTypePointer Output %22 - %3 = OpVariable %23 Output - %2 = OpFunction %6 None %7 - %24 = OpLabel - %31 = OpAccessChain %13 %5 %12 - %32 = OpLoad %10 %31 - %33 = OpINotEqual %8 %32 %15 - %34 = OpAccessChain %13 %5 %16 - %35 = OpLoad %10 %34 - %36 = OpINotEqual %8 %35 %15 - %37 = OpAccessChain %13 %5 %17 - %38 = OpLoad %10 %37 - %39 = OpINotEqual %8 %38 %15 - %40 = OpAccessChain %13 %5 %18 - %41 = OpLoad %10 %40 - %42 = OpINotEqual %8 %41 %15 - OpBranch %44 - %44 = OpLabel - %98 = OpPhi %10 %12 %24 %107 %46 - %97 = OpPhi %8 %33 %24 %105 %46 - OpLoopMerge %45 %46 None - OpBranchConditional %97 %49 %45 - %49 = OpLabel - OpSelectionMerge %51 None - OpBranchConditional %33 %52 %51 - %52 = OpLabel - %55 = OpIAdd %10 %98 %16 - OpBranch %51 - %51 = OpLabel - %100 = OpPhi %10 %98 %49 %55 %52 - %113 = OpSelect %8 %33 %36 %97 - OpSelectionMerge %57 None - OpBranchConditional %36 %58 %57 - %58 = OpLabel - %60 = OpIAdd %10 %100 %16 - %63 = OpLogicalOr %8 %113 %33 - OpSelectionMerge %65 None - OpBranchConditional %39 %66 %65 - %66 = OpLabel - %68 = OpIAdd %10 %100 %18 - %70 = OpLogicalNot %8 %63 - OpBranch %46 - %65 = OpLabel - %72 = OpLogicalOr %8 %63 %20 - OpBranch %46 - %57 = OpLabel - OpBranch %73 - %73 = OpLabel - %99 = OpPhi %10 %100 %57 %109 %75 - OpLoopMerge %74 %75 None - OpBranch %76 - %76 = OpLabel - OpSelectionMerge %78 None - OpBranchConditional %42 %79 %80 - %79 = OpLabel - OpSelectionMerge %82 None - OpSwitch %99 %83 1 %84 2 %85 - %83 = OpLabel - OpBranch %82 - %84 = OpLabel - %87 = OpSelect %10 %113 %16 %17 - %89 = OpIAdd %10 %99 %87 - OpBranch %82 - %85 = OpLabel - OpBranch %75 - %82 = OpLabel - %110 = OpPhi %10 %99 %83 %89 %84 - OpSelectionMerge %91 None - OpBranchConditional %39 %92 %91 - %92 = OpLabel - OpBranch %75 - %91 = OpLabel - OpBranch %78 - %80 = OpLabel - OpBranch %74 - %78 = OpLabel - OpBranch %75 - %75 = OpLabel - %109 = OpPhi %10 %99 %85 %110 %92 %110 %78 - OpBranchConditional %113 %73 %74 - %74 = OpLabel - %108 = OpPhi %10 %99 %80 %109 %75 - OpBranch %46 - %46 = OpLabel - %107 = OpPhi %10 %68 %66 %60 %65 %108 %74 - %105 = OpPhi %8 %70 %66 %72 %65 %113 %74 - OpBranch %44 - %45 = OpLabel - %95 = OpConvertSToF %21 %98 - %96 = OpCompositeConstruct %22 %95 %95 %95 %95 - OpStore %3 %96 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(2, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 4 - OpMemberDecorate %4 2 Offset 8 - OpMemberDecorate %4 3 Offset 12 - OpDecorate %4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeBool - %10 = OpTypeInt 32 1 - %4 = OpTypeStruct %10 %10 %10 %10 - %11 = OpTypePointer Uniform %4 - %5 = OpVariable %11 Uniform - %12 = OpConstant %10 0 - %13 = OpTypePointer Uniform %10 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpConstant %10 1 - %17 = OpConstant %10 2 - %18 = OpConstant %10 3 - %20 = OpConstantFalse %8 - %21 = OpTypeFloat 32 - %22 = OpTypeVector %21 4 - %23 = OpTypePointer Output %22 - %3 = OpVariable %23 Output - %114 = OpUndef %10 - %115 = OpUndef %8 - %2 = OpFunction %6 None %7 - %24 = OpLabel - %31 = OpAccessChain %13 %5 %12 - %32 = OpLoad %10 %31 - %33 = OpINotEqual %8 %32 %15 - %34 = OpAccessChain %13 %5 %16 - %35 = OpLoad %10 %34 - %36 = OpINotEqual %8 %35 %15 - %37 = OpAccessChain %13 %5 %17 - %38 = OpLoad %10 %37 - %39 = OpINotEqual %8 %38 %15 - %40 = OpAccessChain %13 %5 %18 - %41 = OpLoad %10 %40 - %42 = OpINotEqual %8 %41 %15 - OpBranch %44 - %44 = OpLabel - %98 = OpPhi %10 %12 %24 %114 %46 - %97 = OpPhi %8 %33 %24 %115 %46 - OpSelectionMerge %45 None ; Was OpLoopMerge %45 %46 None - OpBranchConditional %97 %49 %45 - %49 = OpLabel - OpSelectionMerge %51 None - OpBranchConditional %33 %52 %51 - %52 = OpLabel - %55 = OpIAdd %10 %98 %16 - OpBranch %51 - %51 = OpLabel - %100 = OpPhi %10 %98 %49 %55 %52 - %113 = OpSelect %8 %33 %36 %97 - OpSelectionMerge %57 None - OpBranchConditional %36 %58 %57 - %58 = OpLabel - %60 = OpIAdd %10 %100 %16 - %63 = OpLogicalOr %8 %113 %33 - OpSelectionMerge %65 None - OpBranchConditional %39 %66 %65 - %66 = OpLabel - %68 = OpIAdd %10 %100 %18 - %70 = OpLogicalNot %8 %63 - OpBranch %65 ; Was OpBranch %46 - %65 = OpLabel - %72 = OpLogicalOr %8 %63 %20 - OpBranch %57 ; Was OpBranch %46 - %57 = OpLabel - OpBranch %73 - %73 = OpLabel - %99 = OpPhi %10 %100 %57 %109 %75 - OpLoopMerge %74 %75 None - OpBranch %76 - %76 = OpLabel - OpSelectionMerge %78 None - OpBranchConditional %42 %79 %80 - %79 = OpLabel - OpSelectionMerge %82 None - OpSwitch %99 %83 1 %84 2 %85 - %83 = OpLabel - OpBranch %82 - %84 = OpLabel - %87 = OpSelect %10 %113 %16 %17 - %89 = OpIAdd %10 %99 %87 - OpBranch %82 - %85 = OpLabel - OpBranch %75 - %82 = OpLabel - %110 = OpPhi %10 %99 %83 %89 %84 - OpSelectionMerge %91 None - OpBranchConditional %39 %92 %91 - %92 = OpLabel - OpBranch %75 - %91 = OpLabel - OpBranch %78 - %80 = OpLabel - OpBranch %74 - %78 = OpLabel - OpBranch %75 - %75 = OpLabel - %109 = OpPhi %10 %99 %85 %110 %92 %110 %78 - OpBranchConditional %113 %73 %74 - %74 = OpLabel - %108 = OpPhi %10 %99 %80 %109 %75 - OpBranch %45 ; Was OpBranch %46 - %46 = OpLabel - %107 = OpPhi %10 ; Was OpPhi %10 %68 %66 %60 %65 %108 %74 - %105 = OpPhi %8 ; Was OpPhi %8 %70 %66 %72 %65 %113 %74 - OpBranch %44 - %45 = OpLabel - %95 = OpConvertSToF %21 %98 - %96 = OpCompositeConstruct %22 %95 %95 %95 %95 - OpStore %3 %96 - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - CheckValid(env, context.get()); - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" %3 - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 4 - OpMemberDecorate %4 2 Offset 8 - OpMemberDecorate %4 3 Offset 12 - OpDecorate %4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - OpDecorate %3 Location 0 - %6 = OpTypeVoid - %7 = OpTypeFunction %6 - %8 = OpTypeBool - %10 = OpTypeInt 32 1 - %4 = OpTypeStruct %10 %10 %10 %10 - %11 = OpTypePointer Uniform %4 - %5 = OpVariable %11 Uniform - %12 = OpConstant %10 0 - %13 = OpTypePointer Uniform %10 - %14 = OpTypeInt 32 0 - %15 = OpConstant %14 0 - %16 = OpConstant %10 1 - %17 = OpConstant %10 2 - %18 = OpConstant %10 3 - %20 = OpConstantFalse %8 - %21 = OpTypeFloat 32 - %22 = OpTypeVector %21 4 - %23 = OpTypePointer Output %22 - %3 = OpVariable %23 Output - %114 = OpUndef %10 - %115 = OpUndef %8 - %116 = OpConstantTrue %8 - %2 = OpFunction %6 None %7 - %24 = OpLabel - %31 = OpAccessChain %13 %5 %12 - %32 = OpLoad %10 %31 - %33 = OpINotEqual %8 %32 %15 - %34 = OpAccessChain %13 %5 %16 - %35 = OpLoad %10 %34 - %36 = OpINotEqual %8 %35 %15 - %37 = OpAccessChain %13 %5 %17 - %38 = OpLoad %10 %37 - %39 = OpINotEqual %8 %38 %15 - %40 = OpAccessChain %13 %5 %18 - %41 = OpLoad %10 %40 - %42 = OpINotEqual %8 %41 %15 - OpBranch %44 - %44 = OpLabel - %98 = OpPhi %10 %12 %24 %114 %46 - %97 = OpPhi %8 %33 %24 %115 %46 - OpSelectionMerge %45 None ; Was OpLoopMerge %45 %46 None - OpBranchConditional %97 %49 %45 - %49 = OpLabel - OpSelectionMerge %51 None - OpBranchConditional %33 %52 %51 - %52 = OpLabel - %55 = OpIAdd %10 %98 %16 - OpBranch %51 - %51 = OpLabel - %100 = OpPhi %10 %98 %49 %55 %52 - %113 = OpSelect %8 %33 %36 %97 - OpSelectionMerge %57 None - OpBranchConditional %36 %58 %57 - %58 = OpLabel - %60 = OpIAdd %10 %100 %16 - %63 = OpLogicalOr %8 %113 %33 - OpSelectionMerge %65 None - OpBranchConditional %39 %66 %65 - %66 = OpLabel - %68 = OpIAdd %10 %100 %18 - %70 = OpLogicalNot %8 %63 - OpBranch %65 ; Was OpBranch %46 - %65 = OpLabel - %72 = OpLogicalOr %8 %63 %20 - OpBranch %57 ; Was OpBranch %46 - %57 = OpLabel - OpBranch %73 - %73 = OpLabel - %99 = OpPhi %10 %100 %57 %114 %75 - OpSelectionMerge %74 None ; Was OpLoopMerge %74 %75 None - OpBranchConditional %116 %76 %74 - %76 = OpLabel - OpSelectionMerge %78 None - OpBranchConditional %42 %79 %80 - %79 = OpLabel - OpSelectionMerge %82 None - OpSwitch %99 %83 1 %84 2 %85 - %83 = OpLabel - OpBranch %82 - %84 = OpLabel - %87 = OpSelect %10 %113 %16 %17 - %89 = OpIAdd %10 %99 %87 - OpBranch %82 - %85 = OpLabel - OpBranch %82 ; Was OpBranch %75 - %82 = OpLabel - %110 = OpPhi %10 %99 %83 %89 %84 %114 %85 ; Was OpPhi %10 %99 %83 %89 %84 - OpSelectionMerge %91 None - OpBranchConditional %39 %92 %91 - %92 = OpLabel - OpBranch %91 ; OpBranch %75 - %91 = OpLabel - OpBranch %78 - %80 = OpLabel - OpBranch %78 ; Was OpBranch %74 - %78 = OpLabel - OpBranch %74 ; Was OpBranch %75 - %75 = OpLabel - %109 = OpPhi %10 ; Was OpPhi %10 %99 %85 %110 %92 %110 %78 - OpBranchConditional %115 %73 %74 - %74 = OpLabel - %108 = OpPhi %10 %114 %75 %114 %78 %114 %73 ; Was OpPhi %10 %99 %80 %109 %75 - OpBranch %45 ; Was OpBranch %46 - %46 = OpLabel - %107 = OpPhi %10 ; Was OpPhi %10 %68 %66 %60 %65 %108 %74 - %105 = OpPhi %8 ; Was OpPhi %8 %70 %66 %72 %65 %113 %74 - OpBranch %44 - %45 = OpLabel - %95 = OpConvertSToF %21 %98 - %96 = OpCompositeConstruct %22 %95 %95 %95 %95 - OpStore %3 %96 - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_1, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, DominanceIssue) { - // Exposes a scenario where redirecting edges results in uses of ids being - // non-dominated. We replace such uses with OpUndef to account for this. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %5 = OpTypeInt 32 1 - %7 = OpTypePointer Function %5 - %6 = OpTypeBool - %8 = OpConstantTrue %6 - %9 = OpConstant %5 10 - %10 = OpConstant %5 20 - %11 = OpConstant %5 30 - %4 = OpFunction %2 None %3 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - OpSelectionMerge %17 None - OpBranchConditional %8 %18 %19 - %18 = OpLabel - OpBranch %14 - %19 = OpLabel - %20 = OpIAdd %5 %9 %10 - OpBranch %17 - %17 = OpLabel - %21 = OpIAdd %5 %20 %11 - OpBranchConditional %8 %14 %15 - %15 = OpLabel - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %5 = OpTypeInt 32 1 - %7 = OpTypePointer Function %5 - %6 = OpTypeBool - %8 = OpConstantTrue %6 - %9 = OpConstant %5 10 - %10 = OpConstant %5 20 - %11 = OpConstant %5 30 - %22 = OpUndef %5 - %4 = OpFunction %2 None %3 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %8 %16 %14 - %16 = OpLabel - OpSelectionMerge %17 None - OpBranchConditional %8 %18 %19 - %18 = OpLabel - OpBranch %17 - %19 = OpLabel - %20 = OpIAdd %5 %9 %10 - OpBranch %17 - %17 = OpLabel - %21 = OpIAdd %5 %22 %11 - OpBranchConditional %8 %14 %14 - %15 = OpLabel - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, AccessChainIssue) { - // Exposes a scenario where redirecting edges results in a use of an id - // generated by an access chain being non-dominated. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %56 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %28 0 Offset 0 - OpDecorate %28 Block - OpDecorate %30 DescriptorSet 0 - OpDecorate %30 Binding 0 - OpDecorate %56 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypePointer Function %7 - %60 = OpTypePointer Private %7 - %10 = OpConstant %6 0 - %11 = OpConstantComposite %7 %10 %10 - %12 = OpTypePointer Function %6 - %59 = OpTypePointer Private %6 - %14 = OpTypeInt 32 1 - %15 = OpTypePointer Function %14 - %17 = OpConstant %14 0 - %24 = OpConstant %14 100 - %25 = OpTypeBool - %28 = OpTypeStruct %6 - %29 = OpTypePointer Uniform %28 - %30 = OpVariable %29 Uniform - %31 = OpTypePointer Uniform %6 - %39 = OpTypeInt 32 0 - %40 = OpConstant %39 1 - %45 = OpConstant %39 0 - %52 = OpConstant %14 1 - %54 = OpTypeVector %6 4 - %55 = OpTypePointer Output %54 - %56 = OpVariable %55 Output - %9 = OpVariable %60 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - %13 = OpVariable %12 Function - %16 = OpVariable %15 Function - %38 = OpVariable %12 Function - OpStore %9 %11 - OpStore %13 %10 - OpStore %16 %17 - OpBranch %18 - %18 = OpLabel - OpLoopMerge %20 %21 None - OpBranch %22 - %22 = OpLabel - %23 = OpLoad %14 %16 - %26 = OpSLessThan %25 %23 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %27 = OpLoad %14 %16 - %32 = OpAccessChain %31 %30 %17 - %33 = OpLoad %6 %32 - %34 = OpConvertFToS %14 %33 - %35 = OpSLessThan %25 %27 %34 - OpSelectionMerge %37 None - OpBranchConditional %35 %36 %44 - %36 = OpLabel - %41 = OpAccessChain %59 %9 %40 - %42 = OpLoad %6 %41 - OpStore %38 %42 - OpBranch %20 - %44 = OpLabel - %46 = OpAccessChain %59 %9 %45 - OpBranch %37 - %37 = OpLabel - %47 = OpLoad %6 %46 - OpStore %38 %47 - %48 = OpLoad %6 %38 - %49 = OpLoad %6 %13 - %50 = OpFAdd %6 %49 %48 - OpStore %13 %50 - OpBranch %21 - %21 = OpLabel - %51 = OpLoad %14 %16 - %53 = OpIAdd %14 %51 %52 - OpStore %16 %53 - OpBranch %18 - %20 = OpLabel - %57 = OpLoad %6 %13 - %58 = OpCompositeConstruct %54 %57 %57 %57 %57 - OpStore %56 %58 - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %56 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpMemberDecorate %28 0 Offset 0 - OpDecorate %28 Block - OpDecorate %30 DescriptorSet 0 - OpDecorate %30 Binding 0 - OpDecorate %56 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 2 - %8 = OpTypePointer Function %7 - %60 = OpTypePointer Private %7 - %10 = OpConstant %6 0 - %11 = OpConstantComposite %7 %10 %10 - %12 = OpTypePointer Function %6 - %59 = OpTypePointer Private %6 - %14 = OpTypeInt 32 1 - %15 = OpTypePointer Function %14 - %17 = OpConstant %14 0 - %24 = OpConstant %14 100 - %25 = OpTypeBool - %28 = OpTypeStruct %6 - %29 = OpTypePointer Uniform %28 - %30 = OpVariable %29 Uniform - %31 = OpTypePointer Uniform %6 - %39 = OpTypeInt 32 0 - %40 = OpConstant %39 1 - %45 = OpConstant %39 0 - %52 = OpConstant %14 1 - %54 = OpTypeVector %6 4 - %55 = OpTypePointer Output %54 - %56 = OpVariable %55 Output - %9 = OpVariable %60 Private - %61 = OpConstantTrue %25 - %62 = OpVariable %59 Private - %4 = OpFunction %2 None %3 - %5 = OpLabel - %13 = OpVariable %12 Function - %16 = OpVariable %15 Function - %38 = OpVariable %12 Function - OpStore %9 %11 - OpStore %13 %10 - OpStore %16 %17 - OpBranch %18 - %18 = OpLabel - OpSelectionMerge %20 None - OpBranchConditional %61 %22 %20 - %22 = OpLabel - %23 = OpLoad %14 %16 - %26 = OpSLessThan %25 %23 %24 - OpBranchConditional %26 %19 %20 - %19 = OpLabel - %27 = OpLoad %14 %16 - %32 = OpAccessChain %31 %30 %17 - %33 = OpLoad %6 %32 - %34 = OpConvertFToS %14 %33 - %35 = OpSLessThan %25 %27 %34 - OpSelectionMerge %37 None - OpBranchConditional %35 %36 %44 - %36 = OpLabel - %41 = OpAccessChain %59 %9 %40 - %42 = OpLoad %6 %41 - OpStore %38 %42 - OpBranch %37 - %44 = OpLabel - %46 = OpAccessChain %59 %9 %45 - OpBranch %37 - %37 = OpLabel - %47 = OpLoad %6 %62 - OpStore %38 %47 - %48 = OpLoad %6 %38 - %49 = OpLoad %6 %13 - %50 = OpFAdd %6 %49 %48 - OpStore %13 %50 - OpBranch %20 - %21 = OpLabel - %51 = OpLoad %14 %16 - %53 = OpIAdd %14 %51 %52 - OpStore %16 %53 - OpBranch %18 - %20 = OpLabel - %57 = OpLoad %6 %13 - %58 = OpCompositeConstruct %54 %57 %57 %57 %57 - OpStore %56 %58 - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, DominanceAndPhiIssue) { - // Exposes an interesting scenario where a use in a phi stops being dominated - // by the block with which it is associated in the phi. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %17 = OpTypeBool - %18 = OpConstantTrue %17 - %19 = OpConstantFalse %17 - %20 = OpTypeInt 32 1 - %21 = OpConstant %20 5 - %22 = OpConstant %20 6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %16 %15 None - OpBranch %7 - %7 = OpLabel - OpSelectionMerge %13 None - OpBranchConditional %18 %8 %9 - %8 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %18 %10 %11 - %9 = OpLabel - OpBranch %16 - %10 = OpLabel - OpBranch %16 - %11 = OpLabel - %23 = OpIAdd %20 %21 %22 - OpBranch %12 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %14 - %14 = OpLabel - %24 = OpPhi %20 %23 %13 - OpBranchConditional %19 %15 %16 - %15 = OpLabel - OpBranch %6 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %17 = OpTypeBool - %18 = OpConstantTrue %17 - %19 = OpConstantFalse %17 - %20 = OpTypeInt 32 1 - %21 = OpConstant %20 5 - %22 = OpConstant %20 6 - %25 = OpUndef %20 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpSelectionMerge %16 None - OpBranchConditional %18 %7 %16 - %7 = OpLabel - OpSelectionMerge %13 None - OpBranchConditional %18 %8 %9 - %8 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %18 %10 %11 - %9 = OpLabel - OpBranch %13 - %10 = OpLabel - OpBranch %12 - %11 = OpLabel - %23 = OpIAdd %20 %21 %22 - OpBranch %12 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpBranch %14 - %14 = OpLabel - %24 = OpPhi %20 %25 %13 - OpBranchConditional %19 %16 %16 - %15 = OpLabel - OpBranch %6 - %16 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, OpLineBeforeOpPhi) { - // Test to ensure the pass knows OpLine and OpPhi instructions can be - // interleaved. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpString "somefile" - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeInt 32 1 - %7 = OpConstant %6 10 - %8 = OpConstant %6 20 - %9 = OpConstant %6 30 - %10 = OpTypeBool - %11 = OpConstantTrue %10 - %2 = OpFunction %4 None %5 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpLoopMerge %14 %15 None - OpBranch %16 - %16 = OpLabel - OpSelectionMerge %17 None - OpBranchConditional %11 %18 %19 - %18 = OpLabel - %20 = OpIAdd %6 %7 %8 - %21 = OpIAdd %6 %7 %9 - OpBranch %17 - %19 = OpLabel - OpBranch %14 - %17 = OpLabel - %22 = OpPhi %6 %20 %18 - OpLine %3 0 0 - %23 = OpPhi %6 %21 %18 - OpBranch %15 - %15 = OpLabel - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpString "somefile" - %4 = OpTypeVoid - %5 = OpTypeFunction %4 - %6 = OpTypeInt 32 1 - %7 = OpConstant %6 10 - %8 = OpConstant %6 20 - %9 = OpConstant %6 30 - %10 = OpTypeBool - %11 = OpConstantTrue %10 - %24 = OpUndef %6 - %2 = OpFunction %4 None %5 - %12 = OpLabel - OpBranch %13 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %11 %16 %14 - %16 = OpLabel - OpSelectionMerge %17 None - OpBranchConditional %11 %18 %19 - %18 = OpLabel - %20 = OpIAdd %6 %7 %8 - %21 = OpIAdd %6 %7 %9 - OpBranch %17 - %19 = OpLabel - OpBranch %17 - %17 = OpLabel - %22 = OpPhi %6 %20 %18 %24 %19 - OpLine %3 0 0 - %23 = OpPhi %6 %21 %18 %24 %19 - OpBranch %14 - %15 = OpLabel - OpBranch %13 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - SelectionMergeIsContinueTarget) { - // Example where a loop's continue target is also the target of a selection. - // In this scenario we cautiously do not apply the transformation. - std::string shader = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %4 = OpTypeFunction %2 - %1 = OpFunction %2 None %4 - %5 = OpLabel - %6 = OpUndef %3 - OpBranch %7 - %7 = OpLabel - %8 = OpPhi %3 %6 %5 %9 %10 - OpLoopMerge %11 %10 None - OpBranch %12 - %12 = OpLabel - %13 = OpUndef %3 - OpSelectionMerge %10 None - OpBranchConditional %13 %14 %10 - %14 = OpLabel - OpBranch %10 - %10 = OpLabel - %9 = OpUndef %3 - OpBranchConditional %9 %7 %11 - %11 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - // There should be no opportunities. - ASSERT_EQ(0, ops.size()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - SwitchSelectionMergeIsContinueTarget) { - // Another example where a loop's continue target is also the target of a - // selection; this time a selection associated with an OpSwitch. We - // cautiously do not apply the transformation. - std::string shader = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %5 = OpTypeInt 32 1 - %4 = OpTypeFunction %2 - %6 = OpConstant %5 2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %14 %15 None - OpBranchConditional %7 %10 %14 - %10 = OpLabel - OpSelectionMerge %15 None - OpSwitch %6 %12 1 %11 2 %11 3 %15 - %11 = OpLabel - OpBranch %12 - %12 = OpLabel - OpBranch %15 - %15 = OpLabel - OpBranch %9 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - // There should be no opportunities. - ASSERT_EQ(0, ops.size()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, ContinueTargetIsSwitchTarget) { - std::string shader = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %5 = OpTypeInt 32 1 - %4 = OpTypeFunction %2 - %6 = OpConstant %5 2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %14 %12 None - OpBranchConditional %7 %10 %14 - %10 = OpLabel - OpSelectionMerge %15 None - OpSwitch %6 %12 1 %11 2 %11 3 %15 - %11 = OpLabel - OpBranch %12 - %12 = OpLabel - OpBranch %9 - %15 = OpLabel - OpBranch %14 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %5 = OpTypeInt 32 1 - %4 = OpTypeFunction %2 - %6 = OpConstant %5 2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %7 %10 %14 - %10 = OpLabel - OpSelectionMerge %15 None - OpSwitch %6 %15 1 %11 2 %11 3 %15 - %11 = OpLabel - OpBranch %15 - %12 = OpLabel - OpBranch %9 - %15 = OpLabel - OpBranch %14 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - MultipleSwitchTargetsAreContinueTarget) { - std::string shader = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %5 = OpTypeInt 32 1 - %4 = OpTypeFunction %2 - %6 = OpConstant %5 2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %14 %12 None - OpBranchConditional %7 %10 %14 - %10 = OpLabel - OpSelectionMerge %15 None - OpSwitch %6 %11 1 %12 2 %12 3 %15 - %11 = OpLabel - OpBranch %12 - %12 = OpLabel - OpBranch %9 - %15 = OpLabel - OpBranch %14 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %5 = OpTypeInt 32 1 - %4 = OpTypeFunction %2 - %6 = OpConstant %5 2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %7 %10 %14 - %10 = OpLabel - OpSelectionMerge %15 None - OpSwitch %6 %11 1 %15 2 %15 3 %15 - %11 = OpLabel - OpBranch %15 - %12 = OpLabel - OpBranch %9 - %15 = OpLabel - OpBranch %14 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, LoopBranchesStraightToMerge) { - std::string shader = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %4 = OpTypeFunction %2 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %14 %12 None - OpBranch %14 - %12 = OpLabel - OpBranch %9 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %4 = OpTypeFunction %2 - %15 = OpTypeBool - %16 = OpConstantTrue %15 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %16 %14 %14 - %12 = OpLabel - OpBranch %9 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - LoopConditionallyJumpsToMergeOrContinue) { - std::string shader = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %4 = OpTypeFunction %2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpLoopMerge %14 %12 None - OpBranchConditional %7 %14 %12 - %12 = OpLabel - OpBranch %9 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - %2 = OpTypeVoid - %3 = OpTypeBool - %4 = OpTypeFunction %2 - %7 = OpConstantTrue %3 - %1 = OpFunction %2 None %4 - %8 = OpLabel - OpBranch %9 - %9 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %7 %14 %14 - %12 = OpLabel - OpBranch %9 - %14 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, MultipleAccessChains) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeStruct %6 - %8 = OpTypeStruct %7 - %9 = OpTypePointer Function %8 - %11 = OpConstant %6 3 - %12 = OpConstantComposite %7 %11 - %13 = OpConstantComposite %8 %12 - %14 = OpTypePointer Function %7 - %16 = OpConstant %6 0 - %19 = OpTypePointer Function %6 - %15 = OpTypeBool - %18 = OpConstantTrue %15 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %10 = OpVariable %9 Function - %20 = OpVariable %19 Function - OpStore %10 %13 - OpBranch %23 - %23 = OpLabel - OpLoopMerge %25 %26 None - OpBranch %27 - %27 = OpLabel - OpSelectionMerge %28 None - OpBranchConditional %18 %29 %25 - %29 = OpLabel - %17 = OpAccessChain %14 %10 %16 - OpBranch %28 - %28 = OpLabel - %21 = OpAccessChain %19 %17 %16 - %22 = OpLoad %6 %21 - %24 = OpAccessChain %19 %10 %16 %16 - OpStore %24 %22 - OpBranch %25 - %26 = OpLabel - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %7 = OpTypeStruct %6 - %8 = OpTypeStruct %7 - %9 = OpTypePointer Function %8 - %11 = OpConstant %6 3 - %12 = OpConstantComposite %7 %11 - %13 = OpConstantComposite %8 %12 - %14 = OpTypePointer Function %7 - %16 = OpConstant %6 0 - %19 = OpTypePointer Function %6 - %15 = OpTypeBool - %18 = OpConstantTrue %15 - %4 = OpFunction %2 None %3 - %5 = OpLabel - %10 = OpVariable %9 Function - %20 = OpVariable %19 Function - %30 = OpVariable %14 Function - OpStore %10 %13 - OpBranch %23 - %23 = OpLabel - OpSelectionMerge %25 None - OpBranchConditional %18 %27 %25 - %27 = OpLabel - OpSelectionMerge %28 None - OpBranchConditional %18 %29 %28 - %29 = OpLabel - %17 = OpAccessChain %14 %10 %16 - OpBranch %28 - %28 = OpLabel - %21 = OpAccessChain %19 %30 %16 - %22 = OpLoad %6 %21 - %24 = OpAccessChain %19 %10 %16 %16 - OpStore %24 %22 - OpBranch %25 - %26 = OpLabel - OpBranch %23 - %25 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - UnreachableInnerLoopContinueBranchingToOuterLoopMerge) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpLoopMerge %9 %10 None - OpBranch %11 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %12 - %13 = OpLabel - OpBranchConditional %6 %9 %11 - %12 = OpLabel - OpBranch %10 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(2, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %6 %11 %9 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %12 - %13 = OpLabel - OpBranchConditional %6 %9 %11 - %12 = OpLabel - OpBranch %9 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - - CheckValid(env, context.get()); - - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %6 %11 %9 - %11 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %6 %12 %12 - %13 = OpLabel - OpBranchConditional %6 %9 %11 - %12 = OpLabel - OpBranch %9 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_1, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - UnreachableInnerLoopContinueBranchingToOuterLoopMerge2) { - // In this test, the branch to the outer loop merge from the inner loop's - // continue is part of a structured selection. - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpLoopMerge %9 %10 None - OpBranch %11 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %12 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %6 %9 %14 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %10 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(2, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %6 %11 %9 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranch %12 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %6 %9 %14 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %9 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - - ASSERT_TRUE(ops[1]->PreconditionHolds()); - ops[1]->TryToApply(); - - CheckValid(env, context.get()); - - std::string after_op_1 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %6 %11 %9 - %11 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %6 %12 %12 - %13 = OpLabel - OpSelectionMerge %14 None - OpBranchConditional %6 %9 %14 - %14 = OpLabel - OpBranch %11 - %12 = OpLabel - OpBranch %9 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_1, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - InnerLoopHeaderBranchesToOuterLoopMerge) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpLoopMerge %9 %10 None - OpBranch %11 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranchConditional %6 %9 %13 - %13 = OpLabel - OpBranchConditional %6 %11 %12 - %12 = OpLabel - OpBranch %10 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - // We cannot transform the inner loop due to its header jumping straight to - // the outer loop merge (the inner loop's merge does not post-dominate its - // header). - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %6 %11 %9 - %11 = OpLabel - OpLoopMerge %12 %13 None - OpBranchConditional %6 %12 %13 - %13 = OpLabel - OpBranchConditional %6 %11 %12 - %12 = OpLabel - OpBranch %9 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); - - // Now look again for more opportunities. - ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - // What was the inner loop should now be transformable, as the jump to the - // outer loop's merge has been redirected. - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - std::string after_another_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeBool - %6 = OpConstantTrue %5 - %2 = OpFunction %3 None %4 - %7 = OpLabel - OpBranch %8 - %8 = OpLabel - OpSelectionMerge %9 None - OpBranchConditional %6 %11 %9 - %11 = OpLabel - OpSelectionMerge %12 None - OpBranchConditional %6 %12 %12 - %13 = OpLabel - OpBranchConditional %6 %11 %12 - %12 = OpLabel - OpBranch %9 - %10 = OpLabel - OpBranchConditional %6 %9 %8 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_another_op_0, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, LongAccessChains) { - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %2 "main" - OpExecutionMode %2 OriginUpperLeft - OpSource ESSL 310 - %3 = OpTypeVoid - %4 = OpTypeFunction %3 - %5 = OpTypeInt 32 1 - %6 = OpTypeInt 32 0 - %7 = OpConstant %6 5 - %8 = OpTypeArray %5 %7 - %9 = OpTypeStruct %8 - %10 = OpTypeStruct %9 %9 - %11 = OpConstant %6 2 - %12 = OpTypeArray %10 %11 - %13 = OpTypeStruct %12 - %14 = OpTypePointer Function %13 - %15 = OpConstant %5 0 - %16 = OpConstant %5 1 - %17 = OpConstant %5 2 - %18 = OpConstant %5 3 - %19 = OpConstant %5 4 - %20 = OpConstantComposite %8 %15 %16 %17 %18 %19 - %21 = OpConstantComposite %9 %20 - %22 = OpConstant %5 5 - %23 = OpConstant %5 6 - %24 = OpConstant %5 7 - %25 = OpConstant %5 8 - %26 = OpConstant %5 9 - %27 = OpConstantComposite %8 %22 %23 %24 %25 %26 - %28 = OpConstantComposite %9 %27 - %29 = OpConstantComposite %10 %21 %28 - %30 = OpConstant %5 10 - %31 = OpConstant %5 11 - %32 = OpConstant %5 12 - %33 = OpConstant %5 13 - %34 = OpConstant %5 14 - %35 = OpConstantComposite %8 %30 %31 %32 %33 %34 - %36 = OpConstantComposite %9 %35 - %37 = OpConstant %5 15 - %38 = OpConstant %5 16 - %39 = OpConstant %5 17 - %40 = OpConstant %5 18 - %41 = OpConstant %5 19 - %42 = OpConstantComposite %8 %37 %38 %39 %40 %41 - %43 = OpConstantComposite %9 %42 - %44 = OpConstantComposite %10 %36 %43 - %45 = OpConstantComposite %12 %29 %44 - %46 = OpConstantComposite %13 %45 - %47 = OpTypePointer Function %12 - %48 = OpTypePointer Function %10 - %49 = OpTypePointer Function %9 - %50 = OpTypePointer Function %8 - %51 = OpTypePointer Function %5 - %52 = OpTypeBool - %53 = OpConstantTrue %52 - %2 = OpFunction %3 None %4 - %54 = OpLabel - %55 = OpVariable %14 Function - OpStore %55 %46 - OpBranch %56 - %56 = OpLabel - OpLoopMerge %57 %58 None - OpBranchConditional %53 %57 %59 - %59 = OpLabel - OpSelectionMerge %60 None - OpBranchConditional %53 %61 %57 - %61 = OpLabel - %62 = OpAccessChain %47 %55 %15 - OpBranch %63 - %63 = OpLabel - OpSelectionMerge %64 None - OpBranchConditional %53 %65 %57 - %65 = OpLabel - %66 = OpAccessChain %48 %62 %16 - OpBranch %67 - %67 = OpLabel - OpSelectionMerge %68 None - OpBranchConditional %53 %69 %57 - %69 = OpLabel - %70 = OpAccessChain %49 %66 %16 - OpBranch %71 - %71 = OpLabel - OpSelectionMerge %72 None - OpBranchConditional %53 %73 %57 - %73 = OpLabel - %74 = OpAccessChain %50 %70 %15 - OpBranch %75 - %75 = OpLabel - OpSelectionMerge %76 None - OpBranchConditional %53 %77 %57 - %77 = OpLabel - %78 = OpAccessChain %51 %74 %17 - OpBranch %79 - %79 = OpLabel - OpSelectionMerge %80 None - OpBranchConditional %53 %81 %57 - %81 = OpLabel - %82 = OpLoad %5 %78 - OpBranch %80 - %80 = OpLabel - OpBranch %76 - %76 = OpLabel - OpBranch %72 - %72 = OpLabel - OpBranch %68 - %68 = OpLabel - OpBranch %64 - %64 = OpLabel - OpBranch %60 - %60 = OpLabel - OpBranch %58 - %58 = OpLabel - OpBranch %56 - %57 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - - ASSERT_EQ(1, ops.size()); - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - - CheckValid(env, context.get()); - - // TODO(2183): When we have a more general solution for handling access - // chains, write an expected result for this test. - // std::string expected = R"( - // Expected text for transformed shader - //)"; - // CheckEqual(env, expected, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, LoopyShaderWithOpDecorate) { - // A shader containing a function that contains a loop and some definitions - // that are "used" in OpDecorate instructions (outside the function). These - // "uses" were causing segfaults because we try to calculate their dominance - // information, which doesn't make sense. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "_GLF_color" - OpName %14 "buf0" - OpMemberName %14 0 "a" - OpName %16 "" - OpDecorate %9 RelaxedPrecision - OpDecorate %9 Location 0 - OpMemberDecorate %14 0 RelaxedPrecision - OpMemberDecorate %14 0 Offset 0 - OpDecorate %14 Block - OpDecorate %16 DescriptorSet 0 - OpDecorate %16 Binding 0 - OpDecorate %21 RelaxedPrecision - OpDecorate %35 RelaxedPrecision - OpDecorate %36 RelaxedPrecision - OpDecorate %39 RelaxedPrecision - OpDecorate %40 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Output %7 - %9 = OpVariable %8 Output - %10 = OpConstant %6 1 - %11 = OpConstantComposite %7 %10 %10 %10 %10 - %14 = OpTypeStruct %6 - %15 = OpTypePointer Uniform %14 - %16 = OpVariable %15 Uniform - %17 = OpTypeInt 32 1 - %18 = OpConstant %17 0 - %19 = OpTypePointer Uniform %6 - %28 = OpConstant %6 2 - %29 = OpTypeBool - %31 = OpTypeInt 32 0 - %32 = OpConstant %31 0 - %33 = OpTypePointer Output %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpStore %9 %11 - %20 = OpAccessChain %19 %16 %18 - %21 = OpLoad %6 %20 - OpBranch %22 - %22 = OpLabel - %40 = OpPhi %6 %21 %5 %39 %23 - %30 = OpFOrdLessThan %29 %40 %28 - OpLoopMerge %24 %23 None - OpBranchConditional %30 %23 %24 - %23 = OpLabel - %34 = OpAccessChain %33 %9 %32 - %35 = OpLoad %6 %34 - %36 = OpFAdd %6 %35 %10 - OpStore %34 %36 - %39 = OpFAdd %6 %40 %10 - OpBranch %22 - %24 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(1, ops.size()); - - ASSERT_TRUE(ops[0]->PreconditionHolds()); - ops[0]->TryToApply(); - CheckValid(env, context.get()); - - std::string after_op_0 = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %9 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %9 "_GLF_color" - OpName %14 "buf0" - OpMemberName %14 0 "a" - OpName %16 "" - OpDecorate %9 RelaxedPrecision - OpDecorate %9 Location 0 - OpMemberDecorate %14 0 RelaxedPrecision - OpMemberDecorate %14 0 Offset 0 - OpDecorate %14 Block - OpDecorate %16 DescriptorSet 0 - OpDecorate %16 Binding 0 - OpDecorate %21 RelaxedPrecision - OpDecorate %35 RelaxedPrecision - OpDecorate %36 RelaxedPrecision - OpDecorate %39 RelaxedPrecision - OpDecorate %40 RelaxedPrecision - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeFloat 32 - %7 = OpTypeVector %6 4 - %8 = OpTypePointer Output %7 - %9 = OpVariable %8 Output - %10 = OpConstant %6 1 - %11 = OpConstantComposite %7 %10 %10 %10 %10 - %14 = OpTypeStruct %6 - %15 = OpTypePointer Uniform %14 - %16 = OpVariable %15 Uniform - %17 = OpTypeInt 32 1 - %18 = OpConstant %17 0 - %19 = OpTypePointer Uniform %6 - %28 = OpConstant %6 2 - %29 = OpTypeBool - %31 = OpTypeInt 32 0 - %32 = OpConstant %31 0 - %33 = OpTypePointer Output %6 - %41 = OpUndef %6 ; Added - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpStore %9 %11 - %20 = OpAccessChain %19 %16 %18 - %21 = OpLoad %6 %20 - OpBranch %22 - %22 = OpLabel - %40 = OpPhi %6 %21 %5 %41 %23 ; Changed - %30 = OpFOrdLessThan %29 %40 %28 - OpSelectionMerge %24 None ; Changed - OpBranchConditional %30 %24 %24 - %23 = OpLabel - %34 = OpAccessChain %33 %9 %32 - %35 = OpLoad %6 %34 - %36 = OpFAdd %6 %35 %10 - OpStore %34 %36 - %39 = OpFAdd %6 %41 %10 ; Changed - OpBranch %22 - %24 = OpLabel - OpReturn - OpFunctionEnd - )"; - CheckEqual(env, after_op_0, context.get()); -} - -TEST(StructuredLoopToSelectionReductionPassTest, - LoopWithCombinedHeaderAndContinue) { - // A shader containing a loop where the header is also the continue target. - // For now, we don't simplify such loops. - - std::string shader = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeBool - %30 = OpConstantFalse %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel ; loop header and continue target - OpLoopMerge %12 %10 None - OpBranchConditional %30 %10 %12 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - const auto env = SPV_ENV_UNIVERSAL_1_3; - const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption); - const auto ops = StructuredLoopToSelectionReductionOpportunityFinder() - .GetAvailableOpportunities(context.get()); - ASSERT_EQ(0, ops.size()); -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/reduce/validation_during_reduction_test.cpp b/3rdparty/spirv-tools/test/reduce/validation_during_reduction_test.cpp deleted file mode 100644 index 2981c2ed8..000000000 --- a/3rdparty/spirv-tools/test/reduce/validation_during_reduction_test.cpp +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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 "source/reduce/reducer.h" -#include "source/reduce/reduction_opportunity.h" -#include "source/reduce/remove_instruction_reduction_opportunity.h" -#include "test/reduce/reduce_test_util.h" - -namespace spvtools { -namespace reduce { -namespace { - -using opt::Function; -using opt::Instruction; -using opt::IRContext; - -// A dumb reduction opportunity finder that finds opportunities to remove global -// values regardless of whether they are referenced. This is very likely to make -// the resulting module invalid. We use this to test the reducer's behavior in -// the scenario where a bad reduction pass leads to an invalid module. -class BlindlyRemoveGlobalValuesReductionOpportunityFinder - : public ReductionOpportunityFinder { - public: - BlindlyRemoveGlobalValuesReductionOpportunityFinder() = default; - - ~BlindlyRemoveGlobalValuesReductionOpportunityFinder() override = default; - - // The name of this pass. - std::string GetName() const final { return "BlindlyRemoveGlobalValuesPass"; } - - // Finds opportunities to remove all global values. Assuming they are all - // referenced (directly or indirectly) from elsewhere in the module, each such - // opportunity will make the module invalid. - std::vector> GetAvailableOpportunities( - IRContext* context) const final { - std::vector> result; - for (auto& inst : context->module()->types_values()) { - if (inst.HasResultId()) { - result.push_back( - MakeUnique(&inst)); - } - } - return result; - } -}; - -// A dumb reduction opportunity that exists at the start of every function whose -// first instruction is an OpVariable instruction. When applied, the OpVariable -// instruction is duplicated (with a fresh result id). This allows each -// reduction step to increase the number of variables to check if the validator -// limits are enforced. -class OpVariableDuplicatorReductionOpportunity : public ReductionOpportunity { - public: - OpVariableDuplicatorReductionOpportunity(Function* function) - : function_(function) {} - - bool PreconditionHolds() override { - Instruction* first_instruction = &*function_->begin()[0].begin(); - return first_instruction->opcode() == SpvOpVariable; - } - - protected: - void Apply() override { - // Duplicate the first OpVariable instruction. - - Instruction* first_instruction = &*function_->begin()[0].begin(); - assert(first_instruction->opcode() == SpvOpVariable && - "Expected first instruction to be OpVariable"); - IRContext* context = first_instruction->context(); - Instruction* cloned_instruction = first_instruction->Clone(context); - cloned_instruction->SetResultId(context->TakeNextId()); - cloned_instruction->InsertBefore(first_instruction); - } - - private: - Function* function_; -}; - -// A reduction opportunity finder that finds -// OpVariableDuplicatorReductionOpportunity. -class OpVariableDuplicatorReductionOpportunityFinder - : public ReductionOpportunityFinder { - public: - OpVariableDuplicatorReductionOpportunityFinder() = default; - - ~OpVariableDuplicatorReductionOpportunityFinder() override = default; - - std::string GetName() const final { - return "LocalVariableAdderReductionOpportunityFinder"; - } - - std::vector> GetAvailableOpportunities( - IRContext* context) const final { - std::vector> result; - for (auto& function : *context->module()) { - Instruction* first_instruction = &*function.begin()[0].begin(); - if (first_instruction->opcode() == SpvOpVariable) { - result.push_back( - MakeUnique(&function)); - } - } - return result; - } -}; - -TEST(ValidationDuringReductionTest, CheckInvalidPassMakesNoProgress) { - // A module whose global values are all referenced, so that any application of - // MakeModuleInvalidPass will make the module invalid. Check that the reducer - // makes no progress, as every step will be invalid and treated as - // uninteresting. - std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %60 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %16 "buf2" - OpMemberName %16 0 "i" - OpName %18 "" - OpName %25 "buf1" - OpMemberName %25 0 "f" - OpName %27 "" - OpName %60 "_GLF_color" - OpMemberDecorate %16 0 Offset 0 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 2 - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 1 - OpDecorate %60 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpTypeStruct %6 - %17 = OpTypePointer Uniform %16 - %18 = OpVariable %17 Uniform - %19 = OpTypePointer Uniform %6 - %22 = OpTypeBool - %24 = OpTypeFloat 32 - %25 = OpTypeStruct %24 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %28 = OpTypePointer Uniform %24 - %31 = OpConstant %24 2 - %56 = OpConstant %6 1 - %58 = OpTypeVector %24 4 - %59 = OpTypePointer Output %58 - %60 = OpVariable %59 Output - %72 = OpUndef %24 - %74 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %73 = OpPhi %6 %74 %5 %77 %34 - %71 = OpPhi %24 %72 %5 %76 %34 - %70 = OpPhi %6 %9 %5 %57 %34 - %20 = OpAccessChain %19 %18 %9 - %21 = OpLoad %6 %20 - %23 = OpSLessThan %22 %70 %21 - OpLoopMerge %12 %34 None - OpBranchConditional %23 %11 %12 - %11 = OpLabel - %29 = OpAccessChain %28 %27 %9 - %30 = OpLoad %24 %29 - %32 = OpFOrdGreaterThan %22 %30 %31 - OpSelectionMerge %90 None - OpBranchConditional %32 %33 %46 - %33 = OpLabel - %40 = OpFAdd %24 %71 %30 - %45 = OpISub %6 %73 %21 - OpBranch %90 - %46 = OpLabel - %50 = OpFMul %24 %71 %30 - %54 = OpSDiv %6 %73 %21 - OpBranch %90 - %90 = OpLabel - %77 = OpPhi %6 %45 %33 %54 %46 - %76 = OpPhi %24 %40 %33 %50 %46 - OpBranch %34 - %34 = OpLabel - %57 = OpIAdd %6 %70 %56 - OpBranch %10 - %12 = OpLabel - %61 = OpAccessChain %28 %27 %9 - %62 = OpLoad %24 %61 - %66 = OpConvertSToF %24 %21 - %68 = OpConvertSToF %24 %73 - %69 = OpCompositeConstruct %58 %62 %71 %66 %68 - OpStore %60 %69 - OpReturn - OpFunctionEnd - )"; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - Reducer reducer(env); - reducer.SetMessageConsumer(NopDiagnostic); - - // Say that every module is interesting. - reducer.SetInterestingnessFunction( - [](const std::vector&, uint32_t) -> bool { return true; }); - - reducer.AddReductionPass( - MakeUnique()); - - std::vector binary_in; - SpirvTools t(env); - - ASSERT_TRUE(t.Assemble(original, &binary_in, kReduceAssembleOption)); - std::vector binary_out; - spvtools::ReducerOptions reducer_options; - reducer_options.set_step_limit(500); - // Don't fail on a validation error; just treat it as uninteresting. - reducer_options.set_fail_on_validation_error(false); - spvtools::ValidatorOptions validator_options; - - Reducer::ReductionResultStatus status = reducer.Run( - std::move(binary_in), &binary_out, reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete); - - // The reducer should have no impact. - CheckEqual(env, original, binary_out); -} - -TEST(ValidationDuringReductionTest, CheckNotAlwaysInvalidCanMakeProgress) { - // A module with just one unreferenced global value. All but one application - // of MakeModuleInvalidPass will make the module invalid. - std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %60 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %16 "buf2" - OpMemberName %16 0 "i" - OpName %18 "" - OpName %25 "buf1" - OpMemberName %25 0 "f" - OpName %27 "" - OpName %60 "_GLF_color" - OpMemberDecorate %16 0 Offset 0 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 2 - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 1 - OpDecorate %60 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpTypeStruct %6 - %17 = OpTypePointer Uniform %16 - %18 = OpVariable %17 Uniform - %19 = OpTypePointer Uniform %6 - %22 = OpTypeBool - %24 = OpTypeFloat 32 - %25 = OpTypeStruct %24 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %28 = OpTypePointer Uniform %24 - %31 = OpConstant %24 2 - %56 = OpConstant %6 1 - %1000 = OpConstant %6 1000 ; It should be possible to remove this instruction without making the module invalid. - %58 = OpTypeVector %24 4 - %59 = OpTypePointer Output %58 - %60 = OpVariable %59 Output - %72 = OpUndef %24 - %74 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %73 = OpPhi %6 %74 %5 %77 %34 - %71 = OpPhi %24 %72 %5 %76 %34 - %70 = OpPhi %6 %9 %5 %57 %34 - %20 = OpAccessChain %19 %18 %9 - %21 = OpLoad %6 %20 - %23 = OpSLessThan %22 %70 %21 - OpLoopMerge %12 %34 None - OpBranchConditional %23 %11 %12 - %11 = OpLabel - %29 = OpAccessChain %28 %27 %9 - %30 = OpLoad %24 %29 - %32 = OpFOrdGreaterThan %22 %30 %31 - OpSelectionMerge %90 None - OpBranchConditional %32 %33 %46 - %33 = OpLabel - %40 = OpFAdd %24 %71 %30 - %45 = OpISub %6 %73 %21 - OpBranch %90 - %46 = OpLabel - %50 = OpFMul %24 %71 %30 - %54 = OpSDiv %6 %73 %21 - OpBranch %90 - %90 = OpLabel - %77 = OpPhi %6 %45 %33 %54 %46 - %76 = OpPhi %24 %40 %33 %50 %46 - OpBranch %34 - %34 = OpLabel - %57 = OpIAdd %6 %70 %56 - OpBranch %10 - %12 = OpLabel - %61 = OpAccessChain %28 %27 %9 - %62 = OpLoad %24 %61 - %66 = OpConvertSToF %24 %21 - %68 = OpConvertSToF %24 %73 - %69 = OpCompositeConstruct %58 %62 %71 %66 %68 - OpStore %60 %69 - OpReturn - OpFunctionEnd - )"; - - // This is the same as the original, except that the constant declaration of - // 1000 is gone. - std::string expected = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "main" %60 - OpExecutionMode %4 OriginUpperLeft - OpSource ESSL 310 - OpName %4 "main" - OpName %16 "buf2" - OpMemberName %16 0 "i" - OpName %18 "" - OpName %25 "buf1" - OpMemberName %25 0 "f" - OpName %27 "" - OpName %60 "_GLF_color" - OpMemberDecorate %16 0 Offset 0 - OpDecorate %16 Block - OpDecorate %18 DescriptorSet 0 - OpDecorate %18 Binding 2 - OpMemberDecorate %25 0 Offset 0 - OpDecorate %25 Block - OpDecorate %27 DescriptorSet 0 - OpDecorate %27 Binding 1 - OpDecorate %60 Location 0 - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %6 = OpTypeInt 32 1 - %9 = OpConstant %6 0 - %16 = OpTypeStruct %6 - %17 = OpTypePointer Uniform %16 - %18 = OpVariable %17 Uniform - %19 = OpTypePointer Uniform %6 - %22 = OpTypeBool - %24 = OpTypeFloat 32 - %25 = OpTypeStruct %24 - %26 = OpTypePointer Uniform %25 - %27 = OpVariable %26 Uniform - %28 = OpTypePointer Uniform %24 - %31 = OpConstant %24 2 - %56 = OpConstant %6 1 - %58 = OpTypeVector %24 4 - %59 = OpTypePointer Output %58 - %60 = OpVariable %59 Output - %72 = OpUndef %24 - %74 = OpUndef %6 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpBranch %10 - %10 = OpLabel - %73 = OpPhi %6 %74 %5 %77 %34 - %71 = OpPhi %24 %72 %5 %76 %34 - %70 = OpPhi %6 %9 %5 %57 %34 - %20 = OpAccessChain %19 %18 %9 - %21 = OpLoad %6 %20 - %23 = OpSLessThan %22 %70 %21 - OpLoopMerge %12 %34 None - OpBranchConditional %23 %11 %12 - %11 = OpLabel - %29 = OpAccessChain %28 %27 %9 - %30 = OpLoad %24 %29 - %32 = OpFOrdGreaterThan %22 %30 %31 - OpSelectionMerge %90 None - OpBranchConditional %32 %33 %46 - %33 = OpLabel - %40 = OpFAdd %24 %71 %30 - %45 = OpISub %6 %73 %21 - OpBranch %90 - %46 = OpLabel - %50 = OpFMul %24 %71 %30 - %54 = OpSDiv %6 %73 %21 - OpBranch %90 - %90 = OpLabel - %77 = OpPhi %6 %45 %33 %54 %46 - %76 = OpPhi %24 %40 %33 %50 %46 - OpBranch %34 - %34 = OpLabel - %57 = OpIAdd %6 %70 %56 - OpBranch %10 - %12 = OpLabel - %61 = OpAccessChain %28 %27 %9 - %62 = OpLoad %24 %61 - %66 = OpConvertSToF %24 %21 - %68 = OpConvertSToF %24 %73 - %69 = OpCompositeConstruct %58 %62 %71 %66 %68 - OpStore %60 %69 - OpReturn - OpFunctionEnd - )"; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - Reducer reducer(env); - reducer.SetMessageConsumer(NopDiagnostic); - - // Say that every module is interesting. - reducer.SetInterestingnessFunction( - [](const std::vector&, uint32_t) -> bool { return true; }); - - reducer.AddReductionPass( - MakeUnique()); - - std::vector binary_in; - SpirvTools t(env); - - ASSERT_TRUE(t.Assemble(original, &binary_in, kReduceAssembleOption)); - std::vector binary_out; - spvtools::ReducerOptions reducer_options; - reducer_options.set_step_limit(500); - // Don't fail on a validation error; just treat it as uninteresting. - reducer_options.set_fail_on_validation_error(false); - spvtools::ValidatorOptions validator_options; - - Reducer::ReductionResultStatus status = reducer.Run( - std::move(binary_in), &binary_out, reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete); - - CheckEqual(env, expected, binary_out); -} - -// Sets up a Reducer for use in the CheckValidationOptions test; avoids -// repetition. -void SetupReducerForCheckValidationOptions(Reducer* reducer) { - reducer->SetMessageConsumer(NopDiagnostic); - - // Say that every module is interesting. - reducer->SetInterestingnessFunction( - [](const std::vector&, uint32_t) -> bool { return true; }); - - // Each "reduction" step will duplicate the first OpVariable instruction in - // the function. - reducer->AddReductionPass( - MakeUnique()); -} - -TEST(ValidationDuringReductionTest, CheckValidationOptions) { - // A module that only validates when the "skip-block-layout" validator option - // is used. Also, the entry point's first instruction creates a local - // variable; this instruction will be duplicated on each reduction step. - std::string original = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %2 "Main" %3 - OpSource HLSL 600 - OpDecorate %3 BuiltIn Position - OpDecorate %4 DescriptorSet 0 - OpDecorate %4 Binding 99 - OpDecorate %5 ArrayStride 16 - OpMemberDecorate %6 0 Offset 0 - OpMemberDecorate %6 1 Offset 32 - OpMemberDecorate %6 1 MatrixStride 16 - OpMemberDecorate %6 1 ColMajor - OpMemberDecorate %6 2 Offset 96 - OpMemberDecorate %6 3 Offset 100 - OpMemberDecorate %6 4 Offset 112 - OpMemberDecorate %6 4 MatrixStride 16 - OpMemberDecorate %6 4 ColMajor - OpMemberDecorate %6 5 Offset 176 - OpDecorate %6 Block - %7 = OpTypeFloat 32 - %8 = OpTypeVector %7 4 - %9 = OpTypeMatrix %8 4 - %10 = OpTypeVector %7 2 - %11 = OpTypeInt 32 1 - %12 = OpTypeInt 32 0 - %13 = OpConstant %12 2 - %14 = OpConstant %11 1 - %15 = OpConstant %11 5 - %5 = OpTypeArray %8 %13 - %6 = OpTypeStruct %5 %9 %12 %10 %9 %7 - %16 = OpTypePointer Uniform %6 - %17 = OpTypePointer Output %8 - %18 = OpTypeVoid - %19 = OpTypeFunction %18 - %20 = OpTypePointer Uniform %7 - %4 = OpVariable %16 Uniform - %3 = OpVariable %17 Output - %21 = OpTypePointer Function %11 - %2 = OpFunction %18 None %19 - %22 = OpLabel - %23 = OpVariable %21 Function - %24 = OpAccessChain %20 %4 %15 - %25 = OpLoad %7 %24 - %26 = OpCompositeConstruct %8 %25 %25 %25 %25 - OpStore %3 %26 - OpReturn - OpFunctionEnd - )"; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - std::vector binary_in; - SpirvTools t(env); - - ASSERT_TRUE(t.Assemble(original, &binary_in, kReduceAssembleOption)); - std::vector binary_out; - spvtools::ReducerOptions reducer_options; - spvtools::ValidatorOptions validator_options; - - reducer_options.set_step_limit(3); - reducer_options.set_fail_on_validation_error(true); - - // Reduction should fail because the initial state is invalid without the - // "skip-block-layout" validator option. Note that the interestingness test - // always returns true. - { - Reducer reducer(env); - SetupReducerForCheckValidationOptions(&reducer); - - Reducer::ReductionResultStatus status = - reducer.Run(std::vector(binary_in), &binary_out, - reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kInitialStateInvalid); - } - - // Try again with validator option. - validator_options.SetSkipBlockLayout(true); - - // Reduction should hit step limit; module is seen as valid, interestingness - // test always succeeds, and the finder yields infinite opportunities. - { - Reducer reducer(env); - SetupReducerForCheckValidationOptions(&reducer); - - Reducer::ReductionResultStatus status = - reducer.Run(std::vector(binary_in), &binary_out, - reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kReachedStepLimit); - } - - // Now set a limit on the number of local variables. - validator_options.SetUniversalLimit(spv_validator_limit_max_local_variables, - 2); - - // Reduction should now fail due to reaching an invalid state; after one step, - // a local variable is added and the module becomes "invalid" given the - // validator limits. - { - Reducer reducer(env); - SetupReducerForCheckValidationOptions(&reducer); - - Reducer::ReductionResultStatus status = - reducer.Run(std::vector(binary_in), &binary_out, - reducer_options, validator_options); - - ASSERT_EQ(status, Reducer::ReductionResultStatus::kStateInvalid); - } -} - -} // namespace -} // namespace reduce -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/scripts/test_compact_ids.py b/3rdparty/spirv-tools/test/scripts/test_compact_ids.py deleted file mode 100644 index 6ca6e67b2..000000000 --- a/3rdparty/spirv-tools/test/scripts/test_compact_ids.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2017 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. -"""Tests correctness of opt pass tools/opt --compact-ids.""" - -import os.path -import sys -import tempfile - -def test_spirv_file(path, temp_dir): - optimized_spv_path = os.path.join(temp_dir, 'optimized.spv') - optimized_dis_path = os.path.join(temp_dir, 'optimized.dis') - converted_spv_path = os.path.join(temp_dir, 'converted.spv') - converted_dis_path = os.path.join(temp_dir, 'converted.dis') - - os.system('tools/spirv-opt ' + path + ' -o ' + optimized_spv_path + - ' --compact-ids') - os.system('tools/spirv-dis ' + optimized_spv_path + ' -o ' + - optimized_dis_path) - - os.system('tools/spirv-dis ' + path + ' -o ' + converted_dis_path) - os.system('tools/spirv-as ' + converted_dis_path + ' -o ' + - converted_spv_path) - os.system('tools/spirv-dis ' + converted_spv_path + ' -o ' + - converted_dis_path) - - with open(converted_dis_path, 'r') as f: - converted_dis = f.readlines()[3:] - - with open(optimized_dis_path, 'r') as f: - optimized_dis = f.readlines()[3:] - - return converted_dis == optimized_dis - -def print_usage(): - template= \ -"""{script} tests correctness of opt pass tools/opt --compact-ids - -USAGE: python {script} [] - -Requires tools/spirv-dis, tools/spirv-as and tools/spirv-opt to be in path -(call the script from the SPIRV-Tools build output directory). - -TIP: In order to test all .spv files under current dir use -find -name "*.spv" -print0 | xargs -0 -s 2000000 python {script} -""" - print(template.format(script=sys.argv[0])); - -def main(): - if not os.path.isfile('tools/spirv-dis'): - print('error: tools/spirv-dis not found') - print_usage() - exit(1) - - if not os.path.isfile('tools/spirv-as'): - print('error: tools/spirv-as not found') - print_usage() - exit(1) - - if not os.path.isfile('tools/spirv-opt'): - print('error: tools/spirv-opt not found') - print_usage() - exit(1) - - paths = sys.argv[1:] - if not paths: - print_usage() - - num_failed = 0 - - temp_dir = tempfile.mkdtemp() - - for path in paths: - success = test_spirv_file(path, temp_dir) - if not success: - print('Test failed for ' + path) - num_failed += 1 - - print('Tested ' + str(len(paths)) + ' files') - - if num_failed: - print(str(num_failed) + ' tests failed') - exit(1) - else: - print('All tests successful') - exit(0) - -if __name__ == '__main__': - main() diff --git a/3rdparty/spirv-tools/test/software_version_test.cpp b/3rdparty/spirv-tools/test/software_version_test.cpp deleted file mode 100644 index 80b944a30..000000000 --- a/3rdparty/spirv-tools/test/software_version_test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2015-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 "gmock/gmock.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::testing::AnyOf; -using ::testing::Eq; -using ::testing::Ge; -using ::testing::StartsWith; - -void CheckFormOfHighLevelVersion(const std::string& version) { - std::istringstream s(version); - char v = 'x'; - int year = -1; - char period = 'x'; - int index = -1; - s >> v >> year >> period >> index; - EXPECT_THAT(v, Eq('v')); - EXPECT_THAT(year, Ge(2016)); - EXPECT_THAT(period, Eq('.')); - EXPECT_THAT(index, Ge(0)); - EXPECT_TRUE(s.good() || s.eof()); - - std::string rest; - s >> rest; - EXPECT_THAT(rest, AnyOf("", "-dev")); -} - -TEST(SoftwareVersion, ShortIsCorrectForm) { - SCOPED_TRACE("short form"); - CheckFormOfHighLevelVersion(spvSoftwareVersionString()); -} - -TEST(SoftwareVersion, DetailedIsCorrectForm) { - const std::string detailed_version(spvSoftwareVersionDetailsString()); - EXPECT_THAT(detailed_version, StartsWith("SPIRV-Tools v")); - - // Parse the high level version. - const std::string from_v = - detailed_version.substr(detailed_version.find_first_of('v')); - const size_t first_space_after_v_or_npos = from_v.find_first_of(' '); - SCOPED_TRACE(detailed_version); - CheckFormOfHighLevelVersion(from_v.substr(0, first_space_after_v_or_npos)); - - // We don't actually care about what comes after the version number. -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/string_utils_test.cpp b/3rdparty/spirv-tools/test/string_utils_test.cpp deleted file mode 100644 index 58514158f..000000000 --- a/3rdparty/spirv-tools/test/string_utils_test.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) 2017 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 "gtest/gtest.h" -#include "source/util/string_utils.h" -#include "spirv-tools/libspirv.h" - -namespace spvtools { -namespace utils { -namespace { - -TEST(ToString, Int) { - EXPECT_EQ("0", ToString(0)); - EXPECT_EQ("1000", ToString(1000)); - EXPECT_EQ("-1", ToString(-1)); - EXPECT_EQ("0", ToString(0LL)); - EXPECT_EQ("1000", ToString(1000LL)); - EXPECT_EQ("-1", ToString(-1LL)); -} - -TEST(ToString, Uint) { - EXPECT_EQ("0", ToString(0U)); - EXPECT_EQ("1000", ToString(1000U)); - EXPECT_EQ("0", ToString(0ULL)); - EXPECT_EQ("1000", ToString(1000ULL)); -} - -TEST(ToString, Float) { - EXPECT_EQ("0", ToString(0.f)); - EXPECT_EQ("1000", ToString(1000.f)); - EXPECT_EQ("-1.5", ToString(-1.5f)); -} - -TEST(ToString, Double) { - EXPECT_EQ("0", ToString(0.)); - EXPECT_EQ("1000", ToString(1000.)); - EXPECT_EQ("-1.5", ToString(-1.5)); -} - -TEST(CardinalToOrdinal, Test) { - EXPECT_EQ("1st", CardinalToOrdinal(1)); - EXPECT_EQ("2nd", CardinalToOrdinal(2)); - EXPECT_EQ("3rd", CardinalToOrdinal(3)); - EXPECT_EQ("4th", CardinalToOrdinal(4)); - EXPECT_EQ("5th", CardinalToOrdinal(5)); - EXPECT_EQ("6th", CardinalToOrdinal(6)); - EXPECT_EQ("7th", CardinalToOrdinal(7)); - EXPECT_EQ("8th", CardinalToOrdinal(8)); - EXPECT_EQ("9th", CardinalToOrdinal(9)); - EXPECT_EQ("10th", CardinalToOrdinal(10)); - EXPECT_EQ("11th", CardinalToOrdinal(11)); - EXPECT_EQ("12th", CardinalToOrdinal(12)); - EXPECT_EQ("13th", CardinalToOrdinal(13)); - EXPECT_EQ("14th", CardinalToOrdinal(14)); - EXPECT_EQ("15th", CardinalToOrdinal(15)); - EXPECT_EQ("16th", CardinalToOrdinal(16)); - EXPECT_EQ("17th", CardinalToOrdinal(17)); - EXPECT_EQ("18th", CardinalToOrdinal(18)); - EXPECT_EQ("19th", CardinalToOrdinal(19)); - EXPECT_EQ("20th", CardinalToOrdinal(20)); - EXPECT_EQ("21st", CardinalToOrdinal(21)); - EXPECT_EQ("22nd", CardinalToOrdinal(22)); - EXPECT_EQ("23rd", CardinalToOrdinal(23)); - EXPECT_EQ("24th", CardinalToOrdinal(24)); - EXPECT_EQ("25th", CardinalToOrdinal(25)); - EXPECT_EQ("26th", CardinalToOrdinal(26)); - EXPECT_EQ("27th", CardinalToOrdinal(27)); - EXPECT_EQ("28th", CardinalToOrdinal(28)); - EXPECT_EQ("29th", CardinalToOrdinal(29)); - EXPECT_EQ("30th", CardinalToOrdinal(30)); - EXPECT_EQ("31st", CardinalToOrdinal(31)); - EXPECT_EQ("32nd", CardinalToOrdinal(32)); - EXPECT_EQ("33rd", CardinalToOrdinal(33)); - EXPECT_EQ("34th", CardinalToOrdinal(34)); - EXPECT_EQ("35th", CardinalToOrdinal(35)); - EXPECT_EQ("100th", CardinalToOrdinal(100)); - EXPECT_EQ("101st", CardinalToOrdinal(101)); - EXPECT_EQ("102nd", CardinalToOrdinal(102)); - EXPECT_EQ("103rd", CardinalToOrdinal(103)); - EXPECT_EQ("104th", CardinalToOrdinal(104)); - EXPECT_EQ("105th", CardinalToOrdinal(105)); - EXPECT_EQ("106th", CardinalToOrdinal(106)); - EXPECT_EQ("107th", CardinalToOrdinal(107)); - EXPECT_EQ("108th", CardinalToOrdinal(108)); - EXPECT_EQ("109th", CardinalToOrdinal(109)); - EXPECT_EQ("110th", CardinalToOrdinal(110)); - EXPECT_EQ("111th", CardinalToOrdinal(111)); - EXPECT_EQ("112th", CardinalToOrdinal(112)); - EXPECT_EQ("113th", CardinalToOrdinal(113)); - EXPECT_EQ("114th", CardinalToOrdinal(114)); - EXPECT_EQ("115th", CardinalToOrdinal(115)); - EXPECT_EQ("116th", CardinalToOrdinal(116)); - EXPECT_EQ("117th", CardinalToOrdinal(117)); - EXPECT_EQ("118th", CardinalToOrdinal(118)); - EXPECT_EQ("119th", CardinalToOrdinal(119)); - EXPECT_EQ("120th", CardinalToOrdinal(120)); - EXPECT_EQ("121st", CardinalToOrdinal(121)); - EXPECT_EQ("122nd", CardinalToOrdinal(122)); - EXPECT_EQ("123rd", CardinalToOrdinal(123)); - EXPECT_EQ("124th", CardinalToOrdinal(124)); - EXPECT_EQ("125th", CardinalToOrdinal(125)); - EXPECT_EQ("126th", CardinalToOrdinal(126)); - EXPECT_EQ("127th", CardinalToOrdinal(127)); - EXPECT_EQ("128th", CardinalToOrdinal(128)); - EXPECT_EQ("129th", CardinalToOrdinal(129)); - EXPECT_EQ("130th", CardinalToOrdinal(130)); - EXPECT_EQ("131st", CardinalToOrdinal(131)); - EXPECT_EQ("132nd", CardinalToOrdinal(132)); - EXPECT_EQ("133rd", CardinalToOrdinal(133)); - EXPECT_EQ("134th", CardinalToOrdinal(134)); - EXPECT_EQ("135th", CardinalToOrdinal(135)); - EXPECT_EQ("1000th", CardinalToOrdinal(1000)); - EXPECT_EQ("1001st", CardinalToOrdinal(1001)); - EXPECT_EQ("1002nd", CardinalToOrdinal(1002)); - EXPECT_EQ("1003rd", CardinalToOrdinal(1003)); - EXPECT_EQ("1004th", CardinalToOrdinal(1004)); - EXPECT_EQ("1005th", CardinalToOrdinal(1005)); - EXPECT_EQ("1006th", CardinalToOrdinal(1006)); - EXPECT_EQ("1007th", CardinalToOrdinal(1007)); - EXPECT_EQ("1008th", CardinalToOrdinal(1008)); - EXPECT_EQ("1009th", CardinalToOrdinal(1009)); - EXPECT_EQ("1010th", CardinalToOrdinal(1010)); - EXPECT_EQ("1011th", CardinalToOrdinal(1011)); - EXPECT_EQ("1012th", CardinalToOrdinal(1012)); - EXPECT_EQ("1013th", CardinalToOrdinal(1013)); - EXPECT_EQ("1014th", CardinalToOrdinal(1014)); - EXPECT_EQ("1015th", CardinalToOrdinal(1015)); - EXPECT_EQ("1016th", CardinalToOrdinal(1016)); - EXPECT_EQ("1017th", CardinalToOrdinal(1017)); - EXPECT_EQ("1018th", CardinalToOrdinal(1018)); - EXPECT_EQ("1019th", CardinalToOrdinal(1019)); - EXPECT_EQ("1020th", CardinalToOrdinal(1020)); - EXPECT_EQ("1021st", CardinalToOrdinal(1021)); - EXPECT_EQ("1022nd", CardinalToOrdinal(1022)); - EXPECT_EQ("1023rd", CardinalToOrdinal(1023)); - EXPECT_EQ("1024th", CardinalToOrdinal(1024)); - EXPECT_EQ("1025th", CardinalToOrdinal(1025)); - EXPECT_EQ("1026th", CardinalToOrdinal(1026)); - EXPECT_EQ("1027th", CardinalToOrdinal(1027)); - EXPECT_EQ("1028th", CardinalToOrdinal(1028)); - EXPECT_EQ("1029th", CardinalToOrdinal(1029)); - EXPECT_EQ("1030th", CardinalToOrdinal(1030)); - EXPECT_EQ("1031st", CardinalToOrdinal(1031)); - EXPECT_EQ("1032nd", CardinalToOrdinal(1032)); - EXPECT_EQ("1033rd", CardinalToOrdinal(1033)); - EXPECT_EQ("1034th", CardinalToOrdinal(1034)); - EXPECT_EQ("1035th", CardinalToOrdinal(1035)); - EXPECT_EQ("1200th", CardinalToOrdinal(1200)); - EXPECT_EQ("1201st", CardinalToOrdinal(1201)); - EXPECT_EQ("1202nd", CardinalToOrdinal(1202)); - EXPECT_EQ("1203rd", CardinalToOrdinal(1203)); - EXPECT_EQ("1204th", CardinalToOrdinal(1204)); - EXPECT_EQ("1205th", CardinalToOrdinal(1205)); - EXPECT_EQ("1206th", CardinalToOrdinal(1206)); - EXPECT_EQ("1207th", CardinalToOrdinal(1207)); - EXPECT_EQ("1208th", CardinalToOrdinal(1208)); - EXPECT_EQ("1209th", CardinalToOrdinal(1209)); - EXPECT_EQ("1210th", CardinalToOrdinal(1210)); - EXPECT_EQ("1211th", CardinalToOrdinal(1211)); - EXPECT_EQ("1212th", CardinalToOrdinal(1212)); - EXPECT_EQ("1213th", CardinalToOrdinal(1213)); - EXPECT_EQ("1214th", CardinalToOrdinal(1214)); - EXPECT_EQ("1215th", CardinalToOrdinal(1215)); - EXPECT_EQ("1216th", CardinalToOrdinal(1216)); - EXPECT_EQ("1217th", CardinalToOrdinal(1217)); - EXPECT_EQ("1218th", CardinalToOrdinal(1218)); - EXPECT_EQ("1219th", CardinalToOrdinal(1219)); - EXPECT_EQ("1220th", CardinalToOrdinal(1220)); - EXPECT_EQ("1221st", CardinalToOrdinal(1221)); - EXPECT_EQ("1222nd", CardinalToOrdinal(1222)); - EXPECT_EQ("1223rd", CardinalToOrdinal(1223)); - EXPECT_EQ("1224th", CardinalToOrdinal(1224)); - EXPECT_EQ("1225th", CardinalToOrdinal(1225)); -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/target_env_test.cpp b/3rdparty/spirv-tools/test/target_env_test.cpp deleted file mode 100644 index 9f80e8345..000000000 --- a/3rdparty/spirv-tools/test/target_env_test.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// 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 "gmock/gmock.h" -#include "source/spirv_target_env.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::testing::AnyOf; -using ::testing::Eq; -using ::testing::StartsWith; -using ::testing::ValuesIn; - -using TargetEnvTest = ::testing::TestWithParam; -TEST_P(TargetEnvTest, CreateContext) { - spv_target_env env = GetParam(); - spv_context context = spvContextCreate(env); - ASSERT_NE(nullptr, context); - spvContextDestroy(context); // Avoid leaking -} - -TEST_P(TargetEnvTest, ValidDescription) { - const char* description = spvTargetEnvDescription(GetParam()); - ASSERT_NE(nullptr, description); - ASSERT_THAT(description, StartsWith("SPIR-V ")); -} - -TEST_P(TargetEnvTest, ValidSpirvVersion) { - auto spirv_version = spvVersionForTargetEnv(GetParam()); - ASSERT_THAT(spirv_version, AnyOf(0x10000, 0x10100, 0x10200, 0x10300)); -} - -INSTANTIATE_TEST_SUITE_P(AllTargetEnvs, TargetEnvTest, - ValuesIn(spvtest::AllTargetEnvironments())); - -TEST(GetContextTest, InvalidTargetEnvProducesNull) { - // Use a value beyond the last valid enum value. - spv_context context = spvContextCreate(static_cast(30)); - EXPECT_EQ(context, nullptr); -} - -// A test case for parsing an environment string. -struct ParseCase { - const char* input; - bool success; // Expect to successfully parse? - spv_target_env env; // The parsed environment, if successful. -}; - -using TargetParseTest = ::testing::TestWithParam; - -TEST_P(TargetParseTest, InvalidTargetEnvProducesNull) { - spv_target_env env; - bool parsed = spvParseTargetEnv(GetParam().input, &env); - EXPECT_THAT(parsed, Eq(GetParam().success)); - EXPECT_THAT(env, Eq(GetParam().env)); -} - -INSTANTIATE_TEST_SUITE_P( - TargetParsing, TargetParseTest, - ValuesIn(std::vector{ - {"spv1.0", true, SPV_ENV_UNIVERSAL_1_0}, - {"spv1.1", true, SPV_ENV_UNIVERSAL_1_1}, - {"spv1.2", true, SPV_ENV_UNIVERSAL_1_2}, - {"spv1.3", true, SPV_ENV_UNIVERSAL_1_3}, - {"vulkan1.0", true, SPV_ENV_VULKAN_1_0}, - {"vulkan1.1", true, SPV_ENV_VULKAN_1_1}, - {"opencl2.1", true, SPV_ENV_OPENCL_2_1}, - {"opencl2.2", true, SPV_ENV_OPENCL_2_2}, - {"opengl4.0", true, SPV_ENV_OPENGL_4_0}, - {"opengl4.1", true, SPV_ENV_OPENGL_4_1}, - {"opengl4.2", true, SPV_ENV_OPENGL_4_2}, - {"opengl4.3", true, SPV_ENV_OPENGL_4_3}, - {"opengl4.5", true, SPV_ENV_OPENGL_4_5}, - {"opencl1.2", true, SPV_ENV_OPENCL_1_2}, - {"opencl1.2embedded", true, SPV_ENV_OPENCL_EMBEDDED_1_2}, - {"opencl2.0", true, SPV_ENV_OPENCL_2_0}, - {"opencl2.0embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_0}, - {"opencl2.1embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_1}, - {"opencl2.2embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_2}, - {"webgpu0", true, SPV_ENV_WEBGPU_0}, - {"opencl2.3", false, SPV_ENV_UNIVERSAL_1_0}, - {"opencl3.0", false, SPV_ENV_UNIVERSAL_1_0}, - {"vulkan1.2", false, SPV_ENV_UNIVERSAL_1_0}, - {"vulkan2.0", false, SPV_ENV_UNIVERSAL_1_0}, - {nullptr, false, SPV_ENV_UNIVERSAL_1_0}, - {"", false, SPV_ENV_UNIVERSAL_1_0}, - {"abc", false, SPV_ENV_UNIVERSAL_1_0}, - })); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/test_fixture.h b/3rdparty/spirv-tools/test/test_fixture.h deleted file mode 100644 index 436993e21..000000000 --- a/3rdparty/spirv-tools/test/test_fixture.h +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -#ifndef TEST_TEST_FIXTURE_H_ -#define TEST_TEST_FIXTURE_H_ - -#include -#include - -#include "test/unit_spirv.h" - -namespace spvtest { - -// RAII for spv_context. -struct ScopedContext { - ScopedContext(spv_target_env env = SPV_ENV_UNIVERSAL_1_0) - : context(spvContextCreate(env)) {} - ~ScopedContext() { spvContextDestroy(context); } - spv_context context; -}; - -// Common setup for TextToBinary tests. SetText() should be called to populate -// the actual test text. -template -class TextToBinaryTestBase : public T { - public: - // Shorthand for SPIR-V compilation result. - using SpirvVector = std::vector; - - // Offset into a SpirvVector at which the first instruction starts. - static const SpirvVector::size_type kFirstInstruction = 5; - - TextToBinaryTestBase() : diagnostic(nullptr), text(), binary(nullptr) { - char textStr[] = "substitute the text member variable with your test"; - text = {textStr, strlen(textStr)}; - } - - virtual ~TextToBinaryTestBase() { - DestroyBinary(); - if (diagnostic) spvDiagnosticDestroy(diagnostic); - } - - // Returns subvector v[from:end). - SpirvVector Subvector(const SpirvVector& v, SpirvVector::size_type from) { - assert(from <= v.size()); - return SpirvVector(v.begin() + from, v.end()); - } - - // Compiles SPIR-V text in the given assembly syntax format, asserting - // compilation success. Returns the compiled code. - SpirvVector CompileSuccessfully(const std::string& txt, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0) { - DestroyBinary(); - DestroyDiagnostic(); - spv_result_t status = - spvTextToBinary(ScopedContext(env).context, txt.c_str(), txt.size(), - &binary, &diagnostic); - EXPECT_EQ(SPV_SUCCESS, status) << txt; - SpirvVector code_copy; - if (status == SPV_SUCCESS) { - code_copy = SpirvVector(binary->code, binary->code + binary->wordCount); - DestroyBinary(); - } else { - spvDiagnosticPrint(diagnostic); - } - return code_copy; - } - - // Compiles SPIR-V text with the given format, asserting compilation failure. - // Returns the error message(s). - std::string CompileFailure(const std::string& txt, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0) { - DestroyBinary(); - DestroyDiagnostic(); - EXPECT_NE(SPV_SUCCESS, - spvTextToBinary(ScopedContext(env).context, txt.c_str(), - txt.size(), &binary, &diagnostic)) - << txt; - DestroyBinary(); - return diagnostic->error; - } - - // Encodes SPIR-V text into binary and then decodes the binary using - // given options. Returns the decoded text. - std::string EncodeAndDecodeSuccessfully( - const std::string& txt, - uint32_t disassemble_options = SPV_BINARY_TO_TEXT_OPTION_NONE, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0) { - DestroyBinary(); - DestroyDiagnostic(); - ScopedContext context(env); - disassemble_options |= SPV_BINARY_TO_TEXT_OPTION_NO_HEADER; - spv_result_t error = spvTextToBinary(context.context, txt.c_str(), - txt.size(), &binary, &diagnostic); - if (error) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - } - EXPECT_EQ(SPV_SUCCESS, error); - if (!binary) return ""; - - spv_text decoded_text; - error = spvBinaryToText(context.context, binary->code, binary->wordCount, - disassemble_options, &decoded_text, &diagnostic); - if (error) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - } - EXPECT_EQ(SPV_SUCCESS, error) << txt; - - const std::string decoded_string = decoded_text->str; - spvTextDestroy(decoded_text); - - return decoded_string; - } - - // Encodes SPIR-V text into binary. This is expected to succeed. - // The given words are then appended to the binary, and the result - // is then decoded. This is expected to fail. - // Returns the error message. - std::string EncodeSuccessfullyDecodeFailed( - const std::string& txt, const SpirvVector& words_to_append) { - DestroyBinary(); - DestroyDiagnostic(); - SpirvVector code = - spvtest::Concatenate({CompileSuccessfully(txt), words_to_append}); - - spv_text decoded_text; - EXPECT_NE(SPV_SUCCESS, - spvBinaryToText(ScopedContext().context, code.data(), code.size(), - SPV_BINARY_TO_TEXT_OPTION_NONE, &decoded_text, - &diagnostic)); - if (diagnostic) { - std::string error_message = diagnostic->error; - spvDiagnosticDestroy(diagnostic); - diagnostic = nullptr; - return error_message; - } - return ""; - } - - // Compiles SPIR-V text, asserts success, and returns the words representing - // the instructions. In particular, skip the words in the SPIR-V header. - SpirvVector CompiledInstructions(const std::string& txt, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0) { - const SpirvVector code = CompileSuccessfully(txt, env); - SpirvVector result; - // Extract just the instructions. - // If the code fails to compile, then return the empty vector. - // In any case, don't crash or invoke undefined behaviour. - if (code.size() >= kFirstInstruction) - result = Subvector(code, kFirstInstruction); - return result; - } - - void SetText(const std::string& code) { - textString = code; - text.str = textString.c_str(); - text.length = textString.size(); - } - - // Destroys the binary, if it exists. - void DestroyBinary() { - spvBinaryDestroy(binary); - binary = nullptr; - } - - // Destroys the diagnostic, if it exists. - void DestroyDiagnostic() { - spvDiagnosticDestroy(diagnostic); - diagnostic = nullptr; - } - - spv_diagnostic diagnostic; - - std::string textString; - spv_text_t text; - spv_binary binary; -}; - -using TextToBinaryTest = TextToBinaryTestBase<::testing::Test>; -} // namespace spvtest - -using RoundTripTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -#endif // TEST_TEST_FIXTURE_H_ diff --git a/3rdparty/spirv-tools/test/text_advance_test.cpp b/3rdparty/spirv-tools/test/text_advance_test.cpp deleted file mode 100644 index 9de77a836..000000000 --- a/3rdparty/spirv-tools/test/text_advance_test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::AutoText; - -TEST(TextAdvance, LeadingNewLines) { - AutoText input("\n\nWord"); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_SUCCESS, data.advance()); - ASSERT_EQ(0u, data.position().column); - ASSERT_EQ(2u, data.position().line); - ASSERT_EQ(2u, data.position().index); -} - -TEST(TextAdvance, LeadingSpaces) { - AutoText input(" Word"); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_SUCCESS, data.advance()); - ASSERT_EQ(4u, data.position().column); - ASSERT_EQ(0u, data.position().line); - ASSERT_EQ(4u, data.position().index); -} - -TEST(TextAdvance, LeadingTabs) { - AutoText input("\t\t\tWord"); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_SUCCESS, data.advance()); - ASSERT_EQ(3u, data.position().column); - ASSERT_EQ(0u, data.position().line); - ASSERT_EQ(3u, data.position().index); -} - -TEST(TextAdvance, LeadingNewLinesSpacesAndTabs) { - AutoText input("\n\n\t Word"); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_SUCCESS, data.advance()); - ASSERT_EQ(3u, data.position().column); - ASSERT_EQ(2u, data.position().line); - ASSERT_EQ(5u, data.position().index); -} - -TEST(TextAdvance, LeadingWhitespaceAfterCommentLine) { - AutoText input("; comment\n \t \tWord"); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_SUCCESS, data.advance()); - ASSERT_EQ(4u, data.position().column); - ASSERT_EQ(1u, data.position().line); - ASSERT_EQ(14u, data.position().index); -} - -TEST(TextAdvance, EOFAfterCommentLine) { - AutoText input("; comment"); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_END_OF_STREAM, data.advance()); -} - -TEST(TextAdvance, NullTerminator) { - AutoText input(""); - AssemblyContext data(input, nullptr); - ASSERT_EQ(SPV_END_OF_STREAM, data.advance()); -} - -TEST(TextAdvance, NoNullTerminatorAfterCommentLine) { - std::string input = "; comment|padding beyond the end"; - spv_text_t text = {input.data(), 9}; - AssemblyContext data(&text, nullptr); - ASSERT_EQ(SPV_END_OF_STREAM, data.advance()); - EXPECT_EQ(9u, data.position().index); -} - -TEST(TextAdvance, NoNullTerminator) { - spv_text_t text = {"OpNop\nSomething else in memory", 6}; - AssemblyContext data(&text, nullptr); - const spv_position_t line_break = {1u, 5u, 5u}; - data.setPosition(line_break); - ASSERT_EQ(SPV_END_OF_STREAM, data.advance()); -} - -// Invokes AssemblyContext::advance() on text, asserts success, and returns -// AssemblyContext::position(). -spv_position_t PositionAfterAdvance(const char* text) { - AutoText input(text); - AssemblyContext data(input, nullptr); - EXPECT_EQ(SPV_SUCCESS, data.advance()); - return data.position(); -} - -TEST(TextAdvance, SkipOverCR) { - const auto pos = PositionAfterAdvance("\rWord"); - EXPECT_EQ(1u, pos.column); - EXPECT_EQ(0u, pos.line); - EXPECT_EQ(1u, pos.index); -} - -TEST(TextAdvance, SkipOverCRs) { - const auto pos = PositionAfterAdvance("\r\r\rWord"); - EXPECT_EQ(3u, pos.column); - EXPECT_EQ(0u, pos.line); - EXPECT_EQ(3u, pos.index); -} - -TEST(TextAdvance, SkipOverCRLF) { - const auto pos = PositionAfterAdvance("\r\nWord"); - EXPECT_EQ(0u, pos.column); - EXPECT_EQ(1u, pos.line); - EXPECT_EQ(2u, pos.index); -} - -TEST(TextAdvance, SkipOverCRLFs) { - const auto pos = PositionAfterAdvance("\r\n\r\nWord"); - EXPECT_EQ(0u, pos.column); - EXPECT_EQ(2u, pos.line); - EXPECT_EQ(4u, pos.index); -} -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_destroy_test.cpp b/3rdparty/spirv-tools/test/text_destroy_test.cpp deleted file mode 100644 index 4c2837ba6..000000000 --- a/3rdparty/spirv-tools/test/text_destroy_test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -TEST(TextDestroy, DestroyNull) { spvBinaryDestroy(nullptr); } - -TEST(TextDestroy, Default) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); - char textStr[] = R"( - OpSource OpenCL_C 12 - OpMemoryModel Physical64 OpenCL - OpSourceExtension "PlaceholderExtensionName" - OpEntryPoint Kernel %0 "" - OpExecutionMode %0 LocalSizeHint 1 1 1 - %1 = OpTypeVoid - %2 = OpTypeBool - %3 = OpTypeInt 8 0 - %4 = OpTypeInt 8 1 - %5 = OpTypeInt 16 0 - %6 = OpTypeInt 16 1 - %7 = OpTypeInt 32 0 - %8 = OpTypeInt 32 1 - %9 = OpTypeInt 64 0 - %10 = OpTypeInt 64 1 - %11 = OpTypeFloat 16 - %12 = OpTypeFloat 32 - %13 = OpTypeFloat 64 - %14 = OpTypeVector %3 2 - )"; - - spv_binary binary = nullptr; - spv_diagnostic diagnostic = nullptr; - EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, textStr, strlen(textStr), - &binary, &diagnostic)); - EXPECT_NE(nullptr, binary); - EXPECT_NE(nullptr, binary->code); - EXPECT_NE(0u, binary->wordCount); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - ASSERT_TRUE(false); - } - - spv_text resultText = nullptr; - EXPECT_EQ(SPV_SUCCESS, - spvBinaryToText(context, binary->code, binary->wordCount, 0, - &resultText, &diagnostic)); - spvBinaryDestroy(binary); - if (diagnostic) { - spvDiagnosticPrint(diagnostic); - spvDiagnosticDestroy(diagnostic); - ASSERT_TRUE(false); - } - EXPECT_NE(nullptr, resultText->str); - EXPECT_NE(0u, resultText->length); - spvTextDestroy(resultText); - spvContextDestroy(context); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_literal_test.cpp b/3rdparty/spirv-tools/test/text_literal_test.cpp deleted file mode 100644 index 28e3500de..000000000 --- a/3rdparty/spirv-tools/test/text_literal_test.cpp +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::testing::Eq; - -TEST(TextLiteral, GoodI32) { - spv_literal_t l; - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-0", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_INT_32, l.type); - EXPECT_EQ(0, l.value.i32); - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-2147483648", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_INT_32, l.type); - EXPECT_EQ((-2147483647L - 1), l.value.i32); -} - -TEST(TextLiteral, GoodU32) { - spv_literal_t l; - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("0", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_UINT_32, l.type); - EXPECT_EQ(0, l.value.i32); - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("4294967295", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_UINT_32, l.type); - EXPECT_EQ(4294967295, l.value.u32); -} - -TEST(TextLiteral, GoodI64) { - spv_literal_t l; - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-2147483649", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_INT_64, l.type); - EXPECT_EQ(-2147483649LL, l.value.i64); -} - -TEST(TextLiteral, GoodU64) { - spv_literal_t l; - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("4294967296", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_UINT_64, l.type); - EXPECT_EQ(4294967296u, l.value.u64); -} - -TEST(TextLiteral, GoodFloat) { - spv_literal_t l; - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("1.0", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_FLOAT_32, l.type); - EXPECT_EQ(1.0, l.value.f); - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("1.5", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_FLOAT_32, l.type); - EXPECT_EQ(1.5, l.value.f); - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-.25", &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_FLOAT_32, l.type); - EXPECT_EQ(-.25, l.value.f); -} - -TEST(TextLiteral, BadString) { - spv_literal_t l; - - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("-", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("--", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("1-2", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("123a", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("12.2.3", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("\"", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("\"z", &l)); - EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("a\"", &l)); -} - -class GoodStringTest - : public ::testing::TestWithParam> {}; - -TEST_P(GoodStringTest, GoodStrings) { - spv_literal_t l; - - ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral(std::get<0>(GetParam()), &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_STRING, l.type); - EXPECT_EQ(std::get<1>(GetParam()), l.str); -} - -INSTANTIATE_TEST_SUITE_P( - TextLiteral, GoodStringTest, - ::testing::ValuesIn(std::vector>{ - {R"("-")", "-"}, - {R"("--")", "--"}, - {R"("1-2")", "1-2"}, - {R"("123a")", "123a"}, - {R"("12.2.3")", "12.2.3"}, - {R"("\"")", "\""}, - {R"("\\")", "\\"}, - {"\"\\foo\nbar\"", "foo\nbar"}, - {"\"\\foo\\\nbar\"", "foo\nbar"}, - {"\"\xE4\xBA\xB2\"", "\xE4\xBA\xB2"}, - {"\"\\\xE4\xBA\xB2\"", "\xE4\xBA\xB2"}, - {"\"this \\\" and this \\\\ and \\\xE4\xBA\xB2\"", - "this \" and this \\ and \xE4\xBA\xB2"}})); - -TEST(TextLiteral, StringTooLong) { - spv_literal_t l; - std::string too_long = - std::string("\"") + - std::string(SPV_LIMIT_LITERAL_STRING_BYTES_MAX + 1, 'a') + "\""; - EXPECT_EQ(SPV_ERROR_OUT_OF_MEMORY, spvTextToLiteral(too_long.data(), &l)); -} - -TEST(TextLiteral, GoodLongString) { - spv_literal_t l; - // The universal limit of 65535 Unicode characters might make this - // fail validation, since SPV_LIMIT_LITERAL_STRING_BYTES_MAX is 4*65535. - // However, as an implementation detail, we'll allow the assembler - // to parse it. Otherwise we'd have to scan the string for valid UTF-8 - // characters. - std::string unquoted(SPV_LIMIT_LITERAL_STRING_BYTES_MAX, 'a'); - std::string good_long = std::string("\"") + unquoted + "\""; - EXPECT_EQ(SPV_SUCCESS, spvTextToLiteral(good_long.data(), &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_STRING, l.type); - EXPECT_EQ(unquoted.data(), l.str); -} - -TEST(TextLiteral, GoodUTF8String) { - const std::string unquoted = - spvtest::MakeLongUTF8String(SPV_LIMIT_LITERAL_STRING_UTF8_CHARS_MAX); - const std::string good_long = std::string("\"") + unquoted + "\""; - spv_literal_t l; - EXPECT_EQ(SPV_SUCCESS, spvTextToLiteral(good_long.data(), &l)); - EXPECT_EQ(SPV_LITERAL_TYPE_STRING, l.type); - EXPECT_EQ(unquoted.data(), l.str); -} - -// A test case for parsing literal numbers. -struct TextLiteralCase { - uint32_t bitwidth; - const char* text; - bool is_signed; - bool success; - std::vector expected_values; -}; - -using IntegerTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -std::vector successfulEncode(const TextLiteralCase& test, - IdTypeClass type) { - spv_instruction_t inst; - std::string message; - auto capture_message = [&message](spv_message_level_t, const char*, - const spv_position_t&, - const char* m) { message = m; }; - IdType expected_type{test.bitwidth, test.is_signed, type}; - EXPECT_EQ(SPV_SUCCESS, - AssemblyContext(nullptr, capture_message) - .binaryEncodeNumericLiteral(test.text, SPV_ERROR_INVALID_TEXT, - expected_type, &inst)) - << message; - return inst.words; -} - -std::string failedEncode(const TextLiteralCase& test, IdTypeClass type) { - spv_instruction_t inst; - std::string message; - auto capture_message = [&message](spv_message_level_t, const char*, - const spv_position_t&, - const char* m) { message = m; }; - IdType expected_type{test.bitwidth, test.is_signed, type}; - EXPECT_EQ(SPV_ERROR_INVALID_TEXT, - AssemblyContext(nullptr, capture_message) - .binaryEncodeNumericLiteral(test.text, SPV_ERROR_INVALID_TEXT, - expected_type, &inst)); - return message; -} - -TEST_P(IntegerTest, IntegerBounds) { - if (GetParam().success) { - EXPECT_THAT(successfulEncode(GetParam(), IdTypeClass::kScalarIntegerType), - Eq(GetParam().expected_values)); - } else { - std::stringstream ss; - ss << "Integer " << GetParam().text << " does not fit in a " - << GetParam().bitwidth << "-bit " - << (GetParam().is_signed ? "signed" : "unsigned") << " integer"; - EXPECT_THAT(failedEncode(GetParam(), IdTypeClass::kScalarIntegerType), - Eq(ss.str())); - } -} - -// Four nicely named methods for making TextLiteralCase values. -// Their names have underscores in some places to make it easier -// to read the table that follows. -TextLiteralCase Make_Ok__Signed(uint32_t bitwidth, const char* text, - std::vector encoding) { - return TextLiteralCase{bitwidth, text, true, true, encoding}; -} -TextLiteralCase Make_Ok__Unsigned(uint32_t bitwidth, const char* text, - std::vector encoding) { - return TextLiteralCase{bitwidth, text, false, true, encoding}; -} -TextLiteralCase Make_Bad_Signed(uint32_t bitwidth, const char* text) { - return TextLiteralCase{bitwidth, text, true, false, {}}; -} -TextLiteralCase Make_Bad_Unsigned(uint32_t bitwidth, const char* text) { - return TextLiteralCase{bitwidth, text, false, false, {}}; -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - DecimalIntegers, IntegerTest, - ::testing::ValuesIn(std::vector{ - // Check max value and overflow value for 1-bit numbers. - Make_Ok__Signed(1, "0", {0}), - Make_Ok__Unsigned(1, "1", {1}), - Make_Bad_Signed(1, "1"), - Make_Bad_Unsigned(1, "2"), - - // Check max value and overflow value for 2-bit numbers. - Make_Ok__Signed(2, "1", {1}), - Make_Ok__Unsigned(2, "3", {3}), - Make_Bad_Signed(2, "2"), - Make_Bad_Unsigned(2, "4"), - - // Check max negative value and overflow value for signed - // 1- and 2-bit numbers. Signed negative numbers are sign-extended. - Make_Ok__Signed(1, "-0", {uint32_t(0)}), - Make_Ok__Signed(1, "-1", {uint32_t(-1)}), - Make_Ok__Signed(2, "-0", {0}), - Make_Ok__Signed(2, "-1", {uint32_t(-1)}), - Make_Ok__Signed(2, "-2", {uint32_t(-2)}), - Make_Bad_Signed(2, "-3"), - - Make_Bad_Unsigned(2, "2224323424242424"), - Make_Ok__Unsigned(16, "65535", {0xFFFF}), - Make_Bad_Unsigned(16, "65536"), - Make_Bad_Signed(16, "65535"), - Make_Ok__Signed(16, "32767", {0x7FFF}), - Make_Ok__Signed(16, "-32768", {0xFFFF8000}), - - // Check values around 32-bits in magnitude. - Make_Ok__Unsigned(33, "4294967296", {0, 1}), - Make_Ok__Unsigned(33, "4294967297", {1, 1}), - Make_Bad_Unsigned(33, "8589934592"), - Make_Bad_Signed(33, "4294967296"), - Make_Ok__Signed(33, "-4294967296", {0x0, 0xFFFFFFFF}), - Make_Ok__Unsigned(64, "4294967296", {0, 1}), - Make_Ok__Unsigned(64, "4294967297", {1, 1}), - - // Check max value and overflow value for 64-bit numbers. - Make_Ok__Signed(64, "9223372036854775807", {0xffffffff, 0x7fffffff}), - Make_Bad_Signed(64, "9223372036854775808"), - Make_Ok__Unsigned(64, "9223372036854775808", {0x00000000, 0x80000000}), - Make_Ok__Unsigned(64, "18446744073709551615", {0xffffffff, 0xffffffff}), - Make_Ok__Signed(64, "-9223372036854775808", {0x00000000, 0x80000000}), - - })); -// clang-format on - -using IntegerLeadingMinusTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(IntegerLeadingMinusTest, CantHaveLeadingMinusOnUnsigned) { - EXPECT_FALSE(GetParam().success); - EXPECT_THAT(failedEncode(GetParam(), IdTypeClass::kScalarIntegerType), - Eq("Cannot put a negative number in an unsigned literal")); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - DecimalAndHexIntegers, IntegerLeadingMinusTest, - ::testing::ValuesIn(std::vector{ - // Unsigned numbers never allow a leading minus sign. - Make_Bad_Unsigned(16, "-0"), - Make_Bad_Unsigned(16, "-0x0"), - Make_Bad_Unsigned(16, "-0x1"), - Make_Bad_Unsigned(32, "-0"), - Make_Bad_Unsigned(32, "-0x0"), - Make_Bad_Unsigned(32, "-0x1"), - Make_Bad_Unsigned(64, "-0"), - Make_Bad_Unsigned(64, "-0x0"), - Make_Bad_Unsigned(64, "-0x1"), - })); - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - HexIntegers, IntegerTest, - ::testing::ValuesIn(std::vector{ - // Check 0x and 0X prefices. - Make_Ok__Signed(16, "0x1234", {0x1234}), - Make_Ok__Signed(16, "0X1234", {0x1234}), - - // Check 1-bit numbers - Make_Ok__Signed(1, "0x0", {0}), - Make_Ok__Signed(1, "0x1", {uint32_t(-1)}), - Make_Ok__Unsigned(1, "0x0", {0}), - Make_Ok__Unsigned(1, "0x1", {1}), - Make_Bad_Signed(1, "0x2"), - Make_Bad_Unsigned(1, "0x2"), - - // Check 2-bit numbers - Make_Ok__Signed(2, "0x0", {0}), - Make_Ok__Signed(2, "0x1", {1}), - Make_Ok__Signed(2, "0x2", {uint32_t(-2)}), - Make_Ok__Signed(2, "0x3", {uint32_t(-1)}), - Make_Ok__Unsigned(2, "0x0", {0}), - Make_Ok__Unsigned(2, "0x1", {1}), - Make_Ok__Unsigned(2, "0x2", {2}), - Make_Ok__Unsigned(2, "0x3", {3}), - Make_Bad_Signed(2, "0x4"), - Make_Bad_Unsigned(2, "0x4"), - - // Check 8-bit numbers - Make_Ok__Signed(8, "0x7f", {0x7f}), - Make_Ok__Signed(8, "0x80", {0xffffff80}), - Make_Ok__Unsigned(8, "0x80", {0x80}), - Make_Ok__Unsigned(8, "0xff", {0xff}), - Make_Bad_Signed(8, "0x100"), - Make_Bad_Unsigned(8, "0x100"), - - // Check 16-bit numbers - Make_Ok__Signed(16, "0x7fff", {0x7fff}), - Make_Ok__Signed(16, "0x8000", {0xffff8000}), - Make_Ok__Unsigned(16, "0x8000", {0x8000}), - Make_Ok__Unsigned(16, "0xffff", {0xffff}), - Make_Bad_Signed(16, "0x10000"), - Make_Bad_Unsigned(16, "0x10000"), - - // Check 32-bit numbers - Make_Ok__Signed(32, "0x7fffffff", {0x7fffffff}), - Make_Ok__Signed(32, "0x80000000", {0x80000000}), - Make_Ok__Unsigned(32, "0x80000000", {0x80000000}), - Make_Ok__Unsigned(32, "0xffffffff", {0xffffffff}), - Make_Bad_Signed(32, "0x100000000"), - Make_Bad_Unsigned(32, "0x100000000"), - - // Check 48-bit numbers - Make_Ok__Unsigned(48, "0x7ffffffff", {0xffffffff, 7}), - Make_Ok__Unsigned(48, "0x800000000", {0, 8}), - Make_Ok__Signed(48, "0x7fffffffffff", {0xffffffff, 0x7fff}), - Make_Ok__Signed(48, "0x800000000000", {0, 0xffff8000}), - Make_Bad_Signed(48, "0x1000000000000"), - Make_Bad_Unsigned(48, "0x1000000000000"), - - // Check 64-bit numbers - Make_Ok__Signed(64, "0x7fffffffffffffff", {0xffffffff, 0x7fffffff}), - Make_Ok__Signed(64, "0x8000000000000000", {0x00000000, 0x80000000}), - Make_Ok__Unsigned(64, "0x7fffffffffffffff", {0xffffffff, 0x7fffffff}), - Make_Ok__Unsigned(64, "0x8000000000000000", {0x00000000, 0x80000000}), - })); -// clang-format on - -TEST(OverflowIntegerParse, Decimal) { - std::string signed_input = "-18446744073709551616"; - std::string expected_message0 = - "Invalid signed integer literal: " + signed_input; - EXPECT_THAT(failedEncode(Make_Bad_Signed(64, signed_input.c_str()), - IdTypeClass::kScalarIntegerType), - Eq(expected_message0)); - - std::string unsigned_input = "18446744073709551616"; - std::string expected_message1 = - "Invalid unsigned integer literal: " + unsigned_input; - EXPECT_THAT(failedEncode(Make_Bad_Unsigned(64, unsigned_input.c_str()), - IdTypeClass::kScalarIntegerType), - Eq(expected_message1)); - - // TODO(dneto): When the given number doesn't have a leading sign, - // we say we're trying to parse an unsigned number, even when the caller - // asked for a signed number. This is kind of weird, but it's an - // artefact of how we do the parsing. - EXPECT_THAT(failedEncode(Make_Bad_Signed(64, unsigned_input.c_str()), - IdTypeClass::kScalarIntegerType), - Eq(expected_message1)); -} - -TEST(OverflowIntegerParse, Hex) { - std::string input = "0x10000000000000000"; - std::string expected_message = "Invalid unsigned integer literal: " + input; - EXPECT_THAT(failedEncode(Make_Bad_Signed(64, input.c_str()), - IdTypeClass::kScalarIntegerType), - Eq(expected_message)); - EXPECT_THAT(failedEncode(Make_Bad_Unsigned(64, input.c_str()), - IdTypeClass::kScalarIntegerType), - Eq(expected_message)); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_start_new_inst_test.cpp b/3rdparty/spirv-tools/test/text_start_new_inst_test.cpp deleted file mode 100644 index ff35ac84c..000000000 --- a/3rdparty/spirv-tools/test/text_start_new_inst_test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::AutoText; - -TEST(TextStartsWithOp, YesAtStart) { - EXPECT_TRUE(AssemblyContext(AutoText("OpFoo"), nullptr).isStartOfNewInst()); - EXPECT_TRUE(AssemblyContext(AutoText("OpFoo"), nullptr).isStartOfNewInst()); - EXPECT_TRUE(AssemblyContext(AutoText("OpEnCL"), nullptr).isStartOfNewInst()); -} - -TEST(TextStartsWithOp, YesAtMiddle) { - { - AutoText text(" OpFoo"); - AssemblyContext dat(text, nullptr); - dat.seekForward(2); - EXPECT_TRUE(dat.isStartOfNewInst()); - } - { - AutoText text("xx OpFoo"); - AssemblyContext dat(text, nullptr); - dat.seekForward(2); - EXPECT_TRUE(dat.isStartOfNewInst()); - } -} - -TEST(TextStartsWithOp, NoIfTooFar) { - AutoText text(" OpFoo"); - AssemblyContext dat(text, nullptr); - dat.seekForward(3); - EXPECT_FALSE(dat.isStartOfNewInst()); -} - -TEST(TextStartsWithOp, NoRegular) { - EXPECT_FALSE( - AssemblyContext(AutoText("Fee Fi Fo Fum"), nullptr).isStartOfNewInst()); - EXPECT_FALSE(AssemblyContext(AutoText("123456"), nullptr).isStartOfNewInst()); - EXPECT_FALSE(AssemblyContext(AutoText("123456"), nullptr).isStartOfNewInst()); - EXPECT_FALSE(AssemblyContext(AutoText("OpenCL"), nullptr).isStartOfNewInst()); -} - -TEST(TextStartsWithOp, YesForValueGenerationForm) { - EXPECT_TRUE( - AssemblyContext(AutoText("%foo = OpAdd"), nullptr).isStartOfNewInst()); - EXPECT_TRUE( - AssemblyContext(AutoText("%foo = OpAdd"), nullptr).isStartOfNewInst()); -} - -TEST(TextStartsWithOp, NoForNearlyValueGeneration) { - EXPECT_FALSE( - AssemblyContext(AutoText("%foo = "), nullptr).isStartOfNewInst()); - EXPECT_FALSE(AssemblyContext(AutoText("%foo "), nullptr).isStartOfNewInst()); - EXPECT_FALSE(AssemblyContext(AutoText("%foo"), nullptr).isStartOfNewInst()); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.annotation_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.annotation_test.cpp deleted file mode 100644 index 61bdf64c8..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.annotation_test.cpp +++ /dev/null @@ -1,549 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Annotation" section of the -// SPIR-V spec. - -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using utils::MakeVector; -using spvtest::TextToBinaryTest; -using ::testing::Combine; -using ::testing::Eq; -using ::testing::Values; -using ::testing::ValuesIn; - -// Test OpDecorate - -using OpDecorateSimpleTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam< - std::tuple>>>; - -TEST_P(OpDecorateSimpleTest, AnySimpleDecoration) { - // This string should assemble, but should not validate. - std::stringstream input; - input << "OpDecorate %1 " << std::get<1>(GetParam()).name(); - for (auto operand : std::get<1>(GetParam()).operands()) - input << " " << operand; - input << std::endl; - EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())), - Eq(MakeInstruction(SpvOpDecorate, - {1, uint32_t(std::get<1>(GetParam()).value())}, - std::get<1>(GetParam()).operands()))); - // Also check disassembly. - EXPECT_THAT( - EncodeAndDecodeSuccessfully(input.str(), SPV_BINARY_TO_TEXT_OPTION_NONE, - std::get<0>(GetParam())), - Eq(input.str())); -} - -// Like above, but parameters to the decoration are IDs. -using OpDecorateSimpleIdTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam< - std::tuple>>>; - -TEST_P(OpDecorateSimpleIdTest, AnySimpleDecoration) { - // This string should assemble, but should not validate. - std::stringstream input; - input << "OpDecorateId %1 " << std::get<1>(GetParam()).name(); - for (auto operand : std::get<1>(GetParam()).operands()) - input << " %" << operand; - input << std::endl; - EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())), - Eq(MakeInstruction(SpvOpDecorateId, - {1, uint32_t(std::get<1>(GetParam()).value())}, - std::get<1>(GetParam()).operands()))); - // Also check disassembly. - EXPECT_THAT( - EncodeAndDecodeSuccessfully(input.str(), SPV_BINARY_TO_TEXT_OPTION_NONE, - std::get<0>(GetParam())), - Eq(input.str())); -} - -#define CASE(NAME) SpvDecoration##NAME, #NAME -INSTANTIATE_TEST_SUITE_P( - TextToBinaryDecorateSimple, OpDecorateSimpleTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector>{ - // The operand literal values are arbitrarily chosen, - // but there are the right number of them. - {CASE(RelaxedPrecision), {}}, - {CASE(SpecId), {100}}, - {CASE(Block), {}}, - {CASE(BufferBlock), {}}, - {CASE(RowMajor), {}}, - {CASE(ColMajor), {}}, - {CASE(ArrayStride), {4}}, - {CASE(MatrixStride), {16}}, - {CASE(GLSLShared), {}}, - {CASE(GLSLPacked), {}}, - {CASE(CPacked), {}}, - // Placeholder line for enum value 12 - {CASE(NoPerspective), {}}, - {CASE(Flat), {}}, - {CASE(Patch), {}}, - {CASE(Centroid), {}}, - {CASE(Sample), {}}, - {CASE(Invariant), {}}, - {CASE(Restrict), {}}, - {CASE(Aliased), {}}, - {CASE(Volatile), {}}, - {CASE(Constant), {}}, - {CASE(Coherent), {}}, - {CASE(NonWritable), {}}, - {CASE(NonReadable), {}}, - {CASE(Uniform), {}}, - {CASE(SaturatedConversion), {}}, - {CASE(Stream), {2}}, - {CASE(Location), {6}}, - {CASE(Component), {3}}, - {CASE(Index), {14}}, - {CASE(Binding), {19}}, - {CASE(DescriptorSet), {7}}, - {CASE(Offset), {12}}, - {CASE(XfbBuffer), {1}}, - {CASE(XfbStride), {8}}, - {CASE(NoContraction), {}}, - {CASE(InputAttachmentIndex), {102}}, - {CASE(Alignment), {16}}, - }))); - -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV11, OpDecorateSimpleTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - Values(EnumCase{ - CASE(MaxByteOffset), {128}}))); - -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV14, OpDecorateSimpleTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_4), - ValuesIn(std::vector>{ - {CASE(Uniform), {}}, - }))); - -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleIdV14, - OpDecorateSimpleIdTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_4), - ValuesIn(std::vector>{ - // In 1.4, UniformId decoration takes a - // scope Id. - {CASE(UniformId), {1}}, - }))); -#undef CASE - -TEST_F(OpDecorateSimpleTest, WrongDecoration) { - EXPECT_THAT(CompileFailure("OpDecorate %1 xxyyzz"), - Eq("Invalid decoration 'xxyyzz'.")); -} - -TEST_F(OpDecorateSimpleTest, ExtraOperandsOnDecorationExpectingNone) { - EXPECT_THAT(CompileFailure("OpDecorate %1 RelaxedPrecision 99"), - Eq("Expected or at the beginning of an " - "instruction, found '99'.")); -} - -TEST_F(OpDecorateSimpleTest, ExtraOperandsOnDecorationExpectingOne) { - EXPECT_THAT(CompileFailure("OpDecorate %1 SpecId 99 100"), - Eq("Expected or at the beginning of an " - "instruction, found '100'.")); -} - -TEST_F(OpDecorateSimpleTest, ExtraOperandsOnDecorationExpectingTwo) { - EXPECT_THAT( - CompileFailure("OpDecorate %1 LinkageAttributes \"abc\" Import 42"), - Eq("Expected or at the beginning of an " - "instruction, found '42'.")); -} - -// A single test case for an enum decoration. -struct DecorateEnumCase { - // Place the enum value first, so it's easier to read the binary dumps when - // the test fails. - uint32_t value; // The value within the enum, e.g. Position - std::string name; - uint32_t enum_value; // Which enum, e.g. BuiltIn - std::string enum_name; -}; - -using OpDecorateEnumTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpDecorateEnumTest, AnyEnumDecoration) { - // This string should assemble, but should not validate. - const std::string input = - "OpDecorate %1 " + GetParam().enum_name + " " + GetParam().name; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpDecorate, {1, GetParam().enum_value, - GetParam().value}))); -} - -// Test OpDecorate BuiltIn. -// clang-format off -#define CASE(NAME) \ - { SpvBuiltIn##NAME, #NAME, SpvDecorationBuiltIn, "BuiltIn" } -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateBuiltIn, OpDecorateEnumTest, - ::testing::ValuesIn(std::vector{ - CASE(Position), - CASE(PointSize), - CASE(ClipDistance), - CASE(CullDistance), - CASE(VertexId), - CASE(InstanceId), - CASE(PrimitiveId), - CASE(InvocationId), - CASE(Layer), - CASE(ViewportIndex), - CASE(TessLevelOuter), - CASE(TessLevelInner), - CASE(TessCoord), - CASE(PatchVertices), - CASE(FragCoord), - CASE(PointCoord), - CASE(FrontFacing), - CASE(SampleId), - CASE(SamplePosition), - CASE(SampleMask), - // Value 21 intentionally missing. - CASE(FragDepth), - CASE(HelperInvocation), - CASE(NumWorkgroups), - CASE(WorkgroupSize), - CASE(WorkgroupId), - CASE(LocalInvocationId), - CASE(GlobalInvocationId), - CASE(LocalInvocationIndex), - CASE(WorkDim), - CASE(GlobalSize), - CASE(EnqueuedWorkgroupSize), - CASE(GlobalOffset), - CASE(GlobalLinearId), - // Value 35 intentionally missing. - CASE(SubgroupSize), - CASE(SubgroupMaxSize), - CASE(NumSubgroups), - CASE(NumEnqueuedSubgroups), - CASE(SubgroupId), - CASE(SubgroupLocalInvocationId), - CASE(VertexIndex), - CASE(InstanceIndex), - })); -#undef CASE -// clang-format on - -TEST_F(OpDecorateEnumTest, WrongBuiltIn) { - EXPECT_THAT(CompileFailure("OpDecorate %1 BuiltIn xxyyzz"), - Eq("Invalid built-in 'xxyyzz'.")); -} - -// Test OpDecorate FuncParamAttr -// clang-format off -#define CASE(NAME) \ - { SpvFunctionParameterAttribute##NAME, #NAME, SpvDecorationFuncParamAttr, "FuncParamAttr" } -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFuncParamAttr, OpDecorateEnumTest, - ::testing::ValuesIn(std::vector{ - CASE(Zext), - CASE(Sext), - CASE(ByVal), - CASE(Sret), - CASE(NoAlias), - CASE(NoCapture), - CASE(NoWrite), - CASE(NoReadWrite), - })); -#undef CASE -// clang-format on - -TEST_F(OpDecorateEnumTest, WrongFuncParamAttr) { - EXPECT_THAT(CompileFailure("OpDecorate %1 FuncParamAttr xxyyzz"), - Eq("Invalid function parameter attribute 'xxyyzz'.")); -} - -// Test OpDecorate FPRoundingMode -// clang-format off -#define CASE(NAME) \ - { SpvFPRoundingMode##NAME, #NAME, SpvDecorationFPRoundingMode, "FPRoundingMode" } -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPRoundingMode, OpDecorateEnumTest, - ::testing::ValuesIn(std::vector{ - CASE(RTE), - CASE(RTZ), - CASE(RTP), - CASE(RTN), - })); -#undef CASE -// clang-format on - -TEST_F(OpDecorateEnumTest, WrongFPRoundingMode) { - EXPECT_THAT(CompileFailure("OpDecorate %1 FPRoundingMode xxyyzz"), - Eq("Invalid floating-point rounding mode 'xxyyzz'.")); -} - -// Test OpDecorate FPFastMathMode. -// These can by named enums for the single-bit masks. However, we don't support -// symbolic combinations of the masks. Rather, they can use ! -// syntax, e.g. !0x3 - -// clang-format off -#define CASE(ENUM,NAME) \ - { SpvFPFastMathMode##ENUM, #NAME, SpvDecorationFPFastMathMode, "FPFastMathMode" } -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPFastMathMode, OpDecorateEnumTest, - ::testing::ValuesIn(std::vector{ - CASE(MaskNone, None), - CASE(NotNaNMask, NotNaN), - CASE(NotInfMask, NotInf), - CASE(NSZMask, NSZ), - CASE(AllowRecipMask, AllowRecip), - CASE(FastMask, Fast), - })); -#undef CASE -// clang-format on - -TEST_F(OpDecorateEnumTest, CombinedFPFastMathMask) { - // Sample a single combination. This ensures we've integrated - // the instruction parsing logic with spvTextParseMask. - const std::string input = "OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ"; - const uint32_t expected_enum = SpvDecorationFPFastMathMode; - const uint32_t expected_mask = SpvFPFastMathModeNotNaNMask | - SpvFPFastMathModeNotInfMask | - SpvFPFastMathModeNSZMask; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpDecorate, {1, expected_enum, expected_mask}))); -} - -TEST_F(OpDecorateEnumTest, WrongFPFastMathMode) { - EXPECT_THAT( - CompileFailure("OpDecorate %1 FPFastMathMode NotNaN|xxyyzz"), - Eq("Invalid floating-point fast math mode operand 'NotNaN|xxyyzz'.")); -} - -// Test OpDecorate Linkage - -// A single test case for a linkage -struct DecorateLinkageCase { - uint32_t linkage_type_value; - std::string linkage_type_name; - std::string external_name; -}; - -using OpDecorateLinkageTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(OpDecorateLinkageTest, AnyLinkageDecoration) { - // This string should assemble, but should not validate. - const std::string input = "OpDecorate %1 LinkageAttributes \"" + - GetParam().external_name + "\" " + - GetParam().linkage_type_name; - std::vector expected_operands{1, SpvDecorationLinkageAttributes}; - std::vector encoded_external_name = - MakeVector(GetParam().external_name); - expected_operands.insert(expected_operands.end(), - encoded_external_name.begin(), - encoded_external_name.end()); - expected_operands.push_back(GetParam().linkage_type_value); - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpDecorate, expected_operands))); -} - -// clang-format off -#define CASE(ENUM) SpvLinkageType##ENUM, #ENUM -INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateLinkage, OpDecorateLinkageTest, - ::testing::ValuesIn(std::vector{ - { CASE(Import), "a" }, - { CASE(Export), "foo" }, - { CASE(Import), "some kind of long name with spaces etc." }, - // TODO(dneto): utf-8, escaping, quoting cases. - })); -#undef CASE -// clang-format on - -TEST_F(OpDecorateLinkageTest, WrongType) { - EXPECT_THAT(CompileFailure("OpDecorate %1 LinkageAttributes \"foo\" xxyyzz"), - Eq("Invalid linkage type 'xxyyzz'.")); -} - -// Test OpGroupMemberDecorate - -TEST_F(TextToBinaryTest, GroupMemberDecorateGoodOneTarget) { - EXPECT_THAT(CompiledInstructions("OpGroupMemberDecorate %group %id0 42"), - Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 42}))); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateGoodTwoTargets) { - EXPECT_THAT( - CompiledInstructions("OpGroupMemberDecorate %group %id0 96 %id1 42"), - Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 96, 3, 42}))); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateMissingGroupId) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidGroupId) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate 16"), - Eq("Expected id to start with %.")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidTargetId) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group 12"), - Eq("Expected id to start with %.")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateMissingTargetMemberNumber) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidTargetMemberNumber) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 %id1"), - Eq("Invalid unsigned integer literal: %id1")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidSecondTargetId) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id1 42 12"), - Eq("Expected id to start with %.")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateMissingSecondTargetMemberNumber) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 42 %id1"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidSecondTargetMemberNumber) { - EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 42 %id1 %id2"), - Eq("Invalid unsigned integer literal: %id2")); -} - -// Test OpMemberDecorate - -using OpMemberDecorateSimpleTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam< - std::tuple>>>; - -TEST_P(OpMemberDecorateSimpleTest, AnySimpleDecoration) { - // This string should assemble, but should not validate. - std::stringstream input; - input << "OpMemberDecorate %1 42 " << std::get<1>(GetParam()).name(); - for (auto operand : std::get<1>(GetParam()).operands()) - input << " " << operand; - input << std::endl; - EXPECT_THAT( - CompiledInstructions(input.str(), std::get<0>(GetParam())), - Eq(MakeInstruction(SpvOpMemberDecorate, - {1, 42, uint32_t(std::get<1>(GetParam()).value())}, - std::get<1>(GetParam()).operands()))); - // Also check disassembly. - EXPECT_THAT( - EncodeAndDecodeSuccessfully(input.str(), SPV_BINARY_TO_TEXT_OPTION_NONE, - std::get<0>(GetParam())), - Eq(input.str())); -} - -#define CASE(NAME) SpvDecoration##NAME, #NAME -INSTANTIATE_TEST_SUITE_P( - TextToBinaryDecorateSimple, OpMemberDecorateSimpleTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector>{ - // The operand literal values are arbitrarily chosen, - // but there are the right number of them. - {CASE(RelaxedPrecision), {}}, - {CASE(SpecId), {100}}, - {CASE(Block), {}}, - {CASE(BufferBlock), {}}, - {CASE(RowMajor), {}}, - {CASE(ColMajor), {}}, - {CASE(ArrayStride), {4}}, - {CASE(MatrixStride), {16}}, - {CASE(GLSLShared), {}}, - {CASE(GLSLPacked), {}}, - {CASE(CPacked), {}}, - // Placeholder line for enum value 12 - {CASE(NoPerspective), {}}, - {CASE(Flat), {}}, - {CASE(Patch), {}}, - {CASE(Centroid), {}}, - {CASE(Sample), {}}, - {CASE(Invariant), {}}, - {CASE(Restrict), {}}, - {CASE(Aliased), {}}, - {CASE(Volatile), {}}, - {CASE(Constant), {}}, - {CASE(Coherent), {}}, - {CASE(NonWritable), {}}, - {CASE(NonReadable), {}}, - {CASE(Uniform), {}}, - {CASE(SaturatedConversion), {}}, - {CASE(Stream), {2}}, - {CASE(Location), {6}}, - {CASE(Component), {3}}, - {CASE(Index), {14}}, - {CASE(Binding), {19}}, - {CASE(DescriptorSet), {7}}, - {CASE(Offset), {12}}, - {CASE(XfbBuffer), {1}}, - {CASE(XfbStride), {8}}, - {CASE(NoContraction), {}}, - {CASE(InputAttachmentIndex), {102}}, - {CASE(Alignment), {16}}, - }))); - -INSTANTIATE_TEST_SUITE_P( - TextToBinaryDecorateSimpleV11, OpMemberDecorateSimpleTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - Values(EnumCase{CASE(MaxByteOffset), {128}}))); -#undef CASE - -TEST_F(OpMemberDecorateSimpleTest, WrongDecoration) { - EXPECT_THAT(CompileFailure("OpMemberDecorate %1 9 xxyyzz"), - Eq("Invalid decoration 'xxyyzz'.")); -} - -TEST_F(OpMemberDecorateSimpleTest, ExtraOperandsOnDecorationExpectingNone) { - EXPECT_THAT(CompileFailure("OpMemberDecorate %1 12 RelaxedPrecision 99"), - Eq("Expected or at the beginning of an " - "instruction, found '99'.")); -} - -TEST_F(OpMemberDecorateSimpleTest, ExtraOperandsOnDecorationExpectingOne) { - EXPECT_THAT(CompileFailure("OpMemberDecorate %1 0 SpecId 99 100"), - Eq("Expected or at the beginning of an " - "instruction, found '100'.")); -} - -TEST_F(OpMemberDecorateSimpleTest, ExtraOperandsOnDecorationExpectingTwo) { - EXPECT_THAT(CompileFailure( - "OpMemberDecorate %1 1 LinkageAttributes \"abc\" Import 42"), - Eq("Expected or at the beginning of an " - "instruction, found '42'.")); -} - -// TODO(dneto): OpMemberDecorate cases for decorations with parameters which -// are: not just lists of literal numbers. - -// TODO(dneto): OpDecorationGroup -// TODO(dneto): OpGroupDecorate - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.barrier_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.barrier_test.cpp deleted file mode 100644 index 545d26ff2..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.barrier_test.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Barrier Instructions" section -// of the SPIR-V spec. - -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::MakeInstruction; -using spvtest::TextToBinaryTest; -using ::testing::_; -using ::testing::ElementsAre; -using ::testing::Eq; - -// Test OpMemoryBarrier - -using OpMemoryBarrier = spvtest::TextToBinaryTest; - -TEST_F(OpMemoryBarrier, Good) { - const std::string input = "OpMemoryBarrier %1 %2\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpMemoryBarrier, {1, 2}))); - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); -} - -TEST_F(OpMemoryBarrier, BadMissingScopeId) { - const std::string input = "OpMemoryBarrier\n"; - EXPECT_THAT(CompileFailure(input), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpMemoryBarrier, BadInvalidScopeId) { - const std::string input = "OpMemoryBarrier 99\n"; - EXPECT_THAT(CompileFailure(input), Eq("Expected id to start with %.")); -} - -TEST_F(OpMemoryBarrier, BadMissingMemorySemanticsId) { - const std::string input = "OpMemoryBarrier %scope\n"; - EXPECT_THAT(CompileFailure(input), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpMemoryBarrier, BadInvalidMemorySemanticsId) { - const std::string input = "OpMemoryBarrier %scope 14\n"; - EXPECT_THAT(CompileFailure(input), Eq("Expected id to start with %.")); -} - -// TODO(dneto): OpControlBarrier -// TODO(dneto): OpGroupAsyncCopy -// TODO(dneto): OpGroupWaitEvents -// TODO(dneto): OpGroupAll -// TODO(dneto): OpGroupAny -// TODO(dneto): OpGroupBroadcast -// TODO(dneto): OpGroupIAdd -// TODO(dneto): OpGroupFAdd -// TODO(dneto): OpGroupFMin -// TODO(dneto): OpGroupUMin -// TODO(dneto): OpGroupSMin -// TODO(dneto): OpGroupFMax -// TODO(dneto): OpGroupUMax -// TODO(dneto): OpGroupSMax - -using NamedMemoryBarrierTest = spvtest::TextToBinaryTest; - -// OpMemoryNamedBarrier is not in 1.0, but it is enabled by a capability. -// We should be able to assemble it. Validation checks are in another test -// file. -TEST_F(NamedMemoryBarrierTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics", - SPV_ENV_UNIVERSAL_1_0), - ElementsAre(spvOpcodeMake(4, SpvOpMemoryNamedBarrier), _, _, _)); -} - -TEST_F(NamedMemoryBarrierTest, ArgumentCount) { - EXPECT_THAT(CompileFailure("OpMemoryNamedBarrier", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompileFailure("OpMemoryNamedBarrier %bar", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompileFailure("OpMemoryNamedBarrier %bar %scope", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics", - SPV_ENV_UNIVERSAL_1_1), - ElementsAre(spvOpcodeMake(4, SpvOpMemoryNamedBarrier), _, _, _)); - EXPECT_THAT( - CompileFailure("OpMemoryNamedBarrier %bar %scope %semantics %extra", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected '=', found end of stream.")); -} - -TEST_F(NamedMemoryBarrierTest, ArgumentTypes) { - EXPECT_THAT(CompileFailure("OpMemoryNamedBarrier 123 %scope %semantics", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); - EXPECT_THAT(CompileFailure("OpMemoryNamedBarrier %bar %scope \"semantics\"", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); -} - -using TypeNamedBarrierTest = spvtest::TextToBinaryTest; - -TEST_F(TypeNamedBarrierTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_0), - ElementsAre(spvOpcodeMake(2, SpvOpTypeNamedBarrier), _)); -} - -TEST_F(TypeNamedBarrierTest, ArgumentCount) { - EXPECT_THAT(CompileFailure("OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, " - "found 'OpTypeNamedBarrier'.")); - EXPECT_THAT( - CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_1), - ElementsAre(spvOpcodeMake(2, SpvOpTypeNamedBarrier), _)); - EXPECT_THAT( - CompileFailure("%t = OpTypeNamedBarrier 1 2 3", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected or at the beginning of an instruction, " - "found '1'.")); -} - -using NamedBarrierInitializeTest = spvtest::TextToBinaryTest; - -TEST_F(NamedBarrierInitializeTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count", - SPV_ENV_UNIVERSAL_1_0), - ElementsAre(spvOpcodeMake(4, SpvOpNamedBarrierInitialize), _, _, _)); -} - -TEST_F(NamedBarrierInitializeTest, ArgumentCount) { - EXPECT_THAT( - CompileFailure("%bar = OpNamedBarrierInitialize", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT(CompileFailure("%bar = OpNamedBarrierInitialize %ype", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count", - SPV_ENV_UNIVERSAL_1_1), - ElementsAre(spvOpcodeMake(4, SpvOpNamedBarrierInitialize), _, _, _)); - EXPECT_THAT( - CompileFailure("%bar = OpNamedBarrierInitialize %type %count \"extra\"", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected or at the beginning of an instruction, " - "found '\"extra\"'.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.composite_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.composite_test.cpp deleted file mode 100644 index 6ae1cd35d..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.composite_test.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2018 Google LLC -// -// 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. - -// Assembler tests for instructions in the "Group Instrucions" section of the -// SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -using ::testing::Eq; -using ::testing::HasSubstr; - -namespace spvtools { -namespace { - -using spvtest::Concatenate; - -using CompositeRoundTripTest = RoundTripTest; - -TEST_F(CompositeRoundTripTest, Good) { - std::string spirv = "%2 = OpCopyLogical %1 %3\n"; - std::string disassembly = EncodeAndDecodeSuccessfully( - spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(CompositeRoundTripTest, V13Bad) { - std::string spirv = "%2 = OpCopyLogical %1 %3\n"; - std::string err = CompileFailure(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_THAT(err, HasSubstr("Invalid Opcode name 'OpCopyLogical'")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.constant_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.constant_test.cpp deleted file mode 100644 index 679bee40c..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.constant_test.cpp +++ /dev/null @@ -1,834 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Group Instrucions" section of the -// SPIR-V spec. - -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::Concatenate; -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using ::testing::Eq; - -// Test Sampler Addressing Mode enum values - -using SamplerAddressingModeTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(SamplerAddressingModeTest, AnySamplerAddressingMode) { - const std::string input = - "%result = OpConstantSampler %type " + GetParam().name() + " 0 Nearest"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpConstantSampler, - {1, 2, GetParam().value(), 0, 0}))); -} - -// clang-format off -#define CASE(NAME) { SpvSamplerAddressingMode##NAME, #NAME } -INSTANTIATE_TEST_SUITE_P( - TextToBinarySamplerAddressingMode, SamplerAddressingModeTest, - ::testing::ValuesIn(std::vector>{ - CASE(None), - CASE(ClampToEdge), - CASE(Clamp), - CASE(Repeat), - CASE(RepeatMirrored), - })); -#undef CASE -// clang-format on - -TEST_F(SamplerAddressingModeTest, WrongMode) { - EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t xxyyzz 0 Nearest"), - Eq("Invalid sampler addressing mode 'xxyyzz'.")); -} - -// Test Sampler Filter Mode enum values - -using SamplerFilterModeTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(SamplerFilterModeTest, AnySamplerFilterMode) { - const std::string input = - "%result = OpConstantSampler %type Clamp 0 " + GetParam().name(); - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpConstantSampler, - {1, 2, 2, 0, GetParam().value()}))); -} - -// clang-format off -#define CASE(NAME) { SpvSamplerFilterMode##NAME, #NAME} -INSTANTIATE_TEST_SUITE_P( - TextToBinarySamplerFilterMode, SamplerFilterModeTest, - ::testing::ValuesIn(std::vector>{ - CASE(Nearest), - CASE(Linear), - })); -#undef CASE -// clang-format on - -TEST_F(SamplerFilterModeTest, WrongMode) { - EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t Clamp 0 xxyyzz"), - Eq("Invalid sampler filter mode 'xxyyzz'.")); -} - -struct ConstantTestCase { - std::string constant_type; - std::string constant_value; - std::vector expected_instructions; -}; - -using OpConstantValidTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpConstantValidTest, ValidTypes) { - const std::string input = "%1 = " + GetParam().constant_type + - "\n" - "%2 = OpConstant %1 " + - GetParam().constant_value + "\n"; - std::vector instructions; - EXPECT_THAT(CompiledInstructions(input), Eq(GetParam().expected_instructions)) - << " type: " << GetParam().constant_type - << " literal: " << GetParam().constant_value; -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpConstantValid, OpConstantValidTest, - ::testing::ValuesIn(std::vector{ - // Check 16 bits - {"OpTypeInt 16 0", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0x1234})})}, - {"OpTypeInt 16 0", "0x8000", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0x8000})})}, - {"OpTypeInt 16 0", "0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 16 0", "65535", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 65535})})}, - {"OpTypeInt 16 0", "0xffff", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 65535})})}, - {"OpTypeInt 16 1", "0x8000", // Test sign extension. - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0xffff8000})})}, - {"OpTypeInt 16 1", "-32", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})}, - {"OpTypeInt 16 1", "0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 16 1", "-0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 16 1", "-0x0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 16 1", "-32768", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32768)})})}, - // Check 32 bits - {"OpTypeInt 32 0", "42", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 42})})}, - {"OpTypeInt 32 1", "-32", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})}, - {"OpTypeInt 32 1", "0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 32 1", "-0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 32 1", "-0x0", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0})})}, - {"OpTypeInt 32 1", "-0x001", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-1)})})}, - {"OpTypeInt 32 1", "2147483647", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu})})}, - {"OpTypeInt 32 1", "-2147483648", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0x80000000u})})}, - {"OpTypeFloat 32", "1.0", - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0x3f800000})})}, - {"OpTypeFloat 32", "10.0", - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0x41200000})})}, - {"OpTypeFloat 32", "-0x1p+128", // -infinity - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0xFF800000})})}, - {"OpTypeFloat 32", "0x1p+128", // +infinity - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0x7F800000})})}, - {"OpTypeFloat 32", "-0x1.8p+128", // A -NaN - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0xFFC00000})})}, - {"OpTypeFloat 32", "-0x1.0002p+128", // A +NaN - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, {1, 2, 0xFF800100})})}, - // Check 48 bits - {"OpTypeInt 48 0", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})}, - {"OpTypeInt 48 0", "0x800000000001", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 1, 0x00008000})})}, - {"OpTypeInt 48 1", "0x800000000000", // Test sign extension. - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0, 0xffff8000})})}, - {"OpTypeInt 48 1", "-32", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}), - MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})}, - // Check 64 bits - {"OpTypeInt 64 0", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})}, - {"OpTypeInt 64 0", "18446744073709551615", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})}, - {"OpTypeInt 64 0", "0xffffffffffffffff", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})}, - {"OpTypeInt 64 1", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})}, - {"OpTypeInt 64 1", "-42", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})}, - {"OpTypeInt 64 1", "-0x01", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})}, - {"OpTypeInt 64 1", "9223372036854775807", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})}, - {"OpTypeInt 64 1", "0x7fffffff", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu, 0})})}, - })); -// clang-format on - -// A test case for checking OpConstant with invalid literals with a leading -// minus. -struct InvalidLeadingMinusCase { - std::string type; - std::string literal; -}; - -using OpConstantInvalidLeadingMinusTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) { - const std::string input = "%1 = " + GetParam().type + - "\n" - "%2 = OpConstant %1 " + - GetParam().literal; - EXPECT_THAT(CompileFailure(input), - Eq("Cannot put a negative number in an unsigned literal")); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpConstantInvalidLeadingMinus, OpConstantInvalidLeadingMinusTest, - ::testing::ValuesIn(std::vector{ - {"OpTypeInt 16 0", "-0"}, - {"OpTypeInt 16 0", "-0x0"}, - {"OpTypeInt 16 0", "-1"}, - {"OpTypeInt 32 0", "-0"}, - {"OpTypeInt 32 0", "-0x0"}, - {"OpTypeInt 32 0", "-1"}, - {"OpTypeInt 64 0", "-0"}, - {"OpTypeInt 64 0", "-0x0"}, - {"OpTypeInt 64 0", "-1"}, - })); -// clang-format on - -// A test case for invalid floating point literals. -struct InvalidFloatConstantCase { - uint32_t width; - std::string literal; -}; - -using OpConstantInvalidFloatConstant = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>; - -TEST_P(OpConstantInvalidFloatConstant, Samples) { - // Check both kinds of instructions that take literal floats. - for (const auto& instruction : {"OpConstant", "OpSpecConstant"}) { - std::stringstream input; - input << "%1 = OpTypeFloat " << GetParam().width << "\n" - << "%2 = " << instruction << " %1 " << GetParam().literal; - std::stringstream expected_error; - expected_error << "Invalid " << GetParam().width - << "-bit float literal: " << GetParam().literal; - EXPECT_THAT(CompileFailure(input.str()), Eq(expected_error.str())); - } -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryInvalidFloatConstant, OpConstantInvalidFloatConstant, - ::testing::ValuesIn(std::vector{ - {16, "abc"}, - {16, "--1"}, - {16, "-+1"}, - {16, "+-1"}, - {16, "++1"}, - {16, "1e30"}, // Overflow is an error for 16-bit floats. - {16, "-1e30"}, - {16, "1e40"}, - {16, "-1e40"}, - {16, "1e400"}, - {16, "-1e400"}, - {32, "abc"}, - {32, "--1"}, - {32, "-+1"}, - {32, "+-1"}, - {32, "++1"}, - {32, "1e40"}, // Overflow is an error for 32-bit floats. - {32, "-1e40"}, - {32, "1e400"}, - {32, "-1e400"}, - {64, "abc"}, - {64, "--1"}, - {64, "-+1"}, - {64, "+-1"}, - {64, "++1"}, - {32, "1e400"}, // Overflow is an error for 64-bit floats. - {32, "-1e400"}, - })); -// clang-format on - -using OpConstantInvalidTypeTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; -TEST_P(OpConstantInvalidTypeTest, InvalidTypes) { - const std::string input = "%1 = " + GetParam() + - "\n" - "%2 = OpConstant %1 0\n"; - EXPECT_THAT( - CompileFailure(input), - Eq("Type for Constant must be a scalar floating point or integer type")); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpConstantInvalidValidType, OpConstantInvalidTypeTest, - ::testing::ValuesIn(std::vector{ - {"OpTypeVoid", - "OpTypeBool", - "OpTypeVector %a 32", - "OpTypeMatrix %a 32", - "OpTypeImage %a 1D 0 0 0 0 Unknown", - "OpTypeSampler", - "OpTypeSampledImage %a", - "OpTypeArray %a %b", - "OpTypeRuntimeArray %a", - "OpTypeStruct %a", - "OpTypeOpaque \"Foo\"", - "OpTypePointer UniformConstant %a", - "OpTypeFunction %a %b", - "OpTypeEvent", - "OpTypeDeviceEvent", - "OpTypeReserveId", - "OpTypeQueue", - "OpTypePipe ReadOnly", - - // Skip OpTypeForwardPointer doesn't even produce a result ID. - // The assembler errors out if we try to check it in this scenario. - - // Try at least one thing that isn't a type at all - "OpNot %a %b" - }, - })); -// clang-format on - -using OpSpecConstantValidTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpSpecConstantValidTest, ValidTypes) { - const std::string input = "%1 = " + GetParam().constant_type + - "\n" - "%2 = OpSpecConstant %1 " + - GetParam().constant_value + "\n"; - std::vector instructions; - EXPECT_THAT(CompiledInstructions(input), - Eq(GetParam().expected_instructions)); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSpecConstantValid, OpSpecConstantValidTest, - ::testing::ValuesIn(std::vector{ - // Check 16 bits - {"OpTypeInt 16 0", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234})})}, - {"OpTypeInt 16 0", "0x8000", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x8000})})}, - {"OpTypeInt 16 1", "0x8000", // Test sign extension. - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0xffff8000})})}, - {"OpTypeInt 16 1", "-32", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})}, - // Check 32 bits - {"OpTypeInt 32 0", "42", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 42})})}, - {"OpTypeInt 32 1", "-32", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})}, - {"OpTypeFloat 32", "1.0", - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x3f800000})})}, - {"OpTypeFloat 32", "10.0", - Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x41200000})})}, - // Check 48 bits - {"OpTypeInt 48 0", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})}, - {"OpTypeInt 48 0", "0x800000000001", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 1, 0x00008000})})}, - {"OpTypeInt 48 1", "0x800000000000", // Test sign extension. - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0, 0xffff8000})})}, - {"OpTypeInt 48 1", "-32", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})}, - // Check 64 bits - {"OpTypeInt 64 0", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})}, - {"OpTypeInt 64 1", "0x1234", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})}, - {"OpTypeInt 64 1", "-42", - Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), - MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})}, - })); -// clang-format on - -using OpSpecConstantInvalidTypeTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpSpecConstantInvalidTypeTest, InvalidTypes) { - const std::string input = "%1 = " + GetParam() + - "\n" - "%2 = OpSpecConstant %1 0\n"; - EXPECT_THAT(CompileFailure(input), - Eq("Type for SpecConstant must be a scalar floating point or " - "integer type")); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSpecConstantInvalidValidType, OpSpecConstantInvalidTypeTest, - ::testing::ValuesIn(std::vector{ - {"OpTypeVoid", - "OpTypeBool", - "OpTypeVector %a 32", - "OpTypeMatrix %a 32", - "OpTypeImage %a 1D 0 0 0 0 Unknown", - "OpTypeSampler", - "OpTypeSampledImage %a", - "OpTypeArray %a %b", - "OpTypeRuntimeArray %a", - "OpTypeStruct %a", - "OpTypeOpaque \"Foo\"", - "OpTypePointer UniformConstant %a", - "OpTypeFunction %a %b", - "OpTypeEvent", - "OpTypeDeviceEvent", - "OpTypeReserveId", - "OpTypeQueue", - "OpTypePipe ReadOnly", - - // Skip testing OpTypeForwardPointer because it doesn't even produce a result ID. - - // Try at least one thing that isn't a type at all - "OpNot %a %b" - }, - })); -// clang-format on - -const int64_t kMaxUnsigned48Bit = (int64_t(1) << 48) - 1; -const int64_t kMaxSigned48Bit = (int64_t(1) << 47) - 1; -const int64_t kMinSigned48Bit = -kMaxSigned48Bit - 1; - -INSTANTIATE_TEST_SUITE_P( - OpConstantRoundTrip, RoundTripTest, - ::testing::ValuesIn(std::vector{ - // 16 bit - "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 0\n", - "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 65535\n", - "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 -32768\n", - "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 32767\n", - "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n", - // 32 bit - std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n"), - std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") + - std::to_string(std::numeric_limits::min()) + "\n", - // 48 bit - std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 0\n"), - std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 ") + - std::to_string(kMaxUnsigned48Bit) + "\n", - std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") + - std::to_string(kMaxSigned48Bit) + "\n", - std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") + - std::to_string(kMinSigned48Bit) + "\n", - // 64 bit - std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 0\n"), - std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") + - std::to_string(std::numeric_limits::min()) + "\n", - // 32-bit float - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0\n", - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 13.5\n", - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -12.5\n", - // 64-bit float - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0\n", - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 1.79767e+308\n", - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -1.79767e+308\n", - })); - -INSTANTIATE_TEST_SUITE_P( - OpConstantHalfRoundTrip, RoundTripTest, - ::testing::ValuesIn(std::vector{ - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x0p+0\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x0p+0\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+0\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.1p+0\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p-1\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.8p+1\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+1\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+0\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.1p+0\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p-1\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.8p+1\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+1\n", - - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-16\n", // some denorms - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-24\n", - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p-24\n", - - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+16\n", // +inf - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+16\n", // -inf - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n", // -inf - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p+16\n", // nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.11p+16\n", // nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffp+16\n", // nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+16\n", // nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.004p+16\n", // nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n", // -nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.11p+16\n", // -nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffp+16\n", // -nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+16\n", // -nan - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.004p+16\n", // -nan - })); - -// clang-format off -// (Clang-format really wants to break up these strings across lines. -INSTANTIATE_TEST_SUITE_P( - OpConstantRoundTripNonFinite, RoundTripTest, - ::testing::ValuesIn(std::vector{ - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128\n", // -inf - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128\n", // inf - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.8p+128\n", // -nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128\n", // -nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0018p+128\n", // -nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.01ep+128\n", // -nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.fffffep+128\n", // -nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128\n", // +nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0002p+128\n", // +nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0018p+128\n", // +nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.01ep+128\n", // +nan - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.fffffep+128\n", // +nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024\n", // -inf - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024\n", // +inf - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.8p+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0fp+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0000000000001p+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.00003p+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.fffffffffffffp+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024\n", // +nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0fp+1024\n", // +nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0000000000001p+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.00003p+1024\n", // -nan - "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.fffffffffffffp+1024\n", // -nan - })); -// clang-format on - -INSTANTIATE_TEST_SUITE_P( - OpSpecConstantRoundTrip, RoundTripTest, - ::testing::ValuesIn(std::vector{ - // 16 bit - "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 0\n", - "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 65535\n", - "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 -32768\n", - "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 32767\n", - "%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n", - // 32 bit - std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n"), - std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") + - std::to_string(std::numeric_limits::min()) + "\n", - // 48 bit - std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 0\n"), - std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 ") + - std::to_string(kMaxUnsigned48Bit) + "\n", - std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") + - std::to_string(kMaxSigned48Bit) + "\n", - std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") + - std::to_string(kMinSigned48Bit) + "\n", - // 64 bit - std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 0\n"), - std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") + - std::to_string(std::numeric_limits::max()) + "\n", - std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") + - std::to_string(std::numeric_limits::min()) + "\n", - // 32-bit float - "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 0\n", - "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 13.5\n", - "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 -12.5\n", - // 64-bit float - "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 0\n", - "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 1.79767e+308\n", - "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 -1.79767e+308\n", - })); - -// Test OpSpecConstantOp - -using OpSpecConstantOpTestWithIds = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>>; - -// The operands to the OpSpecConstantOp opcode are all Ids. -TEST_P(OpSpecConstantOpTestWithIds, Assembly) { - std::stringstream input; - input << "%2 = OpSpecConstantOp %1 " << GetParam().name(); - for (auto id : GetParam().operands()) input << " %" << id; - input << "\n"; - - EXPECT_THAT(CompiledInstructions(input.str()), - Eq(MakeInstruction(SpvOpSpecConstantOp, - {1, 2, uint32_t(GetParam().value())}, - GetParam().operands()))); - - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str()); -} - -// clang-format off -#define CASE1(NAME) { SpvOp##NAME, #NAME, {3} } -#define CASE2(NAME) { SpvOp##NAME, #NAME, {3, 4} } -#define CASE3(NAME) { SpvOp##NAME, #NAME, {3, 4, 5} } -#define CASE4(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6} } -#define CASE5(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7} } -#define CASE6(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7, 8} } -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSpecConstantOp, OpSpecConstantOpTestWithIds, - ::testing::ValuesIn(std::vector>{ - // Conversion - CASE1(SConvert), - CASE1(FConvert), - CASE1(ConvertFToS), - CASE1(ConvertSToF), - CASE1(ConvertFToU), - CASE1(ConvertUToF), - CASE1(UConvert), - CASE1(ConvertPtrToU), - CASE1(ConvertUToPtr), - CASE1(GenericCastToPtr), - CASE1(PtrCastToGeneric), - CASE1(Bitcast), - CASE1(QuantizeToF16), - // Arithmetic - CASE1(SNegate), - CASE1(Not), - CASE2(IAdd), - CASE2(ISub), - CASE2(IMul), - CASE2(UDiv), - CASE2(SDiv), - CASE2(UMod), - CASE2(SRem), - CASE2(SMod), - CASE2(ShiftRightLogical), - CASE2(ShiftRightArithmetic), - CASE2(ShiftLeftLogical), - CASE2(BitwiseOr), - CASE2(BitwiseAnd), - CASE2(BitwiseXor), - CASE1(FNegate), - CASE2(FAdd), - CASE2(FSub), - CASE2(FMul), - CASE2(FDiv), - CASE2(FRem), - CASE2(FMod), - // Composite operations use literal numbers. So they're in another test. - // Logical - CASE2(LogicalOr), - CASE2(LogicalAnd), - CASE1(LogicalNot), - CASE2(LogicalEqual), - CASE2(LogicalNotEqual), - CASE3(Select), - // Comparison - CASE2(IEqual), - CASE2(INotEqual), // Allowed in 1.0 Rev 7 - CASE2(ULessThan), - CASE2(SLessThan), - CASE2(UGreaterThan), - CASE2(SGreaterThan), - CASE2(ULessThanEqual), - CASE2(SLessThanEqual), - CASE2(UGreaterThanEqual), - CASE2(SGreaterThanEqual), - // Memory - // For AccessChain, there is a base Id, then a sequence of index Ids. - // Having no index Ids is a corner case. - CASE1(AccessChain), - CASE2(AccessChain), - CASE6(AccessChain), - CASE1(InBoundsAccessChain), - CASE2(InBoundsAccessChain), - CASE6(InBoundsAccessChain), - // PtrAccessChain also has an element Id. - CASE2(PtrAccessChain), - CASE3(PtrAccessChain), - CASE6(PtrAccessChain), - CASE2(InBoundsPtrAccessChain), - CASE3(InBoundsPtrAccessChain), - CASE6(InBoundsPtrAccessChain), - })); -#undef CASE1 -#undef CASE2 -#undef CASE3 -#undef CASE4 -#undef CASE5 -#undef CASE6 -// clang-format on - -using OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>>; - -// The operands to the OpSpecConstantOp opcode are two Ids followed by a -// sequence of literal numbers. -TEST_P(OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers, Assembly) { - std::stringstream input; - input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3 %4"; - for (auto number : GetParam().operands()) input << " " << number; - input << "\n"; - - EXPECT_THAT(CompiledInstructions(input.str()), - Eq(MakeInstruction(SpvOpSpecConstantOp, - {1, 2, uint32_t(GetParam().value()), 3, 4}, - GetParam().operands()))); - - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str()); -} - -#define CASE(NAME) SpvOp##NAME, #NAME -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSpecConstantOp, - OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers, - ::testing::ValuesIn(std::vector>{ - // For VectorShuffle, there are two vector operands, and at least - // two selector Ids. OpenCL can have up to 16-element vectors. - {CASE(VectorShuffle), {0, 0}}, - {CASE(VectorShuffle), {4, 3, 2, 1}}, - {CASE(VectorShuffle), {0, 2, 4, 6, 1, 3, 5, 7}}, - {CASE(VectorShuffle), - {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}, - // For CompositeInsert, there is an object to insert, the target - // composite, and then literal indices. - {CASE(CompositeInsert), {0}}, - {CASE(CompositeInsert), {4, 3, 99, 1}}, - })); - -using OpSpecConstantOpTestWithOneIdThenLiteralNumbers = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>>; - -// The operands to the OpSpecConstantOp opcode are one Id followed by a -// sequence of literal numbers. -TEST_P(OpSpecConstantOpTestWithOneIdThenLiteralNumbers, Assembly) { - std::stringstream input; - input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3"; - for (auto number : GetParam().operands()) input << " " << number; - input << "\n"; - - EXPECT_THAT(CompiledInstructions(input.str()), - Eq(MakeInstruction(SpvOpSpecConstantOp, - {1, 2, uint32_t(GetParam().value()), 3}, - GetParam().operands()))); - - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str()); -} - -#define CASE(NAME) SpvOp##NAME, #NAME -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSpecConstantOp, - OpSpecConstantOpTestWithOneIdThenLiteralNumbers, - ::testing::ValuesIn(std::vector>{ - // For CompositeExtract, the universal limit permits up to 255 literal - // indices. Let's only test a few. - {CASE(CompositeExtract), {0}}, - {CASE(CompositeExtract), {0, 99, 42, 16, 17, 12, 19}}, - })); - -// TODO(dneto): OpConstantTrue -// TODO(dneto): OpConstantFalse -// TODO(dneto): OpConstantComposite -// TODO(dneto): OpConstantSampler: other variations Param is 0 or 1 -// TODO(dneto): OpConstantNull -// TODO(dneto): OpSpecConstantTrue -// TODO(dneto): OpSpecConstantFalse -// TODO(dneto): OpSpecConstantComposite -// TODO(dneto): Negative tests for OpSpecConstantOp - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.control_flow_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.control_flow_test.cpp deleted file mode 100644 index ae51f55d9..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.control_flow_test.cpp +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Control Flow" section of the -// SPIR-V spec. - -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::Concatenate; -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using spvtest::TextToBinaryTest; -using ::testing::Combine; -using ::testing::Eq; -using ::testing::TestWithParam; -using ::testing::Values; -using ::testing::ValuesIn; - -// Test OpSelectionMerge - -using OpSelectionMergeTest = spvtest::TextToBinaryTestBase< - TestWithParam>>; - -TEST_P(OpSelectionMergeTest, AnySingleSelectionControlMask) { - const std::string input = "OpSelectionMerge %1 " + GetParam().name(); - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSelectionMerge, {1, GetParam().value()}))); -} - -// clang-format off -#define CASE(VALUE,NAME) { SpvSelectionControl##VALUE, NAME} -INSTANTIATE_TEST_SUITE_P(TextToBinarySelectionMerge, OpSelectionMergeTest, - ValuesIn(std::vector>{ - CASE(MaskNone, "None"), - CASE(FlattenMask, "Flatten"), - CASE(DontFlattenMask, "DontFlatten"), - })); -#undef CASE -// clang-format on - -TEST_F(OpSelectionMergeTest, CombinedSelectionControlMask) { - const std::string input = "OpSelectionMerge %1 Flatten|DontFlatten"; - const uint32_t expected_mask = - SpvSelectionControlFlattenMask | SpvSelectionControlDontFlattenMask; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSelectionMerge, {1, expected_mask}))); -} - -TEST_F(OpSelectionMergeTest, WrongSelectionControl) { - // Case sensitive: "flatten" != "Flatten" and thus wrong. - EXPECT_THAT(CompileFailure("OpSelectionMerge %1 flatten|DontFlatten"), - Eq("Invalid selection control operand 'flatten|DontFlatten'.")); -} - -// Test OpLoopMerge - -using OpLoopMergeTest = spvtest::TextToBinaryTestBase< - TestWithParam>>>; - -TEST_P(OpLoopMergeTest, AnySingleLoopControlMask) { - const auto ctrl = std::get<1>(GetParam()); - std::ostringstream input; - input << "OpLoopMerge %merge %continue " << ctrl.name(); - for (auto num : ctrl.operands()) input << " " << num; - EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())), - Eq(MakeInstruction(SpvOpLoopMerge, {1, 2, ctrl.value()}, - ctrl.operands()))); -} - -#define CASE(VALUE, NAME) \ - { SpvLoopControl##VALUE, NAME } -#define CASE1(VALUE, NAME, PARM) \ - { \ - SpvLoopControl##VALUE, NAME, { PARM } \ - } -INSTANTIATE_TEST_SUITE_P( - TextToBinaryLoopMerge, OpLoopMergeTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector>{ - // clang-format off - CASE(MaskNone, "None"), - CASE(UnrollMask, "Unroll"), - CASE(DontUnrollMask, "DontUnroll"), - // clang-format on - }))); - -INSTANTIATE_TEST_SUITE_P( - TextToBinaryLoopMergeV11, OpLoopMergeTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector>{ - // clang-format off - CASE(DependencyInfiniteMask, "DependencyInfinite"), - CASE1(DependencyLengthMask, "DependencyLength", 234), - {SpvLoopControlUnrollMask|SpvLoopControlDependencyLengthMask, - "DependencyLength|Unroll", {33}}, - // clang-format on - }))); -#undef CASE -#undef CASE1 - -TEST_F(OpLoopMergeTest, CombinedLoopControlMask) { - const std::string input = "OpLoopMerge %merge %continue Unroll|DontUnroll"; - const uint32_t expected_mask = - SpvLoopControlUnrollMask | SpvLoopControlDontUnrollMask; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpLoopMerge, {1, 2, expected_mask}))); -} - -TEST_F(OpLoopMergeTest, WrongLoopControl) { - EXPECT_THAT(CompileFailure("OpLoopMerge %m %c none"), - Eq("Invalid loop control operand 'none'.")); -} - -// Test OpSwitch - -TEST_F(TextToBinaryTest, SwitchGoodZeroTargets) { - EXPECT_THAT(CompiledInstructions("OpSwitch %selector %default"), - Eq(MakeInstruction(SpvOpSwitch, {1, 2}))); -} - -TEST_F(TextToBinaryTest, SwitchGoodOneTarget) { - EXPECT_THAT(CompiledInstructions("%1 = OpTypeInt 32 0\n" - "%2 = OpConstant %1 52\n" - "OpSwitch %2 %default 12 %target0"), - Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 52}), - MakeInstruction(SpvOpSwitch, {2, 3, 12, 4})}))); -} - -TEST_F(TextToBinaryTest, SwitchGoodTwoTargets) { - EXPECT_THAT( - CompiledInstructions("%1 = OpTypeInt 32 0\n" - "%2 = OpConstant %1 52\n" - "OpSwitch %2 %default 12 %target0 42 %target1"), - Eq(Concatenate({ - MakeInstruction(SpvOpTypeInt, {1, 32, 0}), - MakeInstruction(SpvOpConstant, {1, 2, 52}), - MakeInstruction(SpvOpSwitch, {2, 3, 12, 4, 42, 5}), - }))); -} - -TEST_F(TextToBinaryTest, SwitchBadMissingSelector) { - EXPECT_THAT(CompileFailure("OpSwitch"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(TextToBinaryTest, SwitchBadInvalidSelector) { - EXPECT_THAT(CompileFailure("OpSwitch 12"), - Eq("Expected id to start with %.")); -} - -TEST_F(TextToBinaryTest, SwitchBadMissingDefault) { - EXPECT_THAT(CompileFailure("OpSwitch %selector"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(TextToBinaryTest, SwitchBadInvalidDefault) { - EXPECT_THAT(CompileFailure("OpSwitch %selector 12"), - Eq("Expected id to start with %.")); -} - -TEST_F(TextToBinaryTest, SwitchBadInvalidLiteral) { - // The assembler recognizes "OpSwitch %selector %default" as a complete - // instruction. Then it tries to parse "%abc" as the start of a new - // instruction, but can't since it hits the end of stream. - const auto input = R"(%i32 = OpTypeInt 32 0 - %selector = OpConstant %i32 42 - OpSwitch %selector %default %abc)"; - EXPECT_THAT(CompileFailure(input), Eq("Expected '=', found end of stream.")); -} - -TEST_F(TextToBinaryTest, SwitchBadMissingTarget) { - EXPECT_THAT(CompileFailure("%1 = OpTypeInt 32 0\n" - "%2 = OpConstant %1 52\n" - "OpSwitch %2 %default 12"), - Eq("Expected operand, found end of stream.")); -} - -// A test case for an OpSwitch. -// It is also parameterized to test encodings OpConstant -// integer literals. This can capture both single and multi-word -// integer literal tests. -struct SwitchTestCase { - std::string constant_type_args; - std::string constant_value_arg; - std::string case_value_arg; - std::vector expected_instructions; -}; - -using OpSwitchValidTest = - spvtest::TextToBinaryTestBase>; - -// Tests the encoding of OpConstant literal values, and also -// the literal integer cases in an OpSwitch. This can -// test both single and multi-word integer literal encodings. -TEST_P(OpSwitchValidTest, ValidTypes) { - const std::string input = "%1 = OpTypeInt " + GetParam().constant_type_args + - "\n" - "%2 = OpConstant %1 " + - GetParam().constant_value_arg + - "\n" - "OpSwitch %2 %default " + - GetParam().case_value_arg + " %4\n"; - std::vector instructions; - EXPECT_THAT(CompiledInstructions(input), - Eq(GetParam().expected_instructions)); -} - -// Constructs a SwitchTestCase from the given integer_width, signedness, -// constant value string, and expected encoded constant. -SwitchTestCase MakeSwitchTestCase(uint32_t integer_width, - uint32_t integer_signedness, - std::string constant_str, - std::vector encoded_constant, - std::string case_value_str, - std::vector encoded_case_value) { - std::stringstream ss; - ss << integer_width << " " << integer_signedness; - return SwitchTestCase{ - ss.str(), - constant_str, - case_value_str, - {Concatenate( - {MakeInstruction(SpvOpTypeInt, - {1, integer_width, integer_signedness}), - MakeInstruction(SpvOpConstant, - Concatenate({{1, 2}, encoded_constant})), - MakeInstruction(SpvOpSwitch, - Concatenate({{2, 3}, encoded_case_value, {4}}))})}}; -} - -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSwitchValid1Word, OpSwitchValidTest, - ValuesIn(std::vector({ - MakeSwitchTestCase(32, 0, "42", {42}, "100", {100}), - MakeSwitchTestCase(32, 1, "-1", {0xffffffff}, "100", {100}), - // SPIR-V 1.0 Rev 1 clarified that for an integer narrower than 32-bits, - // its bits will appear in the lower order bits of the 32-bit word, and - // a signed integer is sign-extended. - MakeSwitchTestCase(7, 0, "127", {127}, "100", {100}), - MakeSwitchTestCase(14, 0, "99", {99}, "100", {100}), - MakeSwitchTestCase(16, 0, "65535", {65535}, "100", {100}), - MakeSwitchTestCase(16, 1, "101", {101}, "100", {100}), - // Demonstrate sign extension - MakeSwitchTestCase(16, 1, "-2", {0xfffffffe}, "100", {100}), - // Hex cases - MakeSwitchTestCase(16, 1, "0x7ffe", {0x7ffe}, "0x1234", {0x1234}), - MakeSwitchTestCase(16, 1, "0x8000", {0xffff8000}, "0x8100", - {0xffff8100}), - MakeSwitchTestCase(16, 0, "0x8000", {0x00008000}, "0x8100", {0x8100}), - }))); - -// NB: The words LOW ORDER bits show up first. -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSwitchValid2Words, OpSwitchValidTest, - ValuesIn(std::vector({ - MakeSwitchTestCase(33, 0, "101", {101, 0}, "500", {500, 0}), - MakeSwitchTestCase(48, 1, "-1", {0xffffffff, 0xffffffff}, "900", - {900, 0}), - MakeSwitchTestCase(64, 1, "-2", {0xfffffffe, 0xffffffff}, "-5", - {0xfffffffb, uint32_t(-1)}), - // Hex cases - MakeSwitchTestCase(48, 1, "0x7fffffffffff", {0xffffffff, 0x00007fff}, - "100", {100, 0}), - MakeSwitchTestCase(48, 1, "0x800000000000", {0x00000000, 0xffff8000}, - "0x800000000000", {0x00000000, 0xffff8000}), - MakeSwitchTestCase(48, 0, "0x800000000000", {0x00000000, 0x00008000}, - "0x800000000000", {0x00000000, 0x00008000}), - MakeSwitchTestCase(63, 0, "0x500000000", {0, 5}, "12", {12, 0}), - MakeSwitchTestCase(64, 0, "0x600000000", {0, 6}, "12", {12, 0}), - MakeSwitchTestCase(64, 1, "0x700000123", {0x123, 7}, "12", {12, 0}), - }))); - -INSTANTIATE_TEST_SUITE_P( - OpSwitchRoundTripUnsignedIntegers, RoundTripTest, - ValuesIn(std::vector({ - // Unsigned 16-bit. - "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 65535\nOpSwitch %2 %3\n", - // Unsigned 32-bit, three non-default cases. - "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 123456\n" - "OpSwitch %2 %3 100 %4 102 %5 1000000 %6\n", - // Unsigned 48-bit, three non-default cases. - "%1 = OpTypeInt 48 0\n%2 = OpConstant %1 5000000000\n" - "OpSwitch %2 %3 100 %4 102 %5 6000000000 %6\n", - // Unsigned 64-bit, three non-default cases. - "%1 = OpTypeInt 64 0\n%2 = OpConstant %1 9223372036854775807\n" - "OpSwitch %2 %3 100 %4 102 %5 9000000000000000000 %6\n", - }))); - -INSTANTIATE_TEST_SUITE_P( - OpSwitchRoundTripSignedIntegers, RoundTripTest, - ValuesIn(std::vector{ - // Signed 16-bit, with two non-default cases - "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 32767\n" - "OpSwitch %2 %3 99 %4 -102 %5\n", - "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 -32768\n" - "OpSwitch %2 %3 99 %4 -102 %5\n", - // Signed 32-bit, two non-default cases. - "%1 = OpTypeInt 32 1\n%2 = OpConstant %1 -123456\n" - "OpSwitch %2 %3 100 %4 -123456 %5\n", - "%1 = OpTypeInt 32 1\n%2 = OpConstant %1 123456\n" - "OpSwitch %2 %3 100 %4 123456 %5\n", - // Signed 48-bit, three non-default cases. - "%1 = OpTypeInt 48 1\n%2 = OpConstant %1 5000000000\n" - "OpSwitch %2 %3 100 %4 -7000000000 %5 6000000000 %6\n", - "%1 = OpTypeInt 48 1\n%2 = OpConstant %1 -5000000000\n" - "OpSwitch %2 %3 100 %4 -7000000000 %5 6000000000 %6\n", - // Signed 64-bit, three non-default cases. - "%1 = OpTypeInt 64 1\n%2 = OpConstant %1 9223372036854775807\n" - "OpSwitch %2 %3 100 %4 7000000000 %5 -1000000000000000000 %6\n", - "%1 = OpTypeInt 64 1\n%2 = OpConstant %1 -9223372036854775808\n" - "OpSwitch %2 %3 100 %4 7000000000 %5 -1000000000000000000 %6\n", - })); - -using OpSwitchInvalidTypeTestCase = - spvtest::TextToBinaryTestBase>; - -TEST_P(OpSwitchInvalidTypeTestCase, InvalidTypes) { - const std::string input = - "%1 = " + GetParam() + - "\n" - "%3 = OpCopyObject %1 %2\n" // We only care the type of the expression - " OpSwitch %3 %default 32 %c\n"; - EXPECT_THAT(CompileFailure(input), - Eq("The selector operand for OpSwitch must be the result of an " - "instruction that generates an integer scalar")); -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - TextToBinaryOpSwitchInvalidTests, OpSwitchInvalidTypeTestCase, - ValuesIn(std::vector{ - {"OpTypeVoid", - "OpTypeBool", - "OpTypeFloat 32", - "OpTypeVector %a 32", - "OpTypeMatrix %a 32", - "OpTypeImage %a 1D 0 0 0 0 Unknown", - "OpTypeSampler", - "OpTypeSampledImage %a", - "OpTypeArray %a %b", - "OpTypeRuntimeArray %a", - "OpTypeStruct %a", - "OpTypeOpaque \"Foo\"", - "OpTypePointer UniformConstant %a", - "OpTypeFunction %a %b", - "OpTypeEvent", - "OpTypeDeviceEvent", - "OpTypeReserveId", - "OpTypeQueue", - "OpTypePipe ReadOnly", - - // Skip OpTypeForwardPointer becasuse it doesn't even produce a result - // ID. - - // At least one thing that isn't a type at all - "OpNot %a %b" - }, - })); -// clang-format on - -// TODO(dneto): OpPhi -// TODO(dneto): OpLoopMerge -// TODO(dneto): OpLabel -// TODO(dneto): OpBranch -// TODO(dneto): OpSwitch -// TODO(dneto): OpKill -// TODO(dneto): OpReturn -// TODO(dneto): OpReturnValue -// TODO(dneto): OpUnreachable -// TODO(dneto): OpLifetimeStart -// TODO(dneto): OpLifetimeStop - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.debug_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.debug_test.cpp deleted file mode 100644 index 39ba5c524..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.debug_test.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Debug" section of the -// SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::MakeInstruction; -using utils::MakeVector; -using spvtest::TextToBinaryTest; -using ::testing::Eq; - -// Test OpSource - -// A single test case for OpSource -struct LanguageCase { - uint32_t get_language_value() const { - return static_cast(language_value); - } - const char* language_name; - SpvSourceLanguage language_value; - uint32_t version; -}; - -// clang-format off -// The list of OpSource cases to use. -const LanguageCase kLanguageCases[] = { -#define CASE(NAME, VERSION) \ - { #NAME, SpvSourceLanguage##NAME, VERSION } - CASE(Unknown, 0), - CASE(Unknown, 999), - CASE(ESSL, 310), - CASE(GLSL, 450), - CASE(OpenCL_C, 120), - CASE(OpenCL_C, 200), - CASE(OpenCL_C, 210), - CASE(OpenCL_CPP, 210), - CASE(HLSL, 5), - CASE(HLSL, 6), -#undef CASE -}; -// clang-format on - -using OpSourceTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpSourceTest, AnyLanguage) { - const std::string input = std::string("OpSource ") + - GetParam().language_name + " " + - std::to_string(GetParam().version); - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSource, {GetParam().get_language_value(), - GetParam().version}))); -} - -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpSourceTest, - ::testing::ValuesIn(kLanguageCases)); - -TEST_F(OpSourceTest, WrongLanguage) { - EXPECT_THAT(CompileFailure("OpSource xxyyzz 12345"), - Eq("Invalid source language 'xxyyzz'.")); -} - -TEST_F(TextToBinaryTest, OpSourceAcceptsOptionalFileId) { - // In the grammar, the file id is an OperandOptionalId. - const std::string input = "OpSource GLSL 450 %file_id"; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSource, {SpvSourceLanguageGLSL, 450, 1}))); -} - -TEST_F(TextToBinaryTest, OpSourceAcceptsOptionalSourceText) { - std::string fake_source = "To be or not to be"; - const std::string input = - "OpSource GLSL 450 %file_id \"" + fake_source + "\""; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSource, {SpvSourceLanguageGLSL, 450, 1}, - MakeVector(fake_source)))); -} - -// Test OpSourceContinued - -using OpSourceContinuedTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpSourceContinuedTest, AnyExtension) { - // TODO(dneto): utf-8, quoting, escaping - const std::string input = - std::string("OpSourceContinued \"") + GetParam() + "\""; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSourceContinued, MakeVector(GetParam())))); -} - -// TODO(dneto): utf-8, quoting, escaping -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpSourceContinuedTest, - ::testing::ValuesIn(std::vector{ - "", "foo bar this and that"})); - -// Test OpSourceExtension - -using OpSourceExtensionTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpSourceExtensionTest, AnyExtension) { - // TODO(dneto): utf-8, quoting, escaping - const std::string input = - std::string("OpSourceExtension \"") + GetParam() + "\""; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpSourceExtension, MakeVector(GetParam())))); -} - -// TODO(dneto): utf-8, quoting, escaping -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpSourceExtensionTest, - ::testing::ValuesIn(std::vector{ - "", "foo bar this and that"})); - -TEST_F(TextToBinaryTest, OpLine) { - EXPECT_THAT(CompiledInstructions("OpLine %srcfile 42 99"), - Eq(MakeInstruction(SpvOpLine, {1, 42, 99}))); -} - -TEST_F(TextToBinaryTest, OpNoLine) { - EXPECT_THAT(CompiledInstructions("OpNoLine"), - Eq(MakeInstruction(SpvOpNoLine, {}))); -} - -using OpStringTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpStringTest, AnyString) { - // TODO(dneto): utf-8, quoting, escaping - const std::string input = - std::string("%result = OpString \"") + GetParam() + "\""; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpString, {1}, MakeVector(GetParam())))); -} - -// TODO(dneto): utf-8, quoting, escaping -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpStringTest, - ::testing::ValuesIn(std::vector{ - "", "foo bar this and that"})); - -using OpNameTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpNameTest, AnyString) { - const std::string input = - std::string("OpName %target \"") + GetParam() + "\""; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpName, {1}, MakeVector(GetParam())))); -} - -// UTF-8, quoting, escaping, etc. are covered in the StringLiterals tests in -// BinaryToText.Literal.cpp. -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpNameTest, - ::testing::Values("", "foo bar this and that")); - -using OpMemberNameTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpMemberNameTest, AnyString) { - // TODO(dneto): utf-8, quoting, escaping - const std::string input = - std::string("OpMemberName %type 42 \"") + GetParam() + "\""; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpMemberName, {1, 42}, MakeVector(GetParam())))); -} - -// TODO(dneto): utf-8, quoting, escaping -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpMemberNameTest, - ::testing::ValuesIn(std::vector{ - "", "foo bar this and that"})); - -// TODO(dneto): Parse failures? - -using OpModuleProcessedTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpModuleProcessedTest, AnyString) { - const std::string input = - std::string("OpModuleProcessed \"") + GetParam() + "\""; - EXPECT_THAT( - CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpModuleProcessed, MakeVector(GetParam())))); -} - -INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpModuleProcessedTest, - ::testing::Values("", "foo bar this and that")); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.device_side_enqueue_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.device_side_enqueue_test.cpp deleted file mode 100644 index 03d7e7419..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.device_side_enqueue_test.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Device-Side Enqueue Instructions" -// section of the SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::MakeInstruction; -using ::testing::Eq; - -// Test OpEnqueueKernel - -struct KernelEnqueueCase { - std::string local_size_source; - std::vector local_size_operands; -}; - -using OpEnqueueKernelGood = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(OpEnqueueKernelGood, Sample) { - const std::string input = - "%result = OpEnqueueKernel %type %queue %flags %NDRange %num_events" - " %wait_events %ret_event %invoke %param %param_size %param_align " + - GetParam().local_size_source; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpEnqueueKernel, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, - GetParam().local_size_operands))); -} - -INSTANTIATE_TEST_SUITE_P( - TextToBinaryTest, OpEnqueueKernelGood, - ::testing::ValuesIn(std::vector{ - // Provide IDs for pointer-to-local arguments for the - // invoked function. - // Test up to 10 such arguments. - // I (dneto) can't find a limit on the number of kernel - // arguments in OpenCL C 2.0 Rev 29, e.g. in section 6.9 - // Restrictions. - {"", {}}, - {"%l0", {13}}, - {"%l0 %l1", {13, 14}}, - {"%l0 %l1 %l2", {13, 14, 15}}, - {"%l0 %l1 %l2 %l3", {13, 14, 15, 16}}, - {"%l0 %l1 %l2 %l3 %l4", {13, 14, 15, 16, 17}}, - {"%l0 %l1 %l2 %l3 %l4 %l5", {13, 14, 15, 16, 17, 18}}, - {"%l0 %l1 %l2 %l3 %l4 %l5 %l6", {13, 14, 15, 16, 17, 18, 19}}, - {"%l0 %l1 %l2 %l3 %l4 %l5 %l6 %l7", {13, 14, 15, 16, 17, 18, 19, 20}}, - {"%l0 %l1 %l2 %l3 %l4 %l5 %l6 %l7 %l8", - {13, 14, 15, 16, 17, 18, 19, 20, 21}}, - {"%l0 %l1 %l2 %l3 %l4 %l5 %l6 %l7 %l8 %l9", - {13, 14, 15, 16, 17, 18, 19, 20, 21, 22}}, - })); - -// Test some bad parses of OpEnqueueKernel. For other cases, we're relying -// on the uniformity of the parsing algorithm. The following two tests, ensure -// that every required ID operand is specified, and is actually an ID operand. -using OpKernelEnqueueBad = spvtest::TextToBinaryTest; - -TEST_F(OpKernelEnqueueBad, MissingLastOperand) { - EXPECT_THAT( - CompileFailure( - "%result = OpEnqueueKernel %type %queue %flags %NDRange %num_events" - " %wait_events %ret_event %invoke %param %param_size"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpKernelEnqueueBad, InvalidLastOperand) { - EXPECT_THAT( - CompileFailure( - "%result = OpEnqueueKernel %type %queue %flags %NDRange %num_events" - " %wait_events %ret_event %invoke %param %param_size 42"), - Eq("Expected id to start with %.")); -} - -// TODO(dneto): OpEnqueueMarker -// TODO(dneto): OpGetKernelNDRangeSubGroupCount -// TODO(dneto): OpGetKernelNDRangeMaxSubGroupSize -// TODO(dneto): OpGetKernelWorkGroupSize -// TODO(dneto): OpGetKernelPreferredWorkGroupSizeMultiple -// TODO(dneto): OpRetainEvent -// TODO(dneto): OpReleaseEvent -// TODO(dneto): OpCreateUserEvent -// TODO(dneto): OpSetUserEventStatus -// TODO(dneto): OpCaptureEventProfilingInfo -// TODO(dneto): OpGetDefaultQueue -// TODO(dneto): OpBuildNDRange -// TODO(dneto): OpBuildNDRange - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.extension_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.extension_test.cpp deleted file mode 100644 index 023763b76..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.extension_test.cpp +++ /dev/null @@ -1,909 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Extension Instruction" section -// of the SPIR-V spec. - -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/latest_version_glsl_std_450_header.h" -#include "source/latest_version_opencl_std_header.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::Concatenate; -using spvtest::MakeInstruction; -using utils::MakeVector; -using spvtest::TextToBinaryTest; -using ::testing::Combine; -using ::testing::Eq; -using ::testing::Values; -using ::testing::ValuesIn; - -// Returns a generator of common Vulkan environment values to be tested. -std::vector CommonVulkanEnvs() { - return {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2, - SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}; -} - -TEST_F(TextToBinaryTest, InvalidExtInstImportName) { - EXPECT_THAT(CompileFailure("%1 = OpExtInstImport \"Haskell.std\""), - Eq("Invalid extended instruction import 'Haskell.std'")); -} - -TEST_F(TextToBinaryTest, InvalidImportId) { - EXPECT_THAT(CompileFailure("%1 = OpTypeVoid\n" - "%2 = OpExtInst %1 %1"), - Eq("Invalid extended instruction import Id 2")); -} - -TEST_F(TextToBinaryTest, InvalidImportInstruction) { - const std::string input = R"(%1 = OpTypeVoid - %2 = OpExtInstImport "OpenCL.std" - %3 = OpExtInst %1 %2 not_in_the_opencl)"; - EXPECT_THAT(CompileFailure(input), - Eq("Invalid extended instruction name 'not_in_the_opencl'.")); -} - -TEST_F(TextToBinaryTest, MultiImport) { - const std::string input = R"(%2 = OpExtInstImport "OpenCL.std" - %2 = OpExtInstImport "OpenCL.std")"; - EXPECT_THAT(CompileFailure(input), - Eq("Import Id is being defined a second time")); -} - -TEST_F(TextToBinaryTest, TooManyArguments) { - const std::string input = R"(%opencl = OpExtInstImport "OpenCL.std" - %2 = OpExtInst %float %opencl cos %x %oops")"; - EXPECT_THAT(CompileFailure(input), Eq("Expected '=', found end of stream.")); -} - -TEST_F(TextToBinaryTest, ExtInstFromTwoDifferentImports) { - const std::string input = R"(%1 = OpExtInstImport "OpenCL.std" -%2 = OpExtInstImport "GLSL.std.450" -%4 = OpExtInst %3 %1 native_sqrt %5 -%7 = OpExtInst %6 %2 MatrixInverse %8 -)"; - - // Make sure it assembles correctly. - EXPECT_THAT( - CompiledInstructions(input), - Eq(Concatenate({ - MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")), - MakeInstruction(SpvOpExtInstImport, {2}, MakeVector("GLSL.std.450")), - MakeInstruction( - SpvOpExtInst, - {3, 4, 1, uint32_t(OpenCLLIB::Entrypoints::Native_sqrt), 5}), - MakeInstruction(SpvOpExtInst, - {6, 7, 2, uint32_t(GLSLstd450MatrixInverse), 8}), - }))); - - // Make sure it disassembles correctly. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); -} - -// A test case for assembling into words in an instruction. -struct AssemblyCase { - std::string input; - std::vector expected; -}; - -using ExtensionAssemblyTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(ExtensionAssemblyTest, Samples) { - const spv_target_env& env = std::get<0>(GetParam()); - const AssemblyCase& ac = std::get<1>(GetParam()); - - // Check that it assembles correctly. - EXPECT_THAT(CompiledInstructions(ac.input, env), Eq(ac.expected)); -} - -using ExtensionRoundTripTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(ExtensionRoundTripTest, Samples) { - const spv_target_env& env = std::get<0>(GetParam()); - const AssemblyCase& ac = std::get<1>(GetParam()); - - // Check that it assembles correctly. - EXPECT_THAT(CompiledInstructions(ac.input, env), Eq(ac.expected)); - - // Check round trip through the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(ac.input, - SPV_BINARY_TO_TEXT_OPTION_NONE, env), - Eq(ac.input)) - << "target env: " << spvTargetEnvDescription(env) << "\n"; -} - -// SPV_KHR_shader_ballot - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_shader_ballot, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {"OpCapability SubgroupBallotKHR\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilitySubgroupBallotKHR})}, - {"%2 = OpSubgroupBallotKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})}, - {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})}, - {"OpDecorate %1 BuiltIn SubgroupEqMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupEqMaskKHR})}, - {"OpDecorate %1 BuiltIn SubgroupGeMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupGeMaskKHR})}, - {"OpDecorate %1 BuiltIn SubgroupGtMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupGtMaskKHR})}, - {"OpDecorate %1 BuiltIn SubgroupLeMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupLeMaskKHR})}, - {"OpDecorate %1 BuiltIn SubgroupLtMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupLtMaskKHR})}, - }))); - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_shader_ballot_vulkan_1_1, ExtensionRoundTripTest, - // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the - // builtin enums. - Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1), - ValuesIn(std::vector{ - {"OpCapability SubgroupBallotKHR\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilitySubgroupBallotKHR})}, - {"%2 = OpSubgroupBallotKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})}, - {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})}, - {"OpDecorate %1 BuiltIn SubgroupEqMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupEqMask})}, - {"OpDecorate %1 BuiltIn SubgroupGeMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupGeMask})}, - {"OpDecorate %1 BuiltIn SubgroupGtMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupGtMask})}, - {"OpDecorate %1 BuiltIn SubgroupLeMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupLeMask})}, - {"OpDecorate %1 BuiltIn SubgroupLtMask\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupLtMask})}, - }))); - -// The old builtin names (with KHR suffix) still work in the assmebler, and -// map to the enums without the KHR. -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_shader_ballot_vulkan_1_1_alias_check, ExtensionAssemblyTest, - // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the - // builtin enums. - Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1), - ValuesIn(std::vector{ - {"OpDecorate %1 BuiltIn SubgroupEqMaskKHR\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupEqMask})}, - {"OpDecorate %1 BuiltIn SubgroupGeMaskKHR\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupGeMask})}, - {"OpDecorate %1 BuiltIn SubgroupGtMaskKHR\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupGtMask})}, - {"OpDecorate %1 BuiltIn SubgroupLeMaskKHR\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupLeMask})}, - {"OpDecorate %1 BuiltIn SubgroupLtMaskKHR\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInSubgroupLtMask})}, - }))); - -// SPV_KHR_shader_draw_parameters - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_shader_draw_parameters, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine( - ValuesIn(CommonVulkanEnvs()), - ValuesIn(std::vector{ - {"OpCapability DrawParameters\n", - MakeInstruction(SpvOpCapability, {SpvCapabilityDrawParameters})}, - {"OpDecorate %1 BuiltIn BaseVertex\n", - MakeInstruction(SpvOpDecorate, - {1, SpvDecorationBuiltIn, SpvBuiltInBaseVertex})}, - {"OpDecorate %1 BuiltIn BaseInstance\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInBaseInstance})}, - {"OpDecorate %1 BuiltIn DrawIndex\n", - MakeInstruction(SpvOpDecorate, - {1, SpvDecorationBuiltIn, SpvBuiltInDrawIndex})}, - }))); - -// SPV_KHR_subgroup_vote - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_subgroup_vote, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(ValuesIn(CommonVulkanEnvs()), - ValuesIn(std::vector{ - {"OpCapability SubgroupVoteKHR\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilitySubgroupVoteKHR})}, - {"%2 = OpSubgroupAnyKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupAnyKHR, {1, 2, 3})}, - {"%2 = OpSubgroupAllKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupAllKHR, {1, 2, 3})}, - {"%2 = OpSubgroupAllEqualKHR %1 %3\n", - MakeInstruction(SpvOpSubgroupAllEqualKHR, {1, 2, 3})}, - }))); - -// SPV_KHR_16bit_storage - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_16bit_storage, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(ValuesIn(CommonVulkanEnvs()), - ValuesIn(std::vector{ - {"OpCapability StorageBuffer16BitAccess\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageUniformBufferBlock16})}, - {"OpCapability StorageBuffer16BitAccess\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageBuffer16BitAccess})}, - {"OpCapability UniformAndStorageBuffer16BitAccess\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityUniformAndStorageBuffer16BitAccess})}, - {"OpCapability UniformAndStorageBuffer16BitAccess\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageUniform16})}, - {"OpCapability StoragePushConstant16\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStoragePushConstant16})}, - {"OpCapability StorageInputOutput16\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageInputOutput16})}, - }))); - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_16bit_storage_alias_check, ExtensionAssemblyTest, - Combine(ValuesIn(CommonVulkanEnvs()), - ValuesIn(std::vector{ - // The old name maps to the new enum. - {"OpCapability StorageUniformBufferBlock16\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageBuffer16BitAccess})}, - // The new name maps to the old enum. - {"OpCapability UniformAndStorageBuffer16BitAccess\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageUniform16})}, - }))); - -// SPV_KHR_device_group - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_device_group, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(ValuesIn(CommonVulkanEnvs()), - ValuesIn(std::vector{ - {"OpCapability DeviceGroup\n", - MakeInstruction(SpvOpCapability, {SpvCapabilityDeviceGroup})}, - {"OpDecorate %1 BuiltIn DeviceIndex\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInDeviceIndex})}, - }))); - -// SPV_KHR_8bit_storage - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_8bit_storage, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine( - ValuesIn(CommonVulkanEnvs()), - ValuesIn(std::vector{ - {"OpCapability StorageBuffer8BitAccess\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStorageBuffer8BitAccess})}, - {"OpCapability UniformAndStorageBuffer8BitAccess\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityUniformAndStorageBuffer8BitAccess})}, - {"OpCapability StoragePushConstant8\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityStoragePushConstant8})}, - }))); - -// SPV_KHR_multiview - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_multiview, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {"OpCapability MultiView\n", - MakeInstruction(SpvOpCapability, {SpvCapabilityMultiView})}, - {"OpDecorate %1 BuiltIn ViewIndex\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInViewIndex})}, - }))); - -// SPV_AMD_shader_explicit_vertex_parameter - -#define PREAMBLE \ - "%1 = OpExtInstImport \"SPV_AMD_shader_explicit_vertex_parameter\"\n" -INSTANTIATE_TEST_SUITE_P( - SPV_AMD_shader_explicit_vertex_parameter, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {PREAMBLE "%3 = OpExtInst %2 %1 InterpolateAtVertexAMD %4 %5\n", - Concatenate( - {MakeInstruction( - SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_explicit_vertex_parameter")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})}, - }))); -#undef PREAMBLE - -// SPV_AMD_shader_trinary_minmax - -#define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_shader_trinary_minmax\"\n" -INSTANTIATE_TEST_SUITE_P( - SPV_AMD_shader_trinary_minmax, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {PREAMBLE "%3 = OpExtInst %2 %1 FMin3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 UMin3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 SMin3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 3, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 FMax3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 UMax3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 5, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 SMax3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 6, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 FMid3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 7, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 UMid3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 8, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 SMid3AMD %4 %5 %6\n", - Concatenate( - {MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_trinary_minmax")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 9, 4, 5, 6})})}, - }))); -#undef PREAMBLE - -// SPV_AMD_gcn_shader - -#define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_gcn_shader\"\n" -INSTANTIATE_TEST_SUITE_P( - SPV_AMD_gcn_shader, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_gcn_shader")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_gcn_shader")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_gcn_shader")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 3})})}, - }))); -#undef PREAMBLE - -// SPV_AMD_shader_ballot - -#define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_shader_ballot\"\n" -INSTANTIATE_TEST_SUITE_P( - SPV_AMD_shader_ballot, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {PREAMBLE "%3 = OpExtInst %2 %1 SwizzleInvocationsAMD %4 %5\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_ballot")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})}, - {PREAMBLE - "%3 = OpExtInst %2 %1 SwizzleInvocationsMaskedAMD %4 %5\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_ballot")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 WriteInvocationAMD %4 %5 %6\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_ballot")), - MakeInstruction(SpvOpExtInst, - {2, 3, 1, 3, 4, 5, 6})})}, - {PREAMBLE "%3 = OpExtInst %2 %1 MbcntAMD %4\n", - Concatenate({MakeInstruction(SpvOpExtInstImport, {1}, - MakeVector("SPV_AMD_shader_ballot")), - MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4})})}, - }))); -#undef PREAMBLE - -// SPV_KHR_variable_pointers - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_variable_pointers, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {"OpCapability VariablePointers\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityVariablePointers})}, - {"OpCapability VariablePointersStorageBuffer\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityVariablePointersStorageBuffer})}, - }))); - -// SPV_KHR_vulkan_memory_model - -INSTANTIATE_TEST_SUITE_P( - SPV_KHR_vulkan_memory_model, ExtensionRoundTripTest, - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - // - // Note: SPV_KHR_vulkan_memory_model adds scope enum value QueueFamilyKHR. - // Scope enums are used in ID definitions elsewhere, that don't know they - // are using particular enums. So the assembler doesn't support assembling - // those enums names into the corresponding values. So there is no asm/dis - // tests for those enums. - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1), - ValuesIn(std::vector{ - {"OpCapability VulkanMemoryModel\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityVulkanMemoryModelKHR})}, - {"OpCapability VulkanMemoryModelDeviceScope\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityVulkanMemoryModelDeviceScopeKHR})}, - {"OpMemoryModel Logical Vulkan\n", - MakeInstruction(SpvOpMemoryModel, {SpvAddressingModelLogical, - SpvMemoryModelVulkanKHR})}, - {"OpStore %1 %2 MakePointerAvailable %3\n", - MakeInstruction(SpvOpStore, - {1, 2, SpvMemoryAccessMakePointerAvailableKHRMask, - 3})}, - {"OpStore %1 %2 Volatile|MakePointerAvailable %3\n", - MakeInstruction(SpvOpStore, - {1, 2, - int(SpvMemoryAccessMakePointerAvailableKHRMask) | - int(SpvMemoryAccessVolatileMask), - 3})}, - {"OpStore %1 %2 Aligned|MakePointerAvailable 4 %3\n", - MakeInstruction(SpvOpStore, - {1, 2, - int(SpvMemoryAccessMakePointerAvailableKHRMask) | - int(SpvMemoryAccessAlignedMask), - 4, 3})}, - {"OpStore %1 %2 MakePointerAvailable|NonPrivatePointer %3\n", - MakeInstruction(SpvOpStore, - {1, 2, - int(SpvMemoryAccessMakePointerAvailableKHRMask) | - int(SpvMemoryAccessNonPrivatePointerKHRMask), - 3})}, - {"%2 = OpLoad %1 %3 MakePointerVisible %4\n", - MakeInstruction(SpvOpLoad, - {1, 2, 3, SpvMemoryAccessMakePointerVisibleKHRMask, - 4})}, - {"%2 = OpLoad %1 %3 Volatile|MakePointerVisible %4\n", - MakeInstruction(SpvOpLoad, - {1, 2, 3, - int(SpvMemoryAccessMakePointerVisibleKHRMask) | - int(SpvMemoryAccessVolatileMask), - 4})}, - {"%2 = OpLoad %1 %3 Aligned|MakePointerVisible 8 %4\n", - MakeInstruction(SpvOpLoad, - {1, 2, 3, - int(SpvMemoryAccessMakePointerVisibleKHRMask) | - int(SpvMemoryAccessAlignedMask), - 8, 4})}, - {"%2 = OpLoad %1 %3 MakePointerVisible|NonPrivatePointer " - "%4\n", - MakeInstruction(SpvOpLoad, - {1, 2, 3, - int(SpvMemoryAccessMakePointerVisibleKHRMask) | - int(SpvMemoryAccessNonPrivatePointerKHRMask), - 4})}, - {"OpCopyMemory %1 %2 " - "MakePointerAvailable|" - "MakePointerVisible|" - "NonPrivatePointer " - "%3 %4\n", - MakeInstruction(SpvOpCopyMemory, - {1, 2, - (int(SpvMemoryAccessMakePointerVisibleKHRMask) | - int(SpvMemoryAccessMakePointerAvailableKHRMask) | - int(SpvMemoryAccessNonPrivatePointerKHRMask)), - 3, 4})}, - {"OpCopyMemorySized %1 %2 %3 " - "MakePointerAvailable|" - "MakePointerVisible|" - "NonPrivatePointer " - "%4 %5\n", - MakeInstruction(SpvOpCopyMemorySized, - {1, 2, 3, - (int(SpvMemoryAccessMakePointerVisibleKHRMask) | - int(SpvMemoryAccessMakePointerAvailableKHRMask) | - int(SpvMemoryAccessNonPrivatePointerKHRMask)), - 4, 5})}, - // Image operands - {"OpImageWrite %1 %2 %3 MakeTexelAvailable " - "%4\n", - MakeInstruction( - SpvOpImageWrite, - {1, 2, 3, int(SpvImageOperandsMakeTexelAvailableKHRMask), 4})}, - {"OpImageWrite %1 %2 %3 MakeTexelAvailable|NonPrivateTexel " - "%4\n", - MakeInstruction(SpvOpImageWrite, - {1, 2, 3, - int(SpvImageOperandsMakeTexelAvailableKHRMask) | - int(SpvImageOperandsNonPrivateTexelKHRMask), - 4})}, - {"OpImageWrite %1 %2 %3 " - "MakeTexelAvailable|NonPrivateTexel|VolatileTexel " - "%4\n", - MakeInstruction(SpvOpImageWrite, - {1, 2, 3, - int(SpvImageOperandsMakeTexelAvailableKHRMask) | - int(SpvImageOperandsNonPrivateTexelKHRMask) | - int(SpvImageOperandsVolatileTexelKHRMask), - 4})}, - {"%2 = OpImageRead %1 %3 %4 MakeTexelVisible " - "%5\n", - MakeInstruction(SpvOpImageRead, - {1, 2, 3, 4, - int(SpvImageOperandsMakeTexelVisibleKHRMask), - 5})}, - {"%2 = OpImageRead %1 %3 %4 " - "MakeTexelVisible|NonPrivateTexel " - "%5\n", - MakeInstruction(SpvOpImageRead, - {1, 2, 3, 4, - int(SpvImageOperandsMakeTexelVisibleKHRMask) | - int(SpvImageOperandsNonPrivateTexelKHRMask), - 5})}, - {"%2 = OpImageRead %1 %3 %4 " - "MakeTexelVisible|NonPrivateTexel|VolatileTexel " - "%5\n", - MakeInstruction(SpvOpImageRead, - {1, 2, 3, 4, - int(SpvImageOperandsMakeTexelVisibleKHRMask) | - int(SpvImageOperandsNonPrivateTexelKHRMask) | - int(SpvImageOperandsVolatileTexelKHRMask), - 5})}, - - // Memory semantics ID values are numbers put into a SPIR-V - // constant integer referenced by Id. There is no token for - // them, and so no assembler or disassembler support required. - // Similar for Scope ID. - }))); - -// SPV_GOOGLE_decorate_string - -// Now that OpDecorateString is the preferred spelling for -// OpDecorateStringGOOGLE use that name in round trip tests, and the GOOGLE -// name in an assembly-only test. - -INSTANTIATE_TEST_SUITE_P( - SPV_GOOGLE_decorate_string, ExtensionRoundTripTest, - Combine( - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {"OpDecorateString %1 UserSemantic \"ABC\"\n", - MakeInstruction(SpvOpDecorateStringGOOGLE, - {1, SpvDecorationHlslSemanticGOOGLE}, - MakeVector("ABC"))}, - {"OpDecorateString %1 UserSemantic \"ABC\"\n", - MakeInstruction(SpvOpDecorateString, - {1, SpvDecorationUserSemantic}, - MakeVector("ABC"))}, - {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n", - MakeInstruction(SpvOpMemberDecorateStringGOOGLE, - {1, 3, SpvDecorationUserSemantic}, - MakeVector("DEF"))}, - {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n", - MakeInstruction(SpvOpMemberDecorateString, - {1, 3, SpvDecorationUserSemantic}, - MakeVector("DEF"))}, - }))); - -INSTANTIATE_TEST_SUITE_P( - SPV_GOOGLE_decorate_string, ExtensionAssemblyTest, - Combine( - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), - ValuesIn(std::vector{ - {"OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE \"ABC\"\n", - MakeInstruction(SpvOpDecorateStringGOOGLE, - {1, SpvDecorationHlslSemanticGOOGLE}, - MakeVector("ABC"))}, - {"OpMemberDecorateStringGOOGLE %1 3 HlslSemanticGOOGLE \"DEF\"\n", - MakeInstruction(SpvOpMemberDecorateStringGOOGLE, - {1, 3, SpvDecorationHlslSemanticGOOGLE}, - MakeVector("DEF"))}, - }))); - -// SPV_GOOGLE_hlsl_functionality1 - -// Now that CounterBuffer is the preferred spelling for HlslCounterBufferGOOGLE, -// use that name in round trip tests, and the GOOGLE name in an assembly-only -// test. -INSTANTIATE_TEST_SUITE_P( - SPV_GOOGLE_hlsl_functionality1, ExtensionRoundTripTest, - Combine( - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), - // HlslSemanticGOOGLE is tested in SPV_GOOGLE_decorate_string, since - // they are coupled together. - ValuesIn(std::vector{ - {"OpDecorateId %1 CounterBuffer %2\n", - MakeInstruction(SpvOpDecorateId, - {1, SpvDecorationHlslCounterBufferGOOGLE, 2})}, - {"OpDecorateId %1 CounterBuffer %2\n", - MakeInstruction(SpvOpDecorateId, - {1, SpvDecorationCounterBuffer, 2})}, - }))); - -INSTANTIATE_TEST_SUITE_P( - SPV_GOOGLE_hlsl_functionality1, ExtensionAssemblyTest, - Combine( - // We'll get coverage over operand tables by trying the universal - // environments, and at least one specific environment. - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), - // HlslSemanticGOOGLE is tested in SPV_GOOGLE_decorate_string, since - // they are coupled together. - ValuesIn(std::vector{ - {"OpDecorateId %1 HlslCounterBufferGOOGLE %2\n", - MakeInstruction(SpvOpDecorateId, - {1, SpvDecorationHlslCounterBufferGOOGLE, 2})}, - }))); - -// SPV_NV_viewport_array2 - -INSTANTIATE_TEST_SUITE_P( - SPV_NV_viewport_array2, ExtensionRoundTripTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, - SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1), - ValuesIn(std::vector{ - {"OpExtension \"SPV_NV_viewport_array2\"\n", - MakeInstruction(SpvOpExtension, - MakeVector("SPV_NV_viewport_array2"))}, - // The EXT and NV extensions have the same token number for this - // capability. - {"OpCapability ShaderViewportIndexLayerEXT\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityShaderViewportIndexLayerNV})}, - // Check the new capability's token number - {"OpCapability ShaderViewportIndexLayerEXT\n", - MakeInstruction(SpvOpCapability, {5254})}, - // Decorations - {"OpDecorate %1 ViewportRelativeNV\n", - MakeInstruction(SpvOpDecorate, - {1, SpvDecorationViewportRelativeNV})}, - {"OpDecorate %1 BuiltIn ViewportMaskNV\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn, - SpvBuiltInViewportMaskNV})}, - }))); - -// SPV_NV_shader_subgroup_partitioned - -INSTANTIATE_TEST_SUITE_P( - SPV_NV_shader_subgroup_partitioned, ExtensionRoundTripTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1), - ValuesIn(std::vector{ - {"OpExtension \"SPV_NV_shader_subgroup_partitioned\"\n", - MakeInstruction(SpvOpExtension, - MakeVector("SPV_NV_shader_subgroup_partitioned"))}, - {"OpCapability GroupNonUniformPartitionedNV\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityGroupNonUniformPartitionedNV})}, - // Check the new capability's token number - {"OpCapability GroupNonUniformPartitionedNV\n", - MakeInstruction(SpvOpCapability, {5297})}, - {"%2 = OpGroupNonUniformPartitionNV %1 %3\n", - MakeInstruction(SpvOpGroupNonUniformPartitionNV, {1, 2, 3})}, - // Check the new instruction's token number - {"%2 = OpGroupNonUniformPartitionNV %1 %3\n", - MakeInstruction(static_cast(5296), {1, 2, 3})}, - // Check the new group operations - {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n", - MakeInstruction(SpvOpGroupIAdd, - {1, 2, 3, SpvGroupOperationPartitionedReduceNV, - 4})}, - {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n", - MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 6, 4})}, - {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n", - MakeInstruction(SpvOpGroupIAdd, - {1, 2, 3, - SpvGroupOperationPartitionedInclusiveScanNV, 4})}, - {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n", - MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 7, 4})}, - {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n", - MakeInstruction(SpvOpGroupIAdd, - {1, 2, 3, - SpvGroupOperationPartitionedExclusiveScanNV, 4})}, - {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n", - MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 8, 4})}, - }))); - -// SPV_EXT_descriptor_indexing - -INSTANTIATE_TEST_SUITE_P( - SPV_EXT_descriptor_indexing, ExtensionRoundTripTest, - Combine( - Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, - SPV_ENV_VULKAN_1_1), - ValuesIn(std::vector{ - {"OpExtension \"SPV_EXT_descriptor_indexing\"\n", - MakeInstruction(SpvOpExtension, - MakeVector("SPV_EXT_descriptor_indexing"))}, - // Check capabilities, by name - {"OpCapability ShaderNonUniform\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityShaderNonUniformEXT})}, - {"OpCapability RuntimeDescriptorArray\n", - MakeInstruction(SpvOpCapability, - {SpvCapabilityRuntimeDescriptorArrayEXT})}, - {"OpCapability InputAttachmentArrayDynamicIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityInputAttachmentArrayDynamicIndexingEXT})}, - {"OpCapability UniformTexelBufferArrayDynamicIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT})}, - {"OpCapability StorageTexelBufferArrayDynamicIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT})}, - {"OpCapability UniformBufferArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityUniformBufferArrayNonUniformIndexingEXT})}, - {"OpCapability SampledImageArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilitySampledImageArrayNonUniformIndexingEXT})}, - {"OpCapability StorageBufferArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityStorageBufferArrayNonUniformIndexingEXT})}, - {"OpCapability StorageImageArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityStorageImageArrayNonUniformIndexingEXT})}, - {"OpCapability InputAttachmentArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT})}, - {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT})}, - {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n", - MakeInstruction( - SpvOpCapability, - {SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT})}, - // Check capabilities, by number - {"OpCapability ShaderNonUniform\n", - MakeInstruction(SpvOpCapability, {5301})}, - {"OpCapability RuntimeDescriptorArray\n", - MakeInstruction(SpvOpCapability, {5302})}, - {"OpCapability InputAttachmentArrayDynamicIndexing\n", - MakeInstruction(SpvOpCapability, {5303})}, - {"OpCapability UniformTexelBufferArrayDynamicIndexing\n", - MakeInstruction(SpvOpCapability, {5304})}, - {"OpCapability StorageTexelBufferArrayDynamicIndexing\n", - MakeInstruction(SpvOpCapability, {5305})}, - {"OpCapability UniformBufferArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5306})}, - {"OpCapability SampledImageArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5307})}, - {"OpCapability StorageBufferArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5308})}, - {"OpCapability StorageImageArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5309})}, - {"OpCapability InputAttachmentArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5310})}, - {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5311})}, - {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n", - MakeInstruction(SpvOpCapability, {5312})}, - - // Check the decoration token - {"OpDecorate %1 NonUniform\n", - MakeInstruction(SpvOpDecorate, {1, SpvDecorationNonUniformEXT})}, - {"OpDecorate %1 NonUniform\n", - MakeInstruction(SpvOpDecorate, {1, 5300})}, - }))); - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.function_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.function_test.cpp deleted file mode 100644 index 55a8e6ce6..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.function_test.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Function" section of the -// SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using spvtest::TextToBinaryTest; -using ::testing::Eq; - -// Test OpFunction - -using OpFunctionControlTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(OpFunctionControlTest, AnySingleFunctionControlMask) { - const std::string input = "%result_id = OpFunction %result_type " + - GetParam().name() + " %function_type "; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpFunction, {1, 2, GetParam().value(), 3}))); -} - -// clang-format off -#define CASE(VALUE,NAME) { SpvFunctionControl##VALUE, NAME } -INSTANTIATE_TEST_SUITE_P(TextToBinaryFunctionTest, OpFunctionControlTest, - ::testing::ValuesIn(std::vector>{ - CASE(MaskNone, "None"), - CASE(InlineMask, "Inline"), - CASE(DontInlineMask, "DontInline"), - CASE(PureMask, "Pure"), - CASE(ConstMask, "Const"), - })); -#undef CASE -// clang-format on - -TEST_F(OpFunctionControlTest, CombinedFunctionControlMask) { - // Sample a single combination. This ensures we've integrated - // the instruction parsing logic with spvTextParseMask. - const std::string input = - "%result_id = OpFunction %result_type Inline|Pure|Const %function_type"; - const uint32_t expected_mask = SpvFunctionControlInlineMask | - SpvFunctionControlPureMask | - SpvFunctionControlConstMask; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpFunction, {1, 2, expected_mask, 3}))); -} - -TEST_F(OpFunctionControlTest, WrongFunctionControl) { - EXPECT_THAT(CompileFailure("%r = OpFunction %t Inline|Unroll %ft"), - Eq("Invalid function control operand 'Inline|Unroll'.")); -} - -// TODO(dneto): OpFunctionParameter -// TODO(dneto): OpFunctionEnd -// TODO(dneto): OpFunctionCall - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.group_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.group_test.cpp deleted file mode 100644 index becc3aa6f..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.group_test.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Group Instrucions" section of the -// SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using ::testing::Eq; - -// Test GroupOperation enum - -using GroupOperationTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(GroupOperationTest, AnyGroupOperation) { - const std::string input = - "%result = OpGroupIAdd %type %scope " + GetParam().name() + " %x"; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, GetParam().value(), 4}))); -} - -// clang-format off -#define CASE(NAME) { SpvGroupOperation##NAME, #NAME} -INSTANTIATE_TEST_SUITE_P(TextToBinaryGroupOperation, GroupOperationTest, - ::testing::ValuesIn(std::vector>{ - CASE(Reduce), - CASE(InclusiveScan), - CASE(ExclusiveScan), - })); -#undef CASE -// clang-format on - -TEST_F(GroupOperationTest, WrongGroupOperation) { - EXPECT_THAT(CompileFailure("%r = OpGroupUMin %t %e xxyyzz %x"), - Eq("Invalid group operation 'xxyyzz'.")); -} - -// TODO(dneto): OpGroupAsyncCopy -// TODO(dneto): OpGroupWaitEvents -// TODO(dneto): OpGroupAll -// TODO(dneto): OpGroupAny -// TODO(dneto): OpGroupBroadcast -// TODO(dneto): OpGroupIAdd -// TODO(dneto): OpGroupFAdd -// TODO(dneto): OpGroupFMin -// TODO(dneto): OpGroupUMin -// TODO(dneto): OpGroupSMin -// TODO(dneto): OpGroupFMax -// TODO(dneto): OpGroupUMax -// TODO(dneto): OpGroupSMax - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.image_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.image_test.cpp deleted file mode 100644 index d445369c2..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.image_test.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Image Instructions" section of -// the SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::MakeInstruction; -using spvtest::TextToBinaryTest; -using ::testing::Eq; - -// An example case for a mask value with operands. -struct ImageOperandsCase { - std::string image_operands; - // The expected mask, followed by its operands. - std::vector expected_mask_and_operands; -}; - -// Test all kinds of image operands. - -using ImageOperandsTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(ImageOperandsTest, Sample) { - const std::string input = - "%2 = OpImageFetch %1 %3 %4" + GetParam().image_operands + "\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpImageFetch, {1, 2, 3, 4}, - GetParam().expected_mask_and_operands))); -} - -#define MASK(NAME) SpvImageOperands##NAME##Mask -INSTANTIATE_TEST_SUITE_P( - TextToBinaryImageOperandsAny, ImageOperandsTest, - ::testing::ValuesIn(std::vector{ - // TODO(dneto): Rev32 adds many more values, and rearranges their - // values. - // Image operands are optional. - {"", {}}, - // Test each kind, alone. - {" Bias %5", {MASK(Bias), 5}}, - {" Lod %5", {MASK(Lod), 5}}, - {" Grad %5 %6", {MASK(Grad), 5, 6}}, - {" ConstOffset %5", {MASK(ConstOffset), 5}}, - {" Offset %5", {MASK(Offset), 5}}, - {" ConstOffsets %5", {MASK(ConstOffsets), 5}}, - {" Sample %5", {MASK(Sample), 5}}, - {" MinLod %5", {MASK(MinLod), 5}}, - })); -#undef MASK -#define MASK(NAME) static_cast(SpvImageOperands##NAME##Mask) -INSTANTIATE_TEST_SUITE_P( - TextToBinaryImageOperandsCombination, ImageOperandsTest, - ::testing::ValuesIn(std::vector{ - // TODO(dneto): Rev32 adds many more values, and rearranges their - // values. - // Test adjacent pairs, so we can easily debug the values when it fails. - {" Bias|Lod %5 %6", {MASK(Bias) | MASK(Lod), 5, 6}}, - {" Lod|Grad %5 %6 %7", {MASK(Lod) | MASK(Grad), 5, 6, 7}}, - {" Grad|ConstOffset %5 %6 %7", - {MASK(Grad) | MASK(ConstOffset), 5, 6, 7}}, - {" ConstOffset|Offset %5 %6", {MASK(ConstOffset) | MASK(Offset), 5, 6}}, - {" Offset|ConstOffsets %5 %6", - {MASK(Offset) | MASK(ConstOffsets), 5, 6}}, - {" ConstOffsets|Sample %5 %6", - {MASK(ConstOffsets) | MASK(Sample), 5, 6}}, - // Test all masks together. - {" Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample" - " %5 %6 %7 %8 %9 %10 %11 %12", - {MASK(Bias) | MASK(Lod) | MASK(Grad) | MASK(ConstOffset) | - MASK(Offset) | MASK(ConstOffsets) | MASK(Sample), - 5, 6, 7, 8, 9, 10, 11, 12}}, - // The same, but with mask value names reversed. - {" Sample|ConstOffsets|Offset|ConstOffset|Grad|Lod|Bias" - " %5 %6 %7 %8 %9 %10 %11 %12", - {MASK(Bias) | MASK(Lod) | MASK(Grad) | MASK(ConstOffset) | - MASK(Offset) | MASK(ConstOffsets) | MASK(Sample), - 5, 6, 7, 8, 9, 10, 11, 12}}})); -#undef MASK - -TEST_F(ImageOperandsTest, WrongOperand) { - EXPECT_THAT(CompileFailure("%r = OpImageFetch %t %i %c xxyyzz"), - Eq("Invalid image operand 'xxyyzz'.")); -} - -// Test OpImage - -using OpImageTest = TextToBinaryTest; - -TEST_F(OpImageTest, Valid) { - const std::string input = "%2 = OpImage %1 %3\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpImage, {1, 2, 3}))); - - // Test the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input); -} - -TEST_F(OpImageTest, InvalidTypeOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImage 42"), - Eq("Expected id to start with %.")); -} - -TEST_F(OpImageTest, MissingSampledImageOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImage %1"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpImageTest, InvalidSampledImageOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImage %1 1000"), - Eq("Expected id to start with %.")); -} - -TEST_F(OpImageTest, TooManyOperands) { - // We should improve this message, to say what instruction we're trying to - // parse. - EXPECT_THAT(CompileFailure("%2 = OpImage %1 %3 %4"), // an Id - Eq("Expected '=', found end of stream.")); - - EXPECT_THAT(CompileFailure("%2 = OpImage %1 %3 99"), // a number - Eq("Expected or at the beginning of an " - "instruction, found '99'.")); - EXPECT_THAT(CompileFailure("%2 = OpImage %1 %3 \"abc\""), // a string - Eq("Expected or at the beginning of an " - "instruction, found '\"abc\"'.")); -} - -// Test OpImageSparseRead - -using OpImageSparseReadTest = TextToBinaryTest; - -TEST_F(OpImageSparseReadTest, OnlyRequiredOperands) { - const std::string input = "%2 = OpImageSparseRead %1 %3 %4\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4}))); - // Test the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input); -} - -// Test all kinds of image operands on OpImageSparseRead - -using ImageSparseReadImageOperandsTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>; - -TEST_P(ImageSparseReadImageOperandsTest, Sample) { - const std::string input = - "%2 = OpImageSparseRead %1 %3 %4" + GetParam().image_operands + "\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4}, - GetParam().expected_mask_and_operands))); - // Test the disassembler. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input); -} - -#define MASK(NAME) SpvImageOperands##NAME##Mask -INSTANTIATE_TEST_SUITE_P(ImageSparseReadImageOperandsAny, - ImageSparseReadImageOperandsTest, - ::testing::ValuesIn(std::vector{ - // Image operands are optional. - {"", {}}, - // Test each kind, alone. - {" Bias %5", {MASK(Bias), 5}}, - {" Lod %5", {MASK(Lod), 5}}, - {" Grad %5 %6", {MASK(Grad), 5, 6}}, - {" ConstOffset %5", {MASK(ConstOffset), 5}}, - {" Offset %5", {MASK(Offset), 5}}, - {" ConstOffsets %5", {MASK(ConstOffsets), 5}}, - {" Sample %5", {MASK(Sample), 5}}, - {" MinLod %5", {MASK(MinLod), 5}}, - })); -#undef MASK -#define MASK(NAME) static_cast(SpvImageOperands##NAME##Mask) -INSTANTIATE_TEST_SUITE_P( - ImageSparseReadImageOperandsCombination, ImageSparseReadImageOperandsTest, - ::testing::ValuesIn(std::vector{ - // values. - // Test adjacent pairs, so we can easily debug the values when it fails. - {" Bias|Lod %5 %6", {MASK(Bias) | MASK(Lod), 5, 6}}, - {" Lod|Grad %5 %6 %7", {MASK(Lod) | MASK(Grad), 5, 6, 7}}, - {" Grad|ConstOffset %5 %6 %7", - {MASK(Grad) | MASK(ConstOffset), 5, 6, 7}}, - {" ConstOffset|Offset %5 %6", {MASK(ConstOffset) | MASK(Offset), 5, 6}}, - {" Offset|ConstOffsets %5 %6", - {MASK(Offset) | MASK(ConstOffsets), 5, 6}}, - {" ConstOffsets|Sample %5 %6", - {MASK(ConstOffsets) | MASK(Sample), 5, 6}}, - // Test all masks together. - {" Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample" - " %5 %6 %7 %8 %9 %10 %11 %12", - {MASK(Bias) | MASK(Lod) | MASK(Grad) | MASK(ConstOffset) | - MASK(Offset) | MASK(ConstOffsets) | MASK(Sample), - 5, 6, 7, 8, 9, 10, 11, 12}}, - // Don't try the masks reversed, since this is a round trip test, - // and the disassembler will sort them. - })); -#undef MASK - -TEST_F(OpImageSparseReadTest, InvalidTypeOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead 42"), - Eq("Expected id to start with %.")); -} - -TEST_F(OpImageSparseReadTest, MissingImageOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpImageSparseReadTest, InvalidImageOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1 1000"), - Eq("Expected id to start with %.")); -} - -TEST_F(OpImageSparseReadTest, MissingCoordinateOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1 %2"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpImageSparseReadTest, InvalidCoordinateOperand) { - EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1 %2 1000"), - Eq("Expected id to start with %.")); -} - -// TODO(dneto): OpSampledImage -// TODO(dneto): OpImageSampleImplicitLod -// TODO(dneto): OpImageSampleExplicitLod -// TODO(dneto): OpImageSampleDrefImplicitLod -// TODO(dneto): OpImageSampleDrefExplicitLod -// TODO(dneto): OpImageSampleProjImplicitLod -// TODO(dneto): OpImageSampleProjExplicitLod -// TODO(dneto): OpImageSampleProjDrefImplicitLod -// TODO(dneto): OpImageSampleProjDrefExplicitLod -// TODO(dneto): OpImageGather -// TODO(dneto): OpImageDrefGather -// TODO(dneto): OpImageRead -// TODO(dneto): OpImageWrite -// TODO(dneto): OpImageQueryFormat -// TODO(dneto): OpImageQueryOrder -// TODO(dneto): OpImageQuerySizeLod -// TODO(dneto): OpImageQuerySize -// TODO(dneto): OpImageQueryLod -// TODO(dneto): OpImageQueryLevels -// TODO(dneto): OpImageQuerySamples -// TODO(dneto): OpImageSparseSampleImplicitLod -// TODO(dneto): OpImageSparseSampleExplicitLod -// TODO(dneto): OpImageSparseSampleDrefImplicitLod -// TODO(dneto): OpImageSparseSampleDrefExplicitLod -// TODO(dneto): OpImageSparseSampleProjImplicitLod -// TODO(dneto): OpImageSparseSampleProjExplicitLod -// TODO(dneto): OpImageSparseSampleProjDrefImplicitLod -// TODO(dneto): OpImageSparseSampleProjDrefExplicitLod -// TODO(dneto): OpImageSparseFetch -// TODO(dneto): OpImageSparseDrefGather -// TODO(dneto): OpImageSparseTexelsResident - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.literal_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.literal_test.cpp deleted file mode 100644 index bcbb63e0d..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.literal_test.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for literal numbers and literal strings. - -#include - -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using spvtest::TextToBinaryTest; - -TEST_F(TextToBinaryTest, LiteralStringInPlaceOfLiteralNumber) { - EXPECT_EQ( - R"(Invalid unsigned integer literal: "I shouldn't be a string")", - CompileFailure(R"(OpSource GLSL "I shouldn't be a string")")); -} - -TEST_F(TextToBinaryTest, GarbageInPlaceOfLiteralString) { - EXPECT_EQ("Invalid literal string 'nice-source-code'.", - CompileFailure("OpSourceExtension nice-source-code")); -} - -TEST_F(TextToBinaryTest, LiteralNumberInPlaceOfLiteralString) { - EXPECT_EQ("Expected literal string, found literal number '1000'.", - CompileFailure("OpSourceExtension 1000")); -} - -TEST_F(TextToBinaryTest, LiteralFloatInPlaceOfLiteralInteger) { - EXPECT_EQ("Invalid unsigned integer literal: 10.5", - CompileFailure("OpSource GLSL 10.5")); - - EXPECT_EQ("Invalid unsigned integer literal: 0.2", - CompileFailure(R"(OpMemberName %type 0.2 "member0.2")")); - - EXPECT_EQ("Invalid unsigned integer literal: 32.42", - CompileFailure("%int = OpTypeInt 32.42 0")); - - EXPECT_EQ("Invalid unsigned integer literal: 4.5", - CompileFailure("%mat = OpTypeMatrix %vec 4.5")); - - EXPECT_EQ("Invalid unsigned integer literal: 1.5", - CompileFailure("OpExecutionMode %main LocalSize 1.5 1.6 1.7")); - - EXPECT_EQ("Invalid unsigned integer literal: 0.123", - CompileFailure("%i32 = OpTypeInt 32 1\n" - "%c = OpConstant %i32 0.123")); -} - -TEST_F(TextToBinaryTest, LiteralInt64) { - const std::string code = - "%1 = OpTypeInt 64 0\n%2 = OpConstant %1 123456789021\n"; - EXPECT_EQ(code, EncodeAndDecodeSuccessfully(code)); -} - -TEST_F(TextToBinaryTest, LiteralDouble) { - const std::string code = - "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 3.14159265358979\n"; - EXPECT_EQ(code, EncodeAndDecodeSuccessfully(code)); -} - -TEST_F(TextToBinaryTest, LiteralStringASCIILong) { - // SPIR-V allows strings up to 65535 characters. - // Test the simple case of UTF-8 code points corresponding - // to ASCII characters. - EXPECT_EQ(65535, SPV_LIMIT_LITERAL_STRING_UTF8_CHARS_MAX); - const std::string code = - "OpSourceExtension \"" + - std::string(SPV_LIMIT_LITERAL_STRING_UTF8_CHARS_MAX, 'o') + "\"\n"; - EXPECT_EQ(code, EncodeAndDecodeSuccessfully(code)); -} - -TEST_F(TextToBinaryTest, LiteralStringUTF8LongEncodings) { - // SPIR-V allows strings up to 65535 characters. - // Test the case of many Unicode characters, each of which has - // a 4-byte UTF-8 encoding. - - // An instruction is at most 65535 words long. The first one - // contains the wordcount and opcode. So the worst case number of - // 4-byte UTF-8 characters is 65533, since we also need to - // store a terminating null character. - - // This string fits exactly into 65534 words. - const std::string good_string = - spvtest::MakeLongUTF8String(65533) - // The following single character has a 3 byte encoding, - // which fits snugly against the terminating null. - + "\xe8\x80\x80"; - - // These strings will overflow any instruction with 0 or 1 other - // arguments, respectively. - const std::string bad_0_arg_string = spvtest::MakeLongUTF8String(65534); - const std::string bad_1_arg_string = spvtest::MakeLongUTF8String(65533); - - const std::string good_code = "OpSourceExtension \"" + good_string + "\"\n"; - EXPECT_EQ(good_code, EncodeAndDecodeSuccessfully(good_code)); - - // Prove that it works on more than one instruction. - const std::string good_code_2 = "OpSourceContinued \"" + good_string + "\"\n"; - EXPECT_EQ(good_code, EncodeAndDecodeSuccessfully(good_code)); - - // Failure cases. - EXPECT_EQ("Instruction too long: more than 65535 words.", - CompileFailure("OpSourceExtension \"" + bad_0_arg_string + "\"\n")); - EXPECT_EQ("Instruction too long: more than 65535 words.", - CompileFailure("OpSourceContinued \"" + bad_0_arg_string + "\"\n")); - EXPECT_EQ("Instruction too long: more than 65535 words.", - CompileFailure("OpName %target \"" + bad_1_arg_string + "\"\n")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.memory_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.memory_test.cpp deleted file mode 100644 index 7b09ed587..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.memory_test.cpp +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Memory Instructions" section of -// the SPIR-V spec. - -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using spvtest::TextToBinaryTest; -using ::testing::Eq; -using ::testing::HasSubstr; - -// Test assembly of Memory Access masks - -using MemoryAccessTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(MemoryAccessTest, AnySingleMemoryAccessMask) { - std::stringstream input; - input << "OpStore %ptr %value " << GetParam().name(); - for (auto operand : GetParam().operands()) input << " " << operand; - EXPECT_THAT(CompiledInstructions(input.str()), - Eq(MakeInstruction(SpvOpStore, {1, 2, GetParam().value()}, - GetParam().operands()))); -} - -INSTANTIATE_TEST_SUITE_P( - TextToBinaryMemoryAccessTest, MemoryAccessTest, - ::testing::ValuesIn(std::vector>{ - {SpvMemoryAccessMaskNone, "None", {}}, - {SpvMemoryAccessVolatileMask, "Volatile", {}}, - {SpvMemoryAccessAlignedMask, "Aligned", {16}}, - {SpvMemoryAccessNontemporalMask, "Nontemporal", {}}, - })); - -TEST_F(TextToBinaryTest, CombinedMemoryAccessMask) { - const std::string input = "OpStore %ptr %value Volatile|Aligned 16"; - const uint32_t expected_mask = - SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask; - EXPECT_THAT(expected_mask, Eq(3u)); - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpStore, {1, 2, expected_mask, 16}))); -} - -// Test Storage Class enum values - -using StorageClassTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(StorageClassTest, AnyStorageClass) { - const std::string input = "%1 = OpVariable %2 " + GetParam().name(); - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpVariable, {1, 2, GetParam().value()}))); -} - -// clang-format off -#define CASE(NAME) { SpvStorageClass##NAME, #NAME, {} } -INSTANTIATE_TEST_SUITE_P( - TextToBinaryStorageClassTest, StorageClassTest, - ::testing::ValuesIn(std::vector>{ - CASE(UniformConstant), - CASE(Input), - CASE(Uniform), - CASE(Output), - CASE(Workgroup), - CASE(CrossWorkgroup), - CASE(Private), - CASE(Function), - CASE(Generic), - CASE(PushConstant), - CASE(AtomicCounter), - CASE(Image), - })); -#undef CASE -// clang-format on - -using MemoryRoundTripTest = RoundTripTest; - -// OpPtrEqual appeared in SPIR-V 1.4 - -TEST_F(MemoryRoundTripTest, OpPtrEqualGood) { - std::string spirv = "%2 = OpPtrEqual %1 %3 %4\n"; - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4), - Eq(MakeInstruction(SpvOpPtrEqual, {1, 2, 3, 4}))); - std::string disassembly = EncodeAndDecodeSuccessfully( - spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpPtrEqualV13Bad) { - std::string spirv = "%2 = OpPtrEqual %1 %3 %4\n"; - std::string err = CompileFailure(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_THAT(err, HasSubstr("Invalid Opcode name 'OpPtrEqual'")); -} - -// OpPtrNotEqual appeared in SPIR-V 1.4 - -TEST_F(MemoryRoundTripTest, OpPtrNotEqualGood) { - std::string spirv = "%2 = OpPtrNotEqual %1 %3 %4\n"; - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4), - Eq(MakeInstruction(SpvOpPtrNotEqual, {1, 2, 3, 4}))); - std::string disassembly = EncodeAndDecodeSuccessfully( - spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpPtrNotEqualV13Bad) { - std::string spirv = "%2 = OpPtrNotEqual %1 %3 %4\n"; - std::string err = CompileFailure(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_THAT(err, HasSubstr("Invalid Opcode name 'OpPtrNotEqual'")); -} - -// OpPtrDiff appeared in SPIR-V 1.4 - -TEST_F(MemoryRoundTripTest, OpPtrDiffGood) { - std::string spirv = "%2 = OpPtrDiff %1 %3 %4\n"; - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4), - Eq(MakeInstruction(SpvOpPtrDiff, {1, 2, 3, 4}))); - std::string disassembly = EncodeAndDecodeSuccessfully( - spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpPtrDiffV13Good) { - // OpPtrDiff is enabled by a capability as well, so we can assemble - // it even in older SPIR-V environments. We do that so we can - // write tests. - std::string spirv = "%2 = OpPtrDiff %1 %3 %4\n"; - std::string disassembly = EncodeAndDecodeSuccessfully( - spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4); -} - -// OpCopyMemory - -TEST_F(MemoryRoundTripTest, OpCopyMemoryNoMemAccessGood) { - std::string spirv = "OpCopyMemory %1 %2\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryTooFewArgsBad) { - std::string spirv = "OpCopyMemory %1\n"; - std::string err = CompileFailure(spirv); - EXPECT_THAT(err, HasSubstr("Expected operand, found end of stream")); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryTooManyArgsBad) { - std::string spirv = "OpCopyMemory %1 %2 %3\n"; - std::string err = CompileFailure(spirv); - EXPECT_THAT(err, HasSubstr("Invalid memory access operand '%3'")); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNoneGood) { - std::string spirv = "OpCopyMemory %1 %2 None\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 0}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVolatileGood) { - std::string spirv = "OpCopyMemory %1 %2 Volatile\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAligned8Good) { - std::string spirv = "OpCopyMemory %1 %2 Aligned 8\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 2, 8}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNontemporalGood) { - std::string spirv = "OpCopyMemory %1 %2 Nontemporal\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 4}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAvGood) { - std::string spirv = "OpCopyMemory %1 %2 MakePointerAvailable %3\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 8, 3}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVisGood) { - std::string spirv = "OpCopyMemory %1 %2 MakePointerVisible %3\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 16, 3}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNonPrivateGood) { - std::string spirv = "OpCopyMemory %1 %2 NonPrivatePointer\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 32}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessMixedGood) { - std::string spirv = - "OpCopyMemory %1 %2 " - "Volatile|Aligned|Nontemporal|MakePointerAvailable|" - "MakePointerVisible|NonPrivatePointer 16 %3 %4\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 63, 16, 3, 4}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessV13Good) { - std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n"; - // Note: This will assemble but should not validate for SPIR-V 1.3 - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1, 1}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessV14Good) { - std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n"; - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1, 1}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessMixedV14Good) { - std::string spirv = - "OpCopyMemory %1 %2 Volatile|Nontemporal|" - "MakePointerVisible %3 " - "Aligned|MakePointerAvailable|NonPrivatePointer 16 %4\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 21, 3, 42, 16, 4}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -// OpCopyMemorySized - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedNoMemAccessGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTooFewArgsBad) { - std::string spirv = "OpCopyMemorySized %1 %2\n"; - std::string err = CompileFailure(spirv); - EXPECT_THAT(err, HasSubstr("Expected operand, found end of stream")); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTooManyArgsBad) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 %4\n"; - std::string err = CompileFailure(spirv); - EXPECT_THAT(err, HasSubstr("Invalid memory access operand '%4'")); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNoneGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 None\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 0}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVolatileGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAligned8Good) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 Aligned 8\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 2, 8}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNontemporalGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 Nontemporal\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 4}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAvGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerAvailable %4\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 8, 4}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVisGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerVisible %4\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 16, 4}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNonPrivateGood) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 NonPrivatePointer\n"; - EXPECT_THAT(CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 32}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessMixedGood) { - std::string spirv = - "OpCopyMemorySized %1 %2 %3 " - "Volatile|Aligned|Nontemporal|MakePointerAvailable|" - "MakePointerVisible|NonPrivatePointer 16 %4 %5\n"; - EXPECT_THAT( - CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 63, 16, 4, 5}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessV13Good) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n"; - // Note: This will assemble but should not validate for SPIR-V 1.3 - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1, 1}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessV14Good) { - std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n"; - EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1, 1}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessMixedV14Good) { - std::string spirv = - "OpCopyMemorySized %1 %2 %3 Volatile|Nontemporal|" - "MakePointerVisible %4 " - "Aligned|MakePointerAvailable|NonPrivatePointer 16 %5\n"; - EXPECT_THAT( - CompiledInstructions(spirv), - Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 21, 4, 42, 16, 5}))); - std::string disassembly = - EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE); - EXPECT_THAT(disassembly, Eq(spirv)); -} - -// TODO(dneto): OpVariable with initializers -// TODO(dneto): OpImageTexelPointer -// TODO(dneto): OpLoad -// TODO(dneto): OpStore -// TODO(dneto): OpAccessChain -// TODO(dneto): OpInBoundsAccessChain -// TODO(dneto): OpPtrAccessChain -// TODO(dneto): OpArrayLength -// TODO(dneto): OpGenercPtrMemSemantics - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.misc_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.misc_test.cpp deleted file mode 100644 index 03b1e0914..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.misc_test.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Miscellaneous" section of the -// SPIR-V spec. - -#include "test/unit_spirv.h" - -#include "gmock/gmock.h" -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using SpirvVector = spvtest::TextToBinaryTest::SpirvVector; -using spvtest::MakeInstruction; -using ::testing::Eq; -using TextToBinaryMisc = spvtest::TextToBinaryTest; - -TEST_F(TextToBinaryMisc, OpNop) { - EXPECT_THAT(CompiledInstructions("OpNop"), Eq(MakeInstruction(SpvOpNop, {}))); -} - -TEST_F(TextToBinaryMisc, OpUndef) { - const SpirvVector code = CompiledInstructions(R"(%f32 = OpTypeFloat 32 - %u = OpUndef %f32)"); - const uint32_t typeID = 1; - EXPECT_THAT(code[1], Eq(typeID)); - EXPECT_THAT(Subvector(code, 3), Eq(MakeInstruction(SpvOpUndef, {typeID, 2}))); -} - -TEST_F(TextToBinaryMisc, OpWrong) { - EXPECT_THAT(CompileFailure(" OpWrong %1 %2"), - Eq("Invalid Opcode name 'OpWrong'")); -} - -TEST_F(TextToBinaryMisc, OpWrongAfterRight) { - const auto assembly = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpXYZ -)"; - EXPECT_THAT(CompileFailure(assembly), Eq("Invalid Opcode name 'OpXYZ'")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.mode_setting_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.mode_setting_test.cpp deleted file mode 100644 index 8ddf42196..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.mode_setting_test.cpp +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Mode-Setting" section of the -// SPIR-V spec. - -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using utils::MakeVector; -using ::testing::Combine; -using ::testing::Eq; -using ::testing::TestWithParam; -using ::testing::Values; -using ::testing::ValuesIn; - -// Test OpMemoryModel - -// An example case for OpMemoryModel -struct MemoryModelCase { - uint32_t get_addressing_value() const { - return static_cast(addressing_value); - } - uint32_t get_memory_value() const { - return static_cast(memory_value); - } - SpvAddressingModel addressing_value; - std::string addressing_name; - SpvMemoryModel memory_value; - std::string memory_name; -}; - -using OpMemoryModelTest = - spvtest::TextToBinaryTestBase>; - -TEST_P(OpMemoryModelTest, AnyMemoryModelCase) { - const std::string input = "OpMemoryModel " + GetParam().addressing_name + - " " + GetParam().memory_name; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpMemoryModel, {GetParam().get_addressing_value(), - GetParam().get_memory_value()}))); -} - -#define CASE(ADDRESSING, MEMORY) \ - { \ - SpvAddressingModel##ADDRESSING, #ADDRESSING, SpvMemoryModel##MEMORY, \ - #MEMORY \ - } -// clang-format off -INSTANTIATE_TEST_SUITE_P(TextToBinaryMemoryModel, OpMemoryModelTest, - ValuesIn(std::vector{ - // These cases exercise each addressing model, and - // each memory model, but not necessarily in - // combination. - CASE(Logical,Simple), - CASE(Logical,GLSL450), - CASE(Physical32,OpenCL), - CASE(Physical64,OpenCL), - })); -#undef CASE -// clang-format on - -TEST_F(OpMemoryModelTest, WrongModel) { - EXPECT_THAT(CompileFailure("OpMemoryModel xxyyzz Simple"), - Eq("Invalid addressing model 'xxyyzz'.")); - EXPECT_THAT(CompileFailure("OpMemoryModel Logical xxyyzz"), - Eq("Invalid memory model 'xxyyzz'.")); -} - -// Test OpEntryPoint - -// An example case for OpEntryPoint -struct EntryPointCase { - uint32_t get_execution_value() const { - return static_cast(execution_value); - } - SpvExecutionModel execution_value; - std::string execution_name; - std::string entry_point_name; -}; - -using OpEntryPointTest = - spvtest::TextToBinaryTestBase>; - -TEST_P(OpEntryPointTest, AnyEntryPointCase) { - // TODO(dneto): utf-8, escaping, quoting cases for entry point name. - const std::string input = "OpEntryPoint " + GetParam().execution_name + - " %1 \"" + GetParam().entry_point_name + "\""; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpEntryPoint, {GetParam().get_execution_value(), 1}, - MakeVector(GetParam().entry_point_name)))); -} - -// clang-format off -#define CASE(NAME) SpvExecutionModel##NAME, #NAME -INSTANTIATE_TEST_SUITE_P(TextToBinaryEntryPoint, OpEntryPointTest, - ValuesIn(std::vector{ - { CASE(Vertex), "" }, - { CASE(TessellationControl), "my tess" }, - { CASE(TessellationEvaluation), "really fancy" }, - { CASE(Geometry), "Euclid" }, - { CASE(Fragment), "FAT32" }, - { CASE(GLCompute), "cubic" }, - { CASE(Kernel), "Sanders" }, - })); -#undef CASE -// clang-format on - -TEST_F(OpEntryPointTest, WrongModel) { - EXPECT_THAT(CompileFailure("OpEntryPoint xxyyzz %1 \"fun\""), - Eq("Invalid execution model 'xxyyzz'.")); -} - -// Test OpExecutionMode -using OpExecutionModeTest = spvtest::TextToBinaryTestBase< - TestWithParam>>>; - -TEST_P(OpExecutionModeTest, AnyExecutionMode) { - // This string should assemble, but should not validate. - std::stringstream input; - input << "OpExecutionMode %1 " << std::get<1>(GetParam()).name(); - for (auto operand : std::get<1>(GetParam()).operands()) - input << " " << operand; - EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())), - Eq(MakeInstruction(SpvOpExecutionMode, - {1, std::get<1>(GetParam()).value()}, - std::get<1>(GetParam()).operands()))); -} - -#define CASE(NAME) SpvExecutionMode##NAME, #NAME -INSTANTIATE_TEST_SUITE_P( - TextToBinaryExecutionMode, OpExecutionModeTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector>{ - // The operand literal values are arbitrarily chosen, - // but there are the right number of them. - {CASE(Invocations), {101}}, - {CASE(SpacingEqual), {}}, - {CASE(SpacingFractionalEven), {}}, - {CASE(SpacingFractionalOdd), {}}, - {CASE(VertexOrderCw), {}}, - {CASE(VertexOrderCcw), {}}, - {CASE(PixelCenterInteger), {}}, - {CASE(OriginUpperLeft), {}}, - {CASE(OriginLowerLeft), {}}, - {CASE(EarlyFragmentTests), {}}, - {CASE(PointMode), {}}, - {CASE(Xfb), {}}, - {CASE(DepthReplacing), {}}, - {CASE(DepthGreater), {}}, - {CASE(DepthLess), {}}, - {CASE(DepthUnchanged), {}}, - {CASE(LocalSize), {64, 1, 2}}, - {CASE(LocalSizeHint), {8, 2, 4}}, - {CASE(InputPoints), {}}, - {CASE(InputLines), {}}, - {CASE(InputLinesAdjacency), {}}, - {CASE(Triangles), {}}, - {CASE(InputTrianglesAdjacency), {}}, - {CASE(Quads), {}}, - {CASE(Isolines), {}}, - {CASE(OutputVertices), {21}}, - {CASE(OutputPoints), {}}, - {CASE(OutputLineStrip), {}}, - {CASE(OutputTriangleStrip), {}}, - {CASE(VecTypeHint), {96}}, - {CASE(ContractionOff), {}}, - }))); - -INSTANTIATE_TEST_SUITE_P( - TextToBinaryExecutionModeV11, OpExecutionModeTest, - Combine(Values(SPV_ENV_UNIVERSAL_1_1), - ValuesIn(std::vector>{ - {CASE(Initializer)}, - {CASE(Finalizer)}, - {CASE(SubgroupSize), {12}}, - {CASE(SubgroupsPerWorkgroup), {64}}}))); -#undef CASE - -TEST_F(OpExecutionModeTest, WrongMode) { - EXPECT_THAT(CompileFailure("OpExecutionMode %1 xxyyzz"), - Eq("Invalid execution mode 'xxyyzz'.")); -} - -TEST_F(OpExecutionModeTest, TooManyModes) { - EXPECT_THAT(CompileFailure("OpExecutionMode %1 Xfb PointMode"), - Eq("Expected or at the beginning of an " - "instruction, found 'PointMode'.")); -} - -// Test OpCapability - -using OpCapabilityTest = - spvtest::TextToBinaryTestBase>>; - -TEST_P(OpCapabilityTest, AnyCapability) { - const std::string input = "OpCapability " + GetParam().name(); - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpCapability, {GetParam().value()}))); -} - -// clang-format off -#define CASE(NAME) { SpvCapability##NAME, #NAME } -INSTANTIATE_TEST_SUITE_P(TextToBinaryCapability, OpCapabilityTest, - ValuesIn(std::vector>{ - CASE(Matrix), - CASE(Shader), - CASE(Geometry), - CASE(Tessellation), - CASE(Addresses), - CASE(Linkage), - CASE(Kernel), - CASE(Vector16), - CASE(Float16Buffer), - CASE(Float16), - CASE(Float64), - CASE(Int64), - CASE(Int64Atomics), - CASE(ImageBasic), - CASE(ImageReadWrite), - CASE(ImageMipmap), - // Value 16 intentionally missing - CASE(Pipes), - CASE(Groups), - CASE(DeviceEnqueue), - CASE(LiteralSampler), - CASE(AtomicStorage), - CASE(Int16), - CASE(TessellationPointSize), - CASE(GeometryPointSize), - CASE(ImageGatherExtended), - // Value 26 intentionally missing - CASE(StorageImageMultisample), - CASE(UniformBufferArrayDynamicIndexing), - CASE(SampledImageArrayDynamicIndexing), - CASE(StorageBufferArrayDynamicIndexing), - CASE(StorageImageArrayDynamicIndexing), - CASE(ClipDistance), - CASE(CullDistance), - CASE(ImageCubeArray), - CASE(SampleRateShading), - CASE(ImageRect), - CASE(SampledRect), - CASE(GenericPointer), - CASE(Int8), - CASE(InputAttachment), - CASE(SparseResidency), - CASE(MinLod), - CASE(Sampled1D), - CASE(Image1D), - CASE(SampledCubeArray), - CASE(SampledBuffer), - CASE(ImageBuffer), - CASE(ImageMSArray), - CASE(StorageImageExtendedFormats), - CASE(ImageQuery), - CASE(DerivativeControl), - CASE(InterpolationFunction), - CASE(TransformFeedback), - })); -#undef CASE -// clang-format on - -using TextToBinaryCapability = spvtest::TextToBinaryTest; - -TEST_F(TextToBinaryCapability, BadMissingCapability) { - EXPECT_THAT(CompileFailure("OpCapability"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(TextToBinaryCapability, BadInvalidCapability) { - EXPECT_THAT(CompileFailure("OpCapability 123"), - Eq("Invalid capability '123'.")); -} - -// TODO(dneto): OpExecutionMode - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.pipe_storage_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.pipe_storage_test.cpp deleted file mode 100644 index f74dbcfdf..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.pipe_storage_test.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// 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 "gmock/gmock.h" -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using ::spvtest::MakeInstruction; -using ::testing::Eq; - -using OpTypePipeStorageTest = spvtest::TextToBinaryTest; - -// It can assemble, but should not validate. Validation checks for version -// and capability are in another test file. -TEST_F(OpTypePipeStorageTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("%res = OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpTypePipeStorage, {1}))); -} - -TEST_F(OpTypePipeStorageTest, ArgumentCount) { - EXPECT_THAT( - CompileFailure("OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, found " - "'OpTypePipeStorage'.")); - EXPECT_THAT( - CompiledInstructions("%res = OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpTypePipeStorage, {1}))); - EXPECT_THAT(CompileFailure("%res = OpTypePipeStorage %1 %2 %3 %4 %5", - SPV_ENV_UNIVERSAL_1_1), - Eq("'=' expected after result id.")); -} - -using OpConstantPipeStorageTest = spvtest::TextToBinaryTest; - -TEST_F(OpConstantPipeStorageTest, OpcodeAssemblesInV10) { - EXPECT_THAT(CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5", - SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpConstantPipeStorage, {1, 2, 3, 4, 5}))); -} - -TEST_F(OpConstantPipeStorageTest, ArgumentCount) { - EXPECT_THAT( - CompileFailure("OpConstantPipeStorage", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, found " - "'OpConstantPipeStorage'.")); - EXPECT_THAT( - CompileFailure("%1 = OpConstantPipeStorage", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 3 4", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT(CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5", - SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpConstantPipeStorage, {1, 2, 3, 4, 5}))); - EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 3 4 5 %6 %7", - SPV_ENV_UNIVERSAL_1_1), - Eq("'=' expected after result id.")); -} - -TEST_F(OpConstantPipeStorageTest, ArgumentTypes) { - EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 %3 4 5", - SPV_ENV_UNIVERSAL_1_1), - Eq("Invalid unsigned integer literal: %3")); - EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 3 %4 5", - SPV_ENV_UNIVERSAL_1_1), - Eq("Invalid unsigned integer literal: %4")); - EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage 2 3 4 5", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); - EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 3 4 \"ab\"", - SPV_ENV_UNIVERSAL_1_1), - Eq("Invalid unsigned integer literal: \"ab\"")); -} - -using OpCreatePipeFromPipeStorageTest = spvtest::TextToBinaryTest; - -TEST_F(OpCreatePipeFromPipeStorageTest, OpcodeAssemblesInV10) { - EXPECT_THAT(CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3", - SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpCreatePipeFromPipeStorage, {1, 2, 3}))); -} - -TEST_F(OpCreatePipeFromPipeStorageTest, ArgumentCount) { - EXPECT_THAT( - CompileFailure("OpCreatePipeFromPipeStorage", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, found " - "'OpCreatePipeFromPipeStorage'.")); - EXPECT_THAT( - CompileFailure("%1 = OpCreatePipeFromPipeStorage", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT(CompileFailure("%1 = OpCreatePipeFromPipeStorage %2 OpNop", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found next instruction instead.")); - EXPECT_THAT(CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3", - SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpCreatePipeFromPipeStorage, {1, 2, 3}))); - EXPECT_THAT(CompileFailure("%1 = OpCreatePipeFromPipeStorage %2 %3 %4 %5", - SPV_ENV_UNIVERSAL_1_1), - Eq("'=' expected after result id.")); -} - -TEST_F(OpCreatePipeFromPipeStorageTest, ArgumentTypes) { - EXPECT_THAT(CompileFailure("%1 = OpCreatePipeFromPipeStorage \"\" %3", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); - EXPECT_THAT(CompileFailure("%1 = OpCreatePipeFromPipeStorage %2 3", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.reserved_sampling_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.reserved_sampling_test.cpp deleted file mode 100644 index 42e4e2aeb..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.reserved_sampling_test.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2017 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. - -// Validation tests for illegal instructions - -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using ::spvtest::MakeInstruction; -using ::testing::Eq; - -using ReservedSamplingInstTest = RoundTripTest; - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjImplicitLod) { - std::string input = "%2 = OpImageSparseSampleProjImplicitLod %1 %3 %4\n"; - EXPECT_THAT( - CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpImageSparseSampleProjImplicitLod, {1, 2, 3, 4}))); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjExplicitLod) { - std::string input = - "%2 = OpImageSparseSampleProjExplicitLod %1 %3 %4 Lod %5\n"; - EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpImageSparseSampleProjExplicitLod, - {1, 2, 3, 4, SpvImageOperandsLodMask, 5}))); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefImplicitLod) { - std::string input = - "%2 = OpImageSparseSampleProjDrefImplicitLod %1 %3 %4 %5\n"; - EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpImageSparseSampleProjDrefImplicitLod, - {1, 2, 3, 4, 5}))); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefExplicitLod) { - std::string input = - "%2 = OpImageSparseSampleProjDrefExplicitLod %1 %3 %4 %5 Lod %6\n"; - EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpImageSparseSampleProjDrefExplicitLod, - {1, 2, 3, 4, 5, SpvImageOperandsLodMask, 6}))); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.subgroup_dispatch_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.subgroup_dispatch_test.cpp deleted file mode 100644 index 967e3c38b..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.subgroup_dispatch_test.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -// Assembler tests for instructions in the "Barrier Instructions" section -// of the SPIR-V spec. - -#include "test/unit_spirv.h" - -#include "gmock/gmock.h" -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using ::spvtest::MakeInstruction; -using ::testing::Eq; - -using OpGetKernelLocalSizeForSubgroupCountTest = spvtest::TextToBinaryTest; - -// We should be able to assemble it. Validation checks are in another test -// file. -TEST_F(OpGetKernelLocalSizeForSubgroupCountTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("%res = OpGetKernelLocalSizeForSubgroupCount %type " - "%sgcount %invoke %param %param_size %param_align", - SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpGetKernelLocalSizeForSubgroupCount, - {1, 2, 3, 4, 5, 6, 7}))); -} - -TEST_F(OpGetKernelLocalSizeForSubgroupCountTest, ArgumentCount) { - EXPECT_THAT(CompileFailure("OpGetKernelLocalSizeForSubgroupCount", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, " - "found 'OpGetKernelLocalSizeForSubgroupCount'.")); - EXPECT_THAT(CompileFailure("%res = OpGetKernelLocalSizeForSubgroupCount", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompileFailure("%1 = OpGetKernelLocalSizeForSubgroupCount %2 %3 %4 %5 %6", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompiledInstructions("%res = OpGetKernelLocalSizeForSubgroupCount %type " - "%sgcount %invoke %param %param_size %param_align", - SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpGetKernelLocalSizeForSubgroupCount, - {1, 2, 3, 4, 5, 6, 7}))); - EXPECT_THAT( - CompileFailure("%res = OpGetKernelLocalSizeForSubgroupCount %type " - "%sgcount %invoke %param %param_size %param_align %extra", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected '=', found end of stream.")); -} - -TEST_F(OpGetKernelLocalSizeForSubgroupCountTest, ArgumentTypes) { - EXPECT_THAT(CompileFailure( - "%1 = OpGetKernelLocalSizeForSubgroupCount 2 %3 %4 %5 %6 %7", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); - EXPECT_THAT( - CompileFailure( - "%1 = OpGetKernelLocalSizeForSubgroupCount %2 %3 %4 %5 %6 \"abc\"", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); -} - -using OpGetKernelMaxNumSubgroupsTest = spvtest::TextToBinaryTest; - -TEST_F(OpGetKernelMaxNumSubgroupsTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type " - "%invoke %param %param_size %param_align", - SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpGetKernelMaxNumSubgroups, {1, 2, 3, 4, 5, 6}))); -} - -TEST_F(OpGetKernelMaxNumSubgroupsTest, ArgumentCount) { - EXPECT_THAT( - CompileFailure("OpGetKernelMaxNumSubgroups", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, found " - "'OpGetKernelMaxNumSubgroups'.")); - EXPECT_THAT(CompileFailure("%res = OpGetKernelMaxNumSubgroups", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT(CompileFailure("%1 = OpGetKernelMaxNumSubgroups %2 %3 %4 %5", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found end of stream.")); - EXPECT_THAT( - CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type " - "%invoke %param %param_size %param_align", - SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpGetKernelMaxNumSubgroups, {1, 2, 3, 4, 5, 6}))); - EXPECT_THAT(CompileFailure("%res = OpGetKernelMaxNumSubgroups %type %invoke " - "%param %param_size %param_align %extra", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected '=', found end of stream.")); -} - -TEST_F(OpGetKernelMaxNumSubgroupsTest, ArgumentTypes) { - EXPECT_THAT(CompileFailure("%1 = OpGetKernelMaxNumSubgroups 2 %3 %4 %5 %6", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); - EXPECT_THAT( - CompileFailure("%1 = OpGetKernelMaxNumSubgroups %2 %3 %4 %5 \"abc\"", - SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary.type_declaration_test.cpp b/3rdparty/spirv-tools/test/text_to_binary.type_declaration_test.cpp deleted file mode 100644 index 1589188fd..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary.type_declaration_test.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Assembler tests for instructions in the "Type-Declaration" section of the -// SPIR-V spec. - -#include -#include - -#include "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::EnumCase; -using spvtest::MakeInstruction; -using ::testing::Eq; - -// Test Dim enums via OpTypeImage - -using DimTest = - spvtest::TextToBinaryTestBase<::testing::TestWithParam>>; - -TEST_P(DimTest, AnyDim) { - const std::string input = - "%1 = OpTypeImage %2 " + GetParam().name() + " 2 3 0 4 Rgba8\n"; - EXPECT_THAT( - CompiledInstructions(input), - Eq(MakeInstruction(SpvOpTypeImage, {1, 2, GetParam().value(), 2, 3, 0, 4, - SpvImageFormatRgba8}))); - - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); -} - -// clang-format off -#define CASE(NAME) {SpvDim##NAME, #NAME} -INSTANTIATE_TEST_SUITE_P( - TextToBinaryDim, DimTest, - ::testing::ValuesIn(std::vector>{ - CASE(1D), - CASE(2D), - CASE(3D), - CASE(Cube), - CASE(Rect), - CASE(Buffer), - CASE(SubpassData), - })); -#undef CASE -// clang-format on - -TEST_F(DimTest, WrongDim) { - EXPECT_THAT(CompileFailure("%i = OpTypeImage %t xxyyzz 1 2 3 4 R8"), - Eq("Invalid dimensionality 'xxyyzz'.")); -} - -// Test ImageFormat enums via OpTypeImage - -using ImageFormatTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(ImageFormatTest, AnyImageFormatAndNoAccessQualifier) { - const std::string input = - "%1 = OpTypeImage %2 1D 2 3 0 4 " + GetParam().name() + "\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpTypeImage, {1, 2, SpvDim1D, 2, 3, 0, 4, - GetParam().value()}))); - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); -} - -// clang-format off -#define CASE(NAME) {SpvImageFormat##NAME, #NAME} -INSTANTIATE_TEST_SUITE_P( - TextToBinaryImageFormat, ImageFormatTest, - ::testing::ValuesIn(std::vector>{ - CASE(Unknown), - CASE(Rgba32f), - CASE(Rgba16f), - CASE(R32f), - CASE(Rgba8), - CASE(Rgba8Snorm), - CASE(Rg32f), - CASE(Rg16f), - CASE(R11fG11fB10f), - CASE(R16f), - CASE(Rgba16), - CASE(Rgb10A2), - CASE(Rg16), - CASE(Rg8), - CASE(R16), - CASE(R8), - CASE(Rgba16Snorm), - CASE(Rg16Snorm), - CASE(Rg8Snorm), - CASE(R16Snorm), - CASE(R8Snorm), - CASE(Rgba32i), - CASE(Rgba16i), - CASE(Rgba8i), - CASE(R32i), - CASE(Rg32i), - CASE(Rg16i), - CASE(Rg8i), - CASE(R16i), - CASE(R8i), - CASE(Rgba32ui), - CASE(Rgba16ui), - CASE(Rgba8ui), - CASE(R32ui), - CASE(Rgb10a2ui), - CASE(Rg32ui), - CASE(Rg16ui), - CASE(Rg8ui), - CASE(R16ui), - CASE(R8ui), - })); -#undef CASE -// clang-format on - -TEST_F(ImageFormatTest, WrongFormat) { - EXPECT_THAT(CompileFailure("%r = OpTypeImage %t 1D 2 3 0 4 xxyyzz"), - Eq("Invalid image format 'xxyyzz'.")); -} - -// Test AccessQualifier enums via OpTypeImage. -using ImageAccessQualifierTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(ImageAccessQualifierTest, AnyAccessQualifier) { - const std::string input = - "%1 = OpTypeImage %2 1D 2 3 0 4 Rgba8 " + GetParam().name() + "\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpTypeImage, - {1, 2, SpvDim1D, 2, 3, 0, 4, - SpvImageFormatRgba8, GetParam().value()}))); - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); -} - -// clang-format off -#define CASE(NAME) {SpvAccessQualifier##NAME, #NAME} -INSTANTIATE_TEST_SUITE_P( - AccessQualifier, ImageAccessQualifierTest, - ::testing::ValuesIn(std::vector>{ - CASE(ReadOnly), - CASE(WriteOnly), - CASE(ReadWrite), - })); -// clang-format on -#undef CASE - -// Test AccessQualifier enums via OpTypePipe. - -using OpTypePipeTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(OpTypePipeTest, AnyAccessQualifier) { - const std::string input = "%1 = OpTypePipe " + GetParam().name() + "\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(MakeInstruction(SpvOpTypePipe, {1, GetParam().value()}))); - // Check the disassembler as well. - EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); -} - -// clang-format off -#define CASE(NAME) {SpvAccessQualifier##NAME, #NAME} -INSTANTIATE_TEST_SUITE_P( - TextToBinaryTypePipe, OpTypePipeTest, - ::testing::ValuesIn(std::vector>{ - CASE(ReadOnly), - CASE(WriteOnly), - CASE(ReadWrite), - })); -#undef CASE -// clang-format on - -TEST_F(OpTypePipeTest, WrongAccessQualifier) { - EXPECT_THAT(CompileFailure("%1 = OpTypePipe xxyyzz"), - Eq("Invalid access qualifier 'xxyyzz'.")); -} - -using OpTypeForwardPointerTest = spvtest::TextToBinaryTest; - -#define CASE(storage_class) \ - do { \ - EXPECT_THAT( \ - CompiledInstructions("OpTypeForwardPointer %pt " #storage_class), \ - Eq(MakeInstruction(SpvOpTypeForwardPointer, \ - {1, SpvStorageClass##storage_class}))); \ - } while (0) - -TEST_F(OpTypeForwardPointerTest, ValidStorageClass) { - CASE(UniformConstant); - CASE(Input); - CASE(Uniform); - CASE(Output); - CASE(Workgroup); - CASE(CrossWorkgroup); - CASE(Private); - CASE(Function); - CASE(Generic); - CASE(PushConstant); - CASE(AtomicCounter); - CASE(Image); - CASE(StorageBuffer); -} - -#undef CASE - -TEST_F(OpTypeForwardPointerTest, MissingType) { - EXPECT_THAT(CompileFailure("OpTypeForwardPointer"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpTypeForwardPointerTest, MissingClass) { - EXPECT_THAT(CompileFailure("OpTypeForwardPointer %pt"), - Eq("Expected operand, found end of stream.")); -} - -TEST_F(OpTypeForwardPointerTest, WrongClass) { - EXPECT_THAT(CompileFailure("OpTypeForwardPointer %pt xxyyzz"), - Eq("Invalid storage class 'xxyyzz'.")); -} - -using OpSizeOfTest = spvtest::TextToBinaryTest; - -// We should be able to assemble it. Validation checks are in another test -// file. -TEST_F(OpSizeOfTest, OpcodeAssemblesInV10) { - EXPECT_THAT( - CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_0), - Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3}))); -} - -TEST_F(OpSizeOfTest, ArgumentCount) { - EXPECT_THAT( - CompileFailure("OpSizeOf", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected at the beginning of an instruction, found " - "'OpSizeOf'.")); - EXPECT_THAT(CompileFailure("%res = OpSizeOf OpNop", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected operand, found next instruction instead.")); - EXPECT_THAT( - CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_1), - Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3}))); - EXPECT_THAT( - CompileFailure("%1 = OpSizeOf %2 %3 44 55 ", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected or at the beginning of an instruction, " - "found '44'.")); -} - -TEST_F(OpSizeOfTest, ArgumentTypes) { - EXPECT_THAT(CompileFailure("%1 = OpSizeOf 2 %3", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); - EXPECT_THAT(CompileFailure("%1 = OpSizeOf %2 \"abc\"", SPV_ENV_UNIVERSAL_1_1), - Eq("Expected id to start with %.")); -} - -// TODO(dneto): OpTypeVoid -// TODO(dneto): OpTypeBool -// TODO(dneto): OpTypeInt -// TODO(dneto): OpTypeFloat -// TODO(dneto): OpTypeVector -// TODO(dneto): OpTypeMatrix -// TODO(dneto): OpTypeImage -// TODO(dneto): OpTypeSampler -// TODO(dneto): OpTypeSampledImage -// TODO(dneto): OpTypeArray -// TODO(dneto): OpTypeRuntimeArray -// TODO(dneto): OpTypeStruct -// TODO(dneto): OpTypeOpaque -// TODO(dneto): OpTypePointer -// TODO(dneto): OpTypeFunction -// TODO(dneto): OpTypeEvent -// TODO(dneto): OpTypeDeviceEvent -// TODO(dneto): OpTypeReserveId -// TODO(dneto): OpTypeQueue - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_to_binary_test.cpp b/3rdparty/spirv-tools/test/text_to_binary_test.cpp deleted file mode 100644 index 57f0a6ce0..000000000 --- a/3rdparty/spirv-tools/test/text_to_binary_test.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "source/spirv_constant.h" -#include "source/util/bitutils.h" -#include "source/util/hex_float.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::AutoText; -using spvtest::Concatenate; -using spvtest::MakeInstruction; -using spvtest::ScopedContext; -using spvtest::TextToBinaryTest; -using testing::Eq; -using testing::IsNull; -using testing::NotNull; - -// An mask parsing test case. -struct MaskCase { - spv_operand_type_t which_enum; - uint32_t expected_value; - const char* expression; -}; - -using GoodMaskParseTest = ::testing::TestWithParam; - -TEST_P(GoodMaskParseTest, GoodMaskExpressions) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); - - uint32_t value; - EXPECT_EQ(SPV_SUCCESS, - AssemblyGrammar(context).parseMaskOperand( - GetParam().which_enum, GetParam().expression, &value)); - EXPECT_EQ(GetParam().expected_value, value); - - spvContextDestroy(context); -} - -INSTANTIATE_TEST_SUITE_P( - ParseMask, GoodMaskParseTest, - ::testing::ValuesIn(std::vector{ - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 0, "None"}, - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 1, "NotNaN"}, - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 2, "NotInf"}, - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 3, "NotNaN|NotInf"}, - // Mask experssions are symmetric. - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 3, "NotInf|NotNaN"}, - // Repeating a value has no effect. - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 3, "NotInf|NotNaN|NotInf"}, - // Using 3 operands still works. - {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, 0x13, "NotInf|NotNaN|Fast"}, - {SPV_OPERAND_TYPE_SELECTION_CONTROL, 0, "None"}, - {SPV_OPERAND_TYPE_SELECTION_CONTROL, 1, "Flatten"}, - {SPV_OPERAND_TYPE_SELECTION_CONTROL, 2, "DontFlatten"}, - // Weirdly, you can specify to flatten and don't flatten a selection. - {SPV_OPERAND_TYPE_SELECTION_CONTROL, 3, "Flatten|DontFlatten"}, - {SPV_OPERAND_TYPE_LOOP_CONTROL, 0, "None"}, - {SPV_OPERAND_TYPE_LOOP_CONTROL, 1, "Unroll"}, - {SPV_OPERAND_TYPE_LOOP_CONTROL, 2, "DontUnroll"}, - // Weirdly, you can specify to unroll and don't unroll a loop. - {SPV_OPERAND_TYPE_LOOP_CONTROL, 3, "Unroll|DontUnroll"}, - {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 0, "None"}, - {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 1, "Inline"}, - {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 2, "DontInline"}, - {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 4, "Pure"}, - {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 8, "Const"}, - {SPV_OPERAND_TYPE_FUNCTION_CONTROL, 0xd, "Inline|Const|Pure"}, - })); - -using BadFPFastMathMaskParseTest = ::testing::TestWithParam; - -TEST_P(BadFPFastMathMaskParseTest, BadMaskExpressions) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); - - uint32_t value; - EXPECT_NE(SPV_SUCCESS, - AssemblyGrammar(context).parseMaskOperand( - SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, GetParam(), &value)); - - spvContextDestroy(context); -} - -INSTANTIATE_TEST_SUITE_P(ParseMask, BadFPFastMathMaskParseTest, - ::testing::ValuesIn(std::vector{ - nullptr, "", "NotValidEnum", "|", "NotInf|", - "|NotInf", "NotInf||NotNaN", - "Unroll" // A good word, but for the wrong enum - })); - -TEST_F(TextToBinaryTest, InvalidText) { - ASSERT_EQ(SPV_ERROR_INVALID_TEXT, - spvTextToBinary(ScopedContext().context, nullptr, 0, &binary, - &diagnostic)); - EXPECT_NE(nullptr, diagnostic); - EXPECT_THAT(diagnostic->error, Eq(std::string("Missing assembly text."))); -} - -TEST_F(TextToBinaryTest, InvalidPointer) { - SetText( - "OpEntryPoint Kernel 0 \"\"\nOpExecutionMode 0 LocalSizeHint 1 1 1\n"); - ASSERT_EQ(SPV_ERROR_INVALID_POINTER, - spvTextToBinary(ScopedContext().context, text.str, text.length, - nullptr, &diagnostic)); -} - -TEST_F(TextToBinaryTest, InvalidPrefix) { - EXPECT_EQ( - "Expected or at the beginning of an instruction, " - "found 'Invalid'.", - CompileFailure("Invalid")); -} - -TEST_F(TextToBinaryTest, EmptyAssemblyString) { - // An empty assembly module is valid! - // It should produce a valid module with zero instructions. - EXPECT_THAT(CompiledInstructions(""), Eq(std::vector{})); -} - -TEST_F(TextToBinaryTest, StringSpace) { - const std::string code = ("OpSourceExtension \"string with spaces\"\n"); - EXPECT_EQ(code, EncodeAndDecodeSuccessfully(code)); -} - -TEST_F(TextToBinaryTest, UnknownBeginningOfInstruction) { - EXPECT_EQ( - "Expected or at the beginning of an instruction, " - "found 'Google'.", - CompileFailure( - "\nOpSource OpenCL_C 12\nOpMemoryModel Physical64 OpenCL\nGoogle\n")); - EXPECT_EQ(4u, diagnostic->position.line + 1); - EXPECT_EQ(1u, diagnostic->position.column + 1); -} - -TEST_F(TextToBinaryTest, NoEqualSign) { - EXPECT_EQ("Expected '=', found end of stream.", - CompileFailure("\nOpSource OpenCL_C 12\n" - "OpMemoryModel Physical64 OpenCL\n%2\n")); - EXPECT_EQ(5u, diagnostic->position.line + 1); - EXPECT_EQ(1u, diagnostic->position.column + 1); -} - -TEST_F(TextToBinaryTest, NoOpCode) { - EXPECT_EQ("Expected opcode, found end of stream.", - CompileFailure("\nOpSource OpenCL_C 12\n" - "OpMemoryModel Physical64 OpenCL\n%2 =\n")); - EXPECT_EQ(5u, diagnostic->position.line + 1); - EXPECT_EQ(1u, diagnostic->position.column + 1); -} - -TEST_F(TextToBinaryTest, WrongOpCode) { - EXPECT_EQ("Invalid Opcode prefix 'Wahahaha'.", - CompileFailure("\nOpSource OpenCL_C 12\n" - "OpMemoryModel Physical64 OpenCL\n%2 = Wahahaha\n")); - EXPECT_EQ(4u, diagnostic->position.line + 1); - EXPECT_EQ(6u, diagnostic->position.column + 1); -} - -TEST_F(TextToBinaryTest, CRLF) { - const std::string input = - "%i32 = OpTypeInt 32 1\r\n%c = OpConstant %i32 123\r\n"; - EXPECT_THAT(CompiledInstructions(input), - Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), - MakeInstruction(SpvOpConstant, {1, 2, 123})}))); -} - -using TextToBinaryFloatValueTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(TextToBinaryFloatValueTest, Samples) { - const std::string input = - "%1 = OpTypeFloat 32\n%2 = OpConstant %1 " + GetParam().first; - EXPECT_THAT(CompiledInstructions(input), - Eq(Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), - MakeInstruction(SpvOpConstant, - {1, 2, GetParam().second})}))); -} - -INSTANTIATE_TEST_SUITE_P( - FloatValues, TextToBinaryFloatValueTest, - ::testing::ValuesIn(std::vector>{ - {"0.0", 0x00000000}, // +0 - {"!0x00000001", 0x00000001}, // +denorm - {"!0x00800000", 0x00800000}, // +norm - {"1.5", 0x3fc00000}, - {"!0x7f800000", 0x7f800000}, // +inf - {"!0x7f800001", 0x7f800001}, // NaN - - {"-0.0", 0x80000000}, // -0 - {"!0x80000001", 0x80000001}, // -denorm - {"!0x80800000", 0x80800000}, // -norm - {"-2.5", 0xc0200000}, - {"!0xff800000", 0xff800000}, // -inf - {"!0xff800001", 0xff800001}, // NaN - })); - -using TextToBinaryHalfValueTest = spvtest::TextToBinaryTestBase< - ::testing::TestWithParam>>; - -TEST_P(TextToBinaryHalfValueTest, Samples) { - const std::string input = - "%1 = OpTypeFloat 16\n%2 = OpConstant %1 " + GetParam().first; - EXPECT_THAT(CompiledInstructions(input), - Eq(Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 16}), - MakeInstruction(SpvOpConstant, - {1, 2, GetParam().second})}))); -} - -INSTANTIATE_TEST_SUITE_P( - HalfValues, TextToBinaryHalfValueTest, - ::testing::ValuesIn(std::vector>{ - {"0.0", 0x00000000}, - {"1.0", 0x00003c00}, - {"1.000844", 0x00003c00}, // Truncate to 1.0 - {"1.000977", 0x00003c01}, // Don't have to truncate - {"1.001465", 0x00003c01}, // Truncate to 1.0000977 - {"1.5", 0x00003e00}, - {"-1.0", 0x0000bc00}, - {"2.0", 0x00004000}, - {"-2.0", 0x0000c000}, - {"0x1p1", 0x00004000}, - {"-0x1p1", 0x0000c000}, - {"0x1.8p1", 0x00004200}, - {"0x1.8p4", 0x00004e00}, - {"0x1.801p4", 0x00004e00}, - {"0x1.804p4", 0x00004e01}, - })); - -TEST(CreateContext, InvalidEnvironment) { - spv_target_env env; - std::memset(&env, 99, sizeof(env)); - EXPECT_THAT(spvContextCreate(env), IsNull()); -} - -TEST(CreateContext, UniversalEnvironment) { - auto c = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); - EXPECT_THAT(c, NotNull()); - spvContextDestroy(c); -} - -TEST(CreateContext, VulkanEnvironment) { - auto c = spvContextCreate(SPV_ENV_VULKAN_1_0); - EXPECT_THAT(c, NotNull()); - spvContextDestroy(c); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/text_word_get_test.cpp b/3rdparty/spirv-tools/test/text_word_get_test.cpp deleted file mode 100644 index b74a680fa..000000000 --- a/3rdparty/spirv-tools/test/text_word_get_test.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -namespace spvtools { -namespace { - -using spvtest::AutoText; - -#define TAB "\t" -#define NEWLINE "\n" -#define BACKSLASH R"(\)" -#define QUOTE R"(")" - -TEST(TextWordGet, NullTerminator) { - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ( - SPV_SUCCESS, - AssemblyContext(AutoText("Word"), nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(4u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(4u, endPosition.index); - ASSERT_STREQ("Word", word.c_str()); -} - -TEST(TextWordGet, TabTerminator) { - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, AssemblyContext(AutoText("Word\t"), nullptr) - .getWord(&word, &endPosition)); - ASSERT_EQ(4u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(4u, endPosition.index); - ASSERT_STREQ("Word", word.c_str()); -} - -TEST(TextWordGet, SpaceTerminator) { - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ( - SPV_SUCCESS, - AssemblyContext(AutoText("Word "), nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(4u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(4u, endPosition.index); - ASSERT_STREQ("Word", word.c_str()); -} - -TEST(TextWordGet, SemicolonTerminator) { - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ( - SPV_SUCCESS, - AssemblyContext(AutoText("Wo;rd"), nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(2u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(2u, endPosition.index); - ASSERT_STREQ("Wo", word.c_str()); -} - -TEST(TextWordGet, NoTerminator) { - const std::string full_text = "abcdefghijklmn"; - for (size_t len = 1; len <= full_text.size(); ++len) { - std::string word; - spv_text_t text = {full_text.data(), len}; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(&text, nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(len, endPosition.column); - ASSERT_EQ(len, endPosition.index); - ASSERT_EQ(full_text.substr(0, len), word); - } -} - -TEST(TextWordGet, MultipleWords) { - AutoText input("Words in a sentence"); - AssemblyContext data(input, nullptr); - - spv_position_t endPosition = {}; - const char* words[] = {"Words", "in", "a", "sentence"}; - - std::string word; - for (uint32_t wordIndex = 0; wordIndex < 4; ++wordIndex) { - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition)); - ASSERT_EQ(strlen(words[wordIndex]), - endPosition.column - data.position().column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(strlen(words[wordIndex]), - endPosition.index - data.position().index); - ASSERT_STREQ(words[wordIndex], word.c_str()); - - data.setPosition(endPosition); - if (3 != wordIndex) { - ASSERT_EQ(SPV_SUCCESS, data.advance()); - } else { - ASSERT_EQ(SPV_END_OF_STREAM, data.advance()); - } - } -} - -TEST(TextWordGet, QuotesAreKept) { - AutoText input(R"("quotes" "around words")"); - const char* expected[] = {R"("quotes")", R"("around words")"}; - AssemblyContext data(input, nullptr); - - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition)); - EXPECT_EQ(8u, endPosition.column); - EXPECT_EQ(0u, endPosition.line); - EXPECT_EQ(8u, endPosition.index); - EXPECT_STREQ(expected[0], word.c_str()); - - // Move to the next word. - data.setPosition(endPosition); - data.seekForward(1); - - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition)); - EXPECT_EQ(23u, endPosition.column); - EXPECT_EQ(0u, endPosition.line); - EXPECT_EQ(23u, endPosition.index); - EXPECT_STREQ(expected[1], word.c_str()); -} - -TEST(TextWordGet, QuotesBetweenWordsActLikeGlue) { - AutoText input(R"(quotes" "between words)"); - const char* expected[] = {R"(quotes" "between)", "words"}; - AssemblyContext data(input, nullptr); - - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition)); - EXPECT_EQ(16u, endPosition.column); - EXPECT_EQ(0u, endPosition.line); - EXPECT_EQ(16u, endPosition.index); - EXPECT_STREQ(expected[0], word.c_str()); - - // Move to the next word. - data.setPosition(endPosition); - data.seekForward(1); - - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition)); - EXPECT_EQ(22u, endPosition.column); - EXPECT_EQ(0u, endPosition.line); - EXPECT_EQ(22u, endPosition.index); - EXPECT_STREQ(expected[1], word.c_str()); -} - -TEST(TextWordGet, QuotingWhitespace) { - AutoText input(QUOTE "white " NEWLINE TAB " space" QUOTE); - // Whitespace surrounded by quotes acts like glue. - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(input, nullptr).getWord(&word, &endPosition)); - EXPECT_EQ(input.str.length(), endPosition.column); - EXPECT_EQ(0u, endPosition.line); - EXPECT_EQ(input.str.length(), endPosition.index); - EXPECT_EQ(input.str, word); -} - -TEST(TextWordGet, QuoteAlone) { - AutoText input(QUOTE); - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(input, nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(1u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(1u, endPosition.index); - ASSERT_STREQ(QUOTE, word.c_str()); -} - -TEST(TextWordGet, EscapeAlone) { - AutoText input(BACKSLASH); - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(input, nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(1u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(1u, endPosition.index); - ASSERT_STREQ(BACKSLASH, word.c_str()); -} - -TEST(TextWordGet, EscapeAtEndOfInput) { - AutoText input("word" BACKSLASH); - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(input, nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(5u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(5u, endPosition.index); - ASSERT_STREQ("word" BACKSLASH, word.c_str()); -} - -TEST(TextWordGet, Escaping) { - AutoText input("w" BACKSLASH QUOTE "o" BACKSLASH NEWLINE "r" BACKSLASH ";d"); - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(input, nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(10u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(10u, endPosition.index); - ASSERT_EQ(input.str, word); -} - -TEST(TextWordGet, EscapingEscape) { - AutoText input("word" BACKSLASH BACKSLASH " abc"); - std::string word; - spv_position_t endPosition = {}; - ASSERT_EQ(SPV_SUCCESS, - AssemblyContext(input, nullptr).getWord(&word, &endPosition)); - ASSERT_EQ(6u, endPosition.column); - ASSERT_EQ(0u, endPosition.line); - ASSERT_EQ(6u, endPosition.index); - ASSERT_STREQ("word" BACKSLASH BACKSLASH, word.c_str()); -} - -TEST(TextWordGet, CRLF) { - AutoText input("abc\r\nd"); - AssemblyContext data(input, nullptr); - std::string word; - spv_position_t pos = {}; - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &pos)); - EXPECT_EQ(3u, pos.column); - EXPECT_STREQ("abc", word.c_str()); - data.setPosition(pos); - data.advance(); - ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &pos)); - EXPECT_EQ(1u, pos.column); - EXPECT_STREQ("d", word.c_str()); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/timer_test.cpp b/3rdparty/spirv-tools/test/timer_test.cpp deleted file mode 100644 index 84ab46dab..000000000 --- a/3rdparty/spirv-tools/test/timer_test.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gtest/gtest.h" -#include "source/util/timer.h" - -namespace spvtools { -namespace utils { -namespace { - -// A mock class to mimic Timer class for a testing purpose. It has fixed -// CPU/WALL/USR/SYS time, RSS delta, and the delta of the number of page faults. -class MockTimer : public Timer { - public: - MockTimer(std::ostream* out, bool measure_mem_usage = false) - : Timer(out, measure_mem_usage) {} - double CPUTime() override { return 0.019123; } - double WallTime() override { return 0.019723; } - double UserTime() override { return 0.012723; } - double SystemTime() override { return 0.002723; } - long RSS() const override { return 360L; } - long PageFault() const override { return 3600L; } -}; - -// This unit test checks whether the actual output of MockTimer::Report() is the -// same as fixed CPU/WALL/USR/SYS time, RSS delta, and the delta of the number -// of page faults that are returned by MockTimer. -TEST(MockTimer, DoNothing) { - std::ostringstream buf; - - PrintTimerDescription(&buf); - MockTimer timer(&buf); - timer.Start(); - - // Do nothing. - - timer.Stop(); - timer.Report("TimerTest"); - - EXPECT_EQ(0.019123, timer.CPUTime()); - EXPECT_EQ(0.019723, timer.WallTime()); - EXPECT_EQ(0.012723, timer.UserTime()); - EXPECT_EQ(0.002723, timer.SystemTime()); - EXPECT_EQ( - " PASS name CPU time WALL time USR time" - " SYS time\n TimerTest 0.02 0.02" - " 0.01 0.00\n", - buf.str()); -} - -// This unit test checks whether the ScopedTimer correctly reports -// the fixed CPU/WALL/USR/SYS time, RSS delta, and the delta of the number of -// page faults that are returned by MockTimer. -TEST(MockTimer, TestScopedTimer) { - std::ostringstream buf; - - { - ScopedTimer scopedtimer(&buf, "ScopedTimerTest"); - // Do nothing. - } - - EXPECT_EQ( - " ScopedTimerTest 0.02 0.02 0.01" - " 0.00\n", - buf.str()); -} - -// A mock class to mimic CumulativeTimer class for a testing purpose. It has -// fixed CPU/WALL/USR/SYS time, RSS delta, and the delta of the number of page -// faults for each measurement (i.e., a pair of Start() and Stop()). If the -// number of measurements increases, it increases |count_stop_| by the number of -// calling Stop() and the amount of each resource usage is proportional to -// |count_stop_|. -class MockCumulativeTimer : public CumulativeTimer { - public: - MockCumulativeTimer(std::ostream* out, bool measure_mem_usage = false) - : CumulativeTimer(out, measure_mem_usage), count_stop_(0) {} - double CPUTime() override { return count_stop_ * 0.019123; } - double WallTime() override { return count_stop_ * 0.019723; } - double UserTime() override { return count_stop_ * 0.012723; } - double SystemTime() override { return count_stop_ * 0.002723; } - long RSS() const override { return count_stop_ * 360L; } - long PageFault() const override { return count_stop_ * 3600L; } - - // Calling Stop() does nothing but just increases |count_stop_| by 1. - void Stop() override { ++count_stop_; } - - private: - unsigned int count_stop_; -}; - -// This unit test checks whether the MockCumulativeTimer correctly reports the -// cumulative CPU/WALL/USR/SYS time, RSS delta, and the delta of the number of -// page faults whose values are fixed for each measurement (i.e., a pair of -// Start() and Stop()). -TEST(MockCumulativeTimer, DoNothing) { - CumulativeTimer* ctimer; - std::ostringstream buf; - - { - ctimer = new MockCumulativeTimer(&buf); - ctimer->Start(); - - // Do nothing. - - ctimer->Stop(); - } - - { - ctimer->Start(); - - // Do nothing. - - ctimer->Stop(); - ctimer->Report("CumulativeTimerTest"); - } - - EXPECT_EQ( - " CumulativeTimerTest 0.04 0.04 0.03" - " 0.01\n", - buf.str()); - - if (ctimer) delete ctimer; -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/tools/CMakeLists.txt b/3rdparty/spirv-tools/test/tools/CMakeLists.txt deleted file mode 100644 index 99f9780c5..000000000 --- a/3rdparty/spirv-tools/test/tools/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2018 Google LLC. -# -# 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. - -add_test(NAME spirv-tools_expect_unittests - COMMAND ${PYTHON_EXECUTABLE} -m unittest expect_unittest.py - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME spirv-tools_spirv_test_framework_unittests - COMMAND ${PYTHON_EXECUTABLE} -m unittest spirv_test_framework_unittest.py - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_subdirectory(opt) diff --git a/3rdparty/spirv-tools/test/tools/expect.py b/3rdparty/spirv-tools/test/tools/expect.py deleted file mode 100755 index 0b51adc9c..000000000 --- a/3rdparty/spirv-tools/test/tools/expect.py +++ /dev/null @@ -1,708 +0,0 @@ -# Copyright (c) 2018 Google LLC -# -# 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. -"""A number of common spirv result checks coded in mixin classes. - -A test case can use these checks by declaring their enclosing mixin classes -as superclass and providing the expected_* variables required by the check_*() -methods in the mixin classes. -""" -import difflib -import functools -import os -import re -import subprocess -import traceback -from spirv_test_framework import SpirvTest -from builtins import bytes - -DEFAULT_SPIRV_VERSION = 0x010000 - -def convert_to_unix_line_endings(source): - """Converts all line endings in source to be unix line endings.""" - result = source.replace('\r\n', '\n').replace('\r', '\n') - return result - - -def substitute_file_extension(filename, extension): - """Substitutes file extension, respecting known shader extensions. - - foo.vert -> foo.vert.[extension] [similarly for .frag, .comp, etc.] - foo.glsl -> foo.[extension] - foo.unknown -> foo.[extension] - foo -> foo.[extension] - """ - if filename[-5:] not in [ - '.vert', '.frag', '.tesc', '.tese', '.geom', '.comp', '.spvasm' - ]: - return filename.rsplit('.', 1)[0] + '.' + extension - else: - return filename + '.' + extension - - -def get_object_filename(source_filename): - """Gets the object filename for the given source file.""" - return substitute_file_extension(source_filename, 'spv') - - -def get_assembly_filename(source_filename): - """Gets the assembly filename for the given source file.""" - return substitute_file_extension(source_filename, 'spvasm') - - -def verify_file_non_empty(filename): - """Checks that a given file exists and is not empty.""" - if not os.path.isfile(filename): - return False, 'Cannot find file: ' + filename - if not os.path.getsize(filename): - return False, 'Empty file: ' + filename - return True, '' - - -class ReturnCodeIsZero(SpirvTest): - """Mixin class for checking that the return code is zero.""" - - def check_return_code_is_zero(self, status): - if status.returncode: - return False, 'Non-zero return code: {ret}\n'.format( - ret=status.returncode) - return True, '' - - -class ReturnCodeIsNonZero(SpirvTest): - """Mixin class for checking that the return code is not zero.""" - - def check_return_code_is_nonzero(self, status): - if not status.returncode: - return False, 'return code is 0' - return True, '' - - -class NoOutputOnStdout(SpirvTest): - """Mixin class for checking that there is no output on stdout.""" - - def check_no_output_on_stdout(self, status): - if status.stdout: - return False, 'Non empty stdout: {out}\n'.format(out=status.stdout) - return True, '' - - -class NoOutputOnStderr(SpirvTest): - """Mixin class for checking that there is no output on stderr.""" - - def check_no_output_on_stderr(self, status): - if status.stderr: - return False, 'Non empty stderr: {err}\n'.format(err=status.stderr) - return True, '' - - -class SuccessfulReturn(ReturnCodeIsZero, NoOutputOnStdout, NoOutputOnStderr): - """Mixin class for checking that return code is zero and no output on - stdout and stderr.""" - pass - - -class NoGeneratedFiles(SpirvTest): - """Mixin class for checking that there is no file generated.""" - - def check_no_generated_files(self, status): - all_files = os.listdir(status.directory) - input_files = status.input_filenames - if all([f.startswith(status.directory) for f in input_files]): - all_files = [os.path.join(status.directory, f) for f in all_files] - generated_files = set(all_files) - set(input_files) - if len(generated_files) == 0: - return True, '' - else: - return False, 'Extra files generated: {}'.format(generated_files) - - -class CorrectBinaryLengthAndPreamble(SpirvTest): - """Provides methods for verifying preamble for a SPIR-V binary.""" - - def verify_binary_length_and_header(self, binary, spv_version=0x10000): - """Checks that the given SPIR-V binary has valid length and header. - - Returns: - False, error string if anything is invalid - True, '' otherwise - Args: - binary: a bytes object containing the SPIR-V binary - spv_version: target SPIR-V version number, with same encoding - as the version word in a SPIR-V header. - """ - - def read_word(binary, index, little_endian): - """Reads the index-th word from the given binary file.""" - word = binary[index * 4:(index + 1) * 4] - if little_endian: - word = reversed(word) - return functools.reduce(lambda w, b: (w << 8) | b, word, 0) - - def check_endianness(binary): - """Checks the endianness of the given SPIR-V binary. - - Returns: - True if it's little endian, False if it's big endian. - None if magic number is wrong. - """ - first_word = read_word(binary, 0, True) - if first_word == 0x07230203: - return True - first_word = read_word(binary, 0, False) - if first_word == 0x07230203: - return False - return None - - num_bytes = len(binary) - if num_bytes % 4 != 0: - return False, ('Incorrect SPV binary: size should be a multiple' - ' of words') - if num_bytes < 20: - return False, 'Incorrect SPV binary: size less than 5 words' - - preamble = binary[0:19] - little_endian = check_endianness(preamble) - # SPIR-V module magic number - if little_endian is None: - return False, 'Incorrect SPV binary: wrong magic number' - - # SPIR-V version number - version = read_word(preamble, 1, little_endian) - # TODO(dneto): Recent Glslang uses version word 0 for opengl_compat - # profile - - if version != spv_version and version != 0: - return False, 'Incorrect SPV binary: wrong version number: ' + hex(version) + ' expected ' + hex(spv_version) - # Shaderc-over-Glslang (0x000d....) or - # SPIRV-Tools (0x0007....) generator number - if read_word(preamble, 2, little_endian) != 0x000d0007 and \ - read_word(preamble, 2, little_endian) != 0x00070000: - return False, ('Incorrect SPV binary: wrong generator magic ' 'number') - # reserved for instruction schema - if read_word(preamble, 4, little_endian) != 0: - return False, 'Incorrect SPV binary: the 5th byte should be 0' - - return True, '' - - -class CorrectObjectFilePreamble(CorrectBinaryLengthAndPreamble): - """Provides methods for verifying preamble for a SPV object file.""" - - def verify_object_file_preamble(self, - filename, - spv_version=DEFAULT_SPIRV_VERSION): - """Checks that the given SPIR-V binary file has correct preamble.""" - - success, message = verify_file_non_empty(filename) - if not success: - return False, message - - with open(filename, 'rb') as object_file: - object_file.seek(0, os.SEEK_END) - num_bytes = object_file.tell() - - object_file.seek(0) - - binary = bytes(object_file.read()) - return self.verify_binary_length_and_header(binary, spv_version) - - return True, '' - - -class CorrectAssemblyFilePreamble(SpirvTest): - """Provides methods for verifying preamble for a SPV assembly file.""" - - def verify_assembly_file_preamble(self, filename): - success, message = verify_file_non_empty(filename) - if not success: - return False, message - - with open(filename) as assembly_file: - line1 = assembly_file.readline() - line2 = assembly_file.readline() - line3 = assembly_file.readline() - - if (line1 != '; SPIR-V\n' or line2 != '; Version: 1.0\n' or - (not line3.startswith('; Generator: Google Shaderc over Glslang;'))): - return False, 'Incorrect SPV assembly' - - return True, '' - - -class ValidObjectFile(SuccessfulReturn, CorrectObjectFilePreamble): - """Mixin class for checking that every input file generates a valid SPIR-V 1.0 - object file following the object file naming rule, and there is no output on - stdout/stderr.""" - - def check_object_file_preamble(self, status): - for input_filename in status.input_filenames: - object_filename = get_object_filename(input_filename) - success, message = self.verify_object_file_preamble( - os.path.join(status.directory, object_filename)) - if not success: - return False, message - return True, '' - - -class ValidObjectFile1_3(ReturnCodeIsZero, CorrectObjectFilePreamble): - """Mixin class for checking that every input file generates a valid SPIR-V 1.3 - object file following the object file naming rule, and there is no output on - stdout/stderr.""" - - def check_object_file_preamble(self, status): - for input_filename in status.input_filenames: - object_filename = get_object_filename(input_filename) - success, message = self.verify_object_file_preamble( - os.path.join(status.directory, object_filename), 0x10300) - if not success: - return False, message - return True, '' - - -class ValidObjectFile1_5(ReturnCodeIsZero, CorrectObjectFilePreamble): - """Mixin class for checking that every input file generates a valid SPIR-V 1.5 - object file following the object file naming rule, and there is no output on - stdout/stderr.""" - - def check_object_file_preamble(self, status): - for input_filename in status.input_filenames: - object_filename = get_object_filename(input_filename) - success, message = self.verify_object_file_preamble( - os.path.join(status.directory, object_filename), 0x10500) - if not success: - return False, message - return True, '' - - -class ValidObjectFileWithAssemblySubstr(SuccessfulReturn, - CorrectObjectFilePreamble): - """Mixin class for checking that every input file generates a valid object - - file following the object file naming rule, there is no output on - stdout/stderr, and the disassmbly contains a specified substring per - input. - """ - - def check_object_file_disassembly(self, status): - for an_input in status.inputs: - object_filename = get_object_filename(an_input.filename) - obj_file = str(os.path.join(status.directory, object_filename)) - success, message = self.verify_object_file_preamble(obj_file) - if not success: - return False, message - cmd = [status.test_manager.disassembler_path, '--no-color', obj_file] - process = subprocess.Popen( - args=cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=status.directory) - output = process.communicate(None) - disassembly = output[0] - if not isinstance(an_input.assembly_substr, str): - return False, 'Missing assembly_substr member' - if an_input.assembly_substr not in disassembly: - return False, ('Incorrect disassembly output:\n{asm}\n' - 'Expected substring not found:\n{exp}'.format( - asm=disassembly, exp=an_input.assembly_substr)) - return True, '' - - -class ValidNamedObjectFile(SuccessfulReturn, CorrectObjectFilePreamble): - """Mixin class for checking that a list of object files with the given - names are correctly generated, and there is no output on stdout/stderr. - - To mix in this class, subclasses need to provide expected_object_filenames - as the expected object filenames. - """ - - def check_object_file_preamble(self, status): - for object_filename in self.expected_object_filenames: - success, message = self.verify_object_file_preamble( - os.path.join(status.directory, object_filename)) - if not success: - return False, message - return True, '' - - -class ValidFileContents(SpirvTest): - """Mixin class to test that a specific file contains specific text - To mix in this class, subclasses need to provide expected_file_contents as - the contents of the file and target_filename to determine the location.""" - - def check_file(self, status): - target_filename = os.path.join(status.directory, self.target_filename) - if not os.path.isfile(target_filename): - return False, 'Cannot find file: ' + target_filename - with open(target_filename, 'r') as target_file: - file_contents = target_file.read() - if isinstance(self.expected_file_contents, str): - if file_contents == self.expected_file_contents: - return True, '' - return False, ('Incorrect file output: \n{act}\n' - 'Expected:\n{exp}' - 'With diff:\n{diff}'.format( - act=file_contents, - exp=self.expected_file_contents, - diff='\n'.join( - list( - difflib.unified_diff( - self.expected_file_contents.split('\n'), - file_contents.split('\n'), - fromfile='expected_output', - tofile='actual_output'))))) - elif isinstance(self.expected_file_contents, type(re.compile(''))): - if self.expected_file_contents.search(file_contents): - return True, '' - return False, ('Incorrect file output: \n{act}\n' - 'Expected matching regex pattern:\n{exp}'.format( - act=file_contents, - exp=self.expected_file_contents.pattern)) - return False, ( - 'Could not open target file ' + target_filename + ' for reading') - - -class ValidAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble): - """Mixin class for checking that every input file generates a valid assembly - file following the assembly file naming rule, and there is no output on - stdout/stderr.""" - - def check_assembly_file_preamble(self, status): - for input_filename in status.input_filenames: - assembly_filename = get_assembly_filename(input_filename) - success, message = self.verify_assembly_file_preamble( - os.path.join(status.directory, assembly_filename)) - if not success: - return False, message - return True, '' - - -class ValidAssemblyFileWithSubstr(ValidAssemblyFile): - """Mixin class for checking that every input file generates a valid assembly - file following the assembly file naming rule, there is no output on - stdout/stderr, and all assembly files have the given substring specified - by expected_assembly_substr. - - To mix in this class, subclasses need to provde expected_assembly_substr - as the expected substring. - """ - - def check_assembly_with_substr(self, status): - for input_filename in status.input_filenames: - assembly_filename = get_assembly_filename(input_filename) - success, message = self.verify_assembly_file_preamble( - os.path.join(status.directory, assembly_filename)) - if not success: - return False, message - with open(assembly_filename, 'r') as f: - content = f.read() - if self.expected_assembly_substr not in convert_to_unix_line_endings( - content): - return False, ('Incorrect assembly output:\n{asm}\n' - 'Expected substring not found:\n{exp}'.format( - asm=content, exp=self.expected_assembly_substr)) - return True, '' - - -class ValidAssemblyFileWithoutSubstr(ValidAssemblyFile): - """Mixin class for checking that every input file generates a valid assembly - file following the assembly file naming rule, there is no output on - stdout/stderr, and no assembly files have the given substring specified - by unexpected_assembly_substr. - - To mix in this class, subclasses need to provde unexpected_assembly_substr - as the substring we expect not to see. - """ - - def check_assembly_for_substr(self, status): - for input_filename in status.input_filenames: - assembly_filename = get_assembly_filename(input_filename) - success, message = self.verify_assembly_file_preamble( - os.path.join(status.directory, assembly_filename)) - if not success: - return False, message - with open(assembly_filename, 'r') as f: - content = f.read() - if self.unexpected_assembly_substr in convert_to_unix_line_endings( - content): - return False, ('Incorrect assembly output:\n{asm}\n' - 'Unexpected substring found:\n{unexp}'.format( - asm=content, exp=self.unexpected_assembly_substr)) - return True, '' - - -class ValidNamedAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble): - """Mixin class for checking that a list of assembly files with the given - names are correctly generated, and there is no output on stdout/stderr. - - To mix in this class, subclasses need to provide expected_assembly_filenames - as the expected assembly filenames. - """ - - def check_object_file_preamble(self, status): - for assembly_filename in self.expected_assembly_filenames: - success, message = self.verify_assembly_file_preamble( - os.path.join(status.directory, assembly_filename)) - if not success: - return False, message - return True, '' - - -class ErrorMessage(SpirvTest): - """Mixin class for tests that fail with a specific error message. - - To mix in this class, subclasses need to provide expected_error as the - expected error message. - - The test should fail if the subprocess was terminated by a signal. - """ - - def check_has_error_message(self, status): - if not status.returncode: - return False, ('Expected error message, but returned success from ' - 'command execution') - if status.returncode < 0: - # On Unix, a negative value -N for Popen.returncode indicates - # termination by signal N. - # https://docs.python.org/2/library/subprocess.html - return False, ('Expected error message, but command was terminated by ' - 'signal ' + str(status.returncode)) - if not status.stderr: - return False, 'Expected error message, but no output on stderr' - if self.expected_error != convert_to_unix_line_endings(status.stderr): - return False, ('Incorrect stderr output:\n{act}\n' - 'Expected:\n{exp}'.format( - act=status.stderr, exp=self.expected_error)) - return True, '' - - -class ErrorMessageSubstr(SpirvTest): - """Mixin class for tests that fail with a specific substring in the error - message. - - To mix in this class, subclasses need to provide expected_error_substr as - the expected error message substring. - - The test should fail if the subprocess was terminated by a signal. - """ - - def check_has_error_message_as_substring(self, status): - if not status.returncode: - return False, ('Expected error message, but returned success from ' - 'command execution') - if status.returncode < 0: - # On Unix, a negative value -N for Popen.returncode indicates - # termination by signal N. - # https://docs.python.org/2/library/subprocess.html - return False, ('Expected error message, but command was terminated by ' - 'signal ' + str(status.returncode)) - if not status.stderr: - return False, 'Expected error message, but no output on stderr' - if self.expected_error_substr not in convert_to_unix_line_endings( - status.stderr): - return False, ('Incorrect stderr output:\n{act}\n' - 'Expected substring not found in stderr:\n{exp}'.format( - act=status.stderr, exp=self.expected_error_substr)) - return True, '' - - -class WarningMessage(SpirvTest): - """Mixin class for tests that succeed but have a specific warning message. - - To mix in this class, subclasses need to provide expected_warning as the - expected warning message. - """ - - def check_has_warning_message(self, status): - if status.returncode: - return False, ('Expected warning message, but returned failure from' - ' command execution') - if not status.stderr: - return False, 'Expected warning message, but no output on stderr' - if self.expected_warning != convert_to_unix_line_endings(status.stderr): - return False, ('Incorrect stderr output:\n{act}\n' - 'Expected:\n{exp}'.format( - act=status.stderr, exp=self.expected_warning)) - return True, '' - - -class ValidObjectFileWithWarning(NoOutputOnStdout, CorrectObjectFilePreamble, - WarningMessage): - """Mixin class for checking that every input file generates a valid object - file following the object file naming rule, with a specific warning message. - """ - - def check_object_file_preamble(self, status): - for input_filename in status.input_filenames: - object_filename = get_object_filename(input_filename) - success, message = self.verify_object_file_preamble( - os.path.join(status.directory, object_filename)) - if not success: - return False, message - return True, '' - - -class ValidAssemblyFileWithWarning(NoOutputOnStdout, - CorrectAssemblyFilePreamble, WarningMessage): - """Mixin class for checking that every input file generates a valid assembly - file following the assembly file naming rule, with a specific warning - message.""" - - def check_assembly_file_preamble(self, status): - for input_filename in status.input_filenames: - assembly_filename = get_assembly_filename(input_filename) - success, message = self.verify_assembly_file_preamble( - os.path.join(status.directory, assembly_filename)) - if not success: - return False, message - return True, '' - - -class StdoutMatch(SpirvTest): - """Mixin class for tests that can expect output on stdout. - - To mix in this class, subclasses need to provide expected_stdout as the - expected stdout output. - - For expected_stdout, if it's True, then they expect something on stdout but - will not check what it is. If it's a string, expect an exact match. If it's - anything else, it is assumed to be a compiled regular expression which will - be matched against re.search(). It will expect - expected_stdout.search(status.stdout) to be true. - """ - - def check_stdout_match(self, status): - # "True" in this case means we expect something on stdout, but we do not - # care what it is, we want to distinguish this from "blah" which means we - # expect exactly the string "blah". - if self.expected_stdout is True: - if not status.stdout: - return False, 'Expected something on stdout' - elif type(self.expected_stdout) == str: - if self.expected_stdout != convert_to_unix_line_endings(status.stdout): - return False, ('Incorrect stdout output:\n{ac}\n' - 'Expected:\n{ex}'.format( - ac=status.stdout, ex=self.expected_stdout)) - else: - converted = convert_to_unix_line_endings(status.stdout) - if not self.expected_stdout.search(converted): - return False, ('Incorrect stdout output:\n{ac}\n' - 'Expected to match regex:\n{ex}'.format( - ac=status.stdout, ex=self.expected_stdout.pattern)) - return True, '' - - -class StderrMatch(SpirvTest): - """Mixin class for tests that can expect output on stderr. - - To mix in this class, subclasses need to provide expected_stderr as the - expected stderr output. - - For expected_stderr, if it's True, then they expect something on stderr, - but will not check what it is. If it's a string, expect an exact match. - If it's anything else, it is assumed to be a compiled regular expression - which will be matched against re.search(). It will expect - expected_stderr.search(status.stderr) to be true. - """ - - def check_stderr_match(self, status): - # "True" in this case means we expect something on stderr, but we do not - # care what it is, we want to distinguish this from "blah" which means we - # expect exactly the string "blah". - if self.expected_stderr is True: - if not status.stderr: - return False, 'Expected something on stderr' - elif type(self.expected_stderr) == str: - if self.expected_stderr != convert_to_unix_line_endings(status.stderr): - return False, ('Incorrect stderr output:\n{ac}\n' - 'Expected:\n{ex}'.format( - ac=status.stderr, ex=self.expected_stderr)) - else: - if not self.expected_stderr.search( - convert_to_unix_line_endings(status.stderr)): - return False, ('Incorrect stderr output:\n{ac}\n' - 'Expected to match regex:\n{ex}'.format( - ac=status.stderr, ex=self.expected_stderr.pattern)) - return True, '' - - -class StdoutNoWiderThan80Columns(SpirvTest): - """Mixin class for tests that require stdout to 80 characters or narrower. - - To mix in this class, subclasses need to provide expected_stdout as the - expected stdout output. - """ - - def check_stdout_not_too_wide(self, status): - if not status.stdout: - return True, '' - else: - for line in status.stdout.splitlines(): - if len(line) > 80: - return False, ('Stdout line longer than 80 columns: %s' % line) - return True, '' - - -class NoObjectFile(SpirvTest): - """Mixin class for checking that no input file has a corresponding object - file.""" - - def check_no_object_file(self, status): - for input_filename in status.input_filenames: - object_filename = get_object_filename(input_filename) - full_object_file = os.path.join(status.directory, object_filename) - print('checking %s' % full_object_file) - if os.path.isfile(full_object_file): - return False, ( - 'Expected no object file, but found: %s' % full_object_file) - return True, '' - - -class NoNamedOutputFiles(SpirvTest): - """Mixin class for checking that no specified output files exist. - - The expected_output_filenames member should be full pathnames.""" - - def check_no_named_output_files(self, status): - for object_filename in self.expected_output_filenames: - if os.path.isfile(object_filename): - return False, ( - 'Expected no output file, but found: %s' % object_filename) - return True, '' - - -class ExecutedListOfPasses(SpirvTest): - """Mixin class for checking that a list of passes where executed. - - It works by analyzing the output of the --print-all flag to spirv-opt. - - For this mixin to work, the class member expected_passes should be a sequence - of pass names as returned by Pass::name(). - """ - - def check_list_of_executed_passes(self, status): - # Collect all the output lines containing a pass name. - pass_names = [] - pass_name_re = re.compile(r'.*IR before pass (?P[\S]+)') - for line in status.stderr.splitlines(): - match = pass_name_re.match(line) - if match: - pass_names.append(match.group('pass_name')) - - for (expected, actual) in zip(self.expected_passes, pass_names): - if expected != actual: - return False, ( - 'Expected pass "%s" but found pass "%s"\n' % (expected, actual)) - - return True, '' diff --git a/3rdparty/spirv-tools/test/tools/expect_unittest.py b/3rdparty/spirv-tools/test/tools/expect_unittest.py deleted file mode 100644 index a28de1b97..000000000 --- a/3rdparty/spirv-tools/test/tools/expect_unittest.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (c) 2019 Google LLC -# -# 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. -"""Tests for the expect module.""" - -import expect -from spirv_test_framework import TestStatus -import re -import unittest - - -class TestStdoutMatchADotC(expect.StdoutMatch): - expected_stdout = re.compile('a.c') - - -class TestExpect(unittest.TestCase): - def test_get_object_name(self): - """Tests get_object_filename().""" - source_and_object_names = [('a.vert', 'a.vert.spv'), - ('b.frag', 'b.frag.spv'), - ('c.tesc', 'c.tesc.spv'), - ('d.tese', 'd.tese.spv'), - ('e.geom', 'e.geom.spv'), - ('f.comp', 'f.comp.spv'), - ('file', 'file.spv'), ('file.', 'file.spv'), - ('file.uk', - 'file.spv'), ('file.vert.', - 'file.vert.spv'), - ('file.vert.bla', - 'file.vert.spv')] - actual_object_names = [ - expect.get_object_filename(f[0]) for f in source_and_object_names - ] - expected_object_names = [f[1] for f in source_and_object_names] - - self.assertEqual(actual_object_names, expected_object_names) - - def test_stdout_match_regex_has_match(self): - test = TestStdoutMatchADotC() - status = TestStatus( - test_manager=None, - returncode=0, - stdout=b'0abc1', - stderr=None, - directory=None, - inputs=None, - input_filenames=None) - self.assertTrue(test.check_stdout_match(status)[0]) - - def test_stdout_match_regex_no_match(self): - test = TestStdoutMatchADotC() - status = TestStatus( - test_manager=None, - returncode=0, - stdout=b'ab', - stderr=None, - directory=None, - inputs=None, - input_filenames=None) - self.assertFalse(test.check_stdout_match(status)[0]) - - def test_stdout_match_regex_empty_stdout(self): - test = TestStdoutMatchADotC() - status = TestStatus( - test_manager=None, - returncode=0, - stdout=b'', - stderr=None, - directory=None, - inputs=None, - input_filenames=None) - self.assertFalse(test.check_stdout_match(status)[0]) diff --git a/3rdparty/spirv-tools/test/tools/opt/CMakeLists.txt b/3rdparty/spirv-tools/test/tools/opt/CMakeLists.txt deleted file mode 100644 index 21aa247f1..000000000 --- a/3rdparty/spirv-tools/test/tools/opt/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2018 Google LLC. -# -# 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. - -if(NOT ${SPIRV_SKIP_TESTS}) - if(${PYTHONINTERP_FOUND}) - add_test(NAME spirv_opt_cli_tools_tests - COMMAND ${PYTHON_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/../spirv_test_framework.py - $ $ $ - --test-dir ${CMAKE_CURRENT_SOURCE_DIR}) - else() - message("Skipping CLI tools tests - Python executable not found") - endif() -endif() diff --git a/3rdparty/spirv-tools/test/tools/opt/flags.py b/3rdparty/spirv-tools/test/tools/opt/flags.py deleted file mode 100644 index 2f6c0a793..000000000 --- a/3rdparty/spirv-tools/test/tools/opt/flags.py +++ /dev/null @@ -1,386 +0,0 @@ -# Copyright (c) 2018 Google LLC -# -# 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. - -import placeholder -import expect -import re - -from spirv_test_framework import inside_spirv_testsuite - - -def empty_main_assembly(): - return """ - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %4 "main" - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd""" - - -@inside_spirv_testsuite('SpirvOptBase') -class TestAssemblyFileAsOnlyParameter(expect.ValidObjectFile1_5): - """Tests that spirv-opt accepts a SPIR-V object file.""" - - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - output = placeholder.TempFileName('output.spv') - spirv_args = [shader, '-o', output] - expected_object_filenames = (output) - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestHelpFlag(expect.ReturnCodeIsZero, expect.StdoutMatch): - """Test the --help flag.""" - - spirv_args = ['--help'] - expected_stdout = re.compile(r'.*The SPIR-V binary is read from ') - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestValidPassFlags(expect.ValidObjectFile1_5, - expect.ExecutedListOfPasses): - """Tests that spirv-opt accepts all valid optimization flags.""" - - flags = [ - '--wrap-opkill', '--ccp', '--cfg-cleanup', '--combine-access-chains', '--compact-ids', - '--convert-local-access-chains', '--copy-propagate-arrays', - '--eliminate-dead-branches', - '--eliminate-dead-code-aggressive', '--eliminate-dead-const', - '--eliminate-dead-functions', '--eliminate-dead-inserts', - '--eliminate-dead-variables', '--eliminate-insert-extract', - '--eliminate-local-multi-store', '--eliminate-local-single-block', - '--eliminate-local-single-store', '--flatten-decorations', - '--fold-spec-const-op-composite', '--freeze-spec-const', - '--if-conversion', '--inline-entry-points-exhaustive', '--loop-fission', - '20', '--loop-fusion', '5', '--loop-unroll', '--loop-unroll-partial', '3', - '--loop-peeling', '--merge-blocks', '--merge-return', '--loop-unswitch', - '--private-to-local', '--reduce-load-size', '--redundancy-elimination', - '--remove-duplicates', '--replace-invalid-opcode', '--ssa-rewrite', - '--scalar-replacement', '--scalar-replacement=42', '--strength-reduction', - '--strip-debug', '--strip-reflect', '--vector-dce', '--workaround-1209', - '--unify-const' - ] - expected_passes = [ - 'wrap-opkill', - 'ccp', - 'cfg-cleanup', - 'combine-access-chains', - 'compact-ids', - 'convert-local-access-chains', - 'copy-propagate-arrays', - 'eliminate-dead-branches', - 'eliminate-dead-code-aggressive', - 'eliminate-dead-const', - 'eliminate-dead-functions', - 'eliminate-dead-inserts', - 'eliminate-dead-variables', - # --eliminate-insert-extract runs the simplify-instructions pass. - 'simplify-instructions', - 'ssa-rewrite', - 'eliminate-local-single-block', - 'eliminate-local-single-store', - 'flatten-decorations', - 'fold-spec-const-op-composite', - 'freeze-spec-const', - 'if-conversion', - 'inline-entry-points-exhaustive', - 'loop-fission', - 'loop-fusion', - 'loop-unroll', - 'loop-unroll', - 'loop-peeling', - 'merge-blocks', - 'merge-return', - 'loop-unswitch', - 'private-to-local', - 'reduce-load-size', - 'redundancy-elimination', - 'remove-duplicates', - 'replace-invalid-opcode', - 'ssa-rewrite', - 'scalar-replacement=100', - 'scalar-replacement=42', - 'strength-reduction', - 'strip-debug', - 'strip-reflect', - 'vector-dce', - 'workaround-1209', - 'unify-const' - ] - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - output = placeholder.TempFileName('output.spv') - spirv_args = [shader, '-o', output, '--print-all'] + flags - expected_object_filenames = (output) - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestPerformanceOptimizationPasses(expect.ValidObjectFile1_5, - expect.ExecutedListOfPasses): - """Tests that spirv-opt schedules all the passes triggered by -O.""" - - flags = ['-O'] - expected_passes = [ - 'wrap-opkill', - 'eliminate-dead-branches', - 'merge-return', - 'inline-entry-points-exhaustive', - 'eliminate-dead-code-aggressive', - 'private-to-local', - 'eliminate-local-single-block', - 'eliminate-local-single-store', - 'eliminate-dead-code-aggressive', - 'scalar-replacement=100', - 'convert-local-access-chains', - 'eliminate-local-single-block', - 'eliminate-local-single-store', - 'eliminate-dead-code-aggressive', - 'ssa-rewrite', - 'eliminate-dead-code-aggressive', - 'ccp', - 'eliminate-dead-code-aggressive', - 'redundancy-elimination', - 'combine-access-chains', - 'simplify-instructions', - 'vector-dce', - 'eliminate-dead-inserts', - 'eliminate-dead-branches', - 'simplify-instructions', - 'if-conversion', - 'copy-propagate-arrays', - 'reduce-load-size', - 'eliminate-dead-code-aggressive', - 'merge-blocks', - 'redundancy-elimination', - 'eliminate-dead-branches', - 'merge-blocks', - 'simplify-instructions', - ] - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - output = placeholder.TempFileName('output.spv') - spirv_args = [shader, '-o', output, '--print-all'] + flags - expected_object_filenames = (output) - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestSizeOptimizationPasses(expect.ValidObjectFile1_5, - expect.ExecutedListOfPasses): - """Tests that spirv-opt schedules all the passes triggered by -Os.""" - - flags = ['-Os'] - expected_passes = [ - 'wrap-opkill', - 'eliminate-dead-branches', - 'merge-return', - 'inline-entry-points-exhaustive', - 'eliminate-dead-functions', - 'private-to-local', - 'scalar-replacement=0', - 'ssa-rewrite', - 'ccp', - 'loop-unroll', - 'eliminate-dead-branches', - 'simplify-instructions', - 'scalar-replacement=0', - 'eliminate-local-single-store', - 'if-conversion', - 'simplify-instructions', - 'eliminate-dead-code-aggressive', - 'eliminate-dead-branches', - 'merge-blocks', - 'convert-local-access-chains', - 'eliminate-local-single-block', - 'eliminate-dead-code-aggressive', - 'copy-propagate-arrays', - 'vector-dce', - 'eliminate-dead-inserts', - 'eliminate-dead-members', - 'eliminate-local-single-store', - 'merge-blocks', - 'ssa-rewrite', - 'redundancy-elimination', - 'simplify-instructions', - 'eliminate-dead-code-aggressive', - 'cfg-cleanup', - ] - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - output = placeholder.TempFileName('output.spv') - spirv_args = [shader, '-o', output, '--print-all'] + flags - expected_object_filenames = (output) - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLegalizationPasses(expect.ValidObjectFile1_5, - expect.ExecutedListOfPasses): - """Tests that spirv-opt schedules all the passes triggered by --legalize-hlsl. - """ - - flags = ['--legalize-hlsl'] - expected_passes = [ - 'wrap-opkill', - 'eliminate-dead-branches', - 'merge-return', - 'inline-entry-points-exhaustive', - 'eliminate-dead-functions', - 'private-to-local', - 'fix-storage-class', - 'eliminate-local-single-block', - 'eliminate-local-single-store', - 'eliminate-dead-code-aggressive', - 'scalar-replacement=0', - 'eliminate-local-single-block', - 'eliminate-local-single-store', - 'eliminate-dead-code-aggressive', - 'ssa-rewrite', - 'eliminate-dead-code-aggressive', - 'ccp', - 'loop-unroll', - 'eliminate-dead-branches', - 'simplify-instructions', - 'eliminate-dead-code-aggressive', - 'copy-propagate-arrays', - 'vector-dce', - 'eliminate-dead-inserts', - 'reduce-load-size', - 'eliminate-dead-code-aggressive', - ] - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - output = placeholder.TempFileName('output.spv') - spirv_args = [shader, '-o', output, '--print-all'] + flags - expected_object_filenames = (output) - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestScalarReplacementArgsNegative(expect.ErrorMessageSubstr): - """Tests invalid arguments to --scalar-replacement.""" - - spirv_args = ['--scalar-replacement=-10'] - expected_error_substr = 'must have no arguments or a non-negative integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestScalarReplacementArgsInvalidNumber(expect.ErrorMessageSubstr): - """Tests invalid arguments to --scalar-replacement.""" - - spirv_args = ['--scalar-replacement=a10f'] - expected_error_substr = 'must have no arguments or a non-negative integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopFissionArgsNegative(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-fission.""" - - spirv_args = ['--loop-fission=-10'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopFissionArgsInvalidNumber(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-fission.""" - - spirv_args = ['--loop-fission=a10f'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopFusionArgsNegative(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-fusion.""" - - spirv_args = ['--loop-fusion=-10'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopFusionArgsInvalidNumber(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-fusion.""" - - spirv_args = ['--loop-fusion=a10f'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopUnrollPartialArgsNegative(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-unroll-partial.""" - - spirv_args = ['--loop-unroll-partial=-10'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopUnrollPartialArgsInvalidNumber(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-unroll-partial.""" - - spirv_args = ['--loop-unroll-partial=a10f'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopPeelingThresholdArgsNegative(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-peeling-threshold.""" - - spirv_args = ['--loop-peeling-threshold=-10'] - expected_error_substr = 'must have a positive integer argument' - - -@inside_spirv_testsuite('SpirvOptFlags') -class TestLoopPeelingThresholdArgsInvalidNumber(expect.ErrorMessageSubstr): - """Tests invalid arguments to --loop-peeling-threshold.""" - - spirv_args = ['--loop-peeling-threshold=a10f'] - expected_error_substr = 'must have a positive integer argument' - -@inside_spirv_testsuite('SpirvOptFlags') -class TestWebGPUToVulkanThenVulkanToWebGPUIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr): - """Tests Vulkan->WebGPU flag cannot be used after WebGPU->Vulkan flag.""" - - spirv_args = ['--webgpu-to-vulkan', '--vulkan-to-webgpu'] - expected_error_substr = 'Cannot use both' - -@inside_spirv_testsuite('SpirvOptFlags') -class TestVulkanToWebGPUThenWebGPUToVulkanIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr): - """Tests WebGPU->Vulkan flag cannot be used after Vulkan->WebGPU flag.""" - - spirv_args = ['--vulkan-to-webgpu', '--webgpu-to-vulkan'] - expected_error_substr = 'Cannot use both' - -@inside_spirv_testsuite('SpirvOptFlags') -class TestTargetEnvThenVulkanToWebGPUIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr): - """Tests Vulkan->WebGPU flag cannot be used after target env flag.""" - - spirv_args = ['--target-env=opengl4.0', '--vulkan-to-webgpu'] - expected_error_substr = 'defines the target environment' - -@inside_spirv_testsuite('SpirvOptFlags') -class TestVulkanToWebGPUThenTargetEnvIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr): - """Tests target env flag cannot be used after Vulkan->WebGPU flag.""" - - spirv_args = ['--vulkan-to-webgpu', '--target-env=opengl4.0'] - expected_error_substr = 'defines the target environment' - -@inside_spirv_testsuite('SpirvOptFlags') -class TestTargetEnvThenWebGPUToVulkanIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr): - """Tests WebGPU->Vulkan flag cannot be used after target env flag.""" - - spirv_args = ['--target-env=opengl4.0', '--webgpu-to-vulkan'] - expected_error_substr = 'defines the target environment' - -@inside_spirv_testsuite('SpirvOptFlags') -class TestWebGPUToVulkanThenTargetEnvIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr): - """Tests target env flag cannot be used after WebGPU->Vulkan flag.""" - - spirv_args = ['--webgpu-to-vulkan', '--target-env=opengl4.0'] - expected_error_substr = 'defines the target environment' diff --git a/3rdparty/spirv-tools/test/tools/opt/oconfig.py b/3rdparty/spirv-tools/test/tools/opt/oconfig.py deleted file mode 100644 index 899d93e56..000000000 --- a/3rdparty/spirv-tools/test/tools/opt/oconfig.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (c) 2018 Google LLC -# -# 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. - -import placeholder -import expect -import re - -from spirv_test_framework import inside_spirv_testsuite - - -def empty_main_assembly(): - return """ - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %4 "main" - OpName %4 "main" - %2 = OpTypeVoid - %3 = OpTypeFunction %2 - %4 = OpFunction %2 None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd""" - - -@inside_spirv_testsuite('SpirvOptConfigFile') -class TestOconfigEmpty(expect.SuccessfulReturn): - """Tests empty config files are accepted.""" - - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - config = placeholder.ConfigFlagsFile('', '.cfg') - spirv_args = [shader, '-o', placeholder.TempFileName('output.spv'), config] - - -@inside_spirv_testsuite('SpirvOptConfigFile') -class TestOconfigComments(expect.SuccessfulReturn): - """Tests empty config files are accepted. - - https://github.com/KhronosGroup/SPIRV-Tools/issues/1778 - """ - - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - config = placeholder.ConfigFlagsFile(""" -# This is a comment. --O ---loop-unroll -""", '.cfg') - spirv_args = [shader, '-o', placeholder.TempFileName('output.spv'), config] - -@inside_spirv_testsuite('SpirvOptConfigFile') -class TestOconfigComments(expect.SuccessfulReturn): - """Tests empty config files are accepted. - - https://github.com/KhronosGroup/SPIRV-Tools/issues/1778 - """ - - shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') - config = placeholder.ConfigFlagsFile(""" -# This is a comment. --O ---relax-struct-store -""", '.cfg') - spirv_args = [shader, '-o', placeholder.TempFileName('output.spv'), config] diff --git a/3rdparty/spirv-tools/test/tools/placeholder.py b/3rdparty/spirv-tools/test/tools/placeholder.py deleted file mode 100755 index 7de3c467a..000000000 --- a/3rdparty/spirv-tools/test/tools/placeholder.py +++ /dev/null @@ -1,213 +0,0 @@ -# Copyright (c) 2018 Google LLC -# -# 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. -"""A number of placeholders and their rules for expansion when used in tests. - -These placeholders, when used in spirv_args or expected_* variables of -SpirvTest, have special meanings. In spirv_args, they will be substituted by -the result of instantiate_for_spirv_args(), while in expected_*, by -instantiate_for_expectation(). A TestCase instance will be passed in as -argument to the instantiate_*() methods. -""" - -import os -import subprocess -import tempfile -from string import Template - - -class PlaceHolderException(Exception): - """Exception class for PlaceHolder.""" - pass - - -class PlaceHolder(object): - """Base class for placeholders.""" - - def instantiate_for_spirv_args(self, testcase): - """Instantiation rules for spirv_args. - - This method will be called when the current placeholder appears in - spirv_args. - - Returns: - A string to replace the current placeholder in spirv_args. - """ - raise PlaceHolderException('Subclass should implement this function.') - - def instantiate_for_expectation(self, testcase): - """Instantiation rules for expected_*. - - This method will be called when the current placeholder appears in - expected_*. - - Returns: - A string to replace the current placeholder in expected_*. - """ - raise PlaceHolderException('Subclass should implement this function.') - - -class FileShader(PlaceHolder): - """Stands for a shader whose source code is in a file.""" - - def __init__(self, source, suffix, assembly_substr=None): - assert isinstance(source, str) - assert isinstance(suffix, str) - self.source = source - self.suffix = suffix - self.filename = None - # If provided, this is a substring which is expected to be in - # the disassembly of the module generated from this input file. - self.assembly_substr = assembly_substr - - def instantiate_for_spirv_args(self, testcase): - """Creates a temporary file and writes the source into it. - - Returns: - The name of the temporary file. - """ - shader, self.filename = tempfile.mkstemp( - dir=testcase.directory, suffix=self.suffix) - shader_object = os.fdopen(shader, 'w') - shader_object.write(self.source) - shader_object.close() - return self.filename - - def instantiate_for_expectation(self, testcase): - assert self.filename is not None - return self.filename - - -class ConfigFlagsFile(PlaceHolder): - """Stands for a configuration file for spirv-opt generated out of a string.""" - - def __init__(self, content, suffix): - assert isinstance(content, str) - assert isinstance(suffix, str) - self.content = content - self.suffix = suffix - self.filename = None - - def instantiate_for_spirv_args(self, testcase): - """Creates a temporary file and writes content into it. - - Returns: - The name of the temporary file. - """ - temp_fd, self.filename = tempfile.mkstemp( - dir=testcase.directory, suffix=self.suffix) - fd = os.fdopen(temp_fd, 'w') - fd.write(self.content) - fd.close() - return '-Oconfig=%s' % self.filename - - def instantiate_for_expectation(self, testcase): - assert self.filename is not None - return self.filename - - -class FileSPIRVShader(PlaceHolder): - """Stands for a source shader file which must be converted to SPIR-V.""" - - def __init__(self, source, suffix, assembly_substr=None): - assert isinstance(source, str) - assert isinstance(suffix, str) - self.source = source - self.suffix = suffix - self.filename = None - # If provided, this is a substring which is expected to be in - # the disassembly of the module generated from this input file. - self.assembly_substr = assembly_substr - - def instantiate_for_spirv_args(self, testcase): - """Creates a temporary file, writes the source into it and assembles it. - - Returns: - The name of the assembled temporary file. - """ - shader, asm_filename = tempfile.mkstemp( - dir=testcase.directory, suffix=self.suffix) - shader_object = os.fdopen(shader, 'w') - shader_object.write(self.source) - shader_object.close() - self.filename = '%s.spv' % asm_filename - cmd = [ - testcase.test_manager.assembler_path, asm_filename, '-o', self.filename - ] - process = subprocess.Popen( - args=cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=testcase.directory) - output = process.communicate() - assert process.returncode == 0 and not output[0] and not output[1] - return self.filename - - def instantiate_for_expectation(self, testcase): - assert self.filename is not None - return self.filename - - -class StdinShader(PlaceHolder): - """Stands for a shader whose source code is from stdin.""" - - def __init__(self, source): - assert isinstance(source, str) - self.source = source - self.filename = None - - def instantiate_for_spirv_args(self, testcase): - """Writes the source code back to the TestCase instance.""" - testcase.stdin_shader = self.source - self.filename = '-' - return self.filename - - def instantiate_for_expectation(self, testcase): - assert self.filename is not None - return self.filename - - -class TempFileName(PlaceHolder): - """Stands for a temporary file's name.""" - - def __init__(self, filename): - assert isinstance(filename, str) - assert filename != '' - self.filename = filename - - def instantiate_for_spirv_args(self, testcase): - return os.path.join(testcase.directory, self.filename) - - def instantiate_for_expectation(self, testcase): - return os.path.join(testcase.directory, self.filename) - - -class SpecializedString(PlaceHolder): - """Returns a string that has been specialized based on TestCase. - - The string is specialized by expanding it as a string.Template - with all of the specialization being done with each $param replaced - by the associated member on TestCase. - """ - - def __init__(self, filename): - assert isinstance(filename, str) - assert filename != '' - self.filename = filename - - def instantiate_for_spirv_args(self, testcase): - return Template(self.filename).substitute(vars(testcase)) - - def instantiate_for_expectation(self, testcase): - return Template(self.filename).substitute(vars(testcase)) diff --git a/3rdparty/spirv-tools/test/tools/spirv_test_framework.py b/3rdparty/spirv-tools/test/tools/spirv_test_framework.py deleted file mode 100755 index 42f83c64a..000000000 --- a/3rdparty/spirv-tools/test/tools/spirv_test_framework.py +++ /dev/null @@ -1,394 +0,0 @@ -# Copyright (c) 2018 Google LLC -# -# 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. -"""Manages and runs tests from the current working directory. - -This will traverse the current working directory and look for python files that -contain subclasses of SpirvTest. - -If a class has an @inside_spirv_testsuite decorator, an instance of that -class will be created and serve as a test case in that testsuite. The test -case is then run by the following steps: - - 1. A temporary directory will be created. - 2. The spirv_args member variable will be inspected and all placeholders in it - will be expanded by calling instantiate_for_spirv_args() on placeholders. - The transformed list elements are then supplied as arguments to the spirv-* - tool under test. - 3. If the environment member variable exists, its write() method will be - invoked. - 4. All expected_* member variables will be inspected and all placeholders in - them will be expanded by calling instantiate_for_expectation() on those - placeholders. After placeholder expansion, if the expected_* variable is - a list, its element will be joined together with '' to form a single - string. These expected_* variables are to be used by the check_*() methods. - 5. The spirv-* tool will be run with the arguments supplied in spirv_args. - 6. All check_*() member methods will be called by supplying a TestStatus as - argument. Each check_*() method is expected to return a (Success, Message) - pair where Success is a boolean indicating success and Message is an error - message. - 7. If any check_*() method fails, the error message is output and the - current test case fails. - -If --leave-output was not specified, all temporary files and directories will -be deleted. -""" - -import argparse -import fnmatch -import inspect -import os -import shutil -import subprocess -import sys -import tempfile -from collections import defaultdict -from placeholder import PlaceHolder - -EXPECTED_BEHAVIOR_PREFIX = 'expected_' -VALIDATE_METHOD_PREFIX = 'check_' - - -def get_all_variables(instance): - """Returns the names of all the variables in instance.""" - return [v for v in dir(instance) if not callable(getattr(instance, v))] - - -def get_all_methods(instance): - """Returns the names of all methods in instance.""" - return [m for m in dir(instance) if callable(getattr(instance, m))] - - -def get_all_superclasses(cls): - """Returns all superclasses of a given class. Omits root 'object' superclass. - - Returns: - A list of superclasses of the given class. The order guarantees that - * A Base class precedes its derived classes, e.g., for "class B(A)", it - will be [..., A, B, ...]. - * When there are multiple base classes, base classes declared first - precede those declared later, e.g., for "class C(A, B), it will be - [..., A, B, C, ...] - """ - classes = [] - for superclass in cls.__bases__: - for c in get_all_superclasses(superclass): - if c is not object and c not in classes: - classes.append(c) - for superclass in cls.__bases__: - if superclass is not object and superclass not in classes: - classes.append(superclass) - - return classes - - -def get_all_test_methods(test_class): - """Gets all validation methods. - - Returns: - A list of validation methods. The order guarantees that - * A method defined in superclass precedes one defined in subclass, - e.g., for "class A(B)", methods defined in B precedes those defined - in A. - * If a subclass has more than one superclass, e.g., "class C(A, B)", - then methods defined in A precedes those defined in B. - """ - classes = get_all_superclasses(test_class) - classes.append(test_class) - all_tests = [ - m for c in classes for m in get_all_methods(c) - if m.startswith(VALIDATE_METHOD_PREFIX) - ] - unique_tests = [] - for t in all_tests: - if t not in unique_tests: - unique_tests.append(t) - return unique_tests - - -class SpirvTest: - """Base class for spirv test cases. - - Subclasses define test cases' facts (shader source code, spirv command, - result validation), which will be used by the TestCase class for running - tests. Subclasses should define spirv_args (specifying spirv_tool command - arguments), and at least one check_*() method (for result validation) for - a full-fledged test case. All check_*() methods should take a TestStatus - parameter and return a (Success, Message) pair, in which Success is a - boolean indicating success and Message is an error message. The test passes - iff all check_*() methods returns true. - - Often, a test case class will delegate the check_* behaviors by inheriting - from other classes. - """ - - def name(self): - return self.__class__.__name__ - - -class TestStatus: - """A struct for holding run status of a test case.""" - - def __init__(self, test_manager, returncode, stdout, stderr, directory, - inputs, input_filenames): - self.test_manager = test_manager - self.returncode = returncode - # Some of our MacOS bots still run Python 2, so need to be backwards - # compatible here. - if type(stdout) is not str: - if sys.version_info[0] is 2: - self.stdout = stdout.decode('utf-8') - elif sys.version_info[0] is 3: - self.stdout = str(stdout, encoding='utf-8') if stdout is not None else stdout - else: - raise Exception('Unable to determine if running Python 2 or 3 from {}'.format(sys.version_info)) - else: - self.stdout = stdout - - if type(stderr) is not str: - if sys.version_info[0] is 2: - self.stderr = stderr.decode('utf-8') - elif sys.version_info[0] is 3: - self.stderr = str(stderr, encoding='utf-8') if stderr is not None else stderr - else: - raise Exception('Unable to determine if running Python 2 or 3 from {}'.format(sys.version_info)) - else: - self.stderr = stderr - - # temporary directory where the test runs - self.directory = directory - # List of inputs, as PlaceHolder objects. - self.inputs = inputs - # the names of input shader files (potentially including paths) - self.input_filenames = input_filenames - - -class SpirvTestException(Exception): - """SpirvTest exception class.""" - pass - - -def inside_spirv_testsuite(testsuite_name): - """Decorator for subclasses of SpirvTest. - - This decorator checks that a class meets the requirements (see below) - for a test case class, and then puts the class in a certain testsuite. - * The class needs to be a subclass of SpirvTest. - * The class needs to have spirv_args defined as a list. - * The class needs to define at least one check_*() methods. - * All expected_* variables required by check_*() methods can only be - of bool, str, or list type. - * Python runtime will throw an exception if the expected_* member - attributes required by check_*() methods are missing. - """ - - def actual_decorator(cls): - if not inspect.isclass(cls): - raise SpirvTestException('Test case should be a class') - if not issubclass(cls, SpirvTest): - raise SpirvTestException( - 'All test cases should be subclasses of SpirvTest') - if 'spirv_args' not in get_all_variables(cls): - raise SpirvTestException('No spirv_args found in the test case') - if not isinstance(cls.spirv_args, list): - raise SpirvTestException('spirv_args needs to be a list') - if not any( - [m.startswith(VALIDATE_METHOD_PREFIX) for m in get_all_methods(cls)]): - raise SpirvTestException('No check_*() methods found in the test case') - if not all( - [isinstance(v, (bool, str, list)) for v in get_all_variables(cls)]): - raise SpirvTestException( - 'expected_* variables are only allowed to be bool, str, or ' - 'list type.') - cls.parent_testsuite = testsuite_name - return cls - - return actual_decorator - - -class TestManager: - """Manages and runs a set of tests.""" - - def __init__(self, executable_path, assembler_path, disassembler_path): - self.executable_path = executable_path - self.assembler_path = assembler_path - self.disassembler_path = disassembler_path - self.num_successes = 0 - self.num_failures = 0 - self.num_tests = 0 - self.leave_output = False - self.tests = defaultdict(list) - - def notify_result(self, test_case, success, message): - """Call this to notify the manager of the results of a test run.""" - self.num_successes += 1 if success else 0 - self.num_failures += 0 if success else 1 - counter_string = str(self.num_successes + self.num_failures) + '/' + str( - self.num_tests) - print('%-10s %-40s ' % (counter_string, test_case.test.name()) + - ('Passed' if success else '-Failed-')) - if not success: - print(' '.join(test_case.command)) - print(message) - - def add_test(self, testsuite, test): - """Add this to the current list of test cases.""" - self.tests[testsuite].append(TestCase(test, self)) - self.num_tests += 1 - - def run_tests(self): - for suite in self.tests: - print('SPIRV tool test suite: "{suite}"'.format(suite=suite)) - for x in self.tests[suite]: - x.runTest() - - -class TestCase: - """A single test case that runs in its own directory.""" - - def __init__(self, test, test_manager): - self.test = test - self.test_manager = test_manager - self.inputs = [] # inputs, as PlaceHolder objects. - self.file_shaders = [] # filenames of shader files. - self.stdin_shader = None # text to be passed to spirv_tool as stdin - - def setUp(self): - """Creates environment and instantiates placeholders for the test case.""" - - self.directory = tempfile.mkdtemp(dir=os.getcwd()) - spirv_args = self.test.spirv_args - # Instantiate placeholders in spirv_args - self.test.spirv_args = [ - arg.instantiate_for_spirv_args(self) - if isinstance(arg, PlaceHolder) else arg for arg in self.test.spirv_args - ] - # Get all shader files' names - self.inputs = [arg for arg in spirv_args if isinstance(arg, PlaceHolder)] - self.file_shaders = [arg.filename for arg in self.inputs] - - if 'environment' in get_all_variables(self.test): - self.test.environment.write(self.directory) - - expectations = [ - v for v in get_all_variables(self.test) - if v.startswith(EXPECTED_BEHAVIOR_PREFIX) - ] - # Instantiate placeholders in expectations - for expectation_name in expectations: - expectation = getattr(self.test, expectation_name) - if isinstance(expectation, list): - expanded_expections = [ - element.instantiate_for_expectation(self) - if isinstance(element, PlaceHolder) else element - for element in expectation - ] - setattr(self.test, expectation_name, expanded_expections) - elif isinstance(expectation, PlaceHolder): - setattr(self.test, expectation_name, - expectation.instantiate_for_expectation(self)) - - def tearDown(self): - """Removes the directory if we were not instructed to do otherwise.""" - if not self.test_manager.leave_output: - shutil.rmtree(self.directory) - - def runTest(self): - """Sets up and runs a test, reports any failures and then cleans up.""" - self.setUp() - success = False - message = '' - try: - self.command = [self.test_manager.executable_path] - self.command.extend(self.test.spirv_args) - - process = subprocess.Popen( - args=self.command, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=self.directory) - output = process.communicate(self.stdin_shader) - test_status = TestStatus(self.test_manager, process.returncode, output[0], - output[1], self.directory, self.inputs, - self.file_shaders) - run_results = [ - getattr(self.test, test_method)(test_status) - for test_method in get_all_test_methods(self.test.__class__) - ] - success, message = zip(*run_results) - success = all(success) - message = '\n'.join(message) - except Exception as e: - success = False - message = str(e) - self.test_manager.notify_result( - self, success, - message + '\nSTDOUT:\n%s\nSTDERR:\n%s' % (output[0], output[1])) - self.tearDown() - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument( - 'spirv_tool', - metavar='path/to/spirv_tool', - type=str, - nargs=1, - help='Path to the spirv-* tool under test') - parser.add_argument( - 'spirv_as', - metavar='path/to/spirv-as', - type=str, - nargs=1, - help='Path to spirv-as') - parser.add_argument( - 'spirv_dis', - metavar='path/to/spirv-dis', - type=str, - nargs=1, - help='Path to spirv-dis') - parser.add_argument( - '--leave-output', - action='store_const', - const=1, - help='Do not clean up temporary directories') - parser.add_argument( - '--test-dir', nargs=1, help='Directory to gather the tests from') - args = parser.parse_args() - default_path = sys.path - root_dir = os.getcwd() - if args.test_dir: - root_dir = args.test_dir[0] - manager = TestManager(args.spirv_tool[0], args.spirv_as[0], args.spirv_dis[0]) - if args.leave_output: - manager.leave_output = True - for root, _, filenames in os.walk(root_dir): - for filename in fnmatch.filter(filenames, '*.py'): - if filename.endswith('nosetest.py'): - # Skip nose tests, which are for testing functions of - # the test framework. - continue - sys.path = default_path - sys.path.append(root) - mod = __import__(os.path.splitext(filename)[0]) - for _, obj, in inspect.getmembers(mod): - if inspect.isclass(obj) and hasattr(obj, 'parent_testsuite'): - manager.add_test(obj.parent_testsuite, obj()) - manager.run_tests() - if manager.num_failures > 0: - sys.exit(-1) - - -if __name__ == '__main__': - main() diff --git a/3rdparty/spirv-tools/test/tools/spirv_test_framework_unittest.py b/3rdparty/spirv-tools/test/tools/spirv_test_framework_unittest.py deleted file mode 100644 index e64e86c01..000000000 --- a/3rdparty/spirv-tools/test/tools/spirv_test_framework_unittest.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) 2019 Google LLC -# -# 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. -"""Tests for the spirv test framework module.""" - -from spirv_test_framework import get_all_test_methods, get_all_superclasses -import unittest - -# Classes to be used in testing get_all_{superclasses|test_methods}() - - -class Root: - - def check_root(self): - pass - - -class A(Root): - - def check_a(self): - pass - - -class B(Root): - - def check_b(self): - pass - - -class C(Root): - - def check_c(self): - pass - - -class D(Root): - - def check_d(self): - pass - - -class E(Root): - - def check_e(self): - pass - - -class H(B, C, D): - - def check_h(self): - pass - - -class I(E): - - def check_i(self): - pass - - -class O(H, I): - - def check_o(self): - pass - - -class U(A, O): - - def check_u(self): - pass - - -class X(U, A): - - def check_x(self): - pass - - -class R1: - - def check_r1(self): - pass - - -class R2: - - def check_r2(self): - pass - - -class Multi(R1, R2): - - def check_multi(self): - pass - - -class TestSpirvTestFramework(unittest.TestCase): - def test_get_all_superclasses(self): - self.assertEqual(get_all_superclasses(A), [Root]) - self.assertEqual(get_all_superclasses(B), [Root]) - self.assertEqual(get_all_superclasses(C), [Root]) - self.assertEqual(get_all_superclasses(D), [Root]) - self.assertEqual(get_all_superclasses(E), [Root]) - - self.assertEqual(get_all_superclasses(H), [Root, B, C, D]) - self.assertEqual(get_all_superclasses(I), [Root, E]) - - self.assertEqual(get_all_superclasses(O), [Root, B, C, D, E, H, I]) - - self.assertEqual(get_all_superclasses( - U), [Root, B, C, D, E, H, I, A, O]) - self.assertEqual(get_all_superclasses( - X), [Root, B, C, D, E, H, I, A, O, U]) - - self.assertEqual(get_all_superclasses(Multi), [R1, R2]) - - def test_get_all_methods(self): - self.assertEqual(get_all_test_methods(A), ['check_root', 'check_a']) - self.assertEqual(get_all_test_methods(B), ['check_root', 'check_b']) - self.assertEqual(get_all_test_methods(C), ['check_root', 'check_c']) - self.assertEqual(get_all_test_methods(D), ['check_root', 'check_d']) - self.assertEqual(get_all_test_methods(E), ['check_root', 'check_e']) - - self.assertEqual( - get_all_test_methods(H), - ['check_root', 'check_b', 'check_c', 'check_d', 'check_h']) - self.assertEqual(get_all_test_methods( - I), ['check_root', 'check_e', 'check_i']) - - self.assertEqual( - get_all_test_methods(O), [ - 'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h', - 'check_i', 'check_o' - ]) - - self.assertEqual( - get_all_test_methods(U), [ - 'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h', - 'check_i', 'check_a', 'check_o', 'check_u' - ]) - - self.assertEqual( - get_all_test_methods(X), [ - 'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h', - 'check_i', 'check_a', 'check_o', 'check_u', 'check_x' - ]) - - self.assertEqual( - get_all_test_methods(Multi), ['check_r1', 'check_r2', 'check_multi']) diff --git a/3rdparty/spirv-tools/test/unit_spirv.cpp b/3rdparty/spirv-tools/test/unit_spirv.cpp deleted file mode 100644 index 085443948..000000000 --- a/3rdparty/spirv-tools/test/unit_spirv.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "test/unit_spirv.h" - -#include "gmock/gmock.h" -#include "source/util/string_utils.h" -#include "test/test_fixture.h" - -namespace spvtools { -namespace { - -using utils::MakeVector; -using ::testing::Eq; -using Words = std::vector; - -TEST(MakeVector, Samples) { - EXPECT_THAT(MakeVector(""), Eq(Words{0})); - EXPECT_THAT(MakeVector("a"), Eq(Words{0x0061})); - EXPECT_THAT(MakeVector("ab"), Eq(Words{0x006261})); - EXPECT_THAT(MakeVector("abc"), Eq(Words{0x00636261})); - EXPECT_THAT(MakeVector("abcd"), Eq(Words{0x64636261, 0x00})); - EXPECT_THAT(MakeVector("abcde"), Eq(Words{0x64636261, 0x0065})); -} - -TEST(WordVectorPrintTo, PreservesFlagsAndFill) { - std::stringstream s; - s << std::setw(4) << std::oct << std::setfill('x') << 8 << " "; - spvtest::PrintTo(spvtest::WordVector({10, 16}), &s); - // The octal setting and fill character should be preserved - // from before the PrintTo. - // Width is reset after each emission of a regular scalar type. - // So set it explicitly again. - s << std::setw(4) << 9; - - EXPECT_THAT(s.str(), Eq("xx10 0x0000000a 0x00000010 xx11")); -} - -TEST_P(RoundTripTest, Sample) { - EXPECT_THAT(EncodeAndDecodeSuccessfully(GetParam()), Eq(GetParam())) - << GetParam(); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/unit_spirv.h b/3rdparty/spirv-tools/test/unit_spirv.h deleted file mode 100644 index 32646620d..000000000 --- a/3rdparty/spirv-tools/test/unit_spirv.h +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -#ifndef TEST_UNIT_SPIRV_H_ -#define TEST_UNIT_SPIRV_H_ - -#include - -#include -#include -#include - -#include "gtest/gtest.h" -#include "source/assembly_grammar.h" -#include "source/binary.h" -#include "source/diagnostic.h" -#include "source/enum_set.h" -#include "source/opcode.h" -#include "source/spirv_endian.h" -#include "source/text.h" -#include "source/text_handler.h" -#include "source/val/validate.h" -#include "spirv-tools/libspirv.h" - -#ifdef __ANDROID__ -#include -namespace std { -template -std::string to_string(const T& val) { - std::ostringstream os; - os << val; - return os.str(); -} -} // namespace std -#endif - -// Determine endianness & predicate tests on it -enum { - I32_ENDIAN_LITTLE = 0x03020100ul, - I32_ENDIAN_BIG = 0x00010203ul, -}; - -static const union { - unsigned char bytes[4]; - uint32_t value; -} o32_host_order = {{0, 1, 2, 3}}; -#define I32_ENDIAN_HOST (o32_host_order.value) - -// A namespace for utilities used in SPIR-V Tools unit tests. -namespace spvtest { - -class WordVector; - -// Emits the given word vector to the given stream. -// This function can be used by the gtest value printer. -void PrintTo(const WordVector& words, ::std::ostream* os); - -// A proxy class to allow us to easily write out vectors of SPIR-V words. -class WordVector { - public: - explicit WordVector(const std::vector& val) : value_(val) {} - explicit WordVector(const spv_binary_t& binary) - : value_(binary.code, binary.code + binary.wordCount) {} - - // Returns the underlying vector. - const std::vector& value() const { return value_; } - - // Returns the string representation of this word vector. - std::string str() const { - std::ostringstream os; - PrintTo(*this, &os); - return os.str(); - } - - private: - const std::vector value_; -}; - -inline void PrintTo(const WordVector& words, ::std::ostream* os) { - size_t count = 0; - const auto saved_flags = os->flags(); - const auto saved_fill = os->fill(); - for (uint32_t value : words.value()) { - *os << "0x" << std::setw(8) << std::setfill('0') << std::hex << value - << " "; - if (count++ % 8 == 7) { - *os << std::endl; - } - } - os->flags(saved_flags); - os->fill(saved_fill); -} - -// Returns a vector of words representing a single instruction with the -// given opcode and operand words as a vector. -inline std::vector MakeInstruction( - SpvOp opcode, const std::vector& args) { - std::vector result{ - spvOpcodeMake(uint16_t(args.size() + 1), opcode)}; - result.insert(result.end(), args.begin(), args.end()); - return result; -} - -// Returns a vector of words representing a single instruction with the -// given opcode and whose operands are the concatenation of the two given -// argument lists. -inline std::vector MakeInstruction( - SpvOp opcode, std::vector args, - const std::vector& extra_args) { - args.insert(args.end(), extra_args.begin(), extra_args.end()); - return MakeInstruction(opcode, args); -} - -// Returns the vector of words representing the concatenation -// of all input vectors. -inline std::vector Concatenate( - const std::vector>& instructions) { - std::vector result; - for (const auto& instruction : instructions) { - result.insert(result.end(), instruction.begin(), instruction.end()); - } - return result; -} - -// A type for easily creating spv_text_t values, with an implicit conversion to -// spv_text. -struct AutoText { - explicit AutoText(const std::string& value) - : str(value), text({str.data(), str.size()}) {} - operator spv_text() { return &text; } - std::string str; - spv_text_t text; -}; - -// An example case for an enumerated value, optionally with operands. -template -class EnumCase { - public: - EnumCase() = default; // Required by ::testing::Combine(). - EnumCase(E val, std::string enum_name, std::vector ops = {}) - : enum_value_(val), name_(enum_name), operands_(ops) {} - // Returns the enum value as a uint32_t. - uint32_t value() const { return static_cast(enum_value_); } - // Returns the name of the enumerant. - const std::string& name() const { return name_; } - // Returns a reference to the operands. - const std::vector& operands() const { return operands_; } - - private: - E enum_value_; - std::string name_; - std::vector operands_; -}; - -// Returns a string with num_4_byte_chars Unicode characters, -// each of which has a 4-byte UTF-8 encoding. -inline std::string MakeLongUTF8String(size_t num_4_byte_chars) { - // An example of a longest valid UTF-8 character. - // Be explicit about the character type because Microsoft compilers can - // otherwise interpret the character string as being over wide (16-bit) - // characters. Ideally, we would just use a C++11 UTF-8 string literal, - // but we want to support older Microsoft compilers. - const std::basic_string earth_africa("\xF0\x9F\x8C\x8D"); - EXPECT_EQ(4u, earth_africa.size()); - - std::string result; - result.reserve(num_4_byte_chars * 4); - for (size_t i = 0; i < num_4_byte_chars; i++) { - result += earth_africa; - } - EXPECT_EQ(4 * num_4_byte_chars, result.size()); - return result; -} - -// Returns a vector of all valid target environment enums. -inline std::vector AllTargetEnvironments() { - return { - SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, - SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_1_2, - SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0, - SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1, - SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2, - SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0, - SPV_ENV_OPENGL_4_1, SPV_ENV_OPENGL_4_2, - SPV_ENV_OPENGL_4_3, SPV_ENV_OPENGL_4_5, - SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, - SPV_ENV_VULKAN_1_1, SPV_ENV_WEBGPU_0, - }; -} - -// Returns the capabilities in a CapabilitySet as an ordered vector. -inline std::vector ElementsIn( - const spvtools::CapabilitySet& capabilities) { - std::vector result; - capabilities.ForEach([&result](SpvCapability c) { result.push_back(c); }); - return result; -} - -} // namespace spvtest -#endif // TEST_UNIT_SPIRV_H_ diff --git a/3rdparty/spirv-tools/test/util/CMakeLists.txt b/3rdparty/spirv-tools/test/util/CMakeLists.txt deleted file mode 100644 index 6679dba7c..000000000 --- a/3rdparty/spirv-tools/test/util/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2017 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. - -add_spvtools_unittest(TARGET utils - SRCS ilist_test.cpp - bit_vector_test.cpp - bitutils_test.cpp - small_vector_test.cpp - LIBS SPIRV-Tools-opt -) diff --git a/3rdparty/spirv-tools/test/util/bit_vector_test.cpp b/3rdparty/spirv-tools/test/util/bit_vector_test.cpp deleted file mode 100644 index 8d967f8f9..000000000 --- a/3rdparty/spirv-tools/test/util/bit_vector_test.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" - -#include "source/util/bit_vector.h" - -namespace spvtools { -namespace utils { -namespace { - -using BitVectorTest = ::testing::Test; - -TEST(BitVectorTest, Initialize) { - BitVector bvec; - - // Checks that all values are 0. Also tests checking a bit past the end of - // the vector containing the bits. - for (int i = 1; i < 10000; i *= 2) { - EXPECT_FALSE(bvec.Get(i)); - } -} - -TEST(BitVectorTest, Set) { - BitVector bvec; - - // Since 10,000 is larger than the initial size, this tests the resizing - // code. - for (int i = 3; i < 10000; i *= 2) { - bvec.Set(i); - } - - // Check that bits that were not set are 0. - for (int i = 1; i < 10000; i *= 2) { - EXPECT_FALSE(bvec.Get(i)); - } - - // Check that bits that were set are 1. - for (int i = 3; i < 10000; i *= 2) { - EXPECT_TRUE(bvec.Get(i)); - } -} - -TEST(BitVectorTest, SetReturnValue) { - BitVector bvec; - - // Make sure |Set| returns false when the bit was not set. - for (int i = 3; i < 10000; i *= 2) { - EXPECT_FALSE(bvec.Set(i)); - } - - // Make sure |Set| returns true when the bit was already set. - for (int i = 3; i < 10000; i *= 2) { - EXPECT_TRUE(bvec.Set(i)); - } -} - -TEST(BitVectorTest, Clear) { - BitVector bvec; - for (int i = 3; i < 10000; i *= 2) { - bvec.Set(i); - } - - // Check that the bits were properly set. - for (int i = 3; i < 10000; i *= 2) { - EXPECT_TRUE(bvec.Get(i)); - } - - // Clear all of the bits except for bit 3. - for (int i = 6; i < 10000; i *= 2) { - bvec.Clear(i); - } - - // Make sure bit 3 was not cleared. - EXPECT_TRUE(bvec.Get(3)); - - // Make sure all of the other bits that were set have been cleared. - for (int i = 6; i < 10000; i *= 2) { - EXPECT_FALSE(bvec.Get(i)); - } -} - -TEST(BitVectorTest, ClearReturnValue) { - BitVector bvec; - for (int i = 3; i < 10000; i *= 2) { - bvec.Set(i); - } - - // Make sure |Clear| returns true if the bit was set. - for (int i = 3; i < 10000; i *= 2) { - EXPECT_TRUE(bvec.Clear(i)); - } - - // Make sure |Clear| returns false if the bit was not set. - for (int i = 3; i < 10000; i *= 2) { - EXPECT_FALSE(bvec.Clear(i)); - } -} - -TEST(BitVectorTest, SimpleOrTest) { - BitVector bvec1; - bvec1.Set(3); - bvec1.Set(4); - - BitVector bvec2; - bvec2.Set(2); - bvec2.Set(4); - - // Check that |bvec1| changed when doing the |Or| operation. - EXPECT_TRUE(bvec1.Or(bvec2)); - - // Check that the values are all correct. - EXPECT_FALSE(bvec1.Get(0)); - EXPECT_FALSE(bvec1.Get(1)); - EXPECT_TRUE(bvec1.Get(2)); - EXPECT_TRUE(bvec1.Get(3)); - EXPECT_TRUE(bvec1.Get(4)); -} - -TEST(BitVectorTest, ResizingOrTest) { - BitVector bvec1; - bvec1.Set(3); - bvec1.Set(4); - - BitVector bvec2; - bvec2.Set(10000); - - // Similar to above except with a large value to test resizing. - EXPECT_TRUE(bvec1.Or(bvec2)); - EXPECT_FALSE(bvec1.Get(0)); - EXPECT_FALSE(bvec1.Get(1)); - EXPECT_FALSE(bvec1.Get(2)); - EXPECT_TRUE(bvec1.Get(3)); - EXPECT_TRUE(bvec1.Get(10000)); -} - -TEST(BitVectorTest, SubsetOrTest) { - BitVector bvec1; - bvec1.Set(3); - bvec1.Set(4); - - BitVector bvec2; - bvec2.Set(3); - - // |Or| returns false if |bvec1| does not change. - EXPECT_FALSE(bvec1.Or(bvec2)); -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/util/bitutils_test.cpp b/3rdparty/spirv-tools/test/util/bitutils_test.cpp deleted file mode 100644 index 3be7ed269..000000000 --- a/3rdparty/spirv-tools/test/util/bitutils_test.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2019 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 "source/util/bitutils.h" - -#include "gmock/gmock.h" - -namespace spvtools { -namespace utils { -namespace { - -using BitUtilsTest = ::testing::Test; - -TEST(BitUtilsTest, MutateBitsWholeWord) { - const uint32_t zero_u32 = 0; - const uint32_t max_u32 = ~0; - - EXPECT_EQ(MutateBits(zero_u32, 0, 0, false), zero_u32); - EXPECT_EQ(MutateBits(max_u32, 0, 0, false), max_u32); - EXPECT_EQ(MutateBits(zero_u32, 0, 32, false), zero_u32); - EXPECT_EQ(MutateBits(zero_u32, 0, 32, true), max_u32); - EXPECT_EQ(MutateBits(max_u32, 0, 32, true), max_u32); - EXPECT_EQ(MutateBits(max_u32, 0, 32, false), zero_u32); -} - -TEST(BitUtilsTest, MutateBitsLow) { - const uint32_t zero_u32 = 0; - const uint32_t one_u32 = 1; - const uint32_t max_u32 = ~0; - - EXPECT_EQ(MutateBits(zero_u32, 0, 1, false), zero_u32); - EXPECT_EQ(MutateBits(zero_u32, 0, 1, true), one_u32); - EXPECT_EQ(MutateBits(max_u32, 0, 1, true), max_u32); - EXPECT_EQ(MutateBits(one_u32, 0, 32, false), zero_u32); - EXPECT_EQ(MutateBits(one_u32, 0, 1, true), one_u32); - EXPECT_EQ(MutateBits(one_u32, 0, 1, false), zero_u32); - EXPECT_EQ(MutateBits(zero_u32, 0, 3, true), uint32_t(7)); - EXPECT_EQ(MutateBits(uint32_t(7), 0, 2, false), uint32_t(4)); -} - -TEST(BitUtilsTest, MutateBitsHigh) { - const uint8_t zero_u8 = 0; - const uint8_t one_u8 = 1; - const uint8_t max_u8 = 255; - - EXPECT_EQ(MutateBits(zero_u8, 7, 0, true), zero_u8); - EXPECT_EQ(MutateBits(zero_u8, 7, 1, true), uint8_t(128)); - EXPECT_EQ(MutateBits(one_u8, 7, 1, true), uint8_t(129)); - EXPECT_EQ(MutateBits(max_u8, 7, 1, true), max_u8); - EXPECT_EQ(MutateBits(max_u8, 7, 1, false), uint8_t(127)); - EXPECT_EQ(MutateBits(max_u8, 6, 2, true), max_u8); - EXPECT_EQ(MutateBits(max_u8, 6, 2, false), uint8_t(63)); -} - -TEST(BitUtilsTest, MutateBitsUint8Mid) { - const uint8_t zero_u8 = 0; - const uint8_t max_u8 = 255; - - EXPECT_EQ(MutateBits(zero_u8, 1, 2, true), uint8_t(6)); - EXPECT_EQ(MutateBits(max_u8, 1, 2, true), max_u8); - EXPECT_EQ(MutateBits(max_u8, 1, 2, false), uint8_t(0xF9)); - EXPECT_EQ(MutateBits(zero_u8, 2, 3, true), uint8_t(0x1C)); -} - -TEST(BitUtilsTest, MutateBitsUint64Mid) { - const uint64_t zero_u64 = 0; - const uint64_t max_u64 = ~zero_u64; - - EXPECT_EQ(MutateBits(zero_u64, 1, 2, true), uint64_t(6)); - EXPECT_EQ(MutateBits(max_u64, 1, 2, true), max_u64); - EXPECT_EQ(MutateBits(max_u64, 1, 2, false), uint64_t(0xFFFFFFFFFFFFFFF9)); - EXPECT_EQ(MutateBits(zero_u64, 2, 3, true), uint64_t(0x000000000000001C)); - EXPECT_EQ(MutateBits(zero_u64, 2, 35, true), uint64_t(0x0000001FFFFFFFFC)); - EXPECT_EQ(MutateBits(zero_u64, 36, 4, true), uint64_t(0x000000F000000000)); - EXPECT_EQ(MutateBits(max_u64, 36, 4, false), uint64_t(0xFFFFFF0FFFFFFFFF)); -} - -TEST(BitUtilsTest, SetHighBitsUint32) { - const uint32_t zero_u32 = 0; - const uint32_t one_u32 = 1; - const uint32_t max_u32 = ~zero_u32; - - EXPECT_EQ(SetHighBits(zero_u32, 0), zero_u32); - EXPECT_EQ(SetHighBits(zero_u32, 1), 0x80000000); - EXPECT_EQ(SetHighBits(one_u32, 1), 0x80000001); - EXPECT_EQ(SetHighBits(one_u32, 2), 0xC0000001); - EXPECT_EQ(SetHighBits(zero_u32, 31), 0xFFFFFFFE); - EXPECT_EQ(SetHighBits(zero_u32, 32), max_u32); - EXPECT_EQ(SetHighBits(max_u32, 32), max_u32); -} - -TEST(BitUtilsTest, ClearHighBitsUint32) { - const uint32_t zero_u32 = 0; - const uint32_t one_u32 = 1; - const uint32_t max_u32 = ~zero_u32; - - EXPECT_EQ(ClearHighBits(zero_u32, 0), zero_u32); - EXPECT_EQ(ClearHighBits(zero_u32, 1), zero_u32); - EXPECT_EQ(ClearHighBits(one_u32, 1), one_u32); - EXPECT_EQ(ClearHighBits(one_u32, 31), one_u32); - EXPECT_EQ(ClearHighBits(one_u32, 32), zero_u32); - EXPECT_EQ(ClearHighBits(max_u32, 0), max_u32); - EXPECT_EQ(ClearHighBits(max_u32, 1), 0x7FFFFFFF); - EXPECT_EQ(ClearHighBits(max_u32, 2), 0x3FFFFFFF); - EXPECT_EQ(ClearHighBits(max_u32, 31), one_u32); - EXPECT_EQ(ClearHighBits(max_u32, 32), zero_u32); -} - -TEST(BitUtilsTest, IsBitSetAtPositionZero) { - const uint32_t zero_u32 = 0; - for (size_t i = 0; i != 32; ++i) { - EXPECT_FALSE(IsBitAtPositionSet(zero_u32, i)); - } - - const uint8_t zero_u8 = 0; - for (size_t i = 0; i != 8; ++i) { - EXPECT_FALSE(IsBitAtPositionSet(zero_u8, i)); - } - - const uint64_t zero_u64 = 0; - for (size_t i = 0; i != 64; ++i) { - EXPECT_FALSE(IsBitAtPositionSet(zero_u64, i)); - } -} - -TEST(BitUtilsTest, IsBitSetAtPositionOne) { - const uint32_t one_u32 = 1; - for (size_t i = 0; i != 32; ++i) { - if (i == 0) { - EXPECT_TRUE(IsBitAtPositionSet(one_u32, i)); - } else { - EXPECT_FALSE(IsBitAtPositionSet(one_u32, i)); - } - } - - const uint32_t two_to_17_u32 = 1 << 17; - for (size_t i = 0; i != 32; ++i) { - if (i == 17) { - EXPECT_TRUE(IsBitAtPositionSet(two_to_17_u32, i)); - } else { - EXPECT_FALSE(IsBitAtPositionSet(two_to_17_u32, i)); - } - } - - const uint8_t two_to_4_u8 = 1 << 4; - for (size_t i = 0; i != 8; ++i) { - if (i == 4) { - EXPECT_TRUE(IsBitAtPositionSet(two_to_4_u8, i)); - } else { - EXPECT_FALSE(IsBitAtPositionSet(two_to_4_u8, i)); - } - } - - const uint64_t two_to_55_u64 = uint64_t(1) << 55; - for (size_t i = 0; i != 64; ++i) { - if (i == 55) { - EXPECT_TRUE(IsBitAtPositionSet(two_to_55_u64, i)); - } else { - EXPECT_FALSE(IsBitAtPositionSet(two_to_55_u64, i)); - } - } -} - -TEST(BitUtilsTest, IsBitSetAtPositionAll) { - const uint32_t max_u32 = ~0; - for (size_t i = 0; i != 32; ++i) { - EXPECT_TRUE(IsBitAtPositionSet(max_u32, i)); - } - - const uint32_t max_u8 = ~uint8_t(0); - for (size_t i = 0; i != 8; ++i) { - EXPECT_TRUE(IsBitAtPositionSet(max_u8, i)); - } - - const uint64_t max_u64 = ~uint64_t(0); - for (size_t i = 0; i != 64; ++i) { - EXPECT_TRUE(IsBitAtPositionSet(max_u64, i)); - } -} -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/util/ilist_test.cpp b/3rdparty/spirv-tools/test/util/ilist_test.cpp deleted file mode 100644 index 4a546f993..000000000 --- a/3rdparty/spirv-tools/test/util/ilist_test.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/util/ilist.h" - -namespace spvtools { -namespace utils { -namespace { - -using ::testing::ElementsAre; -using IListTest = ::testing::Test; - -class TestNode : public IntrusiveNodeBase { - public: - TestNode() : IntrusiveNodeBase() {} - int data_; -}; - -class TestList : public IntrusiveList { - public: - TestList() = default; - TestList(TestList&& that) : IntrusiveList(std::move(that)) {} - TestList& operator=(TestList&& that) { - static_cast&>(*this) = - static_cast&&>(that); - return *this; - } -}; - -// This test checks the push_back method, as well as using an iterator to -// traverse the list from begin() to end(). This implicitly test the -// PreviousNode and NextNode functions. -TEST(IListTest, PushBack) { - TestNode nodes[10]; - TestList list; - for (int i = 0; i < 10; i++) { - nodes[i].data_ = i; - list.push_back(&nodes[i]); - } - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); -} - -// Returns a list containing the values 0 to n-1 using the first n elements of -// nodes to build the list. -TestList BuildList(TestNode nodes[], int n) { - TestList list; - for (int i = 0; i < n; i++) { - nodes[i].data_ = i; - list.push_back(&nodes[i]); - } - return list; -} - -// Test decrementing begin() -TEST(IListTest, DecrementingBegin) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 10); - EXPECT_EQ(--list.begin(), list.end()); -} - -// Test incrementing end() -TEST(IListTest, IncrementingEnd1) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 10); - EXPECT_EQ((++list.end())->data_, 0); -} - -// Test incrementing end() should equal begin() -TEST(IListTest, IncrementingEnd2) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 10); - EXPECT_EQ(++list.end(), list.begin()); -} - -// Test decrementing end() -TEST(IListTest, DecrementingEnd) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 10); - EXPECT_EQ((--list.end())->data_, 9); -} - -// Test the move constructor for the list class. -TEST(IListTest, MoveConstructor) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 10); - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); -} - -// Using a const list so we can test the const_iterator. -TEST(IListTest, ConstIterator) { - TestNode nodes[10]; - const TestList list = BuildList(nodes, 10); - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); -} - -// Uses the move assignement instead of the move constructor. -TEST(IListTest, MoveAssignment) { - TestNode nodes[10]; - TestList list; - list = BuildList(nodes, 10); - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); -} - -// Test inserting a new element at the end of a list using the IntrusiveNodeBase -// "InsertAfter" function. -TEST(IListTest, InsertAfter1) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 5); - - nodes[5].data_ = 5; - nodes[5].InsertAfter(&nodes[4]); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5)); -} - -// Test inserting a new element in the middle of a list using the -// IntrusiveNodeBase "InsertAfter" function. -TEST(IListTest, InsertAfter2) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 5); - - nodes[5].data_ = 5; - nodes[5].InsertAfter(&nodes[2]); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 5, 3, 4)); -} - -// Test moving an element already in the list in the middle of a list using the -// IntrusiveNodeBase "InsertAfter" function. -TEST(IListTest, MoveUsingInsertAfter1) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - nodes[5].InsertAfter(&nodes[2]); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 5, 3, 4)); -} - -// Move the element at the start of the list into the middle. -TEST(IListTest, MoveUsingInsertAfter2) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - nodes[0].InsertAfter(&nodes[2]); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(1, 2, 0, 3, 4, 5)); -} - -// Move an element in the middle of the list to the end. -TEST(IListTest, MoveUsingInsertAfter3) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - nodes[2].InsertAfter(&nodes[5]); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 3, 4, 5, 2)); -} - -// Removing an element from the middle of a list. -TEST(IListTest, Remove1) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - nodes[2].RemoveFromList(); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 3, 4, 5)); -} - -// Removing an element from the beginning of the list. -TEST(IListTest, Remove2) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - nodes[0].RemoveFromList(); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(1, 2, 3, 4, 5)); -} - -// Removing the last element of a list. -TEST(IListTest, Remove3) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - nodes[5].RemoveFromList(); - - std::vector output; - for (auto& i : list) output.push_back(i.data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4)); -} - -// Test that operator== and operator!= work properly for the iterator class. -TEST(IListTest, IteratorEqual) { - TestNode nodes[10]; - TestList list = BuildList(nodes, 6); - - std::vector output; - for (auto i = list.begin(); i != list.end(); ++i) - for (auto j = list.begin(); j != list.end(); ++j) - if (i == j) output.push_back(i->data_); - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5)); -} - -// Test MoveBefore. Moving into middle of a list. -TEST(IListTest, MoveBefore1) { - TestNode nodes[10]; - TestList list1 = BuildList(nodes, 6); - TestList list2 = BuildList(nodes + 6, 3); - - TestList::iterator insertion_point = list1.begin(); - ++insertion_point; - insertion_point.MoveBefore(&list2); - - std::vector output; - for (auto i = list1.begin(); i != list1.end(); ++i) { - output.push_back(i->data_); - } - - EXPECT_THAT(output, ElementsAre(0, 0, 1, 2, 1, 2, 3, 4, 5)); -} - -// Test MoveBefore. Moving to the start of a list. -TEST(IListTest, MoveBefore2) { - TestNode nodes[10]; - TestList list1 = BuildList(nodes, 6); - TestList list2 = BuildList(nodes + 6, 3); - - TestList::iterator insertion_point = list1.begin(); - insertion_point.MoveBefore(&list2); - - std::vector output; - for (auto i = list1.begin(); i != list1.end(); ++i) { - output.push_back(i->data_); - } - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 0, 1, 2, 3, 4, 5)); -} - -// Test MoveBefore. Moving to the end of a list. -TEST(IListTest, MoveBefore3) { - TestNode nodes[10]; - TestList list1 = BuildList(nodes, 6); - TestList list2 = BuildList(nodes + 6, 3); - - TestList::iterator insertion_point = list1.end(); - insertion_point.MoveBefore(&list2); - - std::vector output; - for (auto i = list1.begin(); i != list1.end(); ++i) { - output.push_back(i->data_); - } - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 0, 1, 2)); -} - -// Test MoveBefore. Moving an empty list. -TEST(IListTest, MoveBefore4) { - TestNode nodes[10]; - TestList list1 = BuildList(nodes, 6); - TestList list2; - - TestList::iterator insertion_point = list1.end(); - insertion_point.MoveBefore(&list2); - - std::vector output; - for (auto i = list1.begin(); i != list1.end(); ++i) { - output.push_back(i->data_); - } - - EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5)); -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/util/small_vector_test.cpp b/3rdparty/spirv-tools/test/util/small_vector_test.cpp deleted file mode 100644 index 01d7df185..000000000 --- a/3rdparty/spirv-tools/test/util/small_vector_test.cpp +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "source/util/small_vector.h" - -namespace spvtools { -namespace utils { -namespace { - -using SmallVectorTest = ::testing::Test; - -TEST(SmallVectorTest, Initialize_default) { - SmallVector vec; - - EXPECT_TRUE(vec.empty()); - EXPECT_EQ(vec.size(), 0); - EXPECT_EQ(vec.begin(), vec.end()); -} - -TEST(SmallVectorTest, Initialize_list1) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_FALSE(vec.empty()); - EXPECT_EQ(vec.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec.size(); ++i) { - EXPECT_EQ(vec[i], result[i]); - } -} - -TEST(SmallVectorTest, Initialize_list2) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_FALSE(vec.empty()); - EXPECT_EQ(vec.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec.size(); ++i) { - EXPECT_EQ(vec[i], result[i]); - } -} - -TEST(SmallVectorTest, Initialize_copy1) { - SmallVector vec1 = {0, 1, 2, 3}; - SmallVector vec2(vec1); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - - EXPECT_EQ(vec1, vec2); -} - -TEST(SmallVectorTest, Initialize_copy2) { - SmallVector vec1 = {0, 1, 2, 3}; - SmallVector vec2(vec1); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - - EXPECT_EQ(vec1, vec2); -} - -TEST(SmallVectorTest, Initialize_copy_vec1) { - std::vector vec1 = {0, 1, 2, 3}; - SmallVector vec2(vec1); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - - EXPECT_EQ(vec1, vec2); -} - -TEST(SmallVectorTest, Initialize_copy_vec2) { - std::vector vec1 = {0, 1, 2, 3}; - SmallVector vec2(vec1); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - - EXPECT_EQ(vec1, vec2); -} - -TEST(SmallVectorTest, Initialize_move1) { - SmallVector vec1 = {0, 1, 2, 3}; - SmallVector vec2(std::move(vec1)); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - EXPECT_TRUE(vec1.empty()); -} - -TEST(SmallVectorTest, Initialize_move2) { - SmallVector vec1 = {0, 1, 2, 3}; - SmallVector vec2(std::move(vec1)); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - EXPECT_TRUE(vec1.empty()); -} - -TEST(SmallVectorTest, Initialize_move_vec1) { - std::vector vec1 = {0, 1, 2, 3}; - SmallVector vec2(std::move(vec1)); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - EXPECT_TRUE(vec1.empty()); -} - -TEST(SmallVectorTest, Initialize_move_vec2) { - std::vector vec1 = {0, 1, 2, 3}; - SmallVector vec2(std::move(vec1)); - - EXPECT_EQ(vec2.size(), 4); - - uint32_t result[] = {0, 1, 2, 3}; - for (uint32_t i = 0; i < vec2.size(); ++i) { - EXPECT_EQ(vec2[i], result[i]); - } - EXPECT_TRUE(vec1.empty()); -} - -TEST(SmallVectorTest, Initialize_iterators1) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 4); - uint32_t result[] = {0, 1, 2, 3}; - - uint32_t i = 0; - for (uint32_t p : vec) { - EXPECT_EQ(p, result[i]); - i++; - } -} - -TEST(SmallVectorTest, Initialize_iterators2) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 4); - uint32_t result[] = {0, 1, 2, 3}; - - uint32_t i = 0; - for (uint32_t p : vec) { - EXPECT_EQ(p, result[i]); - i++; - } -} - -TEST(SmallVectorTest, Initialize_iterators3) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 4); - uint32_t result[] = {0, 1, 2, 3}; - - uint32_t i = 0; - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - EXPECT_EQ(*it, result[i]); - i++; - } -} - -TEST(SmallVectorTest, Initialize_iterators4) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 4); - uint32_t result[] = {0, 1, 2, 3}; - - uint32_t i = 0; - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - EXPECT_EQ(*it, result[i]); - i++; - } -} - -TEST(SmallVectorTest, Initialize_iterators_write1) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 4); - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - *it *= 2; - } - - uint32_t result[] = {0, 2, 4, 6}; - - uint32_t i = 0; - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - EXPECT_EQ(*it, result[i]); - i++; - } -} - -TEST(SmallVectorTest, Initialize_iterators_write2) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 4); - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - *it *= 2; - } - - uint32_t result[] = {0, 2, 4, 6}; - - uint32_t i = 0; - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - EXPECT_EQ(*it, result[i]); - i++; - } -} - -TEST(SmallVectorTest, Initialize_front) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.front(), 0); - for (SmallVector::iterator it = vec.begin(); it != vec.end(); - ++it) { - *it += 2; - } - EXPECT_EQ(vec.front(), 2); -} - -TEST(SmallVectorTest, Erase_element_front1) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.front(), 0); - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin()); - EXPECT_EQ(vec.front(), 1); - EXPECT_EQ(vec.size(), 3); -} - -TEST(SmallVectorTest, Erase_element_front2) { - SmallVector vec = {0, 1, 2, 3}; - - EXPECT_EQ(vec.front(), 0); - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin()); - EXPECT_EQ(vec.front(), 1); - EXPECT_EQ(vec.size(), 3); -} - -TEST(SmallVectorTest, Erase_element_back1) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {0, 1, 2}; - - EXPECT_EQ(vec[3], 3); - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin() + 3); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_element_back2) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {0, 1, 2}; - - EXPECT_EQ(vec[3], 3); - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin() + 3); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_element_middle1) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {0, 1, 3}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin() + 2); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_element_middle2) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {0, 1, 3}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin() + 2); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_range_1) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin(), vec.end()); - EXPECT_EQ(vec.size(), 0); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_range_2) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin(), vec.end()); - EXPECT_EQ(vec.size(), 0); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_range_3) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {2, 3}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin(), vec.begin() + 2); - EXPECT_EQ(vec.size(), 2); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_range_4) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {2, 3}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin(), vec.begin() + 2); - EXPECT_EQ(vec.size(), 2); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_range_5) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {0, 3}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin() + 1, vec.begin() + 3); - EXPECT_EQ(vec.size(), 2); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Erase_range_6) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {0, 3}; - - EXPECT_EQ(vec.size(), 4); - vec.erase(vec.begin() + 1, vec.begin() + 3); - EXPECT_EQ(vec.size(), 2); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Push_back) { - SmallVector vec; - SmallVector result = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 0); - vec.push_back(0); - EXPECT_EQ(vec.size(), 1); - vec.push_back(1); - EXPECT_EQ(vec.size(), 2); - vec.push_back(2); - EXPECT_EQ(vec.size(), 3); - vec.push_back(3); - EXPECT_EQ(vec.size(), 4); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Emplace_back) { - SmallVector vec; - SmallVector result = {0, 1, 2, 3}; - - EXPECT_EQ(vec.size(), 0); - vec.emplace_back(0); - EXPECT_EQ(vec.size(), 1); - vec.emplace_back(1); - EXPECT_EQ(vec.size(), 2); - vec.emplace_back(2); - EXPECT_EQ(vec.size(), 3); - vec.emplace_back(3); - EXPECT_EQ(vec.size(), 4); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Clear) { - SmallVector vec = {0, 1, 2, 3}; - SmallVector result = {}; - - EXPECT_EQ(vec.size(), 4); - vec.clear(); - EXPECT_EQ(vec.size(), 0); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Insert1) { - SmallVector vec = {}; - SmallVector insert_values = {10, 11}; - SmallVector result = {10, 11}; - - EXPECT_EQ(vec.size(), 0); - auto ret = - vec.insert(vec.begin(), insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 2); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert2) { - SmallVector vec = {}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {10, 11, 12}; - - EXPECT_EQ(vec.size(), 0); - auto ret = - vec.insert(vec.begin(), insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert3) { - SmallVector vec = {0}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {10, 11, 12, 0}; - - EXPECT_EQ(vec.size(), 1); - auto ret = - vec.insert(vec.begin(), insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 4); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert4) { - SmallVector vec = {0}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {10, 11, 12, 0}; - - EXPECT_EQ(vec.size(), 1); - auto ret = - vec.insert(vec.begin(), insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 4); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert5) { - SmallVector vec = {0, 1, 2}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {0, 1, 2, 10, 11, 12}; - - EXPECT_EQ(vec.size(), 3); - auto ret = vec.insert(vec.end(), insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert6) { - SmallVector vec = {0, 1, 2}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {0, 1, 2, 10, 11, 12}; - - EXPECT_EQ(vec.size(), 3); - auto ret = vec.insert(vec.end(), insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert7) { - SmallVector vec = {0, 1, 2}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {0, 10, 11, 12, 1, 2}; - - EXPECT_EQ(vec.size(), 3); - auto ret = - vec.insert(vec.begin() + 1, insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Insert8) { - SmallVector vec = {0, 1, 2}; - SmallVector insert_values = {10, 11, 12}; - SmallVector result = {0, 10, 11, 12, 1, 2}; - - EXPECT_EQ(vec.size(), 3); - auto ret = - vec.insert(vec.begin() + 1, insert_values.begin(), insert_values.end()); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); - EXPECT_EQ(*ret, 10); -} - -TEST(SmallVectorTest, Resize1) { - SmallVector vec = {0, 1, 2}; - SmallVector result = {0, 1, 2, 10, 10, 10}; - - EXPECT_EQ(vec.size(), 3); - vec.resize(6, 10); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Resize2) { - SmallVector vec = {0, 1, 2}; - SmallVector result = {0, 1, 2, 10, 10, 10}; - - EXPECT_EQ(vec.size(), 3); - vec.resize(6, 10); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Resize3) { - SmallVector vec = {0, 1, 2}; - SmallVector result = {0, 1, 2, 10, 10, 10}; - - EXPECT_EQ(vec.size(), 3); - vec.resize(6, 10); - EXPECT_EQ(vec.size(), 6); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Resize4) { - SmallVector vec = {0, 1, 2, 10, 10, 10}; - SmallVector result = {0, 1, 2}; - - EXPECT_EQ(vec.size(), 6); - vec.resize(3, 10); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Resize5) { - SmallVector vec = {0, 1, 2, 10, 10, 10}; - SmallVector result = {0, 1, 2}; - - EXPECT_EQ(vec.size(), 6); - vec.resize(3, 10); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -TEST(SmallVectorTest, Resize6) { - SmallVector vec = {0, 1, 2, 10, 10, 10}; - SmallVector result = {0, 1, 2}; - - EXPECT_EQ(vec.size(), 6); - vec.resize(3, 10); - EXPECT_EQ(vec.size(), 3); - EXPECT_EQ(vec, result); -} - -} // namespace -} // namespace utils -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/CMakeLists.txt b/3rdparty/spirv-tools/test/val/CMakeLists.txt deleted file mode 100644 index d4bfe1d0c..000000000 --- a/3rdparty/spirv-tools/test/val/CMakeLists.txt +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) 2016 The Khronos Group 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. - -set(VAL_TEST_COMMON_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/../test_fixture.h - ${CMAKE_CURRENT_SOURCE_DIR}/../unit_spirv.h - ${CMAKE_CURRENT_SOURCE_DIR}/val_code_generator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/val_code_generator.h - ${CMAKE_CURRENT_SOURCE_DIR}/val_fixtures.h -) - -add_spvtools_unittest(TARGET val_abcde - SRCS - val_adjacency_test.cpp - val_arithmetics_test.cpp - val_atomics_test.cpp - val_barriers_test.cpp - val_bitwise_test.cpp - val_builtins_test.cpp - val_cfg_test.cpp - val_composites_test.cpp - val_constants_test.cpp - val_conversion_test.cpp - val_data_test.cpp - val_decoration_test.cpp - val_derivatives_test.cpp - val_entry_point.cpp - val_explicit_reserved_test.cpp - val_extensions_test.cpp - val_ext_inst_test.cpp - ${VAL_TEST_COMMON_SRCS} - LIBS ${SPIRV_TOOLS} - PCH_FILE pch_test_val -) - -add_spvtools_unittest(TARGET val_capability - SRCS - val_capability_test.cpp - LIBS ${SPIRV_TOOLS} - PCH_FILE pch_test_val -) - -add_spvtools_unittest(TARGET val_limits - SRCS val_limits_test.cpp - ${VAL_TEST_COMMON_SRCS} - LIBS ${SPIRV_TOOLS} - PCH_FILE pch_test_val -) - -add_spvtools_unittest(TARGET val_fghijklmnop - SRCS - val_function_test.cpp - val_id_test.cpp - val_image_test.cpp - val_interfaces_test.cpp - val_layout_test.cpp - val_literals_test.cpp - val_logicals_test.cpp - val_memory_test.cpp - val_misc_test.cpp - val_modes_test.cpp - val_non_uniform_test.cpp - val_opencl_test.cpp - val_primitives_test.cpp - ${VAL_TEST_COMMON_SRCS} - LIBS ${SPIRV_TOOLS} - PCH_FILE pch_test_val -) - -add_spvtools_unittest(TARGET val_stuvw - SRCS - val_small_type_uses_test.cpp - val_ssa_test.cpp - val_state_test.cpp - val_storage_test.cpp - val_type_unique_test.cpp - val_validation_state_test.cpp - val_version_test.cpp - val_webgpu_test.cpp - ${VAL_TEST_COMMON_SRCS} - LIBS ${SPIRV_TOOLS} - PCH_FILE pch_test_val -) diff --git a/3rdparty/spirv-tools/test/val/pch_test_val.cpp b/3rdparty/spirv-tools/test/val/pch_test_val.cpp deleted file mode 100644 index fc92e375a..000000000 --- a/3rdparty/spirv-tools/test/val/pch_test_val.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "pch_test_val.h" diff --git a/3rdparty/spirv-tools/test/val/pch_test_val.h b/3rdparty/spirv-tools/test/val/pch_test_val.h deleted file mode 100644 index 7b5881c43..000000000 --- a/3rdparty/spirv-tools/test/val/pch_test_val.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2018 The Khronos Group 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" diff --git a/3rdparty/spirv-tools/test/val/val_adjacency_test.cpp b/3rdparty/spirv-tools/test/val/val_adjacency_test.cpp deleted file mode 100644 index e61c03dfd..000000000 --- a/3rdparty/spirv-tools/test/val/val_adjacency_test.cpp +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright (c) 2018 LunarG 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateAdjacency = spvtest::ValidateBase; - -TEST_F(ValidateAdjacency, OpPhiBeginsModuleFail) { - const std::string module = R"( -%result = OpPhi %bool %true %true_label %false %false_label -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -OpBranch %true_label -%true_label = OpLabel -OpBranch %false_label -%false_label = OpLabel -OpBranch %end_label -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(module); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 1[%bool] has not been defined")); -} - -TEST_F(ValidateAdjacency, OpLoopMergeEndsModuleFail) { - const std::string module = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %end %loop None -)"; - - CompileSuccessfully(module); - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Missing OpFunctionEnd at end of module")); -} - -TEST_F(ValidateAdjacency, OpSelectionMergeEndsModuleFail) { - const std::string module = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -OpBranch %merge -%merge = OpLabel -OpSelectionMerge %merge None -)"; - - CompileSuccessfully(module); - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Missing OpFunctionEnd at end of module")); -} - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "OpCapability Shader", - const std::string& execution_model = "Fragment") { - std::ostringstream ss; - ss << capabilities_and_extensions << "\n"; - ss << "OpMemoryModel Logical GLSL450\n"; - ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; - if (execution_model == "Fragment") { - ss << "OpExecutionMode %main OriginUpperLeft\n"; - } - - ss << R"( -%string = OpString "" -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%zero = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%func = OpTypeFunction %void -%func_int = OpTypePointer Function %int -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -TEST_F(ValidateAdjacency, OpPhiPreceededByOpLabelSuccess) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -OpLine %string 0 0 -%result = OpPhi %bool %true %true_label %false %false_label -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpPhiPreceededByOpPhiSuccess) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -%1 = OpPhi %bool %true %true_label %false %false_label -%2 = OpPhi %bool %true %true_label %false %false_label -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpPhiPreceededByOpLineSuccess) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -OpLine %string 0 0 -%result = OpPhi %bool %true %true_label %false %false_label -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpPhiPreceededByBadOpFail) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -OpNop -%result = OpPhi %bool %true %true_label %false %false_label -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi must appear within a non-entry block before all " - "non-OpPhi instructions")); -} - -TEST_F(ValidateAdjacency, OpPhiPreceededByOpLineAndBadOpFail) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -OpNop -OpLine %string 1 1 -%result = OpPhi %bool %true %true_label %false %false_label -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi must appear within a non-entry block before all " - "non-OpPhi instructions")); -} - -TEST_F(ValidateAdjacency, OpPhiFollowedByOpLineGood) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -%result = OpPhi %bool %true %true_label %false %false_label -OpLine %string 1 1 -OpNop -OpNop -OpLine %string 2 1 -OpNop -OpLine %string 3 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpPhiMultipleOpLineAndOpPhiFail) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -OpLine %string 1 1 -%value = OpPhi %int %zero %true_label %int_1 %false_label -OpNop -OpLine %string 2 1 -OpNop -OpLine %string 3 1 -%result = OpPhi %bool %true %true_label %false %false_label -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi must appear within a non-entry block before all " - "non-OpPhi instructions")); -} - -TEST_F(ValidateAdjacency, OpPhiMultipleOpLineAndOpPhiGood) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -OpLine %string 1 1 -%value = OpPhi %int %zero %true_label %int_1 %false_label -OpLine %string 2 1 -%result = OpPhi %bool %true %true_label %false %false_label -OpLine %string 3 1 -OpNop -OpNop -OpLine %string 4 1 -OpNop -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpPhiInEntryBlockBad) { - const std::string body = R"( -OpLine %string 1 1 -%value = OpPhi %int -OpLine %string 2 1 -OpNop -OpLine %string 3 1 -OpNop -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi must appear within a non-entry block before all " - "non-OpPhi instructions")); -} - -TEST_F(ValidateAdjacency, OpVariableInFunctionGood) { - const std::string body = R"( -OpLine %string 1 1 -%var = OpVariable %func_int Function -OpLine %string 2 1 -OpNop -OpLine %string 3 1 -OpNop -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpVariableInFunctionMultipleGood) { - const std::string body = R"( -OpLine %string 1 1 -%1 = OpVariable %func_int Function -OpLine %string 2 1 -%2 = OpVariable %func_int Function -%3 = OpVariable %func_int Function -OpNop -OpLine %string 3 1 -OpNop -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpVariableInFunctionBad) { - const std::string body = R"( -%1 = OpUndef %int -%2 = OpVariable %func_int Function -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("All OpVariable instructions in a function must be the " - "first instructions")); -} - -TEST_F(ValidateAdjacency, OpVariableInFunctionMultipleBad) { - const std::string body = R"( -OpNop -%1 = OpVariable %func_int Function -OpLine %string 1 1 -%2 = OpVariable %func_int Function -OpNop -OpNop -OpLine %string 2 1 -%3 = OpVariable %func_int Function -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("All OpVariable instructions in a function must be the " - "first instructions")); -} - -TEST_F(ValidateAdjacency, OpLoopMergePreceedsOpBranchSuccess) { - const std::string body = R"( -OpBranch %loop -%loop = OpLabel -OpLoopMerge %end %loop None -OpBranch %loop -%end = OpLabel -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpLoopMergePreceedsOpBranchConditionalSuccess) { - const std::string body = R"( -OpBranch %loop -%loop = OpLabel -OpLoopMerge %end %loop None -OpBranchConditional %true %loop %end -%end = OpLabel -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpLoopMergePreceedsBadOpFail) { - const std::string body = R"( -OpBranch %loop -%loop = OpLabel -OpLoopMerge %end %loop None -OpNop -OpBranchConditional %true %loop %end -%end = OpLabel -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpLoopMerge must immediately precede either an " - "OpBranch or OpBranchConditional instruction.")); -} - -TEST_F(ValidateAdjacency, OpSelectionMergePreceedsOpBranchConditionalSuccess) { - const std::string body = R"( -OpSelectionMerge %end_label None -OpBranchConditional %true %true_label %false_label -%true_label = OpLabel -OpBranch %end_label -%false_label = OpLabel -OpBranch %end_label -%end_label = OpLabel -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpSelectionMergePreceedsOpSwitchSuccess) { - const std::string body = R"( -OpSelectionMerge %merge None -OpSwitch %zero %merge 0 %label -%label = OpLabel -OpBranch %merge -%merge = OpLabel -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAdjacency, OpSelectionMergePreceedsBadOpFail) { - const std::string body = R"( -OpSelectionMerge %merge None -OpNop -OpSwitch %zero %merge 0 %label -%label = OpLabel -OpBranch %merge -%merge = OpLabel -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSelectionMerge must immediately precede either an " - "OpBranchConditional or OpSwitch instruction")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_arithmetics_test.cpp b/3rdparty/spirv-tools/test/val/val_arithmetics_test.cpp deleted file mode 100644 index b82fc97e1..000000000 --- a/3rdparty/spirv-tools/test/val/val_arithmetics_test.cpp +++ /dev/null @@ -1,1422 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateArithmetics = spvtest::ValidateBase; - -std::string GenerateCode(const std::string& main_body) { - const std::string prefix = - R"( -OpCapability Shader -OpCapability Int64 -OpCapability Float64 -OpCapability Matrix -%ext_inst = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%f64 = OpTypeFloat 64 -%u64 = OpTypeInt 64 0 -%s64 = OpTypeInt 64 1 -%boolvec2 = OpTypeVector %bool 2 -%s32vec2 = OpTypeVector %s32 2 -%u32vec2 = OpTypeVector %u32 2 -%u64vec2 = OpTypeVector %u64 2 -%f32vec2 = OpTypeVector %f32 2 -%f64vec2 = OpTypeVector %f64 2 -%boolvec3 = OpTypeVector %bool 3 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%s32vec3 = OpTypeVector %s32 3 -%f32vec3 = OpTypeVector %f32 3 -%f64vec3 = OpTypeVector %f64 3 -%boolvec4 = OpTypeVector %bool 4 -%u32vec4 = OpTypeVector %u32 4 -%u64vec4 = OpTypeVector %u64 4 -%s32vec4 = OpTypeVector %s32 4 -%f32vec4 = OpTypeVector %f32 4 -%f64vec4 = OpTypeVector %f64 4 - -%f32mat22 = OpTypeMatrix %f32vec2 2 -%f32mat23 = OpTypeMatrix %f32vec2 3 -%f32mat32 = OpTypeMatrix %f32vec3 2 -%f32mat33 = OpTypeMatrix %f32vec3 3 -%f64mat22 = OpTypeMatrix %f64vec2 2 - -%struct_f32_f32 = OpTypeStruct %f32 %f32 -%struct_u32_u32 = OpTypeStruct %u32 %u32 -%struct_u32_u32_u32 = OpTypeStruct %u32 %u32 %u32 -%struct_s32_s32 = OpTypeStruct %s32 %s32 -%struct_s32_u32 = OpTypeStruct %s32 %u32 -%struct_u32vec2_u32vec2 = OpTypeStruct %u32vec2 %u32vec2 -%struct_s32vec2_s32vec2 = OpTypeStruct %s32vec2 %s32vec2 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 -%f32_pi = OpConstant %f32 3.14159 - -%s32_0 = OpConstant %s32 0 -%s32_1 = OpConstant %s32 1 -%s32_2 = OpConstant %s32 2 -%s32_3 = OpConstant %s32 3 -%s32_4 = OpConstant %s32 4 -%s32_m1 = OpConstant %s32 -1 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64_4 = OpConstant %f64 4 - -%s64_0 = OpConstant %s64 0 -%s64_1 = OpConstant %s64 1 -%s64_2 = OpConstant %s64 2 -%s64_3 = OpConstant %s64 3 -%s64_4 = OpConstant %s64 4 -%s64_m1 = OpConstant %s64 -1 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_4 = OpConstant %u64 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1 -%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2 -%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2 -%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3 -%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3 -%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4 - -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 -%f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4 - -%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12 -%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 -%f32mat32_123123 = OpConstantComposite %f32mat32 %f32vec3_123 %f32vec3_123 -%f32mat33_123123123 = OpConstantComposite %f32mat33 %f32vec3_123 %f32vec3_123 %f32vec3_123 - -%f64mat22_1212 = OpConstantComposite %f64mat22 %f64vec2_12 %f64vec2_12 - -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string suffix = - R"( -OpReturn -OpFunctionEnd)"; - - return prefix + main_body + suffix; -} - -TEST_F(ValidateArithmetics, F32Success) { - const std::string body = R"( -%val1 = OpFMul %f32 %f32_0 %f32_1 -%val2 = OpFSub %f32 %f32_2 %f32_0 -%val3 = OpFAdd %f32 %val1 %val2 -%val4 = OpFNegate %f32 %val3 -%val5 = OpFDiv %f32 %val4 %val1 -%val6 = OpFRem %f32 %val4 %f32_2 -%val7 = OpFMod %f32 %val4 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, F64Success) { - const std::string body = R"( -%val1 = OpFMul %f64 %f64_0 %f64_1 -%val2 = OpFSub %f64 %f64_2 %f64_0 -%val3 = OpFAdd %f64 %val1 %val2 -%val4 = OpFNegate %f64 %val3 -%val5 = OpFDiv %f64 %val4 %val1 -%val6 = OpFRem %f64 %val4 %f64_2 -%val7 = OpFMod %f64 %val4 %f64_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, Int32Success) { - const std::string body = R"( -%val1 = OpIMul %u32 %s32_0 %u32_1 -%val2 = OpIMul %s32 %s32_2 %u32_1 -%val3 = OpIAdd %u32 %val1 %val2 -%val4 = OpIAdd %s32 %val1 %val2 -%val5 = OpISub %u32 %val3 %val4 -%val6 = OpISub %s32 %val4 %val3 -%val7 = OpSDiv %s32 %val4 %val3 -%val8 = OpSNegate %s32 %val7 -%val9 = OpSRem %s32 %val4 %val3 -%val10 = OpSMod %s32 %val4 %val3 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, Int64Success) { - const std::string body = R"( -%val1 = OpIMul %u64 %s64_0 %u64_1 -%val2 = OpIMul %s64 %s64_2 %u64_1 -%val3 = OpIAdd %u64 %val1 %val2 -%val4 = OpIAdd %s64 %val1 %val2 -%val5 = OpISub %u64 %val3 %val4 -%val6 = OpISub %s64 %val4 %val3 -%val7 = OpSDiv %s64 %val4 %val3 -%val8 = OpSNegate %s64 %val7 -%val9 = OpSRem %s64 %val4 %val3 -%val10 = OpSMod %s64 %val4 %val3 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, F32Vec2Success) { - const std::string body = R"( -%val1 = OpFMul %f32vec2 %f32vec2_01 %f32vec2_12 -%val2 = OpFSub %f32vec2 %f32vec2_12 %f32vec2_01 -%val3 = OpFAdd %f32vec2 %val1 %val2 -%val4 = OpFNegate %f32vec2 %val3 -%val5 = OpFDiv %f32vec2 %val4 %val1 -%val6 = OpFRem %f32vec2 %val4 %f32vec2_12 -%val7 = OpFMod %f32vec2 %val4 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, F64Vec2Success) { - const std::string body = R"( -%val1 = OpFMul %f64vec2 %f64vec2_01 %f64vec2_12 -%val2 = OpFSub %f64vec2 %f64vec2_12 %f64vec2_01 -%val3 = OpFAdd %f64vec2 %val1 %val2 -%val4 = OpFNegate %f64vec2 %val3 -%val5 = OpFDiv %f64vec2 %val4 %val1 -%val6 = OpFRem %f64vec2 %val4 %f64vec2_12 -%val7 = OpFMod %f64vec2 %val4 %f64vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, U32Vec2Success) { - const std::string body = R"( -%val1 = OpIMul %u32vec2 %u32vec2_01 %u32vec2_12 -%val2 = OpISub %u32vec2 %u32vec2_12 %u32vec2_01 -%val3 = OpIAdd %u32vec2 %val1 %val2 -%val4 = OpSNegate %u32vec2 %val3 -%val5 = OpSDiv %u32vec2 %val4 %val1 -%val6 = OpSRem %u32vec2 %val4 %u32vec2_12 -%val7 = OpSMod %u32vec2 %val4 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, FNegateTypeIdU32) { - const std::string body = R"( -%val = OpFNegate %u32 %u32_0 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected floating scalar or vector type as Result Type: FNegate")); -} - -TEST_F(ValidateArithmetics, FNegateTypeIdVec2U32) { - const std::string body = R"( -%val = OpFNegate %u32vec2 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected floating scalar or vector type as Result Type: FNegate")); -} - -TEST_F(ValidateArithmetics, FNegateWrongOperand) { - const std::string body = R"( -%val = OpFNegate %f32 %u32_0 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "FNegate operand index 2")); -} - -TEST_F(ValidateArithmetics, FMulTypeIdU32) { - const std::string body = R"( -%val = OpFMul %u32 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected floating scalar or vector type as Result Type: FMul")); -} - -TEST_F(ValidateArithmetics, FMulTypeIdVec2U32) { - const std::string body = R"( -%val = OpFMul %u32vec2 %u32vec2_01 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected floating scalar or vector type as Result Type: FMul")); -} - -TEST_F(ValidateArithmetics, FMulWrongOperand1) { - const std::string body = R"( -%val = OpFMul %f32 %u32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "FMul operand index 2")); -} - -TEST_F(ValidateArithmetics, FMulWrongOperand2) { - const std::string body = R"( -%val = OpFMul %f32 %f32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "FMul operand index 3")); -} - -TEST_F(ValidateArithmetics, FMulWrongVectorOperand1) { - const std::string body = R"( -%val = OpFMul %f64vec3 %f32vec3_123 %f64vec3_012 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "FMul operand index 2")); -} - -TEST_F(ValidateArithmetics, FMulWrongVectorOperand2) { - const std::string body = R"( -%val = OpFMul %f32vec3 %f32vec3_123 %f64vec3_012 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "FMul operand index 3")); -} - -TEST_F(ValidateArithmetics, IMulFloatTypeId) { - const std::string body = R"( -%val = OpIMul %f32 %u32_0 %s32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as Result Type: IMul")); -} - -TEST_F(ValidateArithmetics, IMulFloatOperand1) { - const std::string body = R"( -%val = OpIMul %u32 %f32_0 %s32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as operand: " - "IMul operand index 2")); -} - -TEST_F(ValidateArithmetics, IMulFloatOperand2) { - const std::string body = R"( -%val = OpIMul %u32 %s32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as operand: " - "IMul operand index 3")); -} - -TEST_F(ValidateArithmetics, IMulWrongBitWidthOperand1) { - const std::string body = R"( -%val = OpIMul %u64 %u32_0 %s64_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same bit width " - "as Result Type: IMul operand index 2")); -} - -TEST_F(ValidateArithmetics, IMulWrongBitWidthOperand2) { - const std::string body = R"( -%val = OpIMul %u32 %u32_0 %s64_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same bit width " - "as Result Type: IMul operand index 3")); -} - -TEST_F(ValidateArithmetics, IMulWrongBitWidthVector) { - const std::string body = R"( -%val = OpIMul %u64vec3 %u32vec3_012 %u32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same bit width " - "as Result Type: IMul operand index 2")); -} - -TEST_F(ValidateArithmetics, IMulVectorScalarOperand1) { - const std::string body = R"( -%val = OpIMul %u32vec2 %u32_0 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same dimension " - "as Result Type: IMul operand index 2")); -} - -TEST_F(ValidateArithmetics, IMulVectorScalarOperand2) { - const std::string body = R"( -%val = OpIMul %u32vec2 %u32vec2_01 %u32_0 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same dimension " - "as Result Type: IMul operand index 3")); -} - -TEST_F(ValidateArithmetics, IMulScalarVectorOperand1) { - const std::string body = R"( -%val = OpIMul %s32 %u32vec2_01 %u32_0 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same dimension " - "as Result Type: IMul operand index 2")); -} - -TEST_F(ValidateArithmetics, IMulScalarVectorOperand2) { - const std::string body = R"( -%val = OpIMul %u32 %u32_0 %s32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected arithmetic operands to have the same dimension " - "as Result Type: IMul operand index 3")); -} - -TEST_F(ValidateArithmetics, SNegateFloat) { - const std::string body = R"( -%val = OpSNegate %s32 %f32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as operand: " - "SNegate operand index 2")); -} - -TEST_F(ValidateArithmetics, UDivFloatType) { - const std::string body = R"( -%val = OpUDiv %f32 %u32_2 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected unsigned int scalar or vector type as Result Type: UDiv")); -} - -TEST_F(ValidateArithmetics, UDivSignedIntType) { - const std::string body = R"( -%val = OpUDiv %s32 %u32_2 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected unsigned int scalar or vector type as Result Type: UDiv")); -} - -TEST_F(ValidateArithmetics, UDivWrongOperand1) { - const std::string body = R"( -%val = OpUDiv %u64 %f64_2 %u64_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "UDiv operand index 2")); -} - -TEST_F(ValidateArithmetics, UDivWrongOperand2) { - const std::string body = R"( -%val = OpUDiv %u64 %u64_2 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected arithmetic operands to be of Result Type: " - "UDiv operand index 3")); -} - -TEST_F(ValidateArithmetics, DotSuccess) { - const std::string body = R"( -%val = OpDot %f32 %f32vec2_01 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, DotWrongTypeId) { - const std::string body = R"( -%val = OpDot %u32 %u32vec2_01 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float scalar type as Result Type: Dot")); -} - -TEST_F(ValidateArithmetics, DotNotVectorTypeOperand1) { - const std::string body = R"( -%val = OpDot %f32 %f32 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 6[%float] cannot be a " - "type")); -} - -TEST_F(ValidateArithmetics, DotNotVectorTypeOperand2) { - const std::string body = R"( -%val = OpDot %f32 %f32vec3_012 %f32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected float vector as operand: Dot operand index 3")); -} - -TEST_F(ValidateArithmetics, DotWrongComponentOperand1) { - const std::string body = R"( -%val = OpDot %f64 %f32vec2_01 %f64vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected component type to be equal to Result Type: " - "Dot operand index 2")); -} - -TEST_F(ValidateArithmetics, DotWrongComponentOperand2) { - const std::string body = R"( -%val = OpDot %f32 %f32vec2_01 %f64vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected component type to be equal to Result Type: " - "Dot operand index 3")); -} - -TEST_F(ValidateArithmetics, DotDifferentVectorSize) { - const std::string body = R"( -%val = OpDot %f32 %f32vec2_01 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected operands to have the same number of componenets: Dot")); -} - -TEST_F(ValidateArithmetics, VectorTimesScalarSuccess) { - const std::string body = R"( -%val = OpVectorTimesScalar %f32vec2 %f32vec2_01 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, VectorTimesScalarWrongTypeId) { - const std::string body = R"( -%val = OpVectorTimesScalar %u32vec2 %f32vec2_01 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float vector type as Result Type: " - "VectorTimesScalar")); -} - -TEST_F(ValidateArithmetics, VectorTimesScalarWrongVector) { - const std::string body = R"( -%val = OpVectorTimesScalar %f32vec2 %f32vec3_012 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected vector operand type to be equal to Result Type: " - "VectorTimesScalar")); -} - -TEST_F(ValidateArithmetics, VectorTimesScalarWrongScalar) { - const std::string body = R"( -%val = OpVectorTimesScalar %f32vec2 %f32vec2_01 %f64_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar operand type to be equal to the component " - "type of the vector operand: VectorTimesScalar")); -} - -TEST_F(ValidateArithmetics, MatrixTimesScalarSuccess) { - const std::string body = R"( -%val = OpMatrixTimesScalar %f32mat22 %f32mat22_1212 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, MatrixTimesScalarWrongTypeId) { - const std::string body = R"( -%val = OpMatrixTimesScalar %f32vec2 %f32mat22_1212 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float matrix type as Result Type: " - "MatrixTimesScalar")); -} - -TEST_F(ValidateArithmetics, MatrixTimesScalarWrongMatrix) { - const std::string body = R"( -%val = OpMatrixTimesScalar %f32mat22 %f32vec2_01 %f32_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected matrix operand type to be equal to Result Type: " - "MatrixTimesScalar")); -} - -TEST_F(ValidateArithmetics, MatrixTimesScalarWrongScalar) { - const std::string body = R"( -%val = OpMatrixTimesScalar %f32mat22 %f32mat22_1212 %f64_2 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar operand type to be equal to the component " - "type of the matrix operand: MatrixTimesScalar")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrix2x22Success) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f32vec2_12 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrix3x32Success) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f32vec3_123 %f32mat32_123123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrixWrongTypeId) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32mat22 %f32vec2_12 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float vector type as Result Type: " - "VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrixNotFloatVector) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %u32vec2_12 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float vector type as left operand: " - "VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrixWrongVectorComponent) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f64vec2_12 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected component types of Result Type and vector to be equal: " - "VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrixWrongMatrix) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f32vec2_12 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float matrix type as right operand: " - "VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrixWrongMatrixComponent) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f32vec2_12 %f64mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected component types of Result Type and matrix to be equal: " - "VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrix2eq2x23Fail) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f32vec2_12 %f32mat23_121212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected number of columns of the matrix to be equal to Result Type " - "vector size: VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, VectorTimesMatrix2x32Fail) { - const std::string body = R"( -%val = OpVectorTimesMatrix %f32vec2 %f32vec2_12 %f32mat32_123123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected number of rows of the matrix to be equal to the vector " - "operand size: VectorTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesVector22x2Success) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec2 %f32mat22_1212 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, MatrixTimesVector23x3Success) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec2 %f32mat23_121212 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, MatrixTimesVectorWrongTypeId) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32mat22 %f32mat22_1212 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float vector type as Result Type: " - "MatrixTimesVector")); -} - -TEST_F(ValidateArithmetics, MatrixTimesVectorWrongMatrix) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec3 %f32vec3_123 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float matrix type as left operand: " - "MatrixTimesVector")); -} - -TEST_F(ValidateArithmetics, MatrixTimesVectorWrongMatrixCol) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec3 %f32mat23_121212 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected column type of the matrix to be equal to Result Type: " - "MatrixTimesVector")); -} - -TEST_F(ValidateArithmetics, MatrixTimesVectorWrongVector) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec2 %f32mat22_1212 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float vector type as right operand: " - "MatrixTimesVector")); -} - -TEST_F(ValidateArithmetics, MatrixTimesVectorDifferentComponents) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec2 %f32mat22_1212 %f64vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected component types of the operands to be equal: " - "MatrixTimesVector")); -} - -TEST_F(ValidateArithmetics, MatrixTimesVector22x3Fail) { - const std::string body = R"( -%val = OpMatrixTimesVector %f32vec2 %f32mat22_1212 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected number of columns of the matrix to be equal to the vector " - "size: MatrixTimesVector")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrix22x22Success) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat22_1212 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrix23x32Success) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat23_121212 %f32mat32_123123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrix33x33Success) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat33 %f32mat33_123123123 %f32mat33_123123123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrixWrongTypeId) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32vec2 %f32mat22_1212 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected float matrix type as Result Type: MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrixWrongLeftOperand) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32vec2_12 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected float matrix type as left operand: MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrixWrongRightOperand) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat22_1212 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected float matrix type as right operand: MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrix32x23Fail) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat32_123123 %f32mat23_121212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected column types of Result Type and left matrix to be equal: " - "MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrixDifferentComponents) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat22_1212 %f64mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected component types of Result Type and right " - "matrix to be equal: " - "MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrix23x23Fail) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat23_121212 %f32mat23_121212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected number of columns of Result Type and right " - "matrix to be equal: " - "MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, MatrixTimesMatrix23x22Fail) { - const std::string body = R"( -%val = OpMatrixTimesMatrix %f32mat22 %f32mat23_121212 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected number of columns of left matrix and number " - "of rows of right " - "matrix to be equal: MatrixTimesMatrix")); -} - -TEST_F(ValidateArithmetics, OuterProduct2x2Success) { - const std::string body = R"( -%val = OpOuterProduct %f32mat22 %f32vec2_12 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, OuterProduct3x2Success) { - const std::string body = R"( -%val = OpOuterProduct %f32mat32 %f32vec3_123 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, OuterProduct2x3Success) { - const std::string body = R"( -%val = OpOuterProduct %f32mat23 %f32vec2_01 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, OuterProductWrongTypeId) { - const std::string body = R"( -%val = OpOuterProduct %f32vec2 %f32vec2_01 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected float matrix type as Result Type: " - "OuterProduct")); -} - -TEST_F(ValidateArithmetics, OuterProductWrongLeftOperand) { - const std::string body = R"( -%val = OpOuterProduct %f32mat22 %f32vec3_123 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected column type of Result Type to be equal to the type " - "of the left operand: OuterProduct")); -} - -TEST_F(ValidateArithmetics, OuterProductRightOperandNotFloatVector) { - const std::string body = R"( -%val = OpOuterProduct %f32mat22 %f32vec2_12 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected float vector type as right operand: OuterProduct")); -} - -TEST_F(ValidateArithmetics, OuterProductRightOperandWrongComponent) { - const std::string body = R"( -%val = OpOuterProduct %f32mat22 %f32vec2_12 %f64vec2_01 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected component types of the operands to be equal: " - "OuterProduct")); -} - -TEST_F(ValidateArithmetics, OuterProductRightOperandWrongDimension) { - const std::string body = R"( -%val = OpOuterProduct %f32mat22 %f32vec2_12 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected number of columns of the matrix to be equal to the " - "vector size of the right operand: OuterProduct")); -} - -std::string GenerateCoopMatCode(const std::string& extra_types, - const std::string& main_body) { - const std::string prefix = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%u32_16 = OpConstant %u32 16 -%u32_4 = OpConstant %u32 4 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 -%u32mat = OpTypeCooperativeMatrixNV %u32 %subgroup %u32_8 %u32_8 -%s32mat = OpTypeCooperativeMatrixNV %s32 %subgroup %u32_8 %u32_8 - -%f16_1 = OpConstant %f16 1 -%f32_1 = OpConstant %f32 1 -%u32_1 = OpConstant %u32 1 -%s32_1 = OpConstant %s32 1 - -%f16mat_1 = OpConstantComposite %f16mat %f16_1 -%u32mat_1 = OpConstantComposite %u32mat %u32_1 -%s32mat_1 = OpConstantComposite %s32mat %s32_1 - -%u32_c1 = OpSpecConstant %u32 1 -%u32_c2 = OpSpecConstant %u32 2 - -%f16matc = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_c1 %u32_c2 -%f16matc_1 = OpConstantComposite %f16matc %f16_1 - -%mat16x4 = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_16 %u32_4 -%mat4x16 = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_4 %u32_16 -%mat16x16 = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_16 %u32_16 -%f16mat_16x4_1 = OpConstantComposite %mat16x4 %f16_1 -%f16mat_4x16_1 = OpConstantComposite %mat4x16 %f16_1 -%f16mat_16x16_1 = OpConstantComposite %mat16x16 %f16_1)"; - - const std::string func_begin = - R"( -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string suffix = - R"( -OpReturn -OpFunctionEnd)"; - - return prefix + extra_types + func_begin + main_body + suffix; -} - -TEST_F(ValidateArithmetics, CoopMatSuccess) { - const std::string body = R"( -%val1 = OpFAdd %f16mat %f16mat_1 %f16mat_1 -%val2 = OpFSub %f16mat %f16mat_1 %f16mat_1 -%val3 = OpFDiv %f16mat %f16mat_1 %f16mat_1 -%val4 = OpFNegate %f16mat %f16mat_1 -%val5 = OpIAdd %u32mat %u32mat_1 %u32mat_1 -%val6 = OpISub %u32mat %u32mat_1 %u32mat_1 -%val7 = OpUDiv %u32mat %u32mat_1 %u32mat_1 -%val8 = OpIAdd %s32mat %s32mat_1 %s32mat_1 -%val9 = OpISub %s32mat %s32mat_1 %s32mat_1 -%val10 = OpSDiv %s32mat %s32mat_1 %s32mat_1 -%val11 = OpSNegate %s32mat %s32mat_1 -%val12 = OpMatrixTimesScalar %f16mat %f16mat_1 %f16_1 -%val13 = OpMatrixTimesScalar %u32mat %u32mat_1 %u32_1 -%val14 = OpMatrixTimesScalar %s32mat %s32mat_1 %s32_1 -%val15 = OpCooperativeMatrixMulAddNV %mat16x16 %f16mat_16x4_1 %f16mat_4x16_1 %f16mat_16x16_1 -%val16 = OpCooperativeMatrixMulAddNV %f16matc %f16matc_1 %f16matc_1 %f16matc_1 -)"; - - CompileSuccessfully(GenerateCoopMatCode("", body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, CoopMatFMulFail) { - const std::string body = R"( -%val1 = OpFMul %f16mat %f16mat_1 %f16mat_1 -)"; - - CompileSuccessfully(GenerateCoopMatCode("", body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected floating scalar or vector type as Result Type: FMul")); -} - -TEST_F(ValidateArithmetics, CoopMatMatrixTimesScalarMismatchFail) { - const std::string body = R"( -%val1 = OpMatrixTimesScalar %f16mat %f16mat_1 %f32_1 -)"; - - CompileSuccessfully(GenerateCoopMatCode("", body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar operand type to be equal to the component " - "type of the matrix operand: MatrixTimesScalar")); -} - -TEST_F(ValidateArithmetics, CoopMatScopeFail) { - const std::string types = R"( -%workgroup = OpConstant %u32 2 - -%mat16x16_wg = OpTypeCooperativeMatrixNV %f16 %workgroup %u32_16 %u32_16 -%f16matwg_16x16_1 = OpConstantComposite %mat16x16_wg %f16_1 -)"; - - const std::string body = R"( -%val1 = OpCooperativeMatrixMulAddNV %mat16x16 %f16mat_16x4_1 %f16mat_4x16_1 %f16matwg_16x16_1 -)"; - - CompileSuccessfully(GenerateCoopMatCode(types, body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Cooperative matrix scopes must match: CooperativeMatrixMulAddNV")); -} - -TEST_F(ValidateArithmetics, CoopMatDimFail) { - const std::string body = R"( -%val1 = OpCooperativeMatrixMulAddNV %mat16x16 %f16mat_4x16_1 %f16mat_16x4_1 %f16mat_16x16_1 -)"; - - CompileSuccessfully(GenerateCoopMatCode("", body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cooperative matrix 'M' mismatch: CooperativeMatrixMulAddNV")); -} - -TEST_F(ValidateArithmetics, IAddCarrySuccess) { - const std::string body = R"( -%val1 = OpIAddCarry %struct_u32_u32 %u32_0 %u32_1 -%val2 = OpIAddCarry %struct_u32vec2_u32vec2 %u32vec2_01 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, IAddCarryResultTypeNotStruct) { - const std::string body = R"( -%val = OpIAddCarry %u32 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected a struct as Result Type: IAddCarry")); -} - -TEST_F(ValidateArithmetics, IAddCarryResultTypeNotTwoMembers) { - const std::string body = R"( -%val = OpIAddCarry %struct_u32_u32_u32 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type struct to have two members: IAddCarry")); -} - -TEST_F(ValidateArithmetics, IAddCarryResultTypeMemberNotUnsignedInt) { - const std::string body = R"( -%val = OpIAddCarry %struct_s32_s32 %s32_0 %s32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type struct member types to be " - "unsigned integer scalar " - "or vector: IAddCarry")); -} - -TEST_F(ValidateArithmetics, IAddCarryWrongLeftOperand) { - const std::string body = R"( -%val = OpIAddCarry %struct_u32_u32 %s32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both operands to be of Result Type member " - "type: IAddCarry")); -} - -TEST_F(ValidateArithmetics, IAddCarryWrongRightOperand) { - const std::string body = R"( -%val = OpIAddCarry %struct_u32_u32 %u32_0 %s32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both operands to be of Result Type member " - "type: IAddCarry")); -} - -TEST_F(ValidateArithmetics, OpSMulExtendedSuccess) { - const std::string body = R"( -%val1 = OpSMulExtended %struct_u32_u32 %u32_0 %u32_1 -%val2 = OpSMulExtended %struct_s32_s32 %s32_0 %s32_1 -%val3 = OpSMulExtended %struct_u32vec2_u32vec2 %u32vec2_01 %u32vec2_12 -%val4 = OpSMulExtended %struct_s32vec2_s32vec2 %s32vec2_01 %s32vec2_12 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateArithmetics, SMulExtendedResultTypeMemberNotInt) { - const std::string body = R"( -%val = OpSMulExtended %struct_f32_f32 %f32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type struct member types to be integer scalar " - "or vector: SMulExtended")); -} - -TEST_F(ValidateArithmetics, SMulExtendedResultTypeMembersNotIdentical) { - const std::string body = R"( -%val = OpSMulExtended %struct_s32_u32 %s32_0 %s32_1 -)"; - - CompileSuccessfully(GenerateCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type struct member types to be identical: " - "SMulExtended")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_atomics_test.cpp b/3rdparty/spirv-tools/test/val/val_atomics_test.cpp deleted file mode 100644 index cd723b221..000000000 --- a/3rdparty/spirv-tools/test/val/val_atomics_test.cpp +++ /dev/null @@ -1,2152 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateAtomics = spvtest::ValidateBase; - -std::string GenerateShaderCodeImpl( - const std::string& body, const std::string& capabilities_and_extensions, - const std::string& definitions, const std::string& memory_model) { - std::ostringstream ss; - ss << R"( -OpCapability Shader -)"; - ss << capabilities_and_extensions; - ss << "OpMemoryModel Logical " << memory_model << "\n"; - ss << R"( -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%f32vec4 = OpTypeVector %f32 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0 - -%cross_device = OpConstant %u32 0 -%device = OpConstant %u32 1 -%workgroup = OpConstant %u32 2 -%subgroup = OpConstant %u32 3 -%invocation = OpConstant %u32 4 -%queuefamily = OpConstant %u32 5 - -%relaxed = OpConstant %u32 0 -%acquire = OpConstant %u32 2 -%release = OpConstant %u32 4 -%acquire_release = OpConstant %u32 8 -%acquire_and_release = OpConstant %u32 6 -%sequentially_consistent = OpConstant %u32 16 -%acquire_release_uniform_workgroup = OpConstant %u32 328 - -%f32_ptr = OpTypePointer Workgroup %f32 -%f32_var = OpVariable %f32_ptr Workgroup - -%u32_ptr = OpTypePointer Workgroup %u32 -%u32_var = OpVariable %u32_ptr Workgroup - -%f32vec4_ptr = OpTypePointer Workgroup %f32vec4 -%f32vec4_var = OpVariable %f32vec4_ptr Workgroup - -%f32_ptr_function = OpTypePointer Function %f32 -)"; - ss << definitions; - ss << R"( -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - ss << body; - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& memory_model = "GLSL450") { - const std::string defintions = R"( -%u64 = OpTypeInt 64 0 -%s64 = OpTypeInt 64 1 - -%u64_1 = OpConstant %u64 1 -%s64_1 = OpConstant %s64 1 - -%u64_ptr = OpTypePointer Workgroup %u64 -%s64_ptr = OpTypePointer Workgroup %s64 -%u64_var = OpVariable %u64_ptr Workgroup -%s64_var = OpVariable %s64_ptr Workgroup -)"; - return GenerateShaderCodeImpl( - body, "OpCapability Int64\n" + capabilities_and_extensions, defintions, - memory_model); -} - -std::string GenerateWebGPUShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - const std::string vulkan_memory_capability = R"( -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability VulkanMemoryModelKHR -)"; - const std::string vulkan_memory_extension = R"( -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - return GenerateShaderCodeImpl(body, - vulkan_memory_capability + - capabilities_and_extensions + - vulkan_memory_extension, - "", "VulkanKHR"); -} - -std::string GenerateKernelCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - std::ostringstream ss; - ss << R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability Int64 -)"; - - ss << capabilities_and_extensions; - ss << R"( -OpMemoryModel Physical32 OpenCL -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%u64 = OpTypeInt 64 0 -%f32vec4 = OpTypeVector %f32 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u64_1 = OpConstant %u64 1 -%f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0 - -%cross_device = OpConstant %u32 0 -%device = OpConstant %u32 1 -%workgroup = OpConstant %u32 2 -%subgroup = OpConstant %u32 3 -%invocation = OpConstant %u32 4 - -%relaxed = OpConstant %u32 0 -%acquire = OpConstant %u32 2 -%release = OpConstant %u32 4 -%acquire_release = OpConstant %u32 8 -%acquire_and_release = OpConstant %u32 6 -%sequentially_consistent = OpConstant %u32 16 -%acquire_release_uniform_workgroup = OpConstant %u32 328 -%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288 - -%f32_ptr = OpTypePointer Workgroup %f32 -%f32_var = OpVariable %f32_ptr Workgroup - -%u32_ptr = OpTypePointer Workgroup %u32 -%u32_var = OpVariable %u32_ptr Workgroup - -%u64_ptr = OpTypePointer Workgroup %u64 -%u64_var = OpVariable %u64_ptr Workgroup - -%f32vec4_ptr = OpTypePointer Workgroup %f32vec4 -%f32vec4_var = OpVariable %f32vec4_ptr Workgroup - -%f32_ptr_function = OpTypePointer Function %f32 -%f32_ptr_uniformconstant = OpTypePointer UniformConstant %f32 -%f32_uc_var = OpVariable %f32_ptr_uniformconstant UniformConstant - -%f32_ptr_image = OpTypePointer Image %f32 -%f32_im_var = OpVariable %f32_ptr_image Image - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -TEST_F(ValidateAtomics, AtomicLoadShaderSuccess) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %device %relaxed -%val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire -%val3 = OpAtomicLoad %u64 %u64_var %subgroup %sequentially_consistent -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicLoadKernelSuccess) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed -%val2 = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent -%val3 = OpAtomicLoad %u64 %u64_var %subgroup %acquire -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicLoadInt32VulkanSuccess) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %device %relaxed -%val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateAtomics, AtomicLoadFloatVulkan) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed -%val2 = OpAtomicLoad %f32 %f32_var %workgroup %acquire -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("expected Result Type to be int scalar type")); -} - -TEST_F(ValidateAtomics, AtomicLoadInt64WithCapabilityVulkanSuccess) { - const std::string body = R"( - %val1 = OpAtomicLoad %u64 %u64_var %device %relaxed - %val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire - )"; - - CompileSuccessfully(GenerateShaderCode(body, "OpCapability Int64Atomics\n"), - SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateAtomics, AtomicLoadInt64WithoutCapabilityVulkan) { - const std::string body = R"( - %val1 = OpAtomicLoad %u64 %u64_var %device %relaxed - %val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire - )"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("64-bit atomics require the Int64Atomics capability")); -} - -TEST_F(ValidateAtomics, AtomicStoreOpenCLFunctionPointerStorageTypeSuccess) { - const std::string body = R"( -%f32_var_function = OpVariable %f32_ptr_function Function -OpAtomicStore %f32_var_function %device %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_OPENCL_1_2); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2)); -} - -TEST_F(ValidateAtomics, AtomicStoreVulkanFunctionPointerStorageType) { - const std::string body = R"( -%f32_var_function = OpVariable %f32_ptr_function Function -OpAtomicStore %f32_var_function %device %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicStore: Function storage class forbidden when " - "the Shader capability is declared.")); -} - -// TODO(atgoo@github.com): the corresponding check fails Vulkan CTS, -// reenable once fixed. -TEST_F(ValidateAtomics, DISABLED_AtomicLoadVulkanSubgroup) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %subgroup %acquire -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicLoad: in Vulkan environment memory scope is " - "limited to Device, Workgroup and Invocation")); -} - -TEST_F(ValidateAtomics, AtomicLoadVulkanRelease) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %workgroup %release -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Vulkan spec disallows OpAtomicLoad with Memory Semantics " - "Release, AcquireRelease and SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicLoadVulkanAcquireRelease) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Vulkan spec disallows OpAtomicLoad with Memory Semantics " - "Release, AcquireRelease and SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicLoadVulkanSequentiallyConsistent) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Vulkan spec disallows OpAtomicLoad with Memory Semantics " - "Release, AcquireRelease and SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicLoadShaderFloat) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicLoad: " - "expected Result Type to be int scalar type")); -} - -TEST_F(ValidateAtomics, AtomicLoadVulkanInt64) { - const std::string body = R"( -%val1 = OpAtomicLoad %u64 %u64_var %device %relaxed -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicLoad: 64-bit atomics require the Int64Atomics capability")); -} - -TEST_F(ValidateAtomics, AtomicLoadWebGPUSuccess) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateAtomics, AtomicLoadWebGPUNonQueueFamilyFailure) { - const std::string body = R"( -%val3 = OpAtomicLoad %u32 %u32_var %invocation %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Scope is limited to QueueFamilyKHR for " - "OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, AtomicLoadWebGPUNonRelaxedFailure) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %acquire -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("no bits may be set for Memory Semantics of OpAtomic* " - "instructions")); -} - -TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64Success) { - const std::string body = R"( -%val1 = OpAtomicUMin %u64 %u64_var %device %relaxed %u64_1 -%val2 = OpAtomicUMax %u64 %u64_var %device %relaxed %u64_1 -%val3 = OpAtomicSMin %u64 %u64_var %device %relaxed %u64_1 -%val4 = OpAtomicSMax %u64 %u64_var %device %relaxed %u64_1 -%val5 = OpAtomicAnd %u64 %u64_var %device %relaxed %u64_1 -%val6 = OpAtomicOr %u64 %u64_var %device %relaxed %u64_1 -%val7 = OpAtomicXor %u64 %u64_var %device %relaxed %u64_1 -%val8 = OpAtomicIAdd %u64 %u64_var %device %relaxed %u64_1 -%val9 = OpAtomicExchange %u64 %u64_var %device %relaxed %u64_1 -%val10 = OpAtomicCompareExchange %u64 %u64_var %device %relaxed %relaxed %u64_1 %u64_1 - -%val11 = OpAtomicUMin %s64 %s64_var %device %relaxed %s64_1 -%val12 = OpAtomicUMax %s64 %s64_var %device %relaxed %s64_1 -%val13 = OpAtomicSMin %s64 %s64_var %device %relaxed %s64_1 -%val14 = OpAtomicSMax %s64 %s64_var %device %relaxed %s64_1 -%val15 = OpAtomicAnd %s64 %s64_var %device %relaxed %s64_1 -%val16 = OpAtomicOr %s64 %s64_var %device %relaxed %s64_1 -%val17 = OpAtomicXor %s64 %s64_var %device %relaxed %s64_1 -%val18 = OpAtomicIAdd %s64 %s64_var %device %relaxed %s64_1 -%val19 = OpAtomicExchange %s64 %s64_var %device %relaxed %s64_1 -%val20 = OpAtomicCompareExchange %s64 %s64_var %device %relaxed %relaxed %s64_1 %s64_1 - -%val21 = OpAtomicLoad %u64 %u64_var %device %relaxed -%val22 = OpAtomicLoad %s64 %s64_var %device %relaxed - -OpAtomicStore %u64_var %device %relaxed %u64_1 -OpAtomicStore %s64_var %device %relaxed %s64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body, "OpCapability Int64Atomics\n"), - SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64MissingCapability) { - const std::string body = R"( -%val1 = OpAtomicUMin %u64 %u64_var %device %relaxed %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicUMin: 64-bit atomics require the Int64Atomics capability")); -} - -TEST_F(ValidateAtomics, AtomicLoadWrongResultType) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32vec4 %f32vec4_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicLoad: " - "expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateAtomics, AtomicLoadWrongPointerType) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32 %f32_ptr %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 27[%_ptr_Workgroup_float] cannot be a type")); -} - -TEST_F(ValidateAtomics, AtomicLoadWrongPointerDataType) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %f32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicLoad: " - "expected Pointer to point to a value of type Result Type")); -} - -TEST_F(ValidateAtomics, AtomicLoadWrongScopeType) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32 %f32_var %f32_1 %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicLoad: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicLoadWrongMemorySemanticsType) { - const std::string body = R"( -%val1 = OpAtomicLoad %f32 %f32_var %device %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicLoad: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicStoreKernelSuccess) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -OpAtomicStore %u32_var %subgroup %release %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicStoreShaderSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %device %release %u32_1 -OpAtomicStore %u32_var %subgroup %sequentially_consistent %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicStoreVulkanSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %device %release %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateAtomics, AtomicStoreVulkanAcquire) { - const std::string body = R"( -OpAtomicStore %u32_var %device %acquire %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics " - "Acquire, AcquireRelease and SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicStoreVulkanAcquireRelease) { - const std::string body = R"( -OpAtomicStore %u32_var %device %acquire_release %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics " - "Acquire, AcquireRelease and SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicStoreVulkanSequentiallyConsistent) { - const std::string body = R"( -OpAtomicStore %u32_var %device %sequentially_consistent %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics " - "Acquire, AcquireRelease and SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicStoreWebGPUSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %queuefamily %relaxed %u32_1 -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} -TEST_F(ValidateAtomics, AtomicStoreWebGPUNonQueueFamilyFailure) { - const std::string body = R"( -OpAtomicStore %u32_var %workgroup %relaxed %u32_1 -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Scope is limited to QueueFamilyKHR for " - "OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, AtomicStoreWebGPUNonRelaxedFailure) { - const std::string body = R"( -OpAtomicStore %u32_var %queuefamily %release %u32_1 -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("no bits may be set for Memory Semantics of OpAtomic* " - "instructions")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongPointerType) { - const std::string body = R"( -OpAtomicStore %f32_1 %device %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicStore: expected Pointer to be of type OpTypePointer")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongPointerDataType) { - const std::string body = R"( -OpAtomicStore %f32vec4_var %device %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicStore: " - "expected Pointer to be a pointer to int or float scalar " - "type")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageTypeForOpenCL) { - const std::string body = R"( -OpAtomicStore %f32_im_var %device %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicStore: storage class must be Function, Workgroup, " - "CrossWorkGroup or Generic in the OpenCL environment.")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageType) { - const std::string body = R"( -OpAtomicStore %f32_uc_var %device %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicStore: storage class forbidden by universal " - "validation rules.")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongScopeType) { - const std::string body = R"( -OpAtomicStore %f32_var %f32_1 %relaxed %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicStore: expected scope to be a 32-bit int\n " - "OpAtomicStore %28 %float_1 %uint_0_1 %float_1\n")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongMemorySemanticsType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %f32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicStore: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicStoreWrongValueType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicStore: " - "expected Value type and the type pointed to by Pointer to " - "be the same")); -} - -TEST_F(ValidateAtomics, AtomicExchangeShaderSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val2 = OpAtomicExchange %u32 %u32_var %device %relaxed %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicExchangeKernelSuccess) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0 -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val4 = OpAtomicExchange %u32 %u32_var %device %relaxed %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicExchangeShaderFloat) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicExchange: " - "expected Result Type to be int scalar type")); -} - -TEST_F(ValidateAtomics, AtomicExchangeWrongResultType) { - const std::string body = R"( -OpStore %f32vec4_var %f32vec4_0000 -%val2 = OpAtomicExchange %f32vec4 %f32vec4_var %device %relaxed %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicExchange: " - "expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateAtomics, AtomicExchangeWrongPointerType) { - const std::string body = R"( -%val2 = OpAtomicExchange %f32 %f32vec4_ptr %device %relaxed %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 33[%_ptr_Workgroup_v4float] cannot be a " - "type")); -} - -TEST_F(ValidateAtomics, AtomicExchangeWrongPointerDataType) { - const std::string body = R"( -OpStore %f32vec4_var %f32vec4_0000 -%val2 = OpAtomicExchange %f32 %f32vec4_var %device %relaxed %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicExchange: " - "expected Pointer to point to a value of type Result Type")); -} - -TEST_F(ValidateAtomics, AtomicExchangeWrongScopeType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicExchange %f32 %f32_var %f32_1 %relaxed %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicExchange: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicExchangeWrongMemorySemanticsType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicExchange %f32 %f32_var %device %f32_1 %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicExchange: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicExchangeWrongValueType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicExchange: " - "expected Value to be of type Result Type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeShaderSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeKernelSuccess) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1 -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val4 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeShaderFloat) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val1 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: " - "expected Result Type to be int scalar type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongResultType) { - const std::string body = R"( -OpStore %f32vec4_var %f32vec4_0000 -%val2 = OpAtomicCompareExchange %f32vec4 %f32vec4_var %device %relaxed %relaxed %f32vec4_0000 %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: " - "expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerType) { - const std::string body = R"( -%val2 = OpAtomicCompareExchange %f32 %f32vec4_ptr %device %relaxed %relaxed %f32vec4_0000 %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 33[%_ptr_Workgroup_v4float] cannot be a " - "type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerDataType) { - const std::string body = R"( -OpStore %f32vec4_var %f32vec4_0000 -%val2 = OpAtomicCompareExchange %f32 %f32vec4_var %device %relaxed %relaxed %f32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicCompareExchange: " - "expected Pointer to point to a value of type Result Type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongScopeType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %f32_1 %relaxed %relaxed %f32_0 %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: expected scope to be a 32-bit " - "int")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType1) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %device %f32_1 %relaxed %f32_0 %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: expected Memory Semantics to " - "be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType2) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %f32_1 %f32_0 %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: expected Memory Semantics to " - "be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeUnequalRelease) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %release %f32_0 %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: Memory Semantics Release and " - "AcquireRelease cannot be used for operand Unequal")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongValueType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %u32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: " - "expected Value to be of type Result Type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWrongComparatorType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchange: " - "expected Comparator to be of type Result Type")); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWeakSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val4 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicCompareExchangeWeakWrongResultType) { - const std::string body = R"( -OpAtomicStore %f32_var %device %relaxed %f32_1 -%val2 = OpAtomicCompareExchangeWeak %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicCompareExchangeWeak: " - "expected Result Type to be int scalar type")); -} - -TEST_F(ValidateAtomics, AtomicArithmeticsSuccess) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release -%val2 = OpAtomicIDecrement %u32 %u32_var %device %acquire_release -%val3 = OpAtomicIAdd %u32 %u32_var %device %acquire_release %u32_1 -%val4 = OpAtomicISub %u32 %u32_var %device %acquire_release %u32_1 -%val5 = OpAtomicUMin %u32 %u32_var %device %acquire_release %u32_1 -%val6 = OpAtomicUMax %u32 %u32_var %device %acquire_release %u32_1 -%val7 = OpAtomicSMin %u32 %u32_var %device %sequentially_consistent %u32_1 -%val8 = OpAtomicSMax %u32 %u32_var %device %sequentially_consistent %u32_1 -%val9 = OpAtomicAnd %u32 %u32_var %device %sequentially_consistent %u32_1 -%val10 = OpAtomicOr %u32 %u32_var %device %sequentially_consistent %u32_1 -%val11 = OpAtomicXor %u32 %u32_var %device %sequentially_consistent %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicFlagsSuccess) { - const std::string body = R"( -OpAtomicFlagClear %u32_var %device %release -%val1 = OpAtomicFlagTestAndSet %bool %u32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongResultType) { - const std::string body = R"( -%val1 = OpAtomicFlagTestAndSet %u32 %u32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicFlagTestAndSet: " - "expected Result Type to be bool scalar type")); -} - -TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotPointer) { - const std::string body = R"( -%val1 = OpAtomicFlagTestAndSet %bool %u32_1 %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicFlagTestAndSet: " - "expected Pointer to be of type OpTypePointer")); -} - -TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotIntPointer) { - const std::string body = R"( -%val1 = OpAtomicFlagTestAndSet %bool %f32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicFlagTestAndSet: " - "expected Pointer to point to a value of 32-bit int type")); -} - -TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotInt32Pointer) { - const std::string body = R"( -%val1 = OpAtomicFlagTestAndSet %bool %u64_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicFlagTestAndSet: " - "expected Pointer to point to a value of 32-bit int type")); -} - -TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongScopeType) { - const std::string body = R"( -%val1 = OpAtomicFlagTestAndSet %bool %u32_var %u64_1 %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicFlagTestAndSet: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongMemorySemanticsType) { - const std::string body = R"( -%val1 = OpAtomicFlagTestAndSet %bool %u32_var %device %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicFlagTestAndSet: " - "expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicFlagClearAcquire) { - const std::string body = R"( -OpAtomicFlagClear %u32_var %device %acquire -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics Acquire and AcquireRelease cannot be " - "used with AtomicFlagClear")); -} - -TEST_F(ValidateAtomics, AtomicFlagClearNotPointer) { - const std::string body = R"( -OpAtomicFlagClear %u32_1 %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicFlagClear: " - "expected Pointer to be of type OpTypePointer")); -} - -TEST_F(ValidateAtomics, AtomicFlagClearNotIntPointer) { - const std::string body = R"( -OpAtomicFlagClear %f32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicFlagClear: " - "expected Pointer to point to a value of 32-bit int type")); -} - -TEST_F(ValidateAtomics, AtomicFlagClearNotInt32Pointer) { - const std::string body = R"( -OpAtomicFlagClear %u64_var %device %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicFlagClear: " - "expected Pointer to point to a value of 32-bit int type")); -} - -TEST_F(ValidateAtomics, AtomicFlagClearWrongScopeType) { - const std::string body = R"( -OpAtomicFlagClear %u32_var %u64_1 %relaxed -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicFlagClear: expected scope to be a 32-bit " - "int\n OpAtomicFlagClear %30 %ulong_1 %uint_0_1\n")); -} - -TEST_F(ValidateAtomics, AtomicFlagClearWrongMemorySemanticsType) { - const std::string body = R"( -OpAtomicFlagClear %u32_var %device %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicFlagClear: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateAtomics, AtomicIIncrementAcquireAndRelease) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_and_release -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicIIncrement: Memory Semantics can have at most " - "one of the following bits set: Acquire, Release, " - "AcquireRelease or SequentiallyConsistent")); -} - -TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsShader) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsKernel) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicIIncrement: Memory Semantics UniformMemory " - "requires capability Shader")); -} - -// Lack of the AtomicStorage capability is intentionally ignored, see -// https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning why. -TEST_F(ValidateAtomics, AtomicCounterMemorySemanticsNoCapability) { - const std::string body = R"( - OpAtomicStore %u32_var %device %relaxed %u32_1 -%val1 = OpAtomicIIncrement %u32 %u32_var %device -%acquire_release_atomic_counter_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, AtomicCounterMemorySemanticsWithCapability) { - const std::string body = R"( -OpAtomicStore %u32_var %device %relaxed %u32_1 -%val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_atomic_counter_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body, "OpCapability AtomicStorage\n")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicLoad) { - const std::string body = R"( -%ld = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicStore) { - const std::string body = R"( -OpAtomicStore %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, - VulkanMemoryModelBanSequentiallyConsistentAtomicExchange) { - const std::string body = R"( -%ex = OpAtomicExchange %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, - VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeEqual) { - const std::string body = R"( -%ex = OpAtomicCompareExchange %u32 %u32_var %workgroup %sequentially_consistent %relaxed %u32_0 %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, - VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeUnequal) { - const std::string body = R"( -%ex = OpAtomicCompareExchange %u32 %u32_var %workgroup %relaxed %sequentially_consistent %u32_0 %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, - VulkanMemoryModelBanSequentiallyConsistentAtomicIIncrement) { - const std::string body = R"( -%inc = OpAtomicIIncrement %u32 %u32_var %workgroup %sequentially_consistent -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, - VulkanMemoryModelBanSequentiallyConsistentAtomicIDecrement) { - const std::string body = R"( -%dec = OpAtomicIDecrement %u32 %u32_var %workgroup %sequentially_consistent -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicIAdd) { - const std::string body = R"( -%add = OpAtomicIAdd %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicISub) { - const std::string body = R"( -%sub = OpAtomicISub %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicSMin) { - const std::string body = R"( -%min = OpAtomicSMin %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicUMin) { - const std::string body = R"( -%min = OpAtomicUMin %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicSMax) { - const std::string body = R"( -%max = OpAtomicSMax %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicUMax) { - const std::string body = R"( -%max = OpAtomicUMax %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicAnd) { - const std::string body = R"( -%and = OpAtomicAnd %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicOr) { - const std::string body = R"( -%or = OpAtomicOr %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicXor) { - const std::string body = R"( -%xor = OpAtomicXor %u32 %u32_var %workgroup %sequentially_consistent %u32_0 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateAtomics, OutputMemoryKHRRequiresVulkanMemoryModelKHR) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 4100 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpAtomicStore %var %workgroup %semantics %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicStore: Memory Semantics OutputMemoryKHR " - "requires capability VulkanMemoryModelKHR")); -} - -TEST_F(ValidateAtomics, MakeAvailableKHRRequiresVulkanMemoryModelKHR) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 8196 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpAtomicStore %var %workgroup %semantics %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicStore: Memory Semantics MakeAvailableKHR " - "requires capability VulkanMemoryModelKHR")); -} - -TEST_F(ValidateAtomics, MakeVisibleKHRRequiresVulkanMemoryModelKHR) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 16386 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -%ld = OpAtomicLoad %3 %var %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicLoad: Memory Semantics MakeVisibleKHR requires " - "capability VulkanMemoryModelKHR")); -} - -TEST_F(ValidateAtomics, MakeAvailableKHRRequiresReleaseSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 8448 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpAtomicStore %var %workgroup %semantics %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicStore: MakeAvailableKHR Memory Semantics also requires " - "either Release or AcquireRelease Memory Semantics")); -} - -TEST_F(ValidateAtomics, MakeVisibleKHRRequiresAcquireSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 16640 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -%ld = OpAtomicLoad %3 %var %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("AtomicLoad: MakeVisibleKHR Memory Semantics also requires " - "either Acquire or AcquireRelease Memory Semantics")); -} - -TEST_F(ValidateAtomics, MakeAvailableKHRRequiresStorageSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 8196 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpAtomicStore %var %workgroup %semantics %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicStore: expected Memory Semantics to include a storage class")); -} - -TEST_F(ValidateAtomics, MakeVisibleKHRRequiresStorageSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 16386 -%5 = OpTypeFunction %2 -%workgroup = OpConstant %3 2 -%ptr = OpTypePointer Workgroup %3 -%var = OpVariable %ptr Workgroup -%1 = OpFunction %2 None %5 -%7 = OpLabel -%ld = OpAtomicLoad %3 %var %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicLoad: expected Memory Semantics to include a storage class")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelAllowsQueueFamilyKHR) { - const std::string body = R"( -%val = OpAtomicAnd %u32 %u32_var %queuefamily %relaxed %u32_1 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateAtomics, NonVulkanMemoryModelDisallowsQueueFamilyKHR) { - const std::string body = R"( -%val = OpAtomicAnd %u32 %u32_var %queuefamily %relaxed %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("AtomicAnd: Memory Scope QueueFamilyKHR requires " - "capability VulkanMemoryModelKHR\n %42 = OpAtomicAnd " - "%uint %29 %uint_5 %uint_0_1 %uint_1\n")); -} - -TEST_F(ValidateAtomics, SemanticsSpecConstantShader) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%spec_const = OpSpecConstant %int 0 -%workgroup = OpConstant %int 2 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%ld = OpAtomicLoad %int %var %workgroup %spec_const -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics ids must be OpConstant when Shader " - "capability is present")); -} - -TEST_F(ValidateAtomics, SemanticsSpecConstantKernel) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%spec_const = OpSpecConstant %int 0 -%workgroup = OpConstant %int 2 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%ld = OpAtomicLoad %int %var %workgroup %spec_const -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, ScopeSpecConstantShader) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%spec_const = OpSpecConstant %int 0 -%relaxed = OpConstant %int 0 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%ld = OpAtomicLoad %int %var %spec_const %relaxed -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Scope ids must be OpConstant when Shader capability is present")); -} - -TEST_F(ValidateAtomics, ScopeSpecConstantKernel) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%spec_const = OpSpecConstant %int 0 -%relaxed = OpConstant %int 0 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%ld = OpAtomicLoad %int %var %spec_const %relaxed -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeBad) { - const std::string body = R"( -%val = OpAtomicAnd %u32 %u32_var %device %relaxed %u32_1 -)"; - - const std::string extra = R"(OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeGood) { - const std::string body = R"( -%val = OpAtomicAnd %u32 %u32_var %device %relaxed %u32_1 -)"; - - const std::string extra = R"(OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"), - SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateAtomics, WebGPUCrossDeviceMemoryScopeBad) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %cross_device %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("in WebGPU environment Memory Scope is limited to " - "QueueFamilyKHR for OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, WebGPUDeviceMemoryScopeBad) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %device %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("in WebGPU environment Memory Scope is limited to " - "QueueFamilyKHR for OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, WebGPUWorkgroupMemoryScopeBad) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %workgroup %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("in WebGPU environment Memory Scope is limited to " - "QueueFamilyKHR for OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, WebGPUSubgroupMemoryScopeBad) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %subgroup %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("in WebGPU environment Memory Scope is limited to " - "QueueFamilyKHR for OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, WebGPUInvocationMemoryScopeBad) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %invocation %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("in WebGPU environment Memory Scope is limited to " - "QueueFamilyKHR for OpAtomic* operations")); -} - -TEST_F(ValidateAtomics, WebGPUQueueFamilyMemoryScopeGood) { - const std::string body = R"( -%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %relaxed -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateAtomics, CompareExchangeWeakV13ValV14Good) { - const std::string body = R"( -%val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateAtomics, CompareExchangeWeakV14Bad) { - const std::string body = R"( -%val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_WRONG_VERSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "AtomicCompareExchangeWeak requires SPIR-V version 1.3 or earlier")); -} - -TEST_F(ValidateAtomics, CompareExchangeVolatileMatch) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%volatile = OpConstant %int 32768 -%ptr_wg_int = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %volatile %volatile %int_0 %int_1 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, CompareExchangeVolatileMismatch) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%volatile = OpConstant %int 32768 -%non_volatile = OpConstant %int 0 -%ptr_wg_int = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %non_volatile %volatile %int_0 %int_1 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Volatile mask setting must match for Equal and " - "Unequal memory semantics")); -} - -TEST_F(ValidateAtomics, CompareExchangeVolatileMismatchCooperativeMatrix) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpCapability CooperativeMatrixNV -OpExtension "SPV_KHR_vulkan_memory_model" -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%volatile = OpSpecConstant %int 32768 -%non_volatile = OpSpecConstant %int 32768 -%ptr_wg_int = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %volatile %non_volatile %int_0 %int_1 -OpReturn -OpFunctionEnd -)"; - - // This is ok because we cannot evaluate the spec constant defaults. - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateAtomics, VolatileRequiresVulkanMemoryModel) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%volatile = OpConstant %int 32768 -%ptr_wg_int = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpAtomicLoad %int %wg_var %workgroup %volatile -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics Volatile requires capability " - "VulkanMemoryModelKHR")); -} - -TEST_F(ValidateAtomics, CooperativeMatrixSemanticsMustBeConstant) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%undef = OpUndef %int -%ptr_wg_int = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%ld = OpAtomicLoad %int %wg_var %workgroup %undef -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics must be a constant instruction when " - "CooperativeMatrixNV capability is present")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_barriers_test.cpp b/3rdparty/spirv-tools/test/val/val_barriers_test.cpp deleted file mode 100644 index ae166d954..000000000 --- a/3rdparty/spirv-tools/test/val/val_barriers_test.cpp +++ /dev/null @@ -1,1546 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateBarriers = spvtest::ValidateBase; - -std::string GenerateShaderCodeImpl( - const std::string& body, const std::string& capabilities_and_extensions, - const std::string& definitions, const std::string& execution_model, - const std::string& memory_model) { - std::ostringstream ss; - ss << R"( -OpCapability Shader -)"; - - ss << capabilities_and_extensions; - ss << memory_model << std::endl; - ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; - if (execution_model == "Fragment") { - ss << "OpExecutionMode %main OriginUpperLeft\n"; - } else if (execution_model == "Geometry") { - ss << "OpExecutionMode %main InputPoints\n"; - ss << "OpExecutionMode %main OutputPoints\n"; - } else if (execution_model == "GLCompute") { - ss << "OpExecutionMode %main LocalSize 1 1 1\n"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_4 = OpConstant %u32 4 -)"; - ss << definitions; - ss << R"( -%cross_device = OpConstant %u32 0 -%device = OpConstant %u32 1 -%workgroup = OpConstant %u32 2 -%subgroup = OpConstant %u32 3 -%invocation = OpConstant %u32 4 -%queuefamily = OpConstant %u32 5 - -%none = OpConstant %u32 0 -%acquire = OpConstant %u32 2 -%release = OpConstant %u32 4 -%acquire_release = OpConstant %u32 8 -%acquire_and_release = OpConstant %u32 6 -%sequentially_consistent = OpConstant %u32 16 -%acquire_release_uniform_workgroup = OpConstant %u32 328 -%acquire_uniform_workgroup = OpConstant %u32 322 -%release_uniform_workgroup = OpConstant %u32 324 -%acquire_and_release_uniform = OpConstant %u32 70 -%acquire_release_subgroup = OpConstant %u32 136 -%acquire_release_workgroup = OpConstant %u32 264 -%uniform = OpConstant %u32 64 -%uniform_workgroup = OpConstant %u32 320 -%workgroup_memory = OpConstant %u32 256 -%image_memory = OpConstant %u32 2048 -%uniform_image_memory = OpConstant %u32 2112 - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "GLCompute") { - const std::string int64_capability = R"( -OpCapability Int64 -)"; - const std::string int64_declarations = R"( -%u64 = OpTypeInt 64 0 -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -)"; - const std::string memory_model = "OpMemoryModel Logical GLSL450"; - return GenerateShaderCodeImpl( - body, int64_capability + capabilities_and_extensions, int64_declarations, - execution_model, memory_model); -} - -std::string GenerateWebGPUShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "GLCompute") { - const std::string vulkan_memory_capability = R"( -OpCapability VulkanMemoryModelKHR -)"; - const std::string vulkan_memory_extension = R"( -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - const std::string memory_model = "OpMemoryModel Logical VulkanKHR"; - return GenerateShaderCodeImpl(body, - vulkan_memory_capability + - capabilities_and_extensions + - vulkan_memory_extension, - "", execution_model, memory_model); -} - -std::string GenerateKernelCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - std::ostringstream ss; - ss << R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability Int64 -OpCapability NamedBarrier -)"; - - ss << capabilities_and_extensions; - ss << R"( -OpMemoryModel Physical32 OpenCL -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%u64 = OpTypeInt 64 0 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_4 = OpConstant %f32 4 -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_4 = OpConstant %u32 4 -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_4 = OpConstant %u64 4 - -%cross_device = OpConstant %u32 0 -%device = OpConstant %u32 1 -%workgroup = OpConstant %u32 2 -%subgroup = OpConstant %u32 3 -%invocation = OpConstant %u32 4 - -%none = OpConstant %u32 0 -%acquire = OpConstant %u32 2 -%release = OpConstant %u32 4 -%acquire_release = OpConstant %u32 8 -%acquire_and_release = OpConstant %u32 6 -%sequentially_consistent = OpConstant %u32 16 -%acquire_release_workgroup = OpConstant %u32 264 - -%named_barrier = OpTypeNamedBarrier - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -TEST_F(ValidateBarriers, OpControlBarrierGLComputeSuccess) { - const std::string body = R"( -OpControlBarrier %device %device %none -OpControlBarrier %workgroup %workgroup %acquire -OpControlBarrier %workgroup %device %release -OpControlBarrier %cross_device %cross_device %acquire_release -OpControlBarrier %cross_device %cross_device %sequentially_consistent -OpControlBarrier %cross_device %cross_device %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBarriers, OpControlBarrierKernelSuccess) { - const std::string body = R"( -OpControlBarrier %device %device %none -OpControlBarrier %workgroup %workgroup %acquire -OpControlBarrier %workgroup %device %release -OpControlBarrier %cross_device %cross_device %acquire_release -OpControlBarrier %cross_device %cross_device %sequentially_consistent -OpControlBarrier %cross_device %cross_device %acquire_release_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); -} - -TEST_F(ValidateBarriers, OpControlBarrierTesselationControlSuccess) { - const std::string body = R"( -OpControlBarrier %device %device %none -OpControlBarrier %workgroup %workgroup %acquire -OpControlBarrier %workgroup %device %release -OpControlBarrier %cross_device %cross_device %acquire_release -OpControlBarrier %cross_device %cross_device %sequentially_consistent -OpControlBarrier %cross_device %cross_device %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n", - "TessellationControl")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBarriers, OpControlBarrierVulkanSuccess) { - const std::string body = R"( -OpControlBarrier %workgroup %device %none -OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUAcquireReleaseSuccess) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPURelaxedFailure) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, AcquireRelease must be set for Memory " - "Semantics of OpControlBarrier")); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUMissingWorkgroupFailure) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, WorkgroupMemory must be set for Memory " - "Semantics")); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUUniformFailure) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("For WebGPU only WorkgroupMemory and AcquireRelease may be set " - "for Memory Semantics of OpControlBarrier.")); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUReleaseFailure) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, AcquireRelease must be set for Memory " - "Semantics of OpControlBarrier")); -} - -TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv12) { - const std::string body = R"( -OpControlBarrier %device %device %none -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"), - SPV_ENV_UNIVERSAL_1_2); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpControlBarrier requires one of the following Execution " - "Models: TessellationControl, GLCompute or Kernel")); -} - -TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv13) { - const std::string body = R"( -OpControlBarrier %device %device %none -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"), - SPV_ENV_UNIVERSAL_1_3); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateBarriers, OpControlBarrierFloatExecutionScope) { - const std::string body = R"( -OpControlBarrier %f32_1 %device %none -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpControlBarrierU64ExecutionScope) { - const std::string body = R"( -OpControlBarrier %u64_1 %device %none -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpControlBarrierFloatMemoryScope) { - const std::string body = R"( -OpControlBarrier %device %f32_1 %none -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpControlBarrierU64MemoryScope) { - const std::string body = R"( -OpControlBarrier %device %u64_1 %none -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpControlBarrierFloatMemorySemantics) { - const std::string body = R"( -OpControlBarrier %device %device %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ControlBarrier: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpControlBarrierU64MemorySemantics) { - const std::string body = R"( -OpControlBarrier %device %device %u64_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ControlBarrier: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpControlBarrierVulkanExecutionScopeDevice) { - const std::string body = R"( -OpControlBarrier %device %workgroup %none -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: in Vulkan environment Execution Scope " - "is limited to Workgroup and Subgroup")); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUExecutionScopeDeviceBad) { - const std::string body = R"( -OpControlBarrier %device %workgroup %none -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: in WebGPU environment Execution Scope " - "is limited to Workgroup")); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUExecutionScopeSubgroupBad) { - const std::string body = R"( -OpControlBarrier %subgroup %workgroup %none -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: in WebGPU environment Execution Scope " - "is limited to Workgroup")); -} - -TEST_F(ValidateBarriers, OpControlBarrierVulkanMemoryScopeSubgroup) { - const std::string body = R"( -OpControlBarrier %subgroup %subgroup %none -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ControlBarrier: in Vulkan 1.0 environment Memory Scope is " - "limited to Device, Workgroup and Invocation")); -} - -TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeSubgroup) { - const std::string body = R"( -OpControlBarrier %subgroup %subgroup %none -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeCrossDevice) { - const std::string body = R"( -OpControlBarrier %subgroup %cross_device %none -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: in Vulkan environment, Memory Scope " - "cannot be CrossDevice")); -} - -TEST_F(ValidateBarriers, OpControlBarrierWebGPUMemoryScopeNonWorkgroup) { - const std::string body = R"( -OpControlBarrier %workgroup %subgroup %acquire_release_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: in WebGPU environment Memory Scope is " - "limited to Workgroup for OpControlBarrier")); -} - -TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) { - const std::string body = R"( -OpControlBarrier %device %device %acquire_and_release_uniform -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: Memory Semantics can have at most one " - "of the following bits set: Acquire, Release, " - "AcquireRelease or SequentiallyConsistent")); -} - -// TODO(atgoo@github.com): the corresponding check fails Vulkan CTS, -// reenable once fixed. -TEST_F(ValidateBarriers, DISABLED_OpControlBarrierVulkanSubgroupStorageClass) { - const std::string body = R"( -OpControlBarrier %workgroup %device %acquire_release_subgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ControlBarrier: expected Memory Semantics to include a " - "Vulkan-supported storage class if Memory Semantics is not None")); -} - -TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p1) { - const std::string body = R"( -OpControlBarrier %subgroup %subgroup %acquire_release_subgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionFragment1p1) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpControlBarrier execution scope must be Subgroup for " - "Fragment, Vertex, Geometry and TessellationEvaluation " - "execution models")); -} - -TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) { - const std::string body = R"( -OpControlBarrier %subgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"), - SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpControlBarrier requires one of the following Execution " - "Models: TessellationControl, GLCompute or Kernel")); -} - -TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p1) { - const std::string body = R"( -OpControlBarrier %subgroup %subgroup %acquire_release_subgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionVertex1p1) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpControlBarrier execution scope must be Subgroup for " - "Fragment, Vertex, Geometry and TessellationEvaluation " - "execution models")); -} - -TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) { - const std::string body = R"( -OpControlBarrier %subgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"), - SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpControlBarrier requires one of the following Execution " - "Models: TessellationControl, GLCompute or Kernel")); -} - -TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p1) { - const std::string body = R"( -OpControlBarrier %subgroup %subgroup %acquire_release_subgroup -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionGeometry1p1) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpControlBarrier execution scope must be Subgroup for " - "Fragment, Vertex, Geometry and TessellationEvaluation " - "execution models")); -} - -TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) { - const std::string body = R"( -OpControlBarrier %subgroup %workgroup %acquire_release -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"), - SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpControlBarrier requires one of the following Execution " - "Models: TessellationControl, GLCompute or Kernel")); -} - -TEST_F(ValidateBarriers, - OpControlBarrierSubgroupExecutionTessellationEvaluation1p1) { - const std::string body = R"( -OpControlBarrier %subgroup %subgroup %acquire_release_subgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n", - "TessellationEvaluation"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBarriers, - OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1) { - const std::string body = R"( -OpControlBarrier %workgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n", - "TessellationEvaluation"), - SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpControlBarrier execution scope must be Subgroup for " - "Fragment, Vertex, Geometry and TessellationEvaluation " - "execution models")); -} - -TEST_F(ValidateBarriers, - OpControlBarrierSubgroupExecutionTessellationEvaluation1p0) { - const std::string body = R"( -OpControlBarrier %subgroup %workgroup %acquire_release -)"; - - CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n", - "TessellationEvaluation"), - SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpControlBarrier requires one of the following Execution " - "Models: TessellationControl, GLCompute or Kernel")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierSuccess) { - const std::string body = R"( -OpMemoryBarrier %cross_device %acquire_release_uniform_workgroup -OpMemoryBarrier %device %uniform -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierKernelSuccess) { - const std::string body = R"( -OpMemoryBarrier %cross_device %acquire_release_workgroup -OpMemoryBarrier %device %none -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSuccess) { - const std::string body = R"( -OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUImageMemorySuccess) { - const std::string body = R"( -OpMemoryBarrier %workgroup %image_memory -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUDeviceFailure) { - const std::string body = R"( -OpMemoryBarrier %subgroup %image_memory -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("in WebGPU environment Memory Scope is limited to " - "Workgroup for OpMemoryBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireReleaseFailure) { - const std::string body = R"( -OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ImageMemory must be set for Memory Semantics of " - "OpMemoryBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPURelaxedFailure) { - const std::string body = R"( -OpMemoryBarrier %workgroup %uniform_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ImageMemory must be set for Memory Semantics of " - "OpMemoryBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireFailure) { - const std::string body = R"( -OpMemoryBarrier %workgroup %acquire_uniform_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ImageMemory must be set for Memory Semantics of " - "OpMemoryBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUReleaseFailure) { - const std::string body = R"( -OpMemoryBarrier %workgroup %release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ImageMemory must be set for Memory Semantics of " - "OpMemoryBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUUniformFailure) { - const std::string body = R"( -OpMemoryBarrier %workgroup %uniform_image_memory -)"; - - CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("only ImageMemory may be set for Memory Semantics of " - "OpMemoryBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) { - const std::string body = R"( -OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierU64MemoryScope) { - const std::string body = R"( -OpMemoryBarrier %u64_1 %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemorySemantics) { - const std::string body = R"( -OpMemoryBarrier %device %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierU64MemorySemantics) { - const std::string body = R"( -OpMemoryBarrier %device %u64_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemoryScopeSubgroup) { - const std::string body = R"( -OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("MemoryBarrier: in Vulkan 1.0 environment Memory Scope is " - "limited to Device, Workgroup and Invocation")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierVulkan1p1MemoryScopeSubgroup) { - const std::string body = R"( -OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierAcquireAndRelease) { - const std::string body = R"( -OpMemoryBarrier %device %acquire_and_release_uniform -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: Memory Semantics can have at most one " - "of the following bits set: Acquire, Release, " - "AcquireRelease or SequentiallyConsistent")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsNone) { - const std::string body = R"( -OpMemoryBarrier %device %none -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("MemoryBarrier: Vulkan specification requires Memory Semantics " - "to have one of the following bits set: Acquire, Release, " - "AcquireRelease or SequentiallyConsistent")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsAcquire) { - const std::string body = R"( -OpMemoryBarrier %device %acquire -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: expected Memory Semantics to include a " - "Vulkan-supported storage class")); -} - -TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSubgroupStorageClass) { - const std::string body = R"( -OpMemoryBarrier %device %acquire_release_subgroup -)"; - - CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: expected Memory Semantics to include a " - "Vulkan-supported storage class")); -} - -TEST_F(ValidateBarriers, OpNamedBarrierInitializeSuccess) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %u32_4 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); -} - -TEST_F(ValidateBarriers, OpNamedBarrierInitializeWrongResultType) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %u32 %u32_4 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NamedBarrierInitialize: expected Result Type to be " - "OpTypeNamedBarrier")); -} - -TEST_F(ValidateBarriers, OpNamedBarrierInitializeFloatSubgroupCount) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %f32_4 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be " - "a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpNamedBarrierInitializeU64SubgroupCount) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %u64_4 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be " - "a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryNamedBarrierSuccess) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %u32_4 -OpMemoryNamedBarrier %barrier %workgroup %acquire_release_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); -} - -TEST_F(ValidateBarriers, OpMemoryNamedBarrierNotNamedBarrier) { - const std::string body = R"( -OpMemoryNamedBarrier %u32_1 %workgroup %acquire_release_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryNamedBarrier: expected Named Barrier to be of " - "type OpTypeNamedBarrier")); -} - -TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemoryScope) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %u32_4 -OpMemoryNamedBarrier %barrier %f32_1 %acquire_release_workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("MemoryNamedBarrier: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemorySemantics) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %u32_4 -OpMemoryNamedBarrier %barrier %workgroup %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "MemoryNamedBarrier: expected Memory Semantics to be a 32-bit int")); -} - -TEST_F(ValidateBarriers, OpMemoryNamedBarrierAcquireAndRelease) { - const std::string body = R"( -%barrier = OpNamedBarrierInitialize %named_barrier %u32_4 -OpMemoryNamedBarrier %barrier %workgroup %acquire_and_release -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryNamedBarrier: Memory Semantics can have at most " - "one of the following bits set: Acquire, Release, " - "AcquireRelease or SequentiallyConsistent")); -} - -TEST_F(ValidateBarriers, TypeAsMemoryScope) { - const std::string body = R"( -OpMemoryBarrier %u32 %u32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%uint] cannot be a " - "type")); -} - -TEST_F(ValidateBarriers, - OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpConstant %3 16 -%5 = OpTypeFunction %2 -%6 = OpConstant %3 5 -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpControlBarrier %6 %6 %4 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateBarriers, - OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpConstant %3 16 -%5 = OpTypeFunction %2 -%6 = OpConstant %3 5 -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpMemoryBarrier %6 %4 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("SequentiallyConsistent memory semantics cannot be " - "used with the VulkanKHR memory model.")); -} - -TEST_F(ValidateBarriers, OutputMemoryKHRRequireVulkanMemoryModelKHR) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 4104 -%5 = OpTypeFunction %2 -%device = OpConstant %3 1 -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpControlBarrier %device %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: Memory Semantics OutputMemoryKHR " - "requires capability VulkanMemoryModelKHR")); -} - -TEST_F(ValidateBarriers, MakeAvailableKHRRequireVulkanMemoryModelKHR) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 8264 -%5 = OpTypeFunction %2 -%device = OpConstant %3 1 -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpControlBarrier %device %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: Memory Semantics MakeAvailableKHR " - "requires capability VulkanMemoryModelKHR")); -} - -TEST_F(ValidateBarriers, MakeVisibleKHRRequireVulkanMemoryModelKHR) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%semantics = OpConstant %3 16456 -%5 = OpTypeFunction %2 -%device = OpConstant %3 1 -%1 = OpFunction %2 None %5 -%7 = OpLabel -OpControlBarrier %device %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ControlBarrier: Memory Semantics MakeVisibleKHR " - "requires capability VulkanMemoryModelKHR")); -} - -TEST_F(ValidateBarriers, MakeAvailableKHRRequiresReleaseSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%workgroup = OpConstant %int 2 -%semantics = OpConstant %int 8448 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpControlBarrier %workgroup %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ControlBarrier: MakeAvailableKHR Memory Semantics also " - "requires either Release or AcquireRelease Memory Semantics")); -} - -TEST_F(ValidateBarriers, MakeVisibleKHRRequiresAcquireSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%workgroup = OpConstant %int 2 -%semantics = OpConstant %int 16640 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpControlBarrier %workgroup %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ControlBarrier: MakeVisibleKHR Memory Semantics also requires " - "either Acquire or AcquireRelease Memory Semantics")); -} - -TEST_F(ValidateBarriers, MakeAvailableKHRRequiresStorageSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%workgroup = OpConstant %int 2 -%semantics = OpConstant %int 8196 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpMemoryBarrier %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: expected Memory Semantics to include a " - "storage class")); -} - -TEST_F(ValidateBarriers, MakeVisibleKHRRequiresStorageSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%workgroup = OpConstant %int 2 -%semantics = OpConstant %int 16386 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpMemoryBarrier %workgroup %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MemoryBarrier: expected Memory Semantics to include a " - "storage class")); -} - -TEST_F(ValidateBarriers, SemanticsSpecConstantShader) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%spec_const = OpSpecConstant %int 0 -%workgroup = OpConstant %int 2 -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpMemoryBarrier %workgroup %spec_const -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics ids must be OpConstant when Shader " - "capability is present")); -} - -TEST_F(ValidateBarriers, SemanticsSpecConstantKernel) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%spec_const = OpSpecConstant %int 0 -%workgroup = OpConstant %int 2 -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpMemoryBarrier %workgroup %spec_const -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBarriers, ScopeSpecConstantShader) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%spec_const = OpSpecConstant %int 0 -%relaxed = OpConstant %int 0 -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpMemoryBarrier %spec_const %relaxed -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Scope ids must be OpConstant when Shader " - "capability is present")); -} - -TEST_F(ValidateBarriers, ScopeSpecConstantKernel) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_workgroup Workgroup -%voidfn = OpTypeFunction %void -%spec_const = OpSpecConstant %int 0 -%relaxed = OpConstant %int 0 -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpMemoryBarrier %spec_const %relaxed -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeBad) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%semantics = OpConstant %int 0 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpMemoryBarrier %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeGood) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%semantics = OpConstant %int 0 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpMemoryBarrier %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateBarriers, VolatileMemoryBarrier) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%semantics = OpConstant %int 32768 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpMemoryBarrier %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics Volatile can only be used with " - "atomic instructions")); -} - -TEST_F(ValidateBarriers, VolatileControlBarrier) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%semantics = OpConstant %int 32768 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpControlBarrier %device %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics Volatile can only be used with " - "atomic instructions")); -} - -TEST_F(ValidateBarriers, CooperativeMatrixSpecConstantVolatile) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability CooperativeMatrixNV -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%semantics = OpSpecConstant %int 32768 -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpControlBarrier %device %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBarriers, CooperativeMatrixNonConstantSemantics) { - const std::string text = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability CooperativeMatrixNV -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%semantics = OpUndef %int -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpControlBarrier %device %device %semantics -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory Semantics must be a constant instruction when " - "CooperativeMatrixNV capability is present")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_bitwise_test.cpp b/3rdparty/spirv-tools/test/val/val_bitwise_test.cpp deleted file mode 100644 index 1001def8f..000000000 --- a/3rdparty/spirv-tools/test/val/val_bitwise_test.cpp +++ /dev/null @@ -1,549 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateBitwise = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - const std::string capabilities = - R"( -OpCapability Shader -OpCapability Int64 -OpCapability Float64)"; - - const std::string after_extension_before_body = - R"( -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%f64 = OpTypeFloat 64 -%u64 = OpTypeInt 64 0 -%s64 = OpTypeInt 64 1 -%boolvec2 = OpTypeVector %bool 2 -%s32vec2 = OpTypeVector %s32 2 -%u32vec2 = OpTypeVector %u32 2 -%u64vec2 = OpTypeVector %u64 2 -%f32vec2 = OpTypeVector %f32 2 -%f64vec2 = OpTypeVector %f64 2 -%boolvec3 = OpTypeVector %bool 3 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%s32vec3 = OpTypeVector %s32 3 -%f32vec3 = OpTypeVector %f32 3 -%f64vec3 = OpTypeVector %f64 3 -%boolvec4 = OpTypeVector %bool 4 -%u32vec4 = OpTypeVector %u32 4 -%u64vec4 = OpTypeVector %u64 4 -%s32vec4 = OpTypeVector %s32 4 -%f32vec4 = OpTypeVector %f32 4 -%f64vec4 = OpTypeVector %f64 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 - -%s32_0 = OpConstant %s32 0 -%s32_1 = OpConstant %s32 1 -%s32_2 = OpConstant %s32 2 -%s32_3 = OpConstant %s32 3 -%s32_4 = OpConstant %s32 4 -%s32_m1 = OpConstant %s32 -1 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64_4 = OpConstant %f64 4 - -%s64_0 = OpConstant %s64 0 -%s64_1 = OpConstant %s64 1 -%s64_2 = OpConstant %s64 2 -%s64_3 = OpConstant %s64 3 -%s64_4 = OpConstant %s64 4 -%s64_m1 = OpConstant %s64 -1 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_4 = OpConstant %u64 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1 -%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2 -%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2 -%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3 -%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3 -%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4 - -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string after_body = - R"( -OpReturn -OpFunctionEnd)"; - - return capabilities + capabilities_and_extensions + - after_extension_before_body + body + after_body; -} - -TEST_F(ValidateBitwise, ShiftAllSuccess) { - const std::string body = R"( -%val1 = OpShiftRightLogical %u64 %u64_1 %s32_2 -%val2 = OpShiftRightArithmetic %s32vec2 %s32vec2_12 %s32vec2_12 -%val3 = OpShiftLeftLogical %u32vec2 %s32vec2_12 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBitwise, OpShiftRightLogicalWrongResultType) { - const std::string body = R"( -%val1 = OpShiftRightLogical %bool %u64_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as Result Type: " - "ShiftRightLogical")); -} - -TEST_F(ValidateBitwise, OpShiftRightLogicalBaseNotInt) { - const std::string body = R"( -%val1 = OpShiftRightLogical %u32 %f32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Base to be int scalar or vector: ShiftRightLogical")); -} - -TEST_F(ValidateBitwise, OpShiftRightLogicalBaseWrongDimension) { - const std::string body = R"( -%val1 = OpShiftRightLogical %u32 %u32vec2_12 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Base to have the same dimension as Result Type: " - "ShiftRightLogical")); -} - -TEST_F(ValidateBitwise, OpShiftRightLogicalBaseWrongBitWidth) { - const std::string body = R"( -%val1 = OpShiftRightLogical %u64 %u32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Base to have the same bit width as Result Type: " - "ShiftRightLogical")); -} - -TEST_F(ValidateBitwise, OpShiftRightLogicalShiftNotInt) { - const std::string body = R"( -%val1 = OpShiftRightLogical %u32 %u32_1 %f32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Shift to be int scalar or vector: ShiftRightLogical")); -} - -TEST_F(ValidateBitwise, OpShiftRightLogicalShiftWrongDimension) { - const std::string body = R"( -%val1 = OpShiftRightLogical %u32 %u32_1 %s32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Shift to have the same dimension as Result Type: " - "ShiftRightLogical")); -} - -TEST_F(ValidateBitwise, LogicAllSuccess) { - const std::string body = R"( -%val1 = OpBitwiseOr %u64 %u64_1 %s64_0 -%val2 = OpBitwiseAnd %s64 %s64_1 %u64_0 -%val3 = OpBitwiseXor %s32vec2 %s32vec2_12 %u32vec2_01 -%val4 = OpNot %s32vec2 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBitwise, OpBitwiseAndWrongResultType) { - const std::string body = R"( -%val1 = OpBitwiseAnd %bool %u64_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected int scalar or vector type as Result Type: BitwiseAnd")); -} - -TEST_F(ValidateBitwise, OpBitwiseAndLeftNotInt) { - const std::string body = R"( -%val1 = OpBitwiseAnd %u32 %f32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector as operand: BitwiseAnd " - "operand index 2")); -} - -TEST_F(ValidateBitwise, OpBitwiseAndRightNotInt) { - const std::string body = R"( -%val1 = OpBitwiseAnd %u32 %u32_1 %f32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector as operand: BitwiseAnd " - "operand index 3")); -} - -TEST_F(ValidateBitwise, OpBitwiseAndLeftWrongDimension) { - const std::string body = R"( -%val1 = OpBitwiseAnd %u32 %u32vec2_12 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to have the same dimension as Result Type: " - "BitwiseAnd operand index 2")); -} - -TEST_F(ValidateBitwise, OpBitwiseAndRightWrongDimension) { - const std::string body = R"( -%val1 = OpBitwiseAnd %u32 %s32_2 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to have the same dimension as Result Type: " - "BitwiseAnd operand index 3")); -} - -TEST_F(ValidateBitwise, OpBitwiseAndLeftWrongBitWidth) { - const std::string body = R"( -%val1 = OpBitwiseAnd %u64 %u32_1 %s64_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to have the same bit width as Result Type: " - "BitwiseAnd operand index 2")); -} - -TEST_F(ValidateBitwise, OpBitwiseAndRightWrongBitWidth) { - const std::string body = R"( -%val1 = OpBitwiseAnd %u64 %u64_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to have the same bit width as Result Type: " - "BitwiseAnd operand index 3")); -} - -TEST_F(ValidateBitwise, OpBitFieldInsertSuccess) { - const std::string body = R"( -%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %s32_1 %s32_2 -%val2 = OpBitFieldInsert %s32vec2 %s32vec2_12 %s32vec2_12 %s32_1 %u32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBitwise, OpBitFieldInsertWrongResultType) { - const std::string body = R"( -%val1 = OpBitFieldInsert %bool %u64_1 %u64_2 %s32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected int scalar or vector type as Result Type: BitFieldInsert")); -} - -TEST_F(ValidateBitwise, OpBitFieldInsertWrongBaseType) { - const std::string body = R"( -%val1 = OpBitFieldInsert %u64 %s64_1 %u64_2 %s32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Base Type to be equal to Result Type: BitFieldInsert")); -} - -TEST_F(ValidateBitwise, OpBitFieldInsertWrongInsertType) { - const std::string body = R"( -%val1 = OpBitFieldInsert %u64 %u64_1 %s64_2 %s32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Insert Type to be equal to Result Type: BitFieldInsert")); -} - -TEST_F(ValidateBitwise, OpBitFieldInsertOffsetNotInt) { - const std::string body = R"( -%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %f32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Offset Type to be int scalar: BitFieldInsert")); -} - -TEST_F(ValidateBitwise, OpBitFieldInsertCountNotInt) { - const std::string body = R"( -%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %u32_1 %f32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Count Type to be int scalar: BitFieldInsert")); -} - -TEST_F(ValidateBitwise, OpBitFieldSExtractSuccess) { - const std::string body = R"( -%val1 = OpBitFieldSExtract %u64 %u64_1 %s32_1 %s32_2 -%val2 = OpBitFieldSExtract %s32vec2 %s32vec2_12 %s32_1 %u32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBitwise, OpBitFieldSExtractWrongResultType) { - const std::string body = R"( -%val1 = OpBitFieldSExtract %bool %u64_1 %s32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as Result Type: " - "BitFieldSExtract")); -} - -TEST_F(ValidateBitwise, OpBitFieldSExtractWrongBaseType) { - const std::string body = R"( -%val1 = OpBitFieldSExtract %u64 %s64_1 %s32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Base Type to be equal to Result Type: BitFieldSExtract")); -} - -TEST_F(ValidateBitwise, OpBitFieldSExtractOffsetNotInt) { - const std::string body = R"( -%val1 = OpBitFieldSExtract %u64 %u64_1 %f32_1 %s32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Offset Type to be int scalar: BitFieldSExtract")); -} - -TEST_F(ValidateBitwise, OpBitFieldSExtractCountNotInt) { - const std::string body = R"( -%val1 = OpBitFieldSExtract %u64 %u64_1 %u32_1 %f32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Count Type to be int scalar: BitFieldSExtract")); -} - -TEST_F(ValidateBitwise, OpBitReverseSuccess) { - const std::string body = R"( -%val1 = OpBitReverse %u64 %u64_1 -%val2 = OpBitReverse %s32vec2 %s32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBitwise, OpBitReverseWrongResultType) { - const std::string body = R"( -%val1 = OpBitReverse %bool %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected int scalar or vector type as Result Type: BitReverse")); -} - -TEST_F(ValidateBitwise, OpBitReverseWrongBaseType) { - const std::string body = R"( -%val1 = OpBitReverse %u64 %s64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Base Type to be equal to Result Type: BitReverse")); -} - -TEST_F(ValidateBitwise, OpBitCountSuccess) { - const std::string body = R"( -%val1 = OpBitCount %s32 %u64_1 -%val2 = OpBitCount %u32vec2 %s32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBitwise, OpBitCountWrongResultType) { - const std::string body = R"( -%val1 = OpBitCount %bool %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as Result Type: BitCount")); -} - -TEST_F(ValidateBitwise, OpBitCountBaseNotInt) { - const std::string body = R"( -%val1 = OpBitCount %u32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Base Type to be int scalar or vector: BitCount")); -} - -TEST_F(ValidateBitwise, OpBitCountBaseWrongDimension) { - const std::string body = R"( -%val1 = OpBitCount %u32 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Base dimension to be equal to Result Type dimension: " - "BitCount")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_builtins_test.cpp b/3rdparty/spirv-tools/test/val/val_builtins_test.cpp deleted file mode 100644 index 58593dcf9..000000000 --- a/3rdparty/spirv-tools/test/val/val_builtins_test.cpp +++ /dev/null @@ -1,3379 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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. - -// Tests validation rules of GLSL.450.std and OpenCL.std extended instructions. -// Doesn't test OpenCL.std vector size 2, 3, 4, 8 or 16 rules (not supported -// by standard SPIR-V). - -#include -#include -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/spirv_target_env.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -struct TestResult { - TestResult(spv_result_t in_validation_result = SPV_SUCCESS, - const char* in_error_str = nullptr, - const char* in_error_str2 = nullptr) - : validation_result(in_validation_result), - error_str(in_error_str), - error_str2(in_error_str2) {} - spv_result_t validation_result; - const char* error_str; - const char* error_str2; -}; - -using ::testing::Combine; -using ::testing::HasSubstr; -using ::testing::Not; -using ::testing::Values; -using ::testing::ValuesIn; - -using ValidateBuiltIns = spvtest::ValidateBase; -using ValidateVulkanSubgroupBuiltIns = spvtest::ValidateBase< - std::tuple>; -using ValidateVulkanCombineBuiltInExecutionModelDataTypeResult = - spvtest::ValidateBase>; -using ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult = - spvtest::ValidateBase>; -using ValidateVulkanCombineBuiltInArrayedVariable = spvtest::ValidateBase< - std::tuple>; -using ValidateWebGPUCombineBuiltInArrayedVariable = spvtest::ValidateBase< - std::tuple>; -using ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult = - spvtest::ValidateBase< - std::tuple>; - -bool InitializerRequired(spv_target_env env, const char* const storage_class) { - return spvIsWebGPUEnv(env) && (strncmp(storage_class, "Output", 6) == 0 || - strncmp(storage_class, "Private", 7) == 0 || - strncmp(storage_class, "Function", 8) == 0); -} - -CodeGenerator GetInMainCodeGenerator(spv_target_env env, - const char* const built_in, - const char* const execution_model, - const char* const storage_class, - const char* const capabilities, - const char* const extensions, - const char* const data_type) { - CodeGenerator generator = - spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - if (capabilities) { - generator.capabilities_ += capabilities; - } - if (extensions) { - generator.extensions_ += extensions; - } - - generator.before_types_ = "OpMemberDecorate %built_in_type 0 BuiltIn "; - generator.before_types_ += built_in; - generator.before_types_ += "\n"; - - std::ostringstream after_types; - - after_types << "%built_in_type = OpTypeStruct " << data_type << "\n"; - if (InitializerRequired(env, storage_class)) { - after_types << "%built_in_null = OpConstantNull %built_in_type\n"; - } - after_types << "%built_in_ptr = OpTypePointer " << storage_class - << " %built_in_type\n"; - after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class; - if (InitializerRequired(env, storage_class)) { - after_types << " %built_in_null"; - } - after_types << "\n"; - after_types << "%data_ptr = OpTypePointer " << storage_class << " " - << data_type << "\n"; - generator.after_types_ = after_types.str(); - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = execution_model; - if (strncmp(storage_class, "Input", 5) == 0 || - strncmp(storage_class, "Output", 6) == 0) { - entry_point.interfaces = "%built_in_var"; - } - - std::ostringstream execution_modes; - if (0 == std::strcmp(execution_model, "Fragment")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " OriginUpperLeft\n"; - if (0 == std::strcmp(built_in, "FragDepth")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " DepthReplacing\n"; - } - } - if (0 == std::strcmp(execution_model, "Geometry")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " InputPoints\n"; - execution_modes << "OpExecutionMode %" << entry_point.name - << " OutputPoints\n"; - } - if (0 == std::strcmp(execution_model, "GLCompute")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " LocalSize 1 1 1\n"; - } - entry_point.execution_modes = execution_modes.str(); - - entry_point.body = R"( -%ptr = OpAccessChain %data_ptr %built_in_var %u32_0 -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InMain) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = - GetInMainCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model, - storage_class, NULL, NULL, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InMain) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = - GetInMainCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model, - storage_class, NULL, NULL, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P( - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - InMain) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const char* const capabilities = std::get<4>(GetParam()); - const char* const extensions = std::get<5>(GetParam()); - const TestResult& test_result = std::get<6>(GetParam()); - - CodeGenerator generator = GetInMainCodeGenerator( - SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class, - capabilities, extensions, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -CodeGenerator GetInFunctionCodeGenerator(spv_target_env env, - const char* const built_in, - const char* const execution_model, - const char* const storage_class, - const char* const capabilities, - const char* const extensions, - const char* const data_type) { - CodeGenerator generator = - spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - if (capabilities) { - generator.capabilities_ += capabilities; - } - if (extensions) { - generator.extensions_ += extensions; - } - - generator.before_types_ = "OpMemberDecorate %built_in_type 0 BuiltIn "; - generator.before_types_ += built_in; - generator.before_types_ += "\n"; - - std::ostringstream after_types; - after_types << "%built_in_type = OpTypeStruct " << data_type << "\n"; - if (InitializerRequired(env, storage_class)) { - after_types << "%built_in_null = OpConstantNull %built_in_type\n"; - } - after_types << "%built_in_ptr = OpTypePointer " << storage_class - << " %built_in_type\n"; - after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class; - if (InitializerRequired(env, storage_class)) { - after_types << " %built_in_null"; - } - after_types << "\n"; - after_types << "%data_ptr = OpTypePointer " << storage_class << " " - << data_type << "\n"; - generator.after_types_ = after_types.str(); - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = execution_model; - if (strncmp(storage_class, "Input", 5) == 0 || - strncmp(storage_class, "Output", 6) == 0) { - entry_point.interfaces = "%built_in_var"; - } - - std::ostringstream execution_modes; - if (0 == std::strcmp(execution_model, "Fragment")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " OriginUpperLeft\n"; - if (0 == std::strcmp(built_in, "FragDepth")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " DepthReplacing\n"; - } - } - if (0 == std::strcmp(execution_model, "Geometry")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " InputPoints\n"; - execution_modes << "OpExecutionMode %" << entry_point.name - << " OutputPoints\n"; - } - if (0 == std::strcmp(execution_model, "GLCompute")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " LocalSize 1 1 1\n"; - } - entry_point.execution_modes = execution_modes.str(); - - entry_point.body = R"( -%val2 = OpFunctionCall %void %foo -)"; - - std::string function_body = R"( -%foo = OpFunction %void None %func -%foo_entry = OpLabel -%ptr = OpAccessChain %data_ptr %built_in_var %u32_0 -OpReturn -OpFunctionEnd -)"; - - if (spvIsWebGPUEnv(env)) { - generator.after_types_ += function_body; - } else { - generator.add_at_the_end_ = function_body; - } - - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InFunction) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = - GetInFunctionCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model, - storage_class, NULL, NULL, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InFunction) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = - GetInFunctionCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model, - storage_class, NULL, NULL, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P( - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - InFunction) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const char* const capabilities = std::get<4>(GetParam()); - const char* const extensions = std::get<5>(GetParam()); - const TestResult& test_result = std::get<6>(GetParam()); - - CodeGenerator generator = GetInFunctionCodeGenerator( - SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class, - capabilities, extensions, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -CodeGenerator GetVariableCodeGenerator(spv_target_env env, - const char* const built_in, - const char* const execution_model, - const char* const storage_class, - const char* const capabilities, - const char* const extensions, - const char* const data_type) { - CodeGenerator generator = - spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - if (capabilities) { - generator.capabilities_ += capabilities; - } - if (extensions) { - generator.extensions_ += extensions; - } - - generator.before_types_ = "OpDecorate %built_in_var BuiltIn "; - generator.before_types_ += built_in; - generator.before_types_ += "\n"; - - std::ostringstream after_types; - if (InitializerRequired(env, storage_class)) { - after_types << "%built_in_null = OpConstantNull " << data_type << "\n"; - } - after_types << "%built_in_ptr = OpTypePointer " << storage_class << " " - << data_type << "\n"; - after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class; - if (InitializerRequired(env, storage_class)) { - after_types << " %built_in_null"; - } - after_types << "\n"; - generator.after_types_ = after_types.str(); - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = execution_model; - if (strncmp(storage_class, "Input", 5) == 0 || - strncmp(storage_class, "Output", 6) == 0) { - entry_point.interfaces = "%built_in_var"; - } - // Any kind of reference would do. - entry_point.body = R"( -%val = OpBitcast %u32 %built_in_var -)"; - - std::ostringstream execution_modes; - if (0 == std::strcmp(execution_model, "Fragment")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " OriginUpperLeft\n"; - if (0 == std::strcmp(built_in, "FragDepth")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " DepthReplacing\n"; - } - } - if (0 == std::strcmp(execution_model, "Geometry")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " InputPoints\n"; - execution_modes << "OpExecutionMode %" << entry_point.name - << " OutputPoints\n"; - } - if (0 == std::strcmp(execution_model, "GLCompute")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " LocalSize 1 1 1\n"; - } - entry_point.execution_modes = execution_modes.str(); - - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, Variable) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = - GetVariableCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model, - storage_class, NULL, NULL, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, Variable) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = - GetVariableCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model, - storage_class, NULL, NULL, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P( - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Variable) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const char* const capabilities = std::get<4>(GetParam()); - const char* const extensions = std::get<5>(GetParam()); - const TestResult& test_result = std::get<6>(GetParam()); - - CodeGenerator generator = GetVariableCodeGenerator( - SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class, - capabilities, extensions, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), - Values("Vertex", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Output"), Values("%f32arr2", "%f32arr4"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), - Values("Fragment", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%f32arr2", "%f32arr4"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceFragmentOutput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"), - Values("Output"), Values("%f32arr4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance " - "to be used for variables with Output storage class if " - "execution model is Fragment.", - "which is called with execution model Fragment.")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIdAndInstanceIdVertexInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexId", "InstanceId"), Values("Vertex"), Values("Input"), - Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId to be " - "used.")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceVertexInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), Values("Vertex"), - Values("Input"), Values("%f32arr4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance " - "to be used for variables with Input storage class if " - "execution model is Vertex.", - "which is called with execution model Vertex.")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), Values("GLCompute"), - Values("Input", "Output"), Values("%f32arr4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be used only with Fragment, Vertex, TessellationControl, " - "TessellationEvaluation or Geometry execution models")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceNotArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"), - Values("Input"), Values("%f32vec2", "%f32vec4", "%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float array", - "is not an array")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceNotFloatArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"), - Values("Input"), Values("%u32arr2", "%u64arr4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float array", - "components are not float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceNotF32Array, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"), - Values("Input"), Values("%f64arr2", "%f64arr4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float array", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotFragment, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("FragCoord"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotFragment, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("FragCoord"), Values("Vertex", "GLCompute"), Values("Input"), - Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Output"), - Values("%f32vec4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotInput, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Output"), - Values("%f32vec4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotFloatVector, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f32arr4", "%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotFloatVector, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f32arr4", "%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotFloatVec4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotFloatVec4, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - FragCoordNotF32Vec4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragCoord"), Values("Fragment"), Values("Input"), - Values("%f64vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Output"), - Values("%f32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Output"), - Values("%f32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotFragment, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("FragDepth"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Output"), Values("%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotFragment, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("FragDepth"), Values("Vertex", "GLCompute"), Values("Output"), - Values("%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotOutput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Input"), - Values("%f32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Output storage class", - "uses storage class Input")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotOutput, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Input"), - Values("%f32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Output storage class", - "uses storage class Input")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotFloatScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Output"), - Values("%f32vec4", "%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "is not a float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotFloatScalar, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Output"), - Values("%f32vec4", "%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "is not a float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - FragDepthNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FragDepth"), Values("Fragment"), Values("Output"), - Values("%f64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingAndHelperInvocationSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"), - Values("Input"), Values("%bool"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingSuccess, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FrontFacing"), Values("Fragment"), Values("Input"), - Values("%bool"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingAndHelperInvocationNotFragment, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("FrontFacing", "HelperInvocation"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%bool"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingNotFragment, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("FrontFacing"), Values("Vertex", "GLCompute"), Values("Input"), - Values("%bool"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingAndHelperInvocationNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"), - Values("Output"), Values("%bool"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingNotInput, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FrontFacing"), Values("Fragment"), Values("Output"), - Values("%bool"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingAndHelperInvocationNotBool, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"), - Values("Input"), Values("%f32", "%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a bool scalar", - "is not a bool scalar")))); - -INSTANTIATE_TEST_SUITE_P( - FrontFacingNotBool, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("FrontFacing"), Values("Fragment"), Values("Input"), - Values("%f32", "%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a bool scalar", - "is not a bool scalar")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3Success, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups", - "WorkgroupId"), - Values("GLCompute"), Values("Input"), Values("%u32vec3"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3Success, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"), - Values("GLCompute"), Values("Input"), Values("%u32vec3"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotGLCompute, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups", - "WorkgroupId"), - Values("Vertex", "Fragment", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with GLCompute execution model")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotGLCompute, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"), - Values("Vertex", "Fragment"), Values("Input"), Values("%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with GLCompute execution model")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups", - "WorkgroupId"), - Values("GLCompute"), Values("Output"), Values("%u32vec3"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotInput, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"), - Values("GLCompute"), Values("Output"), Values("%u32vec3"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotIntVector, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups", - "WorkgroupId"), - Values("GLCompute"), Values("Input"), - Values("%u32arr3", "%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit int vector", - "is not an int vector")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotIntVector, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"), - Values("GLCompute"), Values("Input"), - Values("%u32arr3", "%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit int vector", - "is not an int vector")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotIntVec3, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups", - "WorkgroupId"), - Values("GLCompute"), Values("Input"), Values("%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit int vector", - "has 4 components")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotIntVec3, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"), - Values("GLCompute"), Values("Input"), Values("%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit int vector", - "has 4 components")))); - -INSTANTIATE_TEST_SUITE_P( - ComputeShaderInputInt32Vec3NotInt32Vec, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups", - "WorkgroupId"), - Values("GLCompute"), Values("Input"), Values("%u64vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit int vector", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - InvocationIdSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"), - Values("Input"), Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - InvocationIdInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InvocationId"), - Values("Vertex", "Fragment", "GLCompute", "TessellationEvaluation"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with TessellationControl or " - "Geometry execution models")))); - -INSTANTIATE_TEST_SUITE_P( - InvocationIdNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"), - Values("Output"), Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - InvocationIdNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"), - Values("Input"), Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - InvocationIdNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"), - Values("Input"), Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"), - Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexSuccess, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"), - Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), - Values("Geometry", "Fragment", "GLCompute", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Vertex execution model")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexInvalidExecutionModel, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Fragment", "GLCompute"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Vertex execution model")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"), - Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexNotInput, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"), - Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexNotIntScalar, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - InstanceIndexNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"), - Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), Values("Fragment"), - Values("Input"), Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), Values("Geometry"), - Values("Output"), Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), - Values("TessellationControl", "GLCompute"), Values("Input"), - Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be used only with Vertex, TessellationEvaluation, " - "Geometry, or Fragment execution models")))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexExecutionModelEnabledByCapability, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), - Values("Vertex", "TessellationEvaluation"), Values("Output"), - Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "requires the ShaderViewportIndexLayerEXT capability")))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexFragmentNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Output"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "Output storage class if execution model is Fragment", - "which is called with execution model Fragment")))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexGeometryNotOutput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("Layer", "ViewportIndex"), - Values("Vertex", "TessellationEvaluation", "Geometry"), Values("Input"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "Input storage class if execution model is Vertex, " - "TessellationEvaluation, or Geometry", - "which is called with execution model")))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), Values("Fragment"), - Values("Input"), Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), Values("Fragment"), - Values("Input"), Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - PatchVerticesSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PatchVertices"), - Values("TessellationEvaluation", "TessellationControl"), - Values("Input"), Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PatchVerticesInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PatchVertices"), - Values("Vertex", "Fragment", "GLCompute", "Geometry"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with TessellationControl or " - "TessellationEvaluation execution models")))); - -INSTANTIATE_TEST_SUITE_P( - PatchVerticesNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PatchVertices"), - Values("TessellationEvaluation", "TessellationControl"), - Values("Output"), Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - PatchVerticesNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PatchVertices"), - Values("TessellationEvaluation", "TessellationControl"), - Values("Input"), Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - PatchVerticesNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PatchVertices"), - Values("TessellationEvaluation", "TessellationControl"), - Values("Input"), Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - PointCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec2"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PointCoordNotFragment, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("PointCoord"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%f32vec2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - PointCoordNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointCoord"), Values("Fragment"), Values("Output"), - Values("%f32vec2"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - PointCoordNotFloatVector, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointCoord"), Values("Fragment"), Values("Input"), - Values("%f32arr2", "%u32vec2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - PointCoordNotFloatVec3, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float vector", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - PointCoordNotF32Vec4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointCoord"), Values("Fragment"), Values("Input"), - Values("%f64vec2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float vector", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize"), - Values("Vertex", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Output"), Values("%f32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize"), - Values("Geometry", "TessellationControl", "TessellationEvaluation"), - Values("Input"), Values("%f32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeVertexInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize"), Values("Vertex"), Values("Input"), - Values("%f32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow BuiltIn PointSize " - "to be used for variables with Input storage class if " - "execution model is Vertex.", - "which is called with execution model Vertex.")))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize"), Values("GLCompute", "Fragment"), - Values("Input", "Output"), Values("%f32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be used only with Vertex, TessellationControl, " - "TessellationEvaluation or Geometry execution models")))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeNotFloatScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize"), Values("Vertex"), Values("Output"), - Values("%f32vec4", "%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "is not a float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize"), Values("Vertex"), Values("Output"), - Values("%f64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - PositionOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), - Values("Vertex", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Output"), Values("%f32vec4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PositionOutputSuccess, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("Vertex"), Values("Output"), - Values("%f32vec4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PositionOutputFailure, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("Fragment", "GLCompute"), - Values("Output"), Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "WebGPU spec allows BuiltIn Position to be used " - "only with the Vertex execution model.")))); - -INSTANTIATE_TEST_SUITE_P( - PositionInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), - Values("Geometry", "TessellationControl", "TessellationEvaluation"), - Values("Input"), Values("%f32vec4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PositionInputFailure, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("Position"), Values("Vertex", "Fragment", "GLCompute"), - Values("Input"), Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "WebGPU spec allows BuiltIn Position to be only used " - "for variables with Output storage class")))); - -INSTANTIATE_TEST_SUITE_P( - PositionVertexInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("Vertex"), Values("Input"), - Values("%f32vec4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow BuiltIn Position " - "to be used for variables with Input storage class if " - "execution model is Vertex.", - "which is called with execution model Vertex.")))); - -INSTANTIATE_TEST_SUITE_P( - PositionInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("GLCompute", "Fragment"), - Values("Input", "Output"), Values("%f32vec4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be used only with Vertex, TessellationControl, " - "TessellationEvaluation or Geometry execution models")))); - -INSTANTIATE_TEST_SUITE_P( - PositionNotFloatVector, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("Geometry"), Values("Input"), - Values("%f32arr4", "%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - PositionNotFloatVector, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("Position"), Values("Vertex"), Values("Output"), - Values("%f32arr4", "%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector")))); - -INSTANTIATE_TEST_SUITE_P( - PositionNotFloatVec4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("Geometry"), Values("Input"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - PositionNotFloatVec4, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("Position"), Values("Vertex"), Values("Output"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector")))); - -INSTANTIATE_TEST_SUITE_P( - PositionNotF32Vec4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Position"), Values("Geometry"), Values("Input"), - Values("%f64vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PrimitiveId"), - Values("Fragment", "TessellationControl", "TessellationEvaluation", - "Geometry"), - Values("Input"), Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PrimitiveId"), Values("Geometry"), Values("Output"), - Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PrimitiveId"), Values("Vertex", "GLCompute"), - Values("Input"), Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be used only with Fragment, TessellationControl, " - "TessellationEvaluation or Geometry execution models")))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdFragmentNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("PrimitiveId"), Values("Fragment"), Values("Output"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "Output storage class if execution model is Fragment", - "which is called with execution model Fragment")))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdGeometryNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PrimitiveId"), - Values("TessellationControl", "TessellationEvaluation"), - Values("Output"), Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Output storage class if execution model is Tessellation", - "which is called with execution model Tessellation")))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - PrimitiveIdNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"), - Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - SampleIdSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleId"), Values("Fragment"), Values("Input"), - Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - SampleIdInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("SampleId"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - SampleIdNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("SampleId"), Values("Fragment"), Values("Output"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "Vulkan spec allows BuiltIn SampleId to be only used " - "for variables with Input storage class")))); - -INSTANTIATE_TEST_SUITE_P( - SampleIdNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleId"), Values("Fragment"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - SampleIdNotInt32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleId"), Values("Fragment"), Values("Input"), - Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - SampleMaskSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleMask"), Values("Fragment"), Values("Input", "Output"), - Values("%u32arr2", "%u32arr4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - SampleMaskInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("SampleMask"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%u32arr2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - SampleMaskWrongStorageClass, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleMask"), Values("Fragment"), Values("Workgroup"), - Values("%u32arr2"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec allows BuiltIn SampleMask to be only used for " - "variables with Input or Output storage class")))); - -INSTANTIATE_TEST_SUITE_P( - SampleMaskNotArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleMask"), Values("Fragment"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int array", - "is not an array")))); - -INSTANTIATE_TEST_SUITE_P( - SampleMaskNotIntArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleMask"), Values("Fragment"), Values("Input"), - Values("%f32arr2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int array", - "components are not int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - SampleMaskNotInt32Array, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SampleMask"), Values("Fragment"), Values("Input"), - Values("%u64arr2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int array", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - SamplePositionSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"), - Values("%f32vec2"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - SamplePositionNotFragment, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("SamplePosition"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%f32vec2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Fragment execution model")))); - -INSTANTIATE_TEST_SUITE_P( - SamplePositionNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SamplePosition"), Values("Fragment"), Values("Output"), - Values("%f32vec2"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - SamplePositionNotFloatVector, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"), - Values("%f32arr2", "%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - SamplePositionNotFloatVec2, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float vector", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - SamplePositionNotF32Vec2, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"), - Values("%f64vec2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float vector", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - TessCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessCoord"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32vec3"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - TessCoordNotFragment, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("TessCoord"), - Values("Vertex", "GLCompute", "Geometry", "TessellationControl", - "Fragment"), - Values("Input"), Values("%f32vec3"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be used only with TessellationEvaluation execution model")))); - -INSTANTIATE_TEST_SUITE_P( - TessCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessCoord"), Values("Fragment"), Values("Output"), - Values("%f32vec3"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - TessCoordNotFloatVector, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessCoord"), Values("Fragment"), Values("Input"), - Values("%f32arr3", "%u32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - TessCoordNotFloatVec3, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessCoord"), Values("Fragment"), Values("Input"), - Values("%f32vec2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit float vector", - "has 2 components")))); - -INSTANTIATE_TEST_SUITE_P( - TessCoordNotF32Vec3, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessCoord"), Values("Fragment"), Values("Input"), - Values("%f64vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 3-component 32-bit float vector", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterTeseInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32arr4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterTescOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationControl"), - Values("Output"), Values("%f32arr4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), - Values("Vertex", "GLCompute", "Geometry", "Fragment"), - Values("Input"), Values("%f32arr4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with TessellationControl or " - "TessellationEvaluation execution models.")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterOutputTese, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"), - Values("Output"), Values("%f32arr4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be " - "used for variables with Output storage class if execution " - "model is TessellationEvaluation.")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterInputTesc, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationControl"), - Values("Input"), Values("%f32arr4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be " - "used for variables with Input storage class if execution " - "model is TessellationControl.")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterNotArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32vec4", "%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float array", - "is not an array")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterNotFloatArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"), - Values("Input"), Values("%u32arr4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float array", - "components are not float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterNotFloatArr4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32arr3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float array", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelOuterNotF32Arr4, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"), - Values("Input"), Values("%f64arr4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float array", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerTeseInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32arr2"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerTescOutputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationControl"), - Values("Output"), Values("%f32arr2"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), - Values("Vertex", "GLCompute", "Geometry", "Fragment"), - Values("Input"), Values("%f32arr2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with TessellationControl or " - "TessellationEvaluation execution models.")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerOutputTese, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationEvaluation"), - Values("Output"), Values("%f32arr2"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be " - "used for variables with Output storage class if execution " - "model is TessellationEvaluation.")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerInputTesc, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationControl"), - Values("Input"), Values("%f32arr2"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be " - "used for variables with Input storage class if execution " - "model is TessellationControl.")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerNotArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32vec2", "%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float array", - "is not an array")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerNotFloatArray, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationEvaluation"), - Values("Input"), Values("%u32arr2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float array", - "components are not float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerNotFloatArr2, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationEvaluation"), - Values("Input"), Values("%f32arr3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float array", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - TessLevelInnerNotF32Arr2, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("TessLevelInner"), Values("TessellationEvaluation"), - Values("Input"), Values("%f64arr2"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 2-component 32-bit float array", - "has components with bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"), - Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexSuccess, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"), - Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexInvalidExecutionModel, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), - Values("Fragment", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Vertex execution model")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexInvalidExecutionModel, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), Values("Fragment", "GLCompute"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with Vertex execution model")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("VertexIndex"), Values("Vertex"), Values("Output"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "Vulkan spec allows BuiltIn VertexIndex to be only " - "used for variables with Input storage class")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexNotInput, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("VertexIndex"), Values("Vertex"), Values("Output"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "WebGPU spec allows BuiltIn VertexIndex to be only " - "used for variables with Input storage class")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexNotIntScalar, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"), - Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - VertexIndexNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"), - Values("%u64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - LocalInvocationIndexSuccess, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("LocalInvocationIndex"), Values("GLCompute"), - Values("Input"), Values("%u32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - LocalInvocationIndexInvalidExecutionModel, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("LocalInvocationIndex"), Values("Fragment", "Vertex"), - Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "to be used only with GLCompute execution model")))); - -INSTANTIATE_TEST_SUITE_P( - LocalInvocationIndexNotInput, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine( - Values("LocalInvocationIndex"), Values("GLCompute"), Values("Output"), - Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "WebGPU spec allows BuiltIn LocalInvocationIndex to " - "be only used for variables with Input storage " - "class")))); - -INSTANTIATE_TEST_SUITE_P( - LocalInvocationIndexNotIntScalar, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("LocalInvocationIndex"), Values("GLCompute"), - Values("Input"), Values("%f32", "%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int", "is not an int")))); - -INSTANTIATE_TEST_SUITE_P( - WhitelistRejection, - ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("PointSize", "ClipDistance", "CullDistance", "VertexId", - "InstanceId", "PointCoord", "SampleMask", "HelperInvocation", - "WorkgroupId"), - Values("Vertex"), Values("Input"), Values("%u32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "WebGPU does not allow BuiltIn")))); - -CodeGenerator GetArrayedVariableCodeGenerator(spv_target_env env, - const char* const built_in, - const char* const execution_model, - const char* const storage_class, - const char* const data_type) { - CodeGenerator generator = - spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = "OpDecorate %built_in_var BuiltIn "; - generator.before_types_ += built_in; - generator.before_types_ += "\n"; - - std::ostringstream after_types; - after_types << "%built_in_array = OpTypeArray " << data_type << " %u32_3\n"; - if (InitializerRequired(env, storage_class)) { - after_types << "%built_in_array_null = OpConstantNull %built_in_array\n"; - } - - after_types << "%built_in_ptr = OpTypePointer " << storage_class - << " %built_in_array\n"; - after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class; - if (InitializerRequired(env, storage_class)) { - after_types << " %built_in_array_null"; - } - after_types << "\n"; - generator.after_types_ = after_types.str(); - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = execution_model; - entry_point.interfaces = "%built_in_var"; - // Any kind of reference would do. - entry_point.body = R"( -%val = OpBitcast %u32 %built_in_var -)"; - - std::ostringstream execution_modes; - if (0 == std::strcmp(execution_model, "Fragment")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " OriginUpperLeft\n"; - if (0 == std::strcmp(built_in, "FragDepth")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " DepthReplacing\n"; - } - } - if (0 == std::strcmp(execution_model, "Geometry")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " InputPoints\n"; - execution_modes << "OpExecutionMode %" << entry_point.name - << " OutputPoints\n"; - } - if (0 == std::strcmp(execution_model, "GLCompute")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " LocalSize 1 1 1\n"; - } - entry_point.execution_modes = execution_modes.str(); - - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_P(ValidateVulkanCombineBuiltInArrayedVariable, Variable) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = GetArrayedVariableCodeGenerator( - SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -TEST_P(ValidateWebGPUCombineBuiltInArrayedVariable, Variable) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = GetArrayedVariableCodeGenerator( - SPV_ENV_WEBGPU_0, built_in, execution_model, storage_class, data_type); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -INSTANTIATE_TEST_SUITE_P(PointSizeArrayedF32TessControl, - ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("PointSize"), - Values("TessellationControl"), Values("Input"), - Values("%f32"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeArrayedF64TessControl, ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("PointSize"), Values("TessellationControl"), Values("Input"), - Values("%f64"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "has bit width 64")))); - -INSTANTIATE_TEST_SUITE_P( - PointSizeArrayedF32Vertex, ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("PointSize"), Values("Vertex"), Values("Output"), - Values("%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float scalar", - "is not a float scalar")))); - -INSTANTIATE_TEST_SUITE_P(PositionArrayedF32Vec4TessControl, - ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("Position"), - Values("TessellationControl"), Values("Input"), - Values("%f32vec4"), Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - PositionArrayedF32Vec3TessControl, - ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("Position"), Values("TessellationControl"), Values("Input"), - Values("%f32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "has 3 components")))); - -INSTANTIATE_TEST_SUITE_P( - PositionArrayedF32Vec4Vertex, ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("Position"), Values("Vertex"), Values("Output"), - Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - PositionArrayedF32Vec4Vertex, ValidateWebGPUCombineBuiltInArrayedVariable, - Combine(Values("Position"), Values("Vertex"), Values("Output"), - Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit float vector", - "is not a float vector")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceOutputSuccess, - ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("ClipDistance", "CullDistance"), - Values("Geometry", "TessellationControl", "TessellationEvaluation"), - Values("Output"), Values("%f32arr2", "%f32arr4"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceVertexInput, ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"), - Values("Input"), Values("%f32arr4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float array", - "components are not float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - ClipAndCullDistanceNotArray, ValidateVulkanCombineBuiltInArrayedVariable, - Combine(Values("ClipDistance", "CullDistance"), - Values("Geometry", "TessellationControl", "TessellationEvaluation"), - Values("Input"), Values("%f32vec2", "%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit float array", - "components are not float scalar")))); - -INSTANTIATE_TEST_SUITE_P( - SMBuiltinsInputSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"), - Values("Vertex", "Fragment", "TessellationControl", - "TessellationEvaluation", "Geometry", "GLCompute"), - Values("Input"), Values("%u32"), - Values("OpCapability ShaderSMBuiltinsNV\n"), - Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - SMBuiltinsInputMeshSuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Combine( - Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"), - Values("MeshNV", "TaskNV"), Values("Input"), Values("%u32"), - Values("OpCapability ShaderSMBuiltinsNV\nOpCapability MeshShadingNV\n"), - Values("OpExtension \"SPV_NV_shader_sm_builtins\"\nOpExtension " - "\"SPV_NV_mesh_shader\"\n"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - SMBuiltinsInputRaySuccess, - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Combine( - Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"), - Values("RayGenerationNV", "IntersectionNV", "AnyHitNV", "ClosestHitNV", - "MissNV", "CallableNV"), - Values("Input"), Values("%u32"), - Values("OpCapability ShaderSMBuiltinsNV\nOpCapability RayTracingNV\n"), - Values("OpExtension \"SPV_NV_shader_sm_builtins\"\nOpExtension " - "\"SPV_NV_ray_tracing\"\n"), - Values(TestResult()))); - -INSTANTIATE_TEST_SUITE_P( - SMBuiltinsNotInput, - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"), - Values("Vertex", "Fragment", "TessellationControl", - "TessellationEvaluation", "Geometry", "GLCompute"), - Values("Output"), Values("%u32"), - Values("OpCapability ShaderSMBuiltinsNV\n"), - Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class", - "uses storage class Output")))); - -INSTANTIATE_TEST_SUITE_P( - SMBuiltinsNotIntScalar, - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"), - Values("Vertex", "Fragment", "TessellationControl", - "TessellationEvaluation", "Geometry", "GLCompute"), - Values("Input"), Values("%f32", "%u32vec3"), - Values("OpCapability ShaderSMBuiltinsNV\n"), - Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "is not an int scalar")))); - -INSTANTIATE_TEST_SUITE_P( - SMBuiltinsNotInt32, - ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, - Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"), - Values("Vertex", "Fragment", "TessellationControl", - "TessellationEvaluation", "Geometry", "GLCompute"), - Values("Input"), Values("%u64"), - Values("OpCapability ShaderSMBuiltinsNV\n"), - Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int scalar", - "has bit width 64")))); - -CodeGenerator GetWorkgroupSizeSuccessGenerator(spv_target_env env) { - CodeGenerator generator = - env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -%copy = OpCopyObject %u32vec3 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeSuccess) { - CodeGenerator generator = - GetWorkgroupSizeSuccessGenerator(SPV_ENV_VULKAN_1_0); - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeSuccess) { - CodeGenerator generator = GetWorkgroupSizeSuccessGenerator(SPV_ENV_WEBGPU_0); - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -CodeGenerator GetWorkgroupSizeFragmentGenerator(spv_target_env env) { - CodeGenerator generator = - env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Fragment"; - entry_point.execution_modes = "OpExecutionMode %main OriginUpperLeft"; - entry_point.body = R"( -%copy = OpCopyObject %u32vec3 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeFragment) { - CodeGenerator generator = - GetWorkgroupSizeFragmentGenerator(SPV_ENV_VULKAN_1_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec allows BuiltIn WorkgroupSize to be used " - "only with GLCompute execution model")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("is referencing ID <2> (OpConstantComposite) which is " - "decorated with BuiltIn WorkgroupSize in function <1> " - "called with execution model Fragment")); -} - -TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeFragment) { - CodeGenerator generator = GetWorkgroupSizeFragmentGenerator(SPV_ENV_WEBGPU_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("WebGPU spec allows BuiltIn WorkgroupSize to be used " - "only with GLCompute execution model")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("is referencing ID <2> (OpConstantComposite) which is " - "decorated with BuiltIn WorkgroupSize in function <1> " - "called with execution model Fragment")); -} - -TEST_F(ValidateBuiltIns, WorkgroupSizeNotConstant) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.before_types_ = R"( -OpDecorate %copy BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -%copy = OpCopyObject %u32vec3 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("BuiltIns can only target variables, structs or constants")); -} - -CodeGenerator GetWorkgroupSizeNotVectorGenerator(spv_target_env env) { - CodeGenerator generator = - env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstant %u32 16 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -%copy = OpCopyObject %u32 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotVector) { - CodeGenerator generator = - GetWorkgroupSizeNotVectorGenerator(SPV_ENV_VULKAN_1_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpConstant) is not an int vector.")); -} - -TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVector) { - CodeGenerator generator = - GetWorkgroupSizeNotVectorGenerator(SPV_ENV_WEBGPU_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpConstant) is not an int vector.")); -} - -CodeGenerator GetWorkgroupSizeNotIntVectorGenerator(spv_target_env env) { - CodeGenerator generator = - env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %f32vec3 %f32_1 %f32_1 %f32_1 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -%copy = OpCopyObject %f32vec3 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotIntVector) { - CodeGenerator generator = - GetWorkgroupSizeNotIntVectorGenerator(SPV_ENV_VULKAN_1_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpConstantComposite) is not an int vector.")); -} - -TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotIntVector) { - CodeGenerator generator = - GetWorkgroupSizeNotIntVectorGenerator(SPV_ENV_WEBGPU_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpConstantComposite) is not an int vector.")); -} - -CodeGenerator GetWorkgroupSizeNotVec3Generator(spv_target_env env) { - CodeGenerator generator = - env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u32vec2 %u32_1 %u32_1 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -%copy = OpCopyObject %u32vec2 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - return generator; -} - -TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotVec3) { - CodeGenerator generator = - GetWorkgroupSizeNotVec3Generator(SPV_ENV_VULKAN_1_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpConstantComposite) has 2 components.")); -} - -TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVec3) { - CodeGenerator generator = GetWorkgroupSizeNotVec3Generator(SPV_ENV_WEBGPU_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpConstantComposite) has 2 components.")); -} - -TEST_F(ValidateBuiltIns, WorkgroupSizeNotInt32Vec) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u64vec3 %u64_1 %u64_1 %u64_1 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -%copy = OpCopyObject %u64vec3 %workgroup_size -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize variable " - "needs to be a 3-component 32-bit int vector. ID <2> " - "(OpConstantComposite) has components with bit width 64.")); -} - -TEST_F(ValidateBuiltIns, WorkgroupSizePrivateVar) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1 -%private_ptr_u32vec3 = OpTypePointer Private %u32vec3 -%var = OpVariable %private_ptr_u32vec3 Private %workgroup_size -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.body = R"( -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBuiltIns, GeometryPositionInOutSuccess) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpMemberDecorate %input_type 0 BuiltIn Position -OpMemberDecorate %output_type 0 BuiltIn Position -)"; - - generator.after_types_ = R"( -%input_type = OpTypeStruct %f32vec4 -%arrayed_input_type = OpTypeArray %input_type %u32_3 -%input_ptr = OpTypePointer Input %arrayed_input_type -%input = OpVariable %input_ptr Input -%input_f32vec4_ptr = OpTypePointer Input %f32vec4 -%output_type = OpTypeStruct %f32vec4 -%arrayed_output_type = OpTypeArray %output_type %u32_3 -%output_ptr = OpTypePointer Output %arrayed_output_type -%output = OpVariable %output_ptr Output -%output_f32vec4_ptr = OpTypePointer Output %f32vec4 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Geometry"; - entry_point.interfaces = "%input %output"; - entry_point.body = R"( -%input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0 %u32_0 -%output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0 %u32_0 -%pos = OpLoad %f32vec4 %input_pos -OpStore %output_pos %pos -)"; - generator.entry_points_.push_back(std::move(entry_point)); - generator.entry_points_[0].execution_modes = - "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n"; - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBuiltIns, WorkgroupIdNotVec3) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.before_types_ = R"( -OpDecorate %workgroup_size BuiltIn WorkgroupSize -OpDecorate %workgroup_id BuiltIn WorkgroupId -)"; - - generator.after_types_ = R"( -%workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1 - %input_ptr = OpTypePointer Input %u32vec2 - %workgroup_id = OpVariable %input_ptr Input -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "GLCompute"; - entry_point.interfaces = "%workgroup_id"; - entry_point.body = R"( -%copy_size = OpCopyObject %u32vec3 %workgroup_size - %load_id = OpLoad %u32vec2 %workgroup_id -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("According to the Vulkan spec BuiltIn WorkgroupId " - "variable needs to be a 3-component 32-bit int vector. " - "ID <2> (OpVariable) has 2 components.")); -} - -TEST_F(ValidateBuiltIns, TwoBuiltInsFirstFails) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpMemberDecorate %input_type 0 BuiltIn FragCoord -OpMemberDecorate %output_type 0 BuiltIn Position -)"; - - generator.after_types_ = R"( -%input_type = OpTypeStruct %f32vec4 -%input_ptr = OpTypePointer Input %input_type -%input = OpVariable %input_ptr Input -%input_f32vec4_ptr = OpTypePointer Input %f32vec4 -%output_type = OpTypeStruct %f32vec4 -%output_ptr = OpTypePointer Output %output_type -%output = OpVariable %output_ptr Output -%output_f32vec4_ptr = OpTypePointer Output %f32vec4 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Geometry"; - entry_point.interfaces = "%input %output"; - entry_point.body = R"( -%input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0 -%output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0 -%pos = OpLoad %f32vec4 %input_pos -OpStore %output_pos %pos -)"; - generator.entry_points_.push_back(std::move(entry_point)); - generator.entry_points_[0].execution_modes = - "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n"; - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec allows BuiltIn FragCoord to be used only " - "with Fragment execution model")); -} - -TEST_F(ValidateBuiltIns, TwoBuiltInsSecondFails) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpMemberDecorate %input_type 0 BuiltIn Position -OpMemberDecorate %output_type 0 BuiltIn FragCoord -)"; - - generator.after_types_ = R"( -%input_type = OpTypeStruct %f32vec4 -%input_ptr = OpTypePointer Input %input_type -%input = OpVariable %input_ptr Input -%input_f32vec4_ptr = OpTypePointer Input %f32vec4 -%output_type = OpTypeStruct %f32vec4 -%output_ptr = OpTypePointer Output %output_type -%output = OpVariable %output_ptr Output -%output_f32vec4_ptr = OpTypePointer Output %f32vec4 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Geometry"; - entry_point.interfaces = "%input %output"; - entry_point.body = R"( -%input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0 -%output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0 -%pos = OpLoad %f32vec4 %input_pos -OpStore %output_pos %pos -)"; - generator.entry_points_.push_back(std::move(entry_point)); - generator.entry_points_[0].execution_modes = - "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n"; - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec allows BuiltIn FragCoord to be only used " - "for variables with Input storage class")); -} - -TEST_F(ValidateBuiltIns, VertexPositionVariableSuccess) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.before_types_ = R"( -OpDecorate %position BuiltIn Position -)"; - - generator.after_types_ = R"( -%f32vec4_ptr_output = OpTypePointer Output %f32vec4 -%position = OpVariable %f32vec4_ptr_output Output -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Vertex"; - entry_point.interfaces = "%position"; - entry_point.body = R"( -OpStore %position %f32vec4_0123 -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBuiltIns, FragmentPositionTwoEntryPoints) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.before_types_ = R"( -OpMemberDecorate %output_type 0 BuiltIn Position -)"; - - generator.after_types_ = R"( -%output_type = OpTypeStruct %f32vec4 -%output_ptr = OpTypePointer Output %output_type -%output = OpVariable %output_ptr Output -%output_f32vec4_ptr = OpTypePointer Output %f32vec4 -)"; - - EntryPoint entry_point; - entry_point.name = "vmain"; - entry_point.execution_model = "Vertex"; - entry_point.interfaces = "%output"; - entry_point.body = R"( -%val1 = OpFunctionCall %void %foo -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - entry_point.name = "fmain"; - entry_point.execution_model = "Fragment"; - entry_point.interfaces = "%output"; - entry_point.execution_modes = "OpExecutionMode %fmain OriginUpperLeft"; - entry_point.body = R"( -%val2 = OpFunctionCall %void %foo -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - generator.add_at_the_end_ = R"( -%foo = OpFunction %void None %func -%foo_entry = OpLabel -%position = OpAccessChain %output_f32vec4_ptr %output %u32_0 -OpStore %position %f32vec4_0123 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec allows BuiltIn Position to be used only " - "with Vertex, TessellationControl, " - "TessellationEvaluation or Geometry execution models")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("called with execution model Fragment")); -} - -CodeGenerator GetNoDepthReplacingGenerator(spv_target_env env) { - CodeGenerator generator = - spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpMemberDecorate %output_type 0 BuiltIn FragDepth -)"; - - generator.after_types_ = R"( -%output_type = OpTypeStruct %f32 -%output_null = OpConstantNull %output_type -%output_ptr = OpTypePointer Output %output_type -%output = OpVariable %output_ptr Output %output_null -%output_f32_ptr = OpTypePointer Output %f32 -)"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Fragment"; - entry_point.interfaces = "%output"; - entry_point.execution_modes = "OpExecutionMode %main OriginUpperLeft"; - entry_point.body = R"( -%val2 = OpFunctionCall %void %foo -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - const std::string function_body = R"( -%foo = OpFunction %void None %func -%foo_entry = OpLabel -%frag_depth = OpAccessChain %output_f32_ptr %output %u32_0 -OpStore %frag_depth %f32_1 -OpReturn -OpFunctionEnd -)"; - - if (spvIsWebGPUEnv(env)) { - generator.after_types_ += function_body; - } else { - generator.add_at_the_end_ = function_body; - } - - return generator; -} - -TEST_F(ValidateBuiltIns, VulkanFragmentFragDepthNoDepthReplacing) { - CodeGenerator generator = GetNoDepthReplacingGenerator(SPV_ENV_VULKAN_1_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec requires DepthReplacing execution mode to " - "be declared when using BuiltIn FragDepth")); -} - -TEST_F(ValidateBuiltIns, WebGPUFragmentFragDepthNoDepthReplacing) { - CodeGenerator generator = GetNoDepthReplacingGenerator(SPV_ENV_WEBGPU_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("WebGPU spec requires DepthReplacing execution mode to " - "be declared when using BuiltIn FragDepth")); -} - -CodeGenerator GetOneMainHasDepthReplacingOtherHasntGenerator( - spv_target_env env) { - CodeGenerator generator = - spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator() - : CodeGenerator::GetDefaultShaderCodeGenerator(); - - generator.before_types_ = R"( -OpMemberDecorate %output_type 0 BuiltIn FragDepth -)"; - - generator.after_types_ = R"( -%output_type = OpTypeStruct %f32 -%output_null = OpConstantNull %output_type -%output_ptr = OpTypePointer Output %output_type -%output = OpVariable %output_ptr Output %output_null -%output_f32_ptr = OpTypePointer Output %f32 -)"; - - EntryPoint entry_point; - entry_point.name = "main_d_r"; - entry_point.execution_model = "Fragment"; - entry_point.interfaces = "%output"; - entry_point.execution_modes = - "OpExecutionMode %main_d_r OriginUpperLeft\n" - "OpExecutionMode %main_d_r DepthReplacing"; - entry_point.body = R"( -%val2 = OpFunctionCall %void %foo -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - entry_point.name = "main_no_d_r"; - entry_point.execution_model = "Fragment"; - entry_point.interfaces = "%output"; - entry_point.execution_modes = "OpExecutionMode %main_no_d_r OriginUpperLeft"; - entry_point.body = R"( -%val3 = OpFunctionCall %void %foo -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - const std::string function_body = R"( -%foo = OpFunction %void None %func -%foo_entry = OpLabel -%frag_depth = OpAccessChain %output_f32_ptr %output %u32_0 -OpStore %frag_depth %f32_1 -OpReturn -OpFunctionEnd -)"; - - if (spvIsWebGPUEnv(env)) { - generator.after_types_ += function_body; - } else { - generator.add_at_the_end_ = function_body; - } - - return generator; -} - -TEST_F(ValidateBuiltIns, - VulkanFragmentFragDepthOneMainHasDepthReplacingOtherHasnt) { - CodeGenerator generator = - GetOneMainHasDepthReplacingOtherHasntGenerator(SPV_ENV_VULKAN_1_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec requires DepthReplacing execution mode to " - "be declared when using BuiltIn FragDepth")); -} - -TEST_F(ValidateBuiltIns, - WebGPUFragmentFragDepthOneMainHasDepthReplacingOtherHasnt) { - CodeGenerator generator = - GetOneMainHasDepthReplacingOtherHasntGenerator(SPV_ENV_WEBGPU_0); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("WebGPU spec requires DepthReplacing execution mode to " - "be declared when using BuiltIn FragDepth")); -} - -TEST_F(ValidateBuiltIns, AllowInstanceIdWithIntersectionShader) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.capabilities_ += R"( -OpCapability RayTracingNV -)"; - - generator.extensions_ = R"( -OpExtension "SPV_NV_ray_tracing" -)"; - - generator.before_types_ = R"( -OpMemberDecorate %input_type 0 BuiltIn InstanceId -)"; - - generator.after_types_ = R"( -%input_type = OpTypeStruct %u32 -%input_ptr = OpTypePointer Input %input_type -%input = OpVariable %input_ptr Input -)"; - - EntryPoint entry_point; - entry_point.name = "main_d_r"; - entry_point.execution_model = "IntersectionNV"; - entry_point.interfaces = "%input"; - entry_point.body = R"( -%val2 = OpFunctionCall %void %foo -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - generator.add_at_the_end_ = R"( -%foo = OpFunction %void None %func -%foo_entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateBuiltIns, DisallowInstanceIdWithRayGenShader) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.capabilities_ += R"( -OpCapability RayTracingNV -)"; - - generator.extensions_ = R"( -OpExtension "SPV_NV_ray_tracing" -)"; - - generator.before_types_ = R"( -OpMemberDecorate %input_type 0 BuiltIn InstanceId -)"; - - generator.after_types_ = R"( -%input_type = OpTypeStruct %u32 -%input_ptr = OpTypePointer Input %input_type -%input_ptr_u32 = OpTypePointer Input %u32 -%input = OpVariable %input_ptr Input -)"; - - EntryPoint entry_point; - entry_point.name = "main_d_r"; - entry_point.execution_model = "RayGenerationNV"; - entry_point.interfaces = "%input"; - entry_point.body = R"( -%input_member = OpAccessChain %input_ptr_u32 %input %u32_0 -)"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vulkan spec allows BuiltIn InstanceId to be used " - "only with IntersectionNV, ClosestHitNV and " - "AnyHitNV execution models")); -} - -TEST_F(ValidateBuiltIns, ValidBuiltinsForMeshShader) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.capabilities_ += R"( -OpCapability MeshShadingNV -)"; - - generator.extensions_ = R"( -OpExtension "SPV_NV_mesh_shader" -)"; - - generator.before_types_ = R"( -OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId -OpDecorate %gl_PrimitiveID PerPrimitiveNV -OpDecorate %gl_Layer BuiltIn Layer -OpDecorate %gl_Layer PerPrimitiveNV -OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex -OpDecorate %gl_ViewportIndex PerPrimitiveNV -)"; - - generator.after_types_ = R"( -%u32_81 = OpConstant %u32 81 -%_arr_int_uint_81 = OpTypeArray %i32 %u32_81 -%_ptr_Output__arr_int_uint_81 = OpTypePointer Output %_arr_int_uint_81 -%gl_PrimitiveID = OpVariable %_ptr_Output__arr_int_uint_81 Output -%gl_Layer = OpVariable %_ptr_Output__arr_int_uint_81 Output -%gl_ViewportIndex = OpVariable %_ptr_Output__arr_int_uint_81 Output -)"; - - EntryPoint entry_point; - entry_point.name = "main_d_r"; - entry_point.execution_model = "MeshNV"; - entry_point.interfaces = "%gl_PrimitiveID %gl_Layer %gl_ViewportIndex"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateBuiltIns, InvalidBuiltinsForMeshShader) { - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.capabilities_ += R"( -OpCapability MeshShadingNV -)"; - - generator.extensions_ = R"( -OpExtension "SPV_NV_mesh_shader" -)"; - - generator.before_types_ = R"( -OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId -OpDecorate %gl_PrimitiveID PerPrimitiveNV -OpDecorate %gl_Layer BuiltIn Layer -OpDecorate %gl_Layer PerPrimitiveNV -OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex -OpDecorate %gl_ViewportIndex PerPrimitiveNV -)"; - - generator.after_types_ = R"( -%u32_81 = OpConstant %u32 81 -%_arr_float_uint_81 = OpTypeArray %f32 %u32_81 -%_ptr_Output__arr_float_uint_81 = OpTypePointer Output %_arr_float_uint_81 -%gl_PrimitiveID = OpVariable %_ptr_Output__arr_float_uint_81 Output -%gl_Layer = OpVariable %_ptr_Output__arr_float_uint_81 Output -%gl_ViewportIndex = OpVariable %_ptr_Output__arr_float_uint_81 Output -)"; - - EntryPoint entry_point; - entry_point.name = "main_d_r"; - entry_point.execution_model = "MeshNV"; - entry_point.interfaces = "%gl_PrimitiveID %gl_Layer %gl_ViewportIndex"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("needs to be a 32-bit int scalar")); - EXPECT_THAT(getDiagnosticString(), HasSubstr("is not an int scalar")); -} - -TEST_F(ValidateBuiltIns, GetUnderlyingTypeNoAssert) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %4 "PSMa" %12 %17 - OpExecutionMode %4 OriginUpperLeft - OpDecorate %gl_PointCoord BuiltIn PointCoord - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %gl_PointCoord = OpTypeStruct %v4float - %_ptr_Input_v4float = OpTypePointer Input %v4float - %_ptr_Output_v4float = OpTypePointer Output %v4float - %12 = OpVariable %_ptr_Input_v4float Input - %17 = OpVariable %_ptr_Output_v4float Output - %4 = OpFunction %void None %3 - %15 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("did not find an member index to get underlying data " - "type")); -} - -TEST_P(ValidateVulkanSubgroupBuiltIns, InMain) { - const char* const built_in = std::get<0>(GetParam()); - const char* const execution_model = std::get<1>(GetParam()); - const char* const storage_class = std::get<2>(GetParam()); - const char* const data_type = std::get<3>(GetParam()); - const TestResult& test_result = std::get<4>(GetParam()); - - CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator(); - generator.capabilities_ += R"( -OpCapability GroupNonUniformBallot -)"; - - generator.before_types_ = "OpDecorate %built_in_var BuiltIn "; - generator.before_types_ += built_in; - generator.before_types_ += "\n"; - - std::ostringstream after_types; - after_types << "%built_in_ptr = OpTypePointer " << storage_class << " " - << data_type << "\n"; - after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class; - after_types << "\n"; - generator.after_types_ = after_types.str(); - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = execution_model; - if (strncmp(storage_class, "Input", 5) == 0 || - strncmp(storage_class, "Output", 6) == 0) { - entry_point.interfaces = "%built_in_var"; - } - entry_point.body = - std::string("%ld = OpLoad ") + data_type + " %built_in_var\n"; - - std::ostringstream execution_modes; - if (0 == std::strcmp(execution_model, "Fragment")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " OriginUpperLeft\n"; - if (0 == std::strcmp(built_in, "FragDepth")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " DepthReplacing\n"; - } - } - if (0 == std::strcmp(execution_model, "Geometry")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " InputPoints\n"; - execution_modes << "OpExecutionMode %" << entry_point.name - << " OutputPoints\n"; - } - if (0 == std::strcmp(execution_model, "GLCompute")) { - execution_modes << "OpExecutionMode %" << entry_point.name - << " LocalSize 1 1 1\n"; - } - entry_point.execution_modes = execution_modes.str(); - - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_VULKAN_1_1)); - if (test_result.error_str) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } - if (test_result.error_str2) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); - } -} - -INSTANTIATE_TEST_SUITE_P( - SubgroupMaskNotVec4, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask", - "SubgroupLeMask", "SubgroupLtMask"), - Values("GLCompute"), Values("Input"), Values("%u32vec3"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit int vector")))); - -INSTANTIATE_TEST_SUITE_P( - SubgroupMaskNotU32, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask", - "SubgroupLeMask", "SubgroupLtMask"), - Values("GLCompute"), Values("Input"), Values("%f32vec4"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 4-component 32-bit int vector")))); - -INSTANTIATE_TEST_SUITE_P( - SubgroupMaskNotInput, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask", - "SubgroupLeMask", "SubgroupLtMask"), - Values("GLCompute"), Values("Output", "Workgroup", "Private"), - Values("%u32vec4"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class")))); - -INSTANTIATE_TEST_SUITE_P(SubgroupMaskOk, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupEqMask", "SubgroupGeMask", - "SubgroupGtMask", "SubgroupLeMask", - "SubgroupLtMask"), - Values("GLCompute"), Values("Input"), - Values("%u32vec4"), - Values(TestResult(SPV_SUCCESS, "")))); - -TEST_F(ValidateBuiltIns, SubgroupMaskMemberDecorate) { - const std::string text = R"( -OpCapability Shader -OpCapability GroupNonUniformBallot -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %foo "foo" -OpExecutionMode %foo LocalSize 1 1 1 -OpMemberDecorate %struct 0 BuiltIn SubgroupEqMask -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%struct = OpTypeStruct %int -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "BuiltIn SubgroupEqMask cannot be used as a member decoration")); -} - -INSTANTIATE_TEST_SUITE_P( - SubgroupInvocationIdAndSizeNotU32, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"), - Values("GLCompute"), Values("Input"), Values("%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int")))); - -INSTANTIATE_TEST_SUITE_P( - SubgroupInvocationIdAndSizeNotInput, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"), - Values("GLCompute"), Values("Output", "Workgroup", "Private"), - Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class")))); - -INSTANTIATE_TEST_SUITE_P( - SubgroupInvocationIdAndSizeOk, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"), - Values("GLCompute"), Values("Input"), Values("%u32"), - Values(TestResult(SPV_SUCCESS, "")))); - -TEST_F(ValidateBuiltIns, SubgroupSizeMemberDecorate) { - const std::string text = R"( -OpCapability Shader -OpCapability GroupNonUniform -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %foo "foo" -OpExecutionMode %foo LocalSize 1 1 1 -OpMemberDecorate %struct 0 BuiltIn SubgroupSize -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%struct = OpTypeStruct %int -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("BuiltIn SubgroupSize cannot be used as a member decoration")); -} - -INSTANTIATE_TEST_SUITE_P( - SubgroupNumAndIdNotU32, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupId", "NumSubgroups"), Values("GLCompute"), - Values("Input"), Values("%f32"), - Values(TestResult(SPV_ERROR_INVALID_DATA, - "needs to be a 32-bit int")))); - -INSTANTIATE_TEST_SUITE_P( - SubgroupNumAndIdNotInput, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupId", "NumSubgroups"), Values("GLCompute"), - Values("Output", "Workgroup", "Private"), Values("%u32"), - Values(TestResult( - SPV_ERROR_INVALID_DATA, - "to be only used for variables with Input storage class")))); - -INSTANTIATE_TEST_SUITE_P(SubgroupNumAndIdOk, ValidateVulkanSubgroupBuiltIns, - Combine(Values("SubgroupId", "NumSubgroups"), - Values("GLCompute"), Values("Input"), - Values("%u32"), - Values(TestResult(SPV_SUCCESS, "")))); - -TEST_F(ValidateBuiltIns, SubgroupIdMemberDecorate) { - const std::string text = R"( -OpCapability Shader -OpCapability GroupNonUniform -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %foo "foo" -OpExecutionMode %foo LocalSize 1 1 1 -OpMemberDecorate %struct 0 BuiltIn SubgroupId -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%struct = OpTypeStruct %int -%void_fn = OpTypeFunction %void -%foo = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("BuiltIn SubgroupId cannot be used as a member decoration")); -} - -TEST_F(ValidateBuiltIns, TargetIsType) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %void BuiltIn Position -%void = OpTypeVoid -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("BuiltIns can only target variables, structs or constants")); -} - -TEST_F(ValidateBuiltIns, TargetIsVariable) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %wg_var BuiltIn Position -%int = OpTypeInt 32 0 -%int_wg_ptr = OpTypePointer Workgroup %int -%wg_var = OpVariable %int_wg_ptr Workgroup -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBuiltIns, TargetIsStruct) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %struct BuiltIn Position -%struct = OpTypeStruct -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBuiltIns, TargetIsConstant) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %int0 BuiltIn Position -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateBuiltIns, TargetIsSpecConstant) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %int0 BuiltIn Position -%int = OpTypeInt 32 0 -%int0 = OpSpecConstant %int 0 -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_capability_test.cpp b/3rdparty/spirv-tools/test/val/val_capability_test.cpp deleted file mode 100644 index ae1d62bd8..000000000 --- a/3rdparty/spirv-tools/test/val/val_capability_test.cpp +++ /dev/null @@ -1,2663 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Validation tests for Logical Layout - -#include -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/assembly_grammar.h" -#include "source/spirv_target_env.h" -#include "spirv-tools/libspirv.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using spvtest::ScopedContext; -using testing::Combine; -using testing::Eq; -using testing::HasSubstr; -using testing::Values; -using testing::ValuesIn; - -// Parameter for validation test fixtures. The first std::string is a -// capability name that will begin the assembly under test, the second the -// remainder assembly, and the std::vector at the end determines whether the -// test expects success or failure. See below for details and convenience -// methods to access each one. -// -// The assembly to test is composed from a variable top line and a fixed -// remainder. The top line will be an OpCapability instruction, while the -// remainder will be some assembly text that succeeds or fails to assemble -// depending on which capability was chosen. For instance, the following will -// succeed: -// -// OpCapability Pipes ; implies Kernel -// OpLifetimeStop %1 0 ; requires Kernel -// -// and the following will fail: -// -// OpCapability Kernel -// %1 = OpTypeNamedBarrier ; requires NamedBarrier -// -// So how does the test parameter capture which capabilities should cause -// success and which shouldn't? The answer is in the last element: it's a -// std::vector of capabilities that make the remainder assembly succeed. So if -// the first-line capability exists in that std::vector, success is expected; -// otherwise, failure is expected in the tests. -// -// We will use testing::Combine() to vary the first line: when we combine -// AllCapabilities() with a single remainder assembly, we generate enough test -// cases to try the assembly with every possible capability that could be -// declared. However, Combine() only produces tuples -- it cannot produce, say, -// a struct. Therefore, this type must be a tuple. -using CapTestParameter = - std::tuple>>; - -const std::string& Capability(const CapTestParameter& p) { - return std::get<0>(p); -} -const std::string& Remainder(const CapTestParameter& p) { - return std::get<1>(p).first; -} -const std::vector& MustSucceed(const CapTestParameter& p) { - return std::get<1>(p).second; -} - -// Creates assembly to test from p. -std::string MakeAssembly(const CapTestParameter& p) { - std::ostringstream ss; - const std::string& capability = Capability(p); - if (!capability.empty()) { - ss << "OpCapability " << capability << "\n"; - } - ss << Remainder(p); - return ss.str(); -} - -// Expected validation result for p. -spv_result_t ExpectedResult(const CapTestParameter& p) { - const auto& caps = MustSucceed(p); - auto found = find(begin(caps), end(caps), Capability(p)); - return (found == end(caps)) ? SPV_ERROR_INVALID_CAPABILITY : SPV_SUCCESS; -} - -// Assembles using v1.0, unless the parameter's capability requires v1.1. -using ValidateCapability = spvtest::ValidateBase; - -// Always assembles using v1.1. -using ValidateCapabilityV11 = spvtest::ValidateBase; - -// Always assembles using Vulkan 1.0. -// TODO(dneto): Refactor all these tests to scale better across environments. -using ValidateCapabilityVulkan10 = spvtest::ValidateBase; -// Always assembles using OpenGL 4.0. -using ValidateCapabilityOpenGL40 = spvtest::ValidateBase; -// Always assembles using Vulkan 1.1. -using ValidateCapabilityVulkan11 = spvtest::ValidateBase; -// Always assembles using WebGPU. -using ValidateCapabilityWebGPU = spvtest::ValidateBase; - -TEST_F(ValidateCapability, Default) { - const char str[] = R"( - OpCapability Kernel - OpCapability Linkage - OpCapability Matrix - OpMemoryModel Logical OpenCL -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 3 -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// clang-format off -const std::vector& AllCapabilities() { - static const auto r = new std::vector{ - "", - "Matrix", - "Shader", - "Geometry", - "Tessellation", - "Addresses", - "Linkage", - "Kernel", - "Vector16", - "Float16Buffer", - "Float16", - "Float64", - "Int64", - "Int64Atomics", - "ImageBasic", - "ImageReadWrite", - "ImageMipmap", - "Pipes", - "Groups", - "DeviceEnqueue", - "LiteralSampler", - "AtomicStorage", - "Int16", - "TessellationPointSize", - "GeometryPointSize", - "ImageGatherExtended", - "StorageImageMultisample", - "UniformBufferArrayDynamicIndexing", - "SampledImageArrayDynamicIndexing", - "StorageBufferArrayDynamicIndexing", - "StorageImageArrayDynamicIndexing", - "ClipDistance", - "CullDistance", - "ImageCubeArray", - "SampleRateShading", - "ImageRect", - "SampledRect", - "GenericPointer", - "Int8", - "InputAttachment", - "SparseResidency", - "MinLod", - "Sampled1D", - "Image1D", - "SampledCubeArray", - "SampledBuffer", - "ImageBuffer", - "ImageMSArray", - "StorageImageExtendedFormats", - "ImageQuery", - "DerivativeControl", - "InterpolationFunction", - "TransformFeedback", - "GeometryStreams", - "StorageImageReadWithoutFormat", - "StorageImageWriteWithoutFormat", - "MultiViewport", - "SubgroupDispatch", - "NamedBarrier", - "PipeStorage", - "GroupNonUniform", - "GroupNonUniformVote", - "GroupNonUniformArithmetic", - "GroupNonUniformBallot", - "GroupNonUniformShuffle", - "GroupNonUniformShuffleRelative", - "GroupNonUniformClustered", - "GroupNonUniformQuad", - "DrawParameters", - "StorageBuffer16BitAccess", - "StorageUniformBufferBlock16", - "UniformAndStorageBuffer16BitAccess", - "StorageUniform16", - "StoragePushConstant16", - "StorageInputOutput16", - "DeviceGroup", - "MultiView", - "VariablePointersStorageBuffer", - "VariablePointers"}; - return *r; -} - -const std::vector& AllSpirV10Capabilities() { - static const auto r = new std::vector{ - "", - "Matrix", - "Shader", - "Geometry", - "Tessellation", - "Addresses", - "Linkage", - "Kernel", - "Vector16", - "Float16Buffer", - "Float16", - "Float64", - "Int64", - "Int64Atomics", - "ImageBasic", - "ImageReadWrite", - "ImageMipmap", - "Pipes", - "Groups", - "DeviceEnqueue", - "LiteralSampler", - "AtomicStorage", - "Int16", - "TessellationPointSize", - "GeometryPointSize", - "ImageGatherExtended", - "StorageImageMultisample", - "UniformBufferArrayDynamicIndexing", - "SampledImageArrayDynamicIndexing", - "StorageBufferArrayDynamicIndexing", - "StorageImageArrayDynamicIndexing", - "ClipDistance", - "CullDistance", - "ImageCubeArray", - "SampleRateShading", - "ImageRect", - "SampledRect", - "GenericPointer", - "Int8", - "InputAttachment", - "SparseResidency", - "MinLod", - "Sampled1D", - "Image1D", - "SampledCubeArray", - "SampledBuffer", - "ImageBuffer", - "ImageMSArray", - "StorageImageExtendedFormats", - "ImageQuery", - "DerivativeControl", - "InterpolationFunction", - "TransformFeedback", - "GeometryStreams", - "StorageImageReadWithoutFormat", - "StorageImageWriteWithoutFormat", - "MultiViewport"}; - return *r; -} - -const std::vector& AllVulkan10Capabilities() { - static const auto r = new std::vector{ - "", - "Matrix", - "Shader", - "InputAttachment", - "Sampled1D", - "Image1D", - "SampledBuffer", - "ImageBuffer", - "ImageQuery", - "DerivativeControl", - "Geometry", - "Tessellation", - "Float16", - "Float64", - "Int64", - "Int64Atomics", - "Int16", - "TessellationPointSize", - "GeometryPointSize", - "ImageGatherExtended", - "StorageImageMultisample", - "UniformBufferArrayDynamicIndexing", - "SampledImageArrayDynamicIndexing", - "StorageBufferArrayDynamicIndexing", - "StorageImageArrayDynamicIndexing", - "ClipDistance", - "CullDistance", - "ImageCubeArray", - "SampleRateShading", - "Int8", - "SparseResidency", - "MinLod", - "SampledCubeArray", - "ImageMSArray", - "StorageImageExtendedFormats", - "InterpolationFunction", - "StorageImageReadWithoutFormat", - "StorageImageWriteWithoutFormat", - "MultiViewport", - "TransformFeedback", - "GeometryStreams"}; - return *r; -} - -const std::vector& AllVulkan11Capabilities() { - static const auto r = new std::vector{ - "", - "Matrix", - "Shader", - "InputAttachment", - "Sampled1D", - "Image1D", - "SampledBuffer", - "ImageBuffer", - "ImageQuery", - "DerivativeControl", - "Geometry", - "Tessellation", - "Float16", - "Float64", - "Int64", - "Int64Atomics", - "Int16", - "TessellationPointSize", - "GeometryPointSize", - "ImageGatherExtended", - "StorageImageMultisample", - "UniformBufferArrayDynamicIndexing", - "SampledImageArrayDynamicIndexing", - "StorageBufferArrayDynamicIndexing", - "StorageImageArrayDynamicIndexing", - "ClipDistance", - "CullDistance", - "ImageCubeArray", - "SampleRateShading", - "Int8", - "SparseResidency", - "MinLod", - "SampledCubeArray", - "ImageMSArray", - "StorageImageExtendedFormats", - "InterpolationFunction", - "StorageImageReadWithoutFormat", - "StorageImageWriteWithoutFormat", - "MultiViewport", - "GroupNonUniform", - "GroupNonUniformVote", - "GroupNonUniformArithmetic", - "GroupNonUniformBallot", - "GroupNonUniformShuffle", - "GroupNonUniformShuffleRelative", - "GroupNonUniformClustered", - "GroupNonUniformQuad", - "DrawParameters", - "StorageBuffer16BitAccess", - "StorageUniformBufferBlock16", - "UniformAndStorageBuffer16BitAccess", - "StorageUniform16", - "StoragePushConstant16", - "StorageInputOutput16", - "DeviceGroup", - "MultiView", - "VariablePointersStorageBuffer", - "VariablePointers", - "TransformFeedback", - "GeometryStreams"}; - return *r; -} - -const std::vector& AllWebGPUCapabilities() { - static const auto r = new std::vector{ - "", - "Shader", - "Matrix", - "Sampled1D", - "Image1D", - "ImageQuery", - "DerivativeControl"}; - return *r; -} - -const std::vector& MatrixDependencies() { - static const auto r = new std::vector{ - "Matrix", - "Shader", - "Geometry", - "Tessellation", - "AtomicStorage", - "TessellationPointSize", - "GeometryPointSize", - "ImageGatherExtended", - "StorageImageMultisample", - "UniformBufferArrayDynamicIndexing", - "SampledImageArrayDynamicIndexing", - "StorageBufferArrayDynamicIndexing", - "StorageImageArrayDynamicIndexing", - "ClipDistance", - "CullDistance", - "ImageCubeArray", - "SampleRateShading", - "ImageRect", - "SampledRect", - "InputAttachment", - "SparseResidency", - "MinLod", - "SampledCubeArray", - "ImageMSArray", - "StorageImageExtendedFormats", - "ImageQuery", - "DerivativeControl", - "InterpolationFunction", - "TransformFeedback", - "GeometryStreams", - "StorageImageReadWithoutFormat", - "StorageImageWriteWithoutFormat", - "MultiViewport", - "DrawParameters", - "MultiView", - "VariablePointersStorageBuffer", - "VariablePointers"}; - return *r; -} - -const std::vector& ShaderDependencies() { - static const auto r = new std::vector{ - "Shader", - "Geometry", - "Tessellation", - "AtomicStorage", - "TessellationPointSize", - "GeometryPointSize", - "ImageGatherExtended", - "StorageImageMultisample", - "UniformBufferArrayDynamicIndexing", - "SampledImageArrayDynamicIndexing", - "StorageBufferArrayDynamicIndexing", - "StorageImageArrayDynamicIndexing", - "ClipDistance", - "CullDistance", - "ImageCubeArray", - "SampleRateShading", - "ImageRect", - "SampledRect", - "InputAttachment", - "SparseResidency", - "MinLod", - "SampledCubeArray", - "ImageMSArray", - "StorageImageExtendedFormats", - "ImageQuery", - "DerivativeControl", - "InterpolationFunction", - "TransformFeedback", - "GeometryStreams", - "StorageImageReadWithoutFormat", - "StorageImageWriteWithoutFormat", - "MultiViewport", - "DrawParameters", - "MultiView", - "VariablePointersStorageBuffer", - "VariablePointers"}; - return *r; -} - -const std::vector& TessellationDependencies() { - static const auto r = new std::vector{ - "Tessellation", - "TessellationPointSize"}; - return *r; -} - -const std::vector& GeometryDependencies() { - static const auto r = new std::vector{ - "Geometry", - "GeometryPointSize", - "GeometryStreams", - "MultiViewport"}; - return *r; -} - -const std::vector& GeometryTessellationDependencies() { - static const auto r = new std::vector{ - "Tessellation", - "TessellationPointSize", - "Geometry", - "GeometryPointSize", - "GeometryStreams", - "MultiViewport"}; - return *r; -} - -// Returns the names of capabilities that directly depend on Kernel, -// plus itself. -const std::vector& KernelDependencies() { - static const auto r = new std::vector{ - "Kernel", - "Vector16", - "Float16Buffer", - "ImageBasic", - "ImageReadWrite", - "ImageMipmap", - "Pipes", - "DeviceEnqueue", - "LiteralSampler", - "SubgroupDispatch", - "NamedBarrier", - "PipeStorage"}; - return *r; -} - -const std::vector& KernelAndGroupNonUniformDependencies() { - static const auto r = new std::vector{ - "Kernel", - "Vector16", - "Float16Buffer", - "ImageBasic", - "ImageReadWrite", - "ImageMipmap", - "Pipes", - "DeviceEnqueue", - "LiteralSampler", - "SubgroupDispatch", - "NamedBarrier", - "PipeStorage", - "GroupNonUniform", - "GroupNonUniformVote", - "GroupNonUniformArithmetic", - "GroupNonUniformBallot", - "GroupNonUniformShuffle", - "GroupNonUniformShuffleRelative", - "GroupNonUniformClustered", - "GroupNonUniformQuad"}; - return *r; -} - -const std::vector& AddressesDependencies() { - static const auto r = new std::vector{ - "Addresses", - "GenericPointer"}; - return *r; -} - -const std::vector& Sampled1DDependencies() { - static const auto r = new std::vector{ - "Sampled1D", - "Image1D"}; - return *r; -} - -const std::vector& SampledRectDependencies() { - static const auto r = new std::vector{ - "SampledRect", - "ImageRect"}; - return *r; -} - -const std::vector& SampledBufferDependencies() { - static const auto r = new std::vector{ - "SampledBuffer", - "ImageBuffer"}; - return *r; -} - -const char kOpenCLMemoryModel[] = \ - " OpCapability Kernel" - " OpMemoryModel Logical OpenCL "; - -const char kGLSL450MemoryModel[] = \ - " OpCapability Shader" - " OpMemoryModel Logical GLSL450 "; - -const char kVulkanMemoryModel[] = \ - " OpCapability Shader" - " OpCapability VulkanMemoryModelKHR" - " OpExtension \"SPV_KHR_vulkan_memory_model\"" - " OpMemoryModel Logical VulkanKHR "; - -const char kVoidFVoid[] = \ - " %void = OpTypeVoid" - " %void_f = OpTypeFunction %void" - " %func = OpFunction %void None %void_f" - " %label = OpLabel" - " OpReturn" - " OpFunctionEnd "; - -const char kVoidFVoid2[] = \ - " %void_f = OpTypeFunction %voidt" - " %func = OpFunction %voidt None %void_f" - " %label = OpLabel" - " OpReturn" - " OpFunctionEnd "; - -INSTANTIATE_TEST_SUITE_P(ExecutionModel, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint TessellationControl %func \"shader\"" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint TessellationEvaluation %func \"shader\"" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Geometry %func \"shader\"" + - " OpExecutionMode %func InputPoints" + - " OpExecutionMode %func OutputPoints" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Fragment %func \"shader\"" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint GLCompute %func \"shader\"" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Kernel %func \"shader\"" + - std::string(kVoidFVoid), KernelDependencies()) -))); - -INSTANTIATE_TEST_SUITE_P(AddressingAndMemoryModel, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(" OpCapability Shader" - " OpMemoryModel Logical Simple" - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), AllCapabilities()), -std::make_pair(" OpCapability Shader" - " OpMemoryModel Logical GLSL450" - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), AllCapabilities()), -std::make_pair(" OpCapability Kernel" - " OpMemoryModel Logical OpenCL" - " OpEntryPoint Kernel %func \"compute\"" + - std::string(kVoidFVoid), AllCapabilities()), -std::make_pair(" OpCapability Shader" - " OpMemoryModel Physical32 Simple" - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), AddressesDependencies()), -std::make_pair(" OpCapability Shader" - " OpMemoryModel Physical32 GLSL450" - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), AddressesDependencies()), -std::make_pair(" OpCapability Kernel" - " OpMemoryModel Physical32 OpenCL" - " OpEntryPoint Kernel %func \"compute\"" + - std::string(kVoidFVoid), AddressesDependencies()), -std::make_pair(" OpCapability Shader" - " OpMemoryModel Physical64 Simple" - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), AddressesDependencies()), -std::make_pair(" OpCapability Shader" - " OpMemoryModel Physical64 GLSL450" - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid), AddressesDependencies()), -std::make_pair(" OpCapability Kernel" - " OpMemoryModel Physical64 OpenCL" - " OpEntryPoint Kernel %func \"compute\"" + - std::string(kVoidFVoid), AddressesDependencies()) -))); - -INSTANTIATE_TEST_SUITE_P(ExecutionMode, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func Invocations 42" + - " OpExecutionMode %func InputPoints" + - " OpExecutionMode %func OutputPoints" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func SpacingEqual" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func SpacingFractionalEven" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func SpacingFractionalOdd" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func VertexOrderCw" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func VertexOrderCcw" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func PixelCenterInteger" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func OriginLowerLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func EarlyFragmentTests" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func PointMode" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Vertex %func \"shader\" " - "OpExecutionMode %func Xfb" + - std::string(kVoidFVoid), std::vector{"TransformFeedback"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func DepthReplacing" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func DepthGreater" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func DepthLess" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Fragment %func \"shader\" " - "OpExecutionMode %func DepthUnchanged" + - " OpExecutionMode %func OriginUpperLeft" + - std::string(kVoidFVoid), ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"shader\" " - "OpExecutionMode %func LocalSize 42 42 42" + - std::string(kVoidFVoid), AllCapabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Kernel %func \"shader\" " - "OpExecutionMode %func LocalSizeHint 42 42 42" + - std::string(kVoidFVoid), KernelDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func InputPoints" + - " OpExecutionMode %func OutputPoints" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func InputLines" + - " OpExecutionMode %func OutputLineStrip" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func InputLinesAdjacency" + - " OpExecutionMode %func OutputLineStrip" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func Triangles" + - " OpExecutionMode %func OutputTriangleStrip" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func Triangles" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func InputTrianglesAdjacency" + - " OpExecutionMode %func OutputTriangleStrip" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func Quads" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func Isolines" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func OutputVertices 42" + - " OpExecutionMode %func OutputPoints" + - " OpExecutionMode %func InputPoints" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint TessellationControl %func \"shader\" " - "OpExecutionMode %func OutputVertices 42" + - std::string(kVoidFVoid), TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func OutputPoints" + - " OpExecutionMode %func InputPoints" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func OutputLineStrip" + - " OpExecutionMode %func InputLines" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Geometry %func \"shader\" " - "OpExecutionMode %func OutputTriangleStrip" + - " OpExecutionMode %func Triangles" + - std::string(kVoidFVoid), GeometryDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Kernel %func \"shader\" " - "OpExecutionMode %func VecTypeHint 2" + - std::string(kVoidFVoid), KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Kernel %func \"shader\" " - "OpExecutionMode %func ContractionOff" + - std::string(kVoidFVoid), KernelDependencies())))); - -// clang-format on - -INSTANTIATE_TEST_SUITE_P( - ExecutionModeV11, ValidateCapabilityV11, - Combine(ValuesIn(AllCapabilities()), - Values(std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"shader\" " - "OpExecutionMode %func SubgroupSize 1" + - std::string(kVoidFVoid), - std::vector{"SubgroupDispatch"}), - std::make_pair( - std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"shader\" " - "OpExecutionMode %func SubgroupsPerWorkgroup 65535" + - std::string(kVoidFVoid), - std::vector{"SubgroupDispatch"})))); -// clang-format off - -INSTANTIATE_TEST_SUITE_P(StorageClass, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer UniformConstant %intt\n" - " %var = OpVariable %ptrt UniformConstant\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Kernel %func \"compute\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer Input %intt" - " %var = OpVariable %ptrt Input\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer Uniform %intt\n" - " %var = OpVariable %ptrt Uniform\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer Output %intt\n" - " %var = OpVariable %ptrt Output\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer Workgroup %intt\n" - " %var = OpVariable %ptrt Workgroup\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer CrossWorkgroup %intt\n" - " %var = OpVariable %ptrt CrossWorkgroup\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Kernel %func \"compute\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer Private %intt\n" - " %var = OpVariable %ptrt Private\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - " OpEntryPoint Kernel %func \"compute\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer PushConstant %intt\n" - " %var = OpVariable %ptrt PushConstant\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer AtomicCounter %intt\n" - " %var = OpVariable %ptrt AtomicCounter\n" + std::string(kVoidFVoid), - std::vector{"AtomicStorage"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" + - " %intt = OpTypeInt 32 0\n" - " %ptrt = OpTypePointer Image %intt\n" - " %var = OpVariable %ptrt Image\n" + std::string(kVoidFVoid), - AllCapabilities()) -))); - -INSTANTIATE_TEST_SUITE_P(Dim, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt 1D 0 0 0 0 Unknown" + std::string(kVoidFVoid2), - Sampled1DDependencies()), -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt 2D 0 0 0 0 Unknown" + std::string(kVoidFVoid2), - AllCapabilities()), -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt 3D 0 0 0 0 Unknown" + std::string(kVoidFVoid2), - AllCapabilities()), -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt Cube 0 0 0 0 Unknown" + std::string(kVoidFVoid2), - ShaderDependencies()), -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt Rect 0 0 0 0 Unknown" + std::string(kVoidFVoid2), - SampledRectDependencies()), -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt Buffer 0 0 0 0 Unknown" + std::string(kVoidFVoid2), - SampledBufferDependencies()), -std::make_pair(" OpCapability ImageBasic" + - std::string(kOpenCLMemoryModel) + - std::string(" OpEntryPoint Kernel %func \"compute\"") + - " %voidt = OpTypeVoid" - " %imgt = OpTypeImage %voidt SubpassData 0 0 0 2 Unknown" + std::string(kVoidFVoid2), - std::vector{"InputAttachment"}) -))); - -// NOTE: All Sampler Address Modes require kernel capabilities but the -// OpConstantSampler requires LiteralSampler which depends on Kernel -INSTANTIATE_TEST_SUITE_P(SamplerAddressingMode, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" - " %samplert = OpTypeSampler" - " %sampler = OpConstantSampler %samplert None 1 Nearest" + - std::string(kVoidFVoid), - std::vector{"LiteralSampler"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" - " %samplert = OpTypeSampler" - " %sampler = OpConstantSampler %samplert ClampToEdge 1 Nearest" + - std::string(kVoidFVoid), - std::vector{"LiteralSampler"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" - " %samplert = OpTypeSampler" - " %sampler = OpConstantSampler %samplert Clamp 1 Nearest" + - std::string(kVoidFVoid), - std::vector{"LiteralSampler"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" - " %samplert = OpTypeSampler" - " %sampler = OpConstantSampler %samplert Repeat 1 Nearest" + - std::string(kVoidFVoid), - std::vector{"LiteralSampler"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - " OpEntryPoint Vertex %func \"shader\"" - " %samplert = OpTypeSampler" - " %sampler = OpConstantSampler %samplert RepeatMirrored 1 Nearest" + - std::string(kVoidFVoid), - std::vector{"LiteralSampler"}) -))); - -// TODO(umar): Sampler Filter Mode -// TODO(umar): Image Format -// TODO(umar): Image Channel Order -// TODO(umar): Image Channel Data Type -// TODO(umar): Image Operands -// TODO(umar): FP Fast Math Mode -// TODO(umar): FP Rounding Mode -// TODO(umar): Linkage Type -// TODO(umar): Access Qualifier -// TODO(umar): Function Parameter Attribute - -INSTANTIATE_TEST_SUITE_P(Decoration, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt RelaxedPrecision\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Block\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt BufferBlock\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt RowMajor\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - MatrixDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt ColMajor\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - MatrixDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt ArrayStride 1\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt MatrixStride 1\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - MatrixDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt GLSLShared\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt GLSLPacked\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %intt CPacked\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt NoPerspective\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Flat\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Patch\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Centroid\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Sample\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - std::vector{"SampleRateShading"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Invariant\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Restrict\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Aliased\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Volatile\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %intt Constant\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Coherent\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - // NonWritable must target something valid, such as a storage image. - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %var NonWritable " - "%float = OpTypeFloat 32 " - "%imstor = OpTypeImage %float 2D 0 0 0 2 Unknown " - "%ptr = OpTypePointer UniformConstant %imstor " - "%var = OpVariable %ptr UniformConstant " - + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt NonReadable\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - // Uniform must target a non-void value. - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %int0 Uniform\n" - "%intt = OpTypeInt 32 0\n" + - "%int0 = OpConstantNull %intt" - + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %intt SaturatedConversion\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Stream 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - std::vector{"GeometryStreams"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Location 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %var Component 0\n" - "%intt = OpTypeInt 32 0\n" - "%ptr = OpTypePointer Input %intt\n" - "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Index 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Binding 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt DescriptorSet 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt Offset 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt XfbBuffer 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - std::vector{"TransformFeedback"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt XfbStride 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - std::vector{"TransformFeedback"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %intt FuncParamAttr Zext\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %intt FPFastMathMode Fast\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt LinkageAttributes \"other\" Import\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - std::vector{"Linkage"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt NoContraction\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %intt InputAttachmentIndex 0\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - std::vector{"InputAttachment"}), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %intt Alignment 4\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - KernelDependencies()) -))); - -// clang-format on -INSTANTIATE_TEST_SUITE_P( - DecorationSpecId, ValidateCapability, - Combine( - ValuesIn(AllSpirV10Capabilities()), - Values(std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %1 SpecId 1\n" - "%intt = OpTypeInt 32 0\n" - "%1 = OpSpecConstant %intt 0\n" + - std::string(kVoidFVoid), - ShaderDependencies())))); - -INSTANTIATE_TEST_SUITE_P( - DecorationV11, ValidateCapabilityV11, - Combine(ValuesIn(AllCapabilities()), - Values(std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %p MaxByteOffset 0 " - "%i32 = OpTypeInt 32 0 " - "%pi32 = OpTypePointer Workgroup %i32 " - "%p = OpVariable %pi32 Workgroup " + - std::string(kVoidFVoid), - AddressesDependencies()), - // Trying to test OpDecorate here, but if this fails due to - // incorrect OpMemoryModel validation, that must also be - // fixed. - std::make_pair( - std::string("OpMemoryModel Logical OpenCL " - "OpEntryPoint Kernel %func \"compute\" \n" - "OpDecorate %1 SpecId 1 " - "%intt = OpTypeInt 32 0 " - "%1 = OpSpecConstant %intt 0") + - std::string(kVoidFVoid), - KernelDependencies()), - std::make_pair( - std::string("OpMemoryModel Logical Simple " - "OpEntryPoint Vertex %func \"shader\" \n" - "OpDecorate %1 SpecId 1 " - "%intt = OpTypeInt 32 0 " - "%1 = OpSpecConstant %intt 0") + - std::string(kVoidFVoid), - ShaderDependencies())))); -// clang-format off - -INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn Position\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -// Just mentioning PointSize, ClipDistance, or CullDistance as a BuiltIn does -// not trigger the requirement for the associated capability. -// See https://github.com/KhronosGroup/SPIRV-Tools/issues/365 -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn PointSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn ClipDistance\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn CullDistance\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn VertexId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn InstanceId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn PrimitiveId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - GeometryTessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn InvocationId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - GeometryTessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn Layer\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - GeometryDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn ViewportIndex\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - std::vector{"MultiViewport"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn TessLevelOuter\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn TessLevelInner\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn TessCoord\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn PatchVertices\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - TessellationDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn FragCoord\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn PointCoord\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn FrontFacing\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn SampleId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - std::vector{"SampleRateShading"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn SamplePosition\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - std::vector{"SampleRateShading"}), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn SampleMask\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn FragDepth\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn HelperInvocation\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn VertexIndex\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn InstanceIndex\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn NumWorkgroups\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn WorkgroupSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn WorkgroupId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn LocalInvocationId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn GlobalInvocationId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn LocalInvocationIndex\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllCapabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn WorkDim\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn GlobalSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn EnqueuedWorkgroupSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn GlobalOffset\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn GlobalLinearId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn SubgroupSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelAndGroupNonUniformDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn SubgroupMaxSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn NumSubgroups\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelAndGroupNonUniformDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn NumEnqueuedSubgroups\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn SubgroupId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelAndGroupNonUniformDependencies()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn SubgroupLocalInvocationId\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - KernelAndGroupNonUniformDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn VertexIndex\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()), -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "OpDecorate %int0 BuiltIn InstanceIndex\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - ShaderDependencies()) -))); - -// Ensure that mere mention of PointSize, ClipDistance, or CullDistance as -// BuiltIns does not trigger the requirement for the associated -// capability. -// See https://github.com/KhronosGroup/SPIRV-Tools/issues/365 -INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapabilityVulkan10, - Combine( - // All capabilities to try. - ValuesIn(AllSpirV10Capabilities()), - Values( -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpMemberDecorate %block 0 BuiltIn PointSize\n" - "%f32 = OpTypeFloat 32\n" - "%block = OpTypeStruct %f32\n" - "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid), - // Capabilities which should succeed. - AllVulkan10Capabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpMemberDecorate %block 0 BuiltIn ClipDistance\n" - "%f32 = OpTypeFloat 32\n" - "%intt = OpTypeInt 32 0\n" - "%intt_4 = OpConstant %intt 4\n" - "%f32arr4 = OpTypeArray %f32 %intt_4\n" - "%block = OpTypeStruct %f32arr4\n" + std::string(kVoidFVoid), - AllVulkan10Capabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" - "OpMemberDecorate %block 0 BuiltIn CullDistance\n" - "%f32 = OpTypeFloat 32\n" - "%intt = OpTypeInt 32 0\n" - "%intt_4 = OpConstant %intt 4\n" - "%f32arr4 = OpTypeArray %f32 %intt_4\n" - "%block = OpTypeStruct %f32arr4\n" + std::string(kVoidFVoid), - AllVulkan10Capabilities()) -))); - -INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapabilityOpenGL40, - Combine( - // OpenGL 4.0 is based on SPIR-V 1.0 - ValuesIn(AllSpirV10Capabilities()), - Values( -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn PointSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllSpirV10Capabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn ClipDistance\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllSpirV10Capabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn CullDistance\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllSpirV10Capabilities()) -))); - -INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityWebGPU, - Combine( - // All capabilities to try. - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kVulkanMemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + std::string(kVoidFVoid), - AllWebGPUCapabilities()) -))); - -INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityVulkan11, - Combine( - // All capabilities to try. - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn PointSize\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllVulkan11Capabilities()), -std::make_pair(std::string(kGLSL450MemoryModel) + - "OpEntryPoint Vertex %func \"shader\" \n" + - "OpDecorate %int0 BuiltIn CullDistance\n" - "%intt = OpTypeInt 32 0\n" - "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid), - AllVulkan11Capabilities()) -))); - -// TODO(umar): Selection Control -// TODO(umar): Loop Control -// TODO(umar): Function Control -// TODO(umar): Memory Semantics -// TODO(umar): Memory Access -// TODO(umar): Scope -// TODO(umar): Group Operation -// TODO(umar): Kernel Enqueue Flags -// TODO(umar): Kernel Profiling Flags - -INSTANTIATE_TEST_SUITE_P(MatrixOp, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values( -std::make_pair(std::string(kOpenCLMemoryModel) + - "OpEntryPoint Kernel %func \"compute\" \n" + - "%f32 = OpTypeFloat 32\n" - "%vec3 = OpTypeVector %f32 3\n" - "%mat33 = OpTypeMatrix %vec3 3\n" + std::string(kVoidFVoid), - MatrixDependencies())))); -// clang-format on - -#if 0 -// TODO(atgoo@github.com) The following test is not valid as it generates -// invalid combinations of images, instructions and image operands. -// -// Creates assembly containing an OpImageFetch instruction using operands for -// the image-operands part. The assembly defines constants %fzero and %izero -// that can be used for operands where IDs are required. The assembly is valid, -// apart from not declaring any capabilities required by the operands. -string ImageOperandsTemplate(const std::string& operands) { - ostringstream ss; - // clang-format off - ss << R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL - -%i32 = OpTypeInt 32 0 -%f32 = OpTypeFloat 32 -%v4i32 = OpTypeVector %i32 4 -%timg = OpTypeImage %i32 2D 0 0 0 0 Unknown -%pimg = OpTypePointer UniformConstant %timg -%tfun = OpTypeFunction %i32 - -%vimg = OpVariable %pimg UniformConstant -%izero = OpConstant %i32 0 -%fzero = OpConstant %f32 0. - -%main = OpFunction %i32 None %tfun -%lbl = OpLabel -%img = OpLoad %timg %vimg -%r1 = OpImageFetch %v4i32 %img %izero )" << operands << R"( -OpReturnValue %izero -OpFunctionEnd -)"; - // clang-format on - return ss.str(); -} - -INSTANTIATE_TEST_SUITE_P( - TwoImageOperandsMask, ValidateCapability, - Combine( - ValuesIn(AllCapabilities()), - Values(std::make_pair(ImageOperandsTemplate("Bias|Lod %fzero %fzero"), - ShaderDependencies()), - std::make_pair(ImageOperandsTemplate("Lod|Offset %fzero %izero"), - std::vector{"ImageGatherExtended"}), - std::make_pair(ImageOperandsTemplate("Sample|MinLod %izero %fzero"), - std::vector{"MinLod"}), - std::make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"), - AllCapabilities()))), ); -#endif - -// TODO(umar): Instruction capability checks - -spv_result_t spvCoreOperandTableNameLookup(spv_target_env env, - const spv_operand_table table, - const spv_operand_type_t type, - const char* name, - const size_t nameLength) { - if (!table) return SPV_ERROR_INVALID_TABLE; - if (!name) return SPV_ERROR_INVALID_POINTER; - - for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { - const auto& group = table->types[typeIndex]; - if (type != group.type) continue; - for (uint64_t index = 0; index < group.count; ++index) { - const auto& entry = group.entries[index]; - // Check for min version only. - if (spvVersionForTargetEnv(env) >= entry.minVersion && - nameLength == strlen(entry.name) && - !strncmp(entry.name, name, nameLength)) { - return SPV_SUCCESS; - } - } - } - - return SPV_ERROR_INVALID_LOOKUP; -} - -// True if capability exists in core spec of env. -bool Exists(const std::string& capability, spv_target_env env) { - ScopedContext sc(env); - return SPV_SUCCESS == - spvCoreOperandTableNameLookup(env, sc.context->operand_table, - SPV_OPERAND_TYPE_CAPABILITY, - capability.c_str(), capability.size()); -} - -TEST_P(ValidateCapability, Capability) { - const std::string capability = Capability(GetParam()); - spv_target_env env = SPV_ENV_UNIVERSAL_1_0; - if (!capability.empty()) { - if (Exists(capability, SPV_ENV_UNIVERSAL_1_0)) - env = SPV_ENV_UNIVERSAL_1_0; - else if (Exists(capability, SPV_ENV_UNIVERSAL_1_1)) - env = SPV_ENV_UNIVERSAL_1_1; - else if (Exists(capability, SPV_ENV_UNIVERSAL_1_2)) - env = SPV_ENV_UNIVERSAL_1_2; - else - env = SPV_ENV_UNIVERSAL_1_3; - } - const std::string test_code = MakeAssembly(GetParam()); - CompileSuccessfully(test_code, env); - ASSERT_EQ(ExpectedResult(GetParam()), ValidateInstructions(env)) - << "target env: " << spvTargetEnvDescription(env) << "\ntest code:\n" - << test_code; -} - -TEST_P(ValidateCapabilityV11, Capability) { - const std::string capability = Capability(GetParam()); - if (Exists(capability, SPV_ENV_UNIVERSAL_1_1)) { - const std::string test_code = MakeAssembly(GetParam()); - CompileSuccessfully(test_code, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(ExpectedResult(GetParam()), - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)) - << test_code; - } -} - -TEST_P(ValidateCapabilityVulkan10, Capability) { - const std::string capability = Capability(GetParam()); - if (Exists(capability, SPV_ENV_VULKAN_1_0)) { - const std::string test_code = MakeAssembly(GetParam()); - CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_0); - ASSERT_EQ(ExpectedResult(GetParam()), - ValidateInstructions(SPV_ENV_VULKAN_1_0)) - << test_code; - } -} - -TEST_P(ValidateCapabilityVulkan11, Capability) { - const std::string capability = Capability(GetParam()); - if (Exists(capability, SPV_ENV_VULKAN_1_1)) { - const std::string test_code = MakeAssembly(GetParam()); - CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_1); - ASSERT_EQ(ExpectedResult(GetParam()), - ValidateInstructions(SPV_ENV_VULKAN_1_1)) - << test_code; - } -} - -TEST_P(ValidateCapabilityOpenGL40, Capability) { - const std::string capability = Capability(GetParam()); - if (Exists(capability, SPV_ENV_OPENGL_4_0)) { - const std::string test_code = MakeAssembly(GetParam()); - CompileSuccessfully(test_code, SPV_ENV_OPENGL_4_0); - ASSERT_EQ(ExpectedResult(GetParam()), - ValidateInstructions(SPV_ENV_OPENGL_4_0)) - << test_code; - } -} - -TEST_P(ValidateCapabilityWebGPU, Capability) { - const std::string capability = Capability(GetParam()); - if (Exists(capability, SPV_ENV_WEBGPU_0)) { - const std::string test_code = MakeAssembly(GetParam()); - CompileSuccessfully(test_code, SPV_ENV_WEBGPU_0); - ASSERT_EQ(ExpectedResult(GetParam()), - ValidateInstructions(SPV_ENV_WEBGPU_0)) - << test_code; - } -} - -TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) { - // From https://github.com/KhronosGroup/SPIRV-Tools/issues/248 - // The validator was interpreting the memory semantics ID number - // as the value to be checked rather than an ID that references - // another value to be checked. - // In this case a raw ID of 64 was mistaken to mean a literal - // semantic value of UniformMemory, which would require the Shader - // capability. - const char str[] = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL - -; %i32 has ID 1 -%i32 = OpTypeInt 32 0 -%tf = OpTypeFunction %i32 -%pi32 = OpTypePointer CrossWorkgroup %i32 -%var = OpVariable %pi32 CrossWorkgroup -%c = OpConstant %i32 100 -%scope = OpConstant %i32 1 ; Device scope - -; Fake an instruction with 64 as the result id. -; !64 = OpConstantNull %i32 -!0x3002e !1 !64 - -%f = OpFunction %i32 None %tf -%l = OpLabel -%result = OpAtomicIAdd %i32 %var %scope !64 %c -OpReturnValue %result -OpFunctionEnd -)"; - - CompileSuccessfully(str); - - // Since we are forcing usage of 64, the "id bound" in the binary header - // must be overwritten so that 64 is considered within bound. - // ID Bound is at index 3 of the binary. Set it to 65. - OverwriteAssembledBinary(3, 65); - - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCapability, IntSignednessKernelGood) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%i32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCapability, IntSignednessKernelBad) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -%i32 = OpTypeInt 32 1 -)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Signedness in OpTypeInt must always be 0 when " - "Kernel capability is used.")); -} - -TEST_F(ValidateCapability, IntSignednessShaderGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%u32 = OpTypeInt 32 0 -%i32 = OpTypeInt 32 1 -)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCapability, NonVulkan10Capability) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%u32 = OpTypeInt 32 0 -%i32 = OpTypeInt 32 1 -)"; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Linkage is not allowed by Vulkan 1.0")); -} - -TEST_F(ValidateCapability, Vulkan10EnabledByExtension) { - const std::string spirv = R"( -OpCapability Shader -OpCapability DrawParameters -OpExtension "SPV_KHR_shader_draw_parameters" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %func "shader" -OpMemberDecorate %block 0 BuiltIn PointSize -%f32 = OpTypeFloat 32 -%block = OpTypeStruct %f32 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateCapability, Vulkan10NotEnabledByExtension) { - const std::string spirv = R"( -OpCapability Shader -OpCapability DrawParameters -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %func "shader" -OpDecorate %intt BuiltIn PointSize -%intt = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability DrawParameters is not allowed by Vulkan 1.0")); -} - -TEST_F(ValidateCapability, NonOpenCL12FullCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Pipes -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Pipes is not allowed by OpenCL 1.2 Full Profile")); -} - -TEST_F(ValidateCapability, OpenCL12FullEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability ImageBasic -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2)); -} - -TEST_F(ValidateCapability, OpenCL12FullNotEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability Sampled1D is not allowed by OpenCL 1.2 Full Profile")); -} - -TEST_F(ValidateCapability, NonOpenCL12EmbeddedCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Int64 -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability Int64 is not allowed by OpenCL 1.2 Embedded Profile")); -} - -TEST_F(ValidateCapability, OpenCL12EmbeddedEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability ImageBasic -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2)); -} - -TEST_F(ValidateCapability, OpenCL12EmbeddedNotEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Sampled1D is not allowed by OpenCL 1.2 " - "Embedded Profile")); -} - -TEST_F(ValidateCapability, OpenCL20FullCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Pipes -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0)); -} - -TEST_F(ValidateCapability, NonOpenCL20FullCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Matrix -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_2_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability Matrix is not allowed by OpenCL 2.0/2.1 Full Profile")); -} - -TEST_F(ValidateCapability, OpenCL20FullEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability ImageBasic -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0)); -} - -TEST_F(ValidateCapability, OpenCL20FullNotEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_2_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.0/2.1 " - "Full Profile")); -} - -TEST_F(ValidateCapability, NonOpenCL20EmbeddedCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Int64 -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Int64 is not allowed by OpenCL 2.0/2.1 " - "Embedded Profile")); -} - -TEST_F(ValidateCapability, OpenCL20EmbeddedEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability ImageBasic -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0)); -} - -TEST_F(ValidateCapability, OpenCL20EmbeddedNotEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.0/2.1 " - "Embedded Profile")); -} - -TEST_F(ValidateCapability, OpenCL22FullCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability PipeStorage -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2)); -} - -TEST_F(ValidateCapability, NonOpenCL22FullCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Matrix -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_2_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Matrix is not allowed by OpenCL 2.2 Full Profile")); -} - -TEST_F(ValidateCapability, OpenCL22FullEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability ImageBasic -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2)); -} - -TEST_F(ValidateCapability, OpenCL22FullNotEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_2_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability Sampled1D is not allowed by OpenCL 2.2 Full Profile")); -} - -TEST_F(ValidateCapability, NonOpenCL22EmbeddedCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Int64 -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)"; - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability Int64 is not allowed by OpenCL 2.2 Embedded Profile")); -} - -TEST_F(ValidateCapability, OpenCL22EmbeddedEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability ImageBasic -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2)); -} - -TEST_F(ValidateCapability, OpenCL22EmbeddedNotEnabledByCapability) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability Linkage -OpCapability Sampled1D -OpMemoryModel Physical64 OpenCL -%u32 = OpTypeInt 32 0 -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.2 " - "Embedded Profile")); -} - -// Three tests to check enablement of an enum (a decoration) which is not -// in core, and is directly enabled by a capability, but not directly enabled -// by an extension. See https://github.com/KhronosGroup/SPIRV-Tools/issues/1596 - -TEST_F(ValidateCapability, DecorationFromExtensionMissingEnabledByCapability) { - // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in - // turn is enabled by SPV_NV_viewport_array2. - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical Simple -OpDecorate %void ViewportRelativeNV -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 2 of Decorate requires one of these " - "capabilities: ShaderViewportMaskNV")); -} - -TEST_F(ValidateCapability, CapabilityEnabledByMissingExtension) { - // Capability ShaderViewportMaskNV is enabled by SPV_NV_viewport_array2. - const std::string spirv = R"( -OpCapability Shader -OpCapability ShaderViewportMaskNV -OpMemoryModel Logical Simple -)" + std::string(kVoidFVoid); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("operand ShaderViewportMaskNV(5255) requires one of " - "these extensions: SPV_NV_viewport_array2")); -} - -TEST_F(ValidateCapability, - DecorationEnabledByCapabilityEnabledByPresentExtension) { - // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in - // turn is enabled by SPV_NV_viewport_array2. - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability ShaderViewportMaskNV -OpExtension "SPV_NV_viewport_array2" -OpMemoryModel Logical Simple -OpDecorate %void ViewportRelativeNV -%void = OpTypeVoid -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)) - << getDiagnosticString(); -} - -// Three tests to check enablement of an instruction which is not in core, and -// is directly enabled by a capability, but not directly enabled by an -// extension. See https://github.com/KhronosGroup/SPIRV-Tools/issues/1624 -// Instruction OpSubgroupShuffleINTEL is enabled by SubgroupShuffleINTEL, which -// in turn is enabled by SPV_INTEL_subgroups. - -TEST_F(ValidateCapability, InstructionFromExtensionMissingEnabledByCapability) { - // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in - // turn is enabled by SPV_NV_viewport_array2. - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -; OpCapability SubgroupShuffleINTEL -OpExtension "SPV_INTEL_subgroups" -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %main "main" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%voidfn = OpTypeFunction %void -%zero = OpConstant %uint 0 -%main = OpFunction %void None %voidfn -%entry = OpLabel -%foo = OpSubgroupShuffleINTEL %uint %zero %zero -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Opcode SubgroupShuffleINTEL requires one of these " - "capabilities: SubgroupShuffleINTEL")); -} - -TEST_F(ValidateCapability, - InstructionEnablingCapabilityEnabledByMissingExtension) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability SubgroupShuffleINTEL -; OpExtension "SPV_INTEL_subgroups" -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %main "main" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%voidfn = OpTypeFunction %void -%zero = OpConstant %uint 0 -%main = OpFunction %void None %voidfn -%entry = OpLabel -%foo = OpSubgroupShuffleINTEL %uint %zero %zero -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("operand SubgroupShuffleINTEL(5568) requires one of " - "these extensions: SPV_INTEL_subgroups")); -} - -TEST_F(ValidateCapability, - InstructionEnabledByCapabilityEnabledByPresentExtension) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Addresses -OpCapability SubgroupShuffleINTEL -OpExtension "SPV_INTEL_subgroups" -OpMemoryModel Physical32 OpenCL -OpEntryPoint Kernel %main "main" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%voidfn = OpTypeFunction %void -%zero = OpConstant %uint 0 -%main = OpFunction %void None %voidfn -%entry = OpLabel -%foo = OpSubgroupShuffleINTEL %uint %zero %zero -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)) - << getDiagnosticString(); -} - -TEST_F(ValidateCapability, VulkanMemoryModelWithVulkanKHR) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)) - << getDiagnosticString(); -} - -TEST_F(ValidateCapability, VulkanMemoryModelWithGLSL450) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical GLSL450 -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("VulkanMemoryModelKHR capability must only be " - "specified if the VulkanKHR memory model is used")); -} - -// In the grammar, SubgroupEqMask and SubgroupMaskKHR have different enabling -// lists of extensions. -TEST_F(ValidateCapability, SubgroupEqMaskEnabledByExtension) { - const std::string spirv = R"( -OpCapability Shader -OpCapability SubgroupBallotKHR -OpExtension "SPV_KHR_shader_ballot" -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %main "main" -OpDecorate %var BuiltIn SubgroupEqMask -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%ptr_uint = OpTypePointer Private %uint -%var = OpVariable %ptr_uint Private -%fn = OpTypeFunction %void -%main = OpFunction %void None %fn -%entry = OpLabel -%val = OpLoad %uint %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)) - << getDiagnosticString(); -} - -// Test that extensions incorporated into SPIR-V 1.5 no longer require -// the associated OpExtension instruction. Test one capability per extension. - -struct CapabilityExtensionVersionCase { - std::string capability; - std::string capability_new_name; - std::string extension; - spv_target_env last_version_requiring_extension; - spv_target_env first_version_in_core; -}; - -using ValidateCapabilityExtensionVersionTest = - spvtest::ValidateBase; - -// Returns a minimal shader module with the given capability instruction. -std::string MinimalShaderModuleWithCapability(std::string cap) { - std::string mem_model = - (cap.find("VulkanMemory") == 0) ? "VulkanKHR" : "GLSL450"; - std::string extra_cap = (cap.find("VulkanMemoryModelDeviceScope") == 0) - ? "\nOpCapability VulkanMemoryModelKHR\n" - : ""; - return std::string("OpCapability ") + cap + extra_cap + R"( -OpCapability Shader -OpMemoryModel Logical )" + mem_model + R"( -OpEntryPoint Vertex %main "main" -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; -} - -TEST_P(ValidateCapabilityExtensionVersionTest, FailsInOlderSpirvVersion) { - const auto spirv = MinimalShaderModuleWithCapability(GetParam().capability); - CompileSuccessfully(spirv, GetParam().last_version_requiring_extension); - EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, - ValidateInstructions(GetParam().last_version_requiring_extension)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(std::string("1st operand of Capability: operand ") + - GetParam().capability_new_name)) - << spirv << "\n"; - EXPECT_THAT(getDiagnosticString(), - HasSubstr(std::string("requires one of these extensions: ") + - GetParam().extension)); -} - -TEST_P(ValidateCapabilityExtensionVersionTest, - SucceedsInNewerSpirvVersionWithOldName) { - const auto spirv = MinimalShaderModuleWithCapability(GetParam().capability); - CompileSuccessfully(spirv, GetParam().first_version_in_core); - EXPECT_EQ(SPV_SUCCESS, - ValidateInstructions(GetParam().first_version_in_core)); - EXPECT_THAT(getDiagnosticString(), Eq("")) << spirv << "\n"; -} - -TEST_P(ValidateCapabilityExtensionVersionTest, - SucceedsInNewerSpirvVersionWithNewName) { - const auto spirv = - MinimalShaderModuleWithCapability(GetParam().capability_new_name); - CompileSuccessfully(spirv, GetParam().first_version_in_core); - EXPECT_EQ(SPV_SUCCESS, - ValidateInstructions(GetParam().first_version_in_core)); - EXPECT_THAT(getDiagnosticString(), Eq("")) << spirv << "\n"; -} - -std::vector CapVersionCases1_5() { -#define IN15NOSUFFIX(C, E) \ - { C, C, E, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5 } -#define IN15(C, C_WITHOUT_SUFFIX, E) \ - { C, C_WITHOUT_SUFFIX, E, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5 } - return std::vector{ - // SPV_KHR_8bit_storage - IN15NOSUFFIX("StorageBuffer8BitAccess", "SPV_KHR_8bit_storage"), - IN15NOSUFFIX("UniformAndStorageBuffer8BitAccess", "SPV_KHR_8bit_storage"), - IN15NOSUFFIX("StoragePushConstant8", "SPV_KHR_8bit_storage"), - // SPV_EXT_descriptor_indexing - IN15("ShaderNonUniformEXT", "ShaderNonUniform", - "SPV_EXT_descriptor_indexing"), - IN15("RuntimeDescriptorArrayEXT", "RuntimeDescriptorArray", - "SPV_EXT_descriptor_indexing"), - IN15("InputAttachmentArrayDynamicIndexingEXT", - "InputAttachmentArrayDynamicIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("UniformTexelBufferArrayDynamicIndexingEXT", - "UniformTexelBufferArrayDynamicIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("StorageTexelBufferArrayDynamicIndexingEXT", - "StorageTexelBufferArrayDynamicIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("UniformBufferArrayNonUniformIndexingEXT", - "UniformBufferArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("SampledImageArrayNonUniformIndexingEXT", - "SampledImageArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("StorageBufferArrayNonUniformIndexingEXT", - "StorageBufferArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("StorageImageArrayNonUniformIndexingEXT", - "StorageImageArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("InputAttachmentArrayNonUniformIndexingEXT", - "InputAttachmentArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("UniformTexelBufferArrayNonUniformIndexingEXT", - "UniformTexelBufferArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - IN15("StorageTexelBufferArrayNonUniformIndexingEXT", - "StorageTexelBufferArrayNonUniformIndexing", - "SPV_EXT_descriptor_indexing"), - // SPV_EXT_physical_storage_buffer - IN15("PhysicalStorageBufferAddressesEXT", - "PhysicalStorageBufferAddresses", "SPV_EXT_physical_storage_buffer"), - // SPV_KHR_vulkan_memory_model - IN15("VulkanMemoryModelKHR", "VulkanMemoryModel", - "SPV_KHR_vulkan_memory_model"), - IN15("VulkanMemoryModelDeviceScopeKHR", "VulkanMemoryModelDeviceScope", - "SPV_KHR_vulkan_memory_model"), - }; -#undef IN15 -} - -INSTANTIATE_TEST_SUITE_P(NewInSpirv1_5, ValidateCapabilityExtensionVersionTest, - ValuesIn(CapVersionCases1_5())); - -TEST_P(ValidateCapability, - CapShaderViewportIndexLayerFailsInOlderSpirvVersion) { - const auto spirv = - MinimalShaderModuleWithCapability("ShaderViewportIndexLayerEXT"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "1st operand of Capability: operand ShaderViewportIndexLayerEXT")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions: " - "SPV_EXT_shader_viewport_index_layer")); -} - -TEST_P(ValidateCapability, CapShaderViewportIndexLayerFailsInNewSpirvVersion) { - const auto spirv = - MinimalShaderModuleWithCapability("ShaderViewportIndexLayerEXT"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5); - EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "1st operand of Capability: operand ShaderViewportIndexLayerEXT")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions: " - "SPV_EXT_shader_viewport_index_layer")); -} - -TEST_F(ValidateCapability, CapShaderViewportIndexSucceedsInNewSpirvVersion) { - const auto spirv = MinimalShaderModuleWithCapability("ShaderViewportIndex"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateCapability, CapShaderLayerSucceedsInNewSpirvVersion) { - const auto spirv = MinimalShaderModuleWithCapability("ShaderLayer"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_cfg_test.cpp b/3rdparty/spirv-tools/test/val/val_cfg_test.cpp deleted file mode 100644 index 22dd11792..000000000 --- a/3rdparty/spirv-tools/test/val/val_cfg_test.cpp +++ /dev/null @@ -1,4192 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Validation tests for Control Flow Graph - -#include -#include -#include -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/diagnostic.h" -#include "source/spirv_target_env.h" -#include "source/val/validate.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; - -using ValidateCFG = spvtest::ValidateBase; -using spvtest::ScopedContext; - -std::string nameOps() { return ""; } - -template -std::string nameOps(std::pair head, Args... names) { - return "OpName %" + head.first + " \"" + head.second + "\"\n" + - nameOps(names...); -} - -template -std::string nameOps(std::string head, Args... names) { - return "OpName %" + head + " \"" + head + "\"\n" + nameOps(names...); -} - -/// This class allows the easy creation of complex control flow without writing -/// SPIR-V. This class is used in the test cases below. -class Block { - std::string label_; - std::string body_; - SpvOp type_; - std::vector successors_; - - public: - /// Creates a Block with a given label - /// - /// @param[in]: label the label id of the block - /// @param[in]: type the branch instruciton that ends the block - explicit Block(std::string label, SpvOp type = SpvOpBranch) - : label_(label), body_(), type_(type), successors_() {} - - /// Sets the instructions which will appear in the body of the block - Block& SetBody(std::string body) { - body_ = body; - return *this; - } - - Block& AppendBody(std::string body) { - body_ += body; - return *this; - } - - /// Converts the block into a SPIR-V string - operator std::string() { - std::stringstream out; - out << std::setw(8) << "%" + label_ + " = OpLabel \n"; - if (!body_.empty()) { - out << body_; - } - - switch (type_) { - case SpvOpBranchConditional: - out << "OpBranchConditional %cond "; - for (Block& b : successors_) { - out << "%" + b.label_ + " "; - } - break; - case SpvOpSwitch: { - out << "OpSwitch %one %" + successors_.front().label_; - std::stringstream ss; - for (size_t i = 1; i < successors_.size(); i++) { - ss << " " << i << " %" << successors_[i].label_; - } - out << ss.str(); - } break; - case SpvOpLoopMerge: { - assert(successors_.size() == 2); - out << "OpLoopMerge %" + successors_[0].label_ + " %" + - successors_[0].label_ + "None"; - } break; - - case SpvOpReturn: - assert(successors_.size() == 0); - out << "OpReturn\n"; - break; - case SpvOpUnreachable: - assert(successors_.size() == 0); - out << "OpUnreachable\n"; - break; - case SpvOpBranch: - assert(successors_.size() == 1); - out << "OpBranch %" + successors_.front().label_; - break; - case SpvOpKill: - assert(successors_.size() == 0); - out << "OpKill\n"; - break; - default: - assert(1 == 0 && "Unhandled"); - } - out << "\n"; - - return out.str(); - } - friend Block& operator>>(Block& curr, std::vector successors); - friend Block& operator>>(Block& lhs, Block& successor); -}; - -/// Assigns the successors for the Block on the lhs -Block& operator>>(Block& lhs, std::vector successors) { - if (lhs.type_ == SpvOpBranchConditional) { - assert(successors.size() == 2); - } else if (lhs.type_ == SpvOpSwitch) { - assert(successors.size() > 1); - } - lhs.successors_ = successors; - return lhs; -} - -/// Assigns the successor for the Block on the lhs -Block& operator>>(Block& lhs, Block& successor) { - assert(lhs.type_ == SpvOpBranch); - lhs.successors_.push_back(successor); - return lhs; -} - -const std::string& GetDefaultHeader(SpvCapability cap) { - static const std::string shader_header = - "OpCapability Shader\n" - "OpCapability Linkage\n" - "OpMemoryModel Logical GLSL450\n"; - - static const std::string kernel_header = - "OpCapability Kernel\n" - "OpCapability Linkage\n" - "OpMemoryModel Logical OpenCL\n"; - - return (cap == SpvCapabilityShader) ? shader_header : kernel_header; -} - -const std::string& GetWebGPUHeader() { - static const std::string header = - "OpCapability Shader\n" - "OpCapability VulkanMemoryModelKHR\n" - "OpExtension \"SPV_KHR_vulkan_memory_model\"\n" - "OpMemoryModel Logical VulkanKHR\n"; - return header; -} - -const std::string& types_consts() { - static const std::string types = - "%voidt = OpTypeVoid\n" - "%boolt = OpTypeBool\n" - "%intt = OpTypeInt 32 0\n" - "%one = OpConstant %intt 1\n" - "%two = OpConstant %intt 2\n" - "%ptrt = OpTypePointer Function %intt\n" - "%funct = OpTypeFunction %voidt\n"; - return types; -} - -INSTANTIATE_TEST_SUITE_P(StructuredControlFlow, ValidateCFG, - ::testing::Values(SpvCapabilityShader, - SpvCapabilityKernel)); - -TEST_P(ValidateCFG, LoopReachableFromEntryButNeverLeadingToReturn) { - // In this case, the loop is reachable from a node without a predecessor, - // but never reaches a node with a return. - // - // This motivates the need for the pseudo-exit node to have a node - // from a cycle in its predecessors list. Otherwise the validator's - // post-dominance calculation will go into an infinite loop. - // - // For more motivation, see - // https://github.com/KhronosGroup/SPIRV-Tools/issues/279 - std::string str = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - - OpName %entry "entry" - OpName %loop "loop" - OpName %exit "exit" - -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt - -%main = OpFunction %voidt None %funct -%entry = OpLabel - OpBranch %loop -%loop = OpLabel - OpLoopMerge %exit %loop None - OpBranch %loop -%exit = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << str; -} - -TEST_P(ValidateCFG, LoopUnreachableFromEntryButLeadingToReturn) { - // In this case, the loop is not reachable from a node without a - // predecessor, but eventually reaches a node with a return. - // - // This motivates the need for the pseudo-entry node to have a node - // from a cycle in its successors list. Otherwise the validator's - // dominance calculation will go into an infinite loop. - // - // For more motivation, see - // https://github.com/KhronosGroup/SPIRV-Tools/issues/279 - // Before that fix, we'd have an infinite loop when calculating - // post-dominators. - std::string str = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - - OpName %entry "entry" - OpName %loop "loop" - OpName %cont "cont" - OpName %exit "exit" - -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%boolt = OpTypeBool -%false = OpConstantFalse %boolt - -%main = OpFunction %voidt None %funct -%entry = OpLabel - OpReturn - -%loop = OpLabel - OpLoopMerge %exit %cont None - OpBranch %cont - -%cont = OpLabel - OpBranchConditional %false %loop %exit - -%exit = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) - << str << getDiagnosticString(); -} - -TEST_P(ValidateCFG, Simple) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block cont("cont"); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - loop.SetBody("OpLoopMerge %merge %cont None\n"); - } - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("loop", "entry", "cont", "merge", - std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({cont, merge}); - str += cont >> loop; - str += merge; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, Variable) { - Block entry("entry"); - Block cont("cont"); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%var = OpVariable %ptrt Function\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps(std::make_pair("func", "Main")) + types_consts() + - " %func = OpFunction %voidt None %funct\n"; - str += entry >> cont; - str += cont >> exit; - str += exit; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, VariableNotInFirstBlockBad) { - Block entry("entry"); - Block cont("cont"); - Block exit("exit", SpvOpReturn); - - // This operation should only be performed in the entry block - cont.SetBody("%var = OpVariable %ptrt Function\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps(std::make_pair("func", "Main")) + types_consts() + - " %func = OpFunction %voidt None %funct\n"; - - str += entry >> cont; - str += cont >> exit; - str += exit; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("All OpVariable instructions in a function must be the " - "first instructions in the first block")); -} - -TEST_P(ValidateCFG, BlockSelfLoopIsOk) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("loop", "merge", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - // loop branches to itself, but does not trigger an error. - str += loop >> std::vector({merge, loop}); - str += merge; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_P(ValidateCFG, BlockAppearsBeforeDominatorBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block cont("cont"); - Block branch("branch", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) branch.SetBody("OpSelectionMerge %merge None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("cont", "branch", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> branch; - str += cont >> merge; // cont appears before its dominator - str += branch >> std::vector({cont, merge}); - str += merge; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("Block .\\[%cont\\] appears in the binary " - "before its dominator .\\[%branch\\]\n" - " %branch = OpLabel\n")); -} - -TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop"); - Block selection("selection", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.SetBody(" OpLoopMerge %merge %loop None\n"); - - // cannot share the same merge - if (is_shader) selection.SetBody("OpSelectionMerge %merge None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("merge", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> selection; - str += selection >> std::vector({loop, merge}); - str += merge; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("Block .\\[%merge\\] is already a merge block " - "for another header\n" - " %Main = OpFunction %void None %9\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksSelectionBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block selection("selection", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) selection.SetBody(" OpSelectionMerge %merge None\n"); - - // cannot share the same merge - if (is_shader) loop.SetBody(" OpLoopMerge %merge %loop None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("merge", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> selection; - str += selection >> std::vector({merge, loop}); - str += loop >> std::vector({loop, merge}); - str += merge; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("Block .\\[%merge\\] is already a merge block " - "for another header\n" - " %Main = OpFunction %void None %9\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceEntryBlock) { - Block entry("entry"); - Block bad("bad"); - Block end("end", SpvOpReturn); - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "bad", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> bad; - str += bad >> entry; // Cannot target entry block - str += end; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("First block .\\[%entry\\] of function " - ".\\[%Main\\] is targeted by block .\\[%bad\\]\n" - " %Main = OpFunction %void None %10\n")); -} - -TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceValue) { - Block entry("entry"); - entry.SetBody("%undef = OpUndef %voidt\n"); - Block bad("bad"); - Block end("end", SpvOpReturn); - Block badvalue("undef"); // This referenes the OpUndef. - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "bad", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> bad; - str += - bad >> badvalue; // Check branch to a function value (it's not a block!) - str += end; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("'Target Label' operands for OpBranch must " - "be the ID of an OpLabel instruction")); -} - -TEST_P(ValidateCFG, BranchConditionalTrueTargetFirstBlockBad) { - Block entry("entry"); - Block bad("bad", SpvOpBranchConditional); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - bad.SetBody(" OpLoopMerge %entry %exit None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "bad", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> bad; - str += bad >> std::vector({entry, exit}); // cannot target entry block - str += exit; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("First block .\\[%entry\\] of function .\\[%Main\\] " - "is targeted by block .\\[%bad\\]\n" - " %Main = OpFunction %void None %10\n")); -} - -TEST_P(ValidateCFG, BranchConditionalFalseTargetFirstBlockBad) { - Block entry("entry"); - Block bad("bad", SpvOpBranchConditional); - Block t("t"); - Block merge("merge"); - Block end("end", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - bad.SetBody("OpLoopMerge %merge %cont None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "bad", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> bad; - str += bad >> std::vector({t, entry}); - str += merge >> end; - str += end; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("First block .\\[%entry\\] of function .\\[%Main\\] " - "is targeted by block .\\[%bad\\]\n" - " %Main = OpFunction %void None %10\n")); -} - -TEST_P(ValidateCFG, SwitchTargetFirstBlockBad) { - Block entry("entry"); - Block bad("bad", SpvOpSwitch); - Block block1("block1"); - Block block2("block2"); - Block block3("block3"); - Block def("def"); // default block - Block merge("merge"); - Block end("end", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - bad.SetBody("OpSelectionMerge %merge None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "bad", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> bad; - str += bad >> std::vector({def, block1, block2, block3, entry}); - str += def >> merge; - str += block1 >> merge; - str += block2 >> merge; - str += block3 >> merge; - str += merge >> end; - str += end; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("First block .\\[%entry\\] of function .\\[%Main\\] " - "is targeted by block .\\[%bad\\]\n" - " %Main = OpFunction %void None %10\n")); -} - -TEST_P(ValidateCFG, BranchToBlockInOtherFunctionBad) { - Block entry("entry"); - Block middle("middle", SpvOpBranchConditional); - Block end("end", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - middle.SetBody("OpSelectionMerge %end None\n"); - - Block entry2("entry2"); - Block middle2("middle2"); - Block end2("end2", SpvOpReturn); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("middle2", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> middle; - str += middle >> std::vector({end, middle2}); - str += end; - str += "OpFunctionEnd\n"; - - str += "%func2 = OpFunction %voidt None %funct\n"; - str += entry2 >> middle2; - str += middle2 >> end2; - str += end2; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("Block\\(s\\) \\{.\\[%middle2\\]\\} are referenced but not " - "defined in function .\\[%Main\\]\n" - " %Main = OpFunction %void None %9\n")); -} - -TEST_P(ValidateCFG, HeaderDoesntDominatesMergeBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block head("head", SpvOpBranchConditional); - Block f("f"); - Block merge("merge", SpvOpReturn); - - head.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - - if (is_shader) head.AppendBody("OpSelectionMerge %merge None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("head", "merge", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> merge; - str += head >> std::vector({merge, f}); - str += f >> merge; - str += merge; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("The selection construct with the selection header " - ".\\[%head\\] does not dominate the merge block " - ".\\[%merge\\]\n %merge = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, HeaderDoesntStrictlyDominateMergeBad) { - // If a merge block is reachable, then it must be strictly dominated by - // its header block. - bool is_shader = GetParam() == SpvCapabilityShader; - Block head("head", SpvOpBranchConditional); - Block exit("exit", SpvOpReturn); - - head.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - - if (is_shader) head.AppendBody("OpSelectionMerge %head None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("head", "exit", std::make_pair("func", "Main")) + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += head >> std::vector({exit, exit}); - str += exit; - str += "OpFunctionEnd\n"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("The selection construct with the selection header " - ".\\[%head\\] does not strictly dominate the merge block " - ".\\[%head\\]\n %head = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << str; - } -} - -std::string GetUnreachableMergeNoMergeInst(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - Block entry("entry"); - Block branch("branch", SpvOpBranchConditional); - Block t("t", SpvOpReturn); - Block f("f", SpvOpReturn); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (!spvIsWebGPUEnv(env) && cap == SpvCapabilityShader) - branch.AppendBody("OpSelectionMerge %merge None\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", std::make_pair("func", "Main")); - str += types_consts() + "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({t, f}); - str += t; - str += f; - str += merge; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeNoMergeInst) { - CompileSuccessfully( - GetUnreachableMergeNoMergeInst(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeNoMergeInst) { - CompileSuccessfully( - GetUnreachableMergeNoMergeInst(SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, all blocks must be reachable")); -} - -std::string GetUnreachableMergeTerminatedBy(SpvCapability cap, - spv_target_env env, SpvOp op) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranchConditional); - Block t("t", SpvOpReturn); - Block f("f", SpvOpReturn); - Block merge("merge", op); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpSelectionMerge %merge None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({t, f}); - str += t; - str += f; - str += merge; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpUnreachable) { - CompileSuccessfully(GetUnreachableMergeTerminatedBy( - GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpUnreachable)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, UnreachableMergeTerminatedByOpKill) { - CompileSuccessfully(GetUnreachableMergeTerminatedBy( - SpvCapabilityShader, SPV_ENV_UNIVERSAL_1_0, SpvOpKill)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpReturn) { - CompileSuccessfully(GetUnreachableMergeTerminatedBy( - GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpReturn)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeTerminatedByOpUnreachable) { - CompileSuccessfully(GetUnreachableMergeTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpUnreachable)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeTerminatedByOpKill) { - CompileSuccessfully(GetUnreachableMergeTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpKill)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must terminate with OpUnreachable")); -} - -TEST_P(ValidateCFG, WebGPUUnreachableMergeTerminatedByOpReturn) { - CompileSuccessfully(GetUnreachableMergeTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpReturn)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must terminate with OpUnreachable")); -} - -std::string GetUnreachableContinueTerminatedBy(SpvCapability cap, - spv_target_env env, SpvOp op) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranch); - Block merge("merge", SpvOpReturn); - Block target("target", op); - - if (op == SpvOpBranch) target >> branch; - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpLoopMerge %merge %target None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", "target", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({merge}); - str += merge; - str += target; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpUnreachable) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpUnreachable)); - if (GetParam() == SpvCapabilityShader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("targeted by 0 back-edge blocks")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_F(ValidateCFG, UnreachableContinueTerminatedBySpvOpKill) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - SpvCapabilityShader, SPV_ENV_UNIVERSAL_1_0, SpvOpKill)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("targeted by 0 back-edge blocks")); -} - -TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpReturn) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpReturn)); - if (GetParam() == SpvCapabilityShader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("targeted by 0 back-edge blocks")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpBranch) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpBranch)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpUnreachable) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpUnreachable)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, unreachable continue-target must " - "terminate with OpBranch.\n %12 = OpLabel\n")); -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpKill) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpKill)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, unreachable continue-target must " - "terminate with OpBranch.\n %12 = OpLabel\n")); -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpReturn) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpReturn)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, unreachable continue-target must " - "terminate with OpBranch.\n %12 = OpLabel\n")); -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpBranch) { - CompileSuccessfully(GetUnreachableContinueTerminatedBy( - SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpBranch)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -std::string GetUnreachableMergeUnreachableMergeInst(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block body("body", SpvOpReturn); - Block entry("entry"); - Block branch("branch", SpvOpBranchConditional); - Block t("t", SpvOpReturn); - Block f("f", SpvOpReturn); - Block merge("merge", SpvOpUnreachable); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpSelectionMerge %merge None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += body; - str += merge; - str += entry >> branch; - str += branch >> std::vector({t, f}); - str += t; - str += f; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeUnreachableMergeInst) { - CompileSuccessfully(GetUnreachableMergeUnreachableMergeInst( - GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeUnreachableMergeInst) { - CompileSuccessfully(GetUnreachableMergeUnreachableMergeInst( - SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be referenced by a reachable merge instruction")); -} - -std::string GetUnreachableContinueUnreachableLoopInst(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block body("body", SpvOpReturn); - Block entry("entry"); - Block branch("branch", SpvOpBranch); - Block merge("merge", SpvOpReturn); - Block target("target", SpvOpBranch); - - target >> branch; - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpLoopMerge %merge %target None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", "target", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += body; - str += target; - str += merge; - str += entry >> branch; - str += branch >> std::vector({merge}); - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableContinueUnreachableLoopInst) { - CompileSuccessfully(GetUnreachableContinueUnreachableLoopInst( - GetParam(), SPV_ENV_UNIVERSAL_1_0)); - if (GetParam() == SpvCapabilityShader) { - // Shader causes additional structured CFG checks that cause a failure. - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Back-edges (1[%branch] -> 3[%target]) can only be " - "formed between a block and a loop header.")); - - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueUnreachableLoopInst) { - CompileSuccessfully(GetUnreachableContinueUnreachableLoopInst( - SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be referenced by a reachable loop instruction")); -} - -std::string GetUnreachableMergeWithComplexBody(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranchConditional); - Block t("t", SpvOpReturn); - Block f("f", SpvOpReturn); - Block merge("merge", SpvOpUnreachable); - - entry.AppendBody(spvIsWebGPUEnv(env) - ? "%dummy = OpVariable %intptrt Function %two\n" - : "%dummy = OpVariable %intptrt Function\n"); - entry.AppendBody("%cond = OpSLessThan %boolt %one %two\n"); - merge.AppendBody("OpStore %dummy %one\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpSelectionMerge %merge None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%intptrt = OpTypePointer Function %intt\n"; - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({t, f}); - str += t; - str += f; - str += merge; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeWithComplexBody) { - CompileSuccessfully( - GetUnreachableMergeWithComplexBody(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeWithComplexBody) { - CompileSuccessfully(GetUnreachableMergeWithComplexBody(SpvCapabilityShader, - SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must only contain an OpLabel and OpUnreachable instruction")); -} - -std::string GetUnreachableContinueWithComplexBody(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranch); - Block merge("merge", SpvOpReturn); - Block target("target", SpvOpBranch); - - target >> branch; - - entry.AppendBody(spvIsWebGPUEnv(env) - ? "%dummy = OpVariable %intptrt Function %two\n" - : "%dummy = OpVariable %intptrt Function\n"); - target.AppendBody("OpStore %dummy %one\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpLoopMerge %merge %target None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", "target", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%intptrt = OpTypePointer Function %intt\n"; - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({merge}); - str += merge; - str += target; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableContinueWithComplexBody) { - CompileSuccessfully( - GetUnreachableContinueWithComplexBody(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueWithComplexBody) { - CompileSuccessfully(GetUnreachableContinueWithComplexBody(SpvCapabilityShader, - SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must only contain an OpLabel and an OpBranch instruction")); -} - -std::string GetUnreachableMergeWithBranchUse(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranchConditional); - Block t("t", SpvOpBranch); - Block f("f", SpvOpReturn); - Block merge("merge", SpvOpUnreachable); - - entry.AppendBody("%cond = OpSLessThan %boolt %one %two\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpSelectionMerge %merge None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({t, f}); - str += t >> merge; - str += f; - str += merge; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeWithBranchUse) { - CompileSuccessfully( - GetUnreachableMergeWithBranchUse(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeWithBranchUse) { - CompileSuccessfully( - GetUnreachableMergeWithBranchUse(SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("cannot be the target of a branch.")); -} - -std::string GetUnreachableMergeWithMultipleUses(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranchConditional); - Block t("t", SpvOpReturn); - Block f("f", SpvOpReturn); - Block merge("merge", SpvOpUnreachable); - Block duplicate("duplicate", SpvOpBranchConditional); - - entry.AppendBody("%cond = OpSLessThan %boolt %one %two\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) { - branch.AppendBody("OpSelectionMerge %merge None\n"); - duplicate.AppendBody("OpSelectionMerge %merge None\n"); - } - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({t, f}); - str += duplicate >> std::vector({t, f}); - str += t; - str += f; - str += merge; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeWithMultipleUses) { - CompileSuccessfully( - GetUnreachableMergeWithMultipleUses(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - if (GetParam() == SpvCapabilityShader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("is already a merge block for another header")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeWithMultipleUses) { - CompileSuccessfully(GetUnreachableMergeWithMultipleUses(SpvCapabilityShader, - SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("is already a merge block for another header")); -} - -std::string GetUnreachableContinueWithBranchUse(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block foo("foo", SpvOpBranch); - Block branch("branch", SpvOpBranch); - Block merge("merge", SpvOpReturn); - Block target("target", SpvOpBranch); - - foo >> target; - target >> branch; - - entry.AppendBody(spvIsWebGPUEnv(env) - ? "%dummy = OpVariable %intptrt Function %two\n" - : "%dummy = OpVariable %intptrt Function\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) - branch.AppendBody("OpLoopMerge %merge %target None\n"); - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", "target", std::make_pair("func", "Main")); - - str += types_consts(); - str += "%intptrt = OpTypePointer Function %intt\n"; - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({merge}); - str += merge; - str += target; - str += foo; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableContinueWithBranchUse) { - CompileSuccessfully( - GetUnreachableContinueWithBranchUse(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableContinueWithBranchUse) { - CompileSuccessfully(GetUnreachableContinueWithBranchUse(SpvCapabilityShader, - SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("cannot be the target of a branch.")); -} - -std::string GetReachableMergeAndContinue(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranch); - Block merge("merge", SpvOpReturn); - Block target("target", SpvOpBranch); - Block body("body", SpvOpBranchConditional); - Block t("t", SpvOpBranch); - Block f("f", SpvOpBranch); - - target >> branch; - body.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - t >> merge; - f >> target; - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) { - branch.AppendBody("OpLoopMerge %merge %target None\n"); - body.AppendBody("OpSelectionMerge %f None\n"); - } - - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", "target", "body", "t", "f", - std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({body}); - str += body >> std::vector({t, f}); - str += t; - str += f; - str += merge; - str += target; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, ReachableMergeAndContinue) { - CompileSuccessfully( - GetReachableMergeAndContinue(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUReachableMergeAndContinue) { - CompileSuccessfully( - GetReachableMergeAndContinue(SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -std::string GetUnreachableMergeAndContinue(SpvCapability cap, - spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block branch("branch", SpvOpBranch); - Block merge("merge", SpvOpReturn); - Block target("target", SpvOpBranch); - Block body("body", SpvOpBranchConditional); - Block t("t", SpvOpReturn); - Block f("f", SpvOpReturn); - - target >> branch; - body.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (cap == SpvCapabilityShader) { - branch.AppendBody("OpLoopMerge %merge %target None\n"); - body.AppendBody("OpSelectionMerge %target None\n"); - } - - if (!spvIsWebGPUEnv(env)) - str += nameOps("branch", "merge", "target", "body", "t", "f", - std::make_pair("func", "Main")); - - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> branch; - str += branch >> std::vector({body}); - str += body >> std::vector({t, f}); - str += t; - str += f; - str += merge; - str += target; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableMergeAndContinue) { - CompileSuccessfully( - GetUnreachableMergeAndContinue(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableMergeAndContinue) { - CompileSuccessfully( - GetUnreachableMergeAndContinue(SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("unreachable merge-blocks must terminate with OpUnreachable")); -} - -std::string GetUnreachableBlock(SpvCapability cap, spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block unreachable("unreachable"); - Block exit("exit", SpvOpReturn); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (!spvIsWebGPUEnv(env)) - str += nameOps("unreachable", "exit", std::make_pair("func", "Main")); - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - str += entry >> exit; - str += unreachable >> exit; - str += exit; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableBlock) { - CompileSuccessfully(GetUnreachableBlock(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableBlock) { - CompileSuccessfully( - GetUnreachableBlock(SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), HasSubstr("all blocks must be reachable")); -} - -std::string GetUnreachableBranch(SpvCapability cap, spv_target_env env) { - std::string header = - spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap); - - Block entry("entry"); - Block unreachable("unreachable", SpvOpBranchConditional); - Block unreachablechildt("unreachablechildt"); - Block unreachablechildf("unreachablechildf"); - Block merge("merge"); - Block exit("exit", SpvOpReturn); - - unreachable.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (cap == SpvCapabilityShader) - unreachable.AppendBody("OpSelectionMerge %merge None\n"); - - std::string str = header; - if (spvIsWebGPUEnv(env)) { - str += - "OpEntryPoint Fragment %func \"func\"\n" - "OpExecutionMode %func OriginUpperLeft\n"; - } - if (!spvIsWebGPUEnv(env)) - str += nameOps("unreachable", "exit", std::make_pair("func", "Main")); - str += types_consts(); - str += "%func = OpFunction %voidt None %funct\n"; - - str += entry >> exit; - str += - unreachable >> std::vector({unreachablechildt, unreachablechildf}); - str += unreachablechildt >> merge; - str += unreachablechildf >> merge; - str += merge >> exit; - str += exit; - str += "OpFunctionEnd\n"; - - return str; -} - -TEST_P(ValidateCFG, UnreachableBranch) { - CompileSuccessfully(GetUnreachableBranch(GetParam(), SPV_ENV_UNIVERSAL_1_0)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WebGPUUnreachableBranch) { - CompileSuccessfully( - GetUnreachableBranch(SpvCapabilityShader, SPV_ENV_WEBGPU_0)); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), HasSubstr("all blocks must be reachable")); -} - -TEST_P(ValidateCFG, EmptyFunction) { - std::string str = GetDefaultHeader(GetParam()) + std::string(types_consts()) + - R"(%func = OpFunction %voidt None %funct - %l = OpLabel - OpReturn - OpFunctionEnd)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, SingleBlockLoop) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.AppendBody("OpLoopMerge %exit %loop None\n"); - - std::string str = GetDefaultHeader(GetParam()) + std::string(types_consts()) + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({loop, exit}); - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, NestedLoops) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop1("loop1"); - Block loop1_cont_break_block("loop1_cont_break_block", - SpvOpBranchConditional); - Block loop2("loop2", SpvOpBranchConditional); - Block loop2_merge("loop2_merge"); - Block loop1_merge("loop1_merge"); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - loop1.SetBody("OpLoopMerge %loop1_merge %loop2 None\n"); - loop2.SetBody("OpLoopMerge %loop2_merge %loop2 None\n"); - } - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("loop2", "loop2_merge") + types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop1; - str += loop1 >> loop1_cont_break_block; - str += loop1_cont_break_block >> std::vector({loop1_merge, loop2}); - str += loop2 >> std::vector({loop2, loop2_merge}); - str += loop2_merge >> loop1; - str += loop1_merge >> exit; - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, NestedSelection) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - const int N = 256; - std::vector if_blocks; - std::vector merge_blocks; - Block inner("inner"); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - - if_blocks.emplace_back("if0", SpvOpBranchConditional); - - if (is_shader) if_blocks[0].SetBody("OpSelectionMerge %if_merge0 None\n"); - merge_blocks.emplace_back("if_merge0", SpvOpReturn); - - for (int i = 1; i < N; i++) { - std::stringstream ss; - ss << i; - if_blocks.emplace_back("if" + ss.str(), SpvOpBranchConditional); - if (is_shader) - if_blocks[i].SetBody("OpSelectionMerge %if_merge" + ss.str() + " None\n"); - merge_blocks.emplace_back("if_merge" + ss.str(), SpvOpBranch); - } - std::string str = GetDefaultHeader(GetParam()) + std::string(types_consts()) + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> if_blocks[0]; - for (int i = 0; i < N - 1; i++) { - str += - if_blocks[i] >> std::vector({if_blocks[i + 1], merge_blocks[i]}); - } - str += if_blocks.back() >> std::vector({inner, merge_blocks.back()}); - str += inner >> merge_blocks.back(); - for (int i = N - 1; i > 0; i--) { - str += merge_blocks[i] >> merge_blocks[i - 1]; - } - str += merge_blocks[0]; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateCFG, BackEdgeBlockDoesntPostDominateContinueTargetBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop1("loop1", SpvOpBranchConditional); - Block loop2("loop2", SpvOpBranchConditional); - Block loop2_merge("loop2_merge"); - Block loop1_cont("loop1_cont", SpvOpBranchConditional); - Block be_block("be_block"); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - loop1.SetBody("OpLoopMerge %exit %loop1_cont None\n"); - loop2.SetBody("OpLoopMerge %loop2_merge %loop2 None\n"); - } - - std::string str = - GetDefaultHeader(GetParam()) + - nameOps("loop1", "loop2", "be_block", "loop1_cont", "loop2_merge") + - types_consts() + "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop1; - str += loop1 >> std::vector({loop2, exit}); - str += loop2 >> std::vector({loop2, loop2_merge}); - str += loop2_merge >> loop1_cont; - str += loop1_cont >> std::vector({be_block, exit}); - str += be_block >> loop1; - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (GetParam() == SpvCapabilityShader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("The continue construct with the continue target " - ".\\[%loop1_cont\\] is not post dominated by the " - "back-edge block .\\[%be_block\\]\n" - " %be_block = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, BranchingToNonLoopHeaderBlockBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block split("split", SpvOpBranchConditional); - Block t("t"); - Block f("f"); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) split.SetBody("OpSelectionMerge %exit None\n"); - - std::string str = GetDefaultHeader(GetParam()) + nameOps("split", "f") + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> split; - str += split >> std::vector({t, f}); - str += t >> exit; - str += f >> split; - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("Back-edges \\(.\\[%f\\] -> .\\[%split\\]\\) can only " - "be formed between a block and a loop header.\n" - " %f = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, BranchingToSameNonLoopHeaderBlockBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block split("split", SpvOpBranchConditional); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) split.SetBody("OpSelectionMerge %exit None\n"); - - std::string str = GetDefaultHeader(GetParam()) + nameOps("split") + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> split; - str += split >> std::vector({split, exit}); - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex( - "Back-edges \\(.\\[%split\\] -> .\\[%split\\]\\) can only be " - "formed between a block and a loop header.\n %split = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, MultipleBackEdgeBlocksToLoopHeaderBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block back0("back0"); - Block back1("back1"); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.SetBody("OpLoopMerge %merge %back0 None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("loop", "back0", "back1") + types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({back0, back1}); - str += back0 >> loop; - str += back1 >> loop; - str += merge; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex( - "Loop header .\\[%loop\\] is targeted by 2 back-edge blocks but " - "the standard requires exactly one\n %loop = OpLabel\n")) - << str; - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, ContinueTargetMustBePostDominatedByBackEdge) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block cheader("cheader", SpvOpBranchConditional); - Block be_block("be_block"); - Block merge("merge", SpvOpReturn); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.SetBody("OpLoopMerge %merge %cheader None\n"); - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("cheader", "be_block") + types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({cheader, merge}); - str += cheader >> std::vector({exit, be_block}); - str += exit; // Branches out of a continue construct - str += be_block >> loop; - str += merge; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("The continue construct with the continue target " - ".\\[%cheader\\] is not post dominated by the " - "back-edge block .\\[%be_block\\]\n" - " %be_block = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, BranchOutOfConstructToMergeBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block cont("cont", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n"); - - std::string str = GetDefaultHeader(GetParam()) + nameOps("cont", "loop") + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({cont, merge}); - str += cont >> std::vector({loop, merge}); - str += merge; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("The continue construct with the continue target " - ".\\[%loop\\] is not post dominated by the " - "back-edge block .\\[%cont\\]\n" - " %cont = OpLabel\n")) - << str; - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, BranchOutOfConstructBad) { - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block cont("cont", SpvOpBranchConditional); - Block merge("merge"); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n"); - - std::string str = GetDefaultHeader(GetParam()) + nameOps("cont", "loop") + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({cont, merge}); - str += cont >> std::vector({loop, exit}); - str += merge >> exit; - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("The continue construct with the continue target " - ".\\[%loop\\] is not post dominated by the " - "back-edge block .\\[%cont\\]\n" - " %cont = OpLabel\n")); - } else { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_F(ValidateCFG, OpSwitchToUnreachableBlock) { - Block entry("entry", SpvOpSwitch); - Block case0("case0"); - Block case1("case1"); - Block case2("case2"); - Block def("default", SpvOpUnreachable); - Block phi("phi", SpvOpReturn); - - std::string str = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %id -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 430 -OpName %main "main" -OpDecorate %id BuiltIn GlobalInvocationId -%void = OpTypeVoid -%voidf = OpTypeFunction %void -%u32 = OpTypeInt 32 0 -%f32 = OpTypeFloat 32 -%uvec3 = OpTypeVector %u32 3 -%fvec3 = OpTypeVector %f32 3 -%uvec3ptr = OpTypePointer Input %uvec3 -%id = OpVariable %uvec3ptr Input -%one = OpConstant %u32 1 -%three = OpConstant %u32 3 -%main = OpFunction %void None %voidf -)"; - - entry.SetBody( - "%idval = OpLoad %uvec3 %id\n" - "%x = OpCompositeExtract %u32 %idval 0\n" - "%selector = OpUMod %u32 %x %three\n" - "OpSelectionMerge %phi None\n"); - str += entry >> std::vector({def, case0, case1, case2}); - str += case1 >> phi; - str += def; - str += phi; - str += case0 >> phi; - str += case2 >> phi; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, LoopWithZeroBackEdgesBad) { - std::string str = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpName %loop "loop" -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%main = OpFunction %voidt None %funct -%loop = OpLabel - OpLoopMerge %exit %loop None - OpBranch %exit -%exit = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("Loop header .\\[%loop\\] is targeted by " - "0 back-edge blocks but the standard requires exactly " - "one\n %loop = OpLabel\n")); -} - -TEST_F(ValidateCFG, LoopWithBackEdgeFromUnreachableContinueConstructGood) { - std::string str = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpName %loop "loop" -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%floatt = OpTypeFloat 32 -%boolt = OpTypeBool -%one = OpConstant %floatt 1 -%two = OpConstant %floatt 2 -%main = OpFunction %voidt None %funct -%entry = OpLabel - OpBranch %loop -%loop = OpLabel - OpLoopMerge %exit %cont None - OpBranch %16 -%16 = OpLabel -%cond = OpFOrdLessThan %boolt %one %two - OpBranchConditional %cond %body %exit -%body = OpLabel - OpReturn -%cont = OpLabel ; Reachable only from OpLoopMerge ContinueTarget parameter - OpBranch %loop ; Should be considered a back-edge -%exit = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_P(ValidateCFG, - NestedConstructWithUnreachableMergeBlockBranchingToOuterMergeBlock) { - // Test for https://github.com/KhronosGroup/SPIRV-Tools/issues/297 - // The nested construct has an unreachable merge block. In the - // augmented CFG that merge block - // we still determine that the - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry", SpvOpBranchConditional); - Block inner_head("inner_head", SpvOpBranchConditional); - Block inner_true("inner_true", SpvOpReturn); - Block inner_false("inner_false", SpvOpReturn); - Block inner_merge("inner_merge"); - Block exit("exit", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - entry.AppendBody("OpSelectionMerge %exit None\n"); - inner_head.SetBody("OpSelectionMerge %inner_merge None\n"); - } - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "inner_merge", "exit") + types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> std::vector({inner_head, exit}); - str += inner_head >> std::vector({inner_true, inner_false}); - str += inner_true; - str += inner_false; - str += inner_merge >> exit; - str += exit; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_P(ValidateCFG, ContinueTargetCanBeMergeBlockForNestedStructure) { - // The continue construct cannot be the merge target of a nested selection - // because the loop construct must contain "if_merge" because it contains - // "if_head". - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop"); - Block if_head("if_head", SpvOpBranchConditional); - Block if_true("if_true"); - Block if_merge("if_merge", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - loop.SetBody("OpLoopMerge %merge %if_merge None\n"); - if_head.SetBody("OpSelectionMerge %if_merge None\n"); - } - - std::string str = - GetDefaultHeader(GetParam()) + - nameOps("entry", "loop", "if_head", "if_true", "if_merge", "merge") + - types_consts() + "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> if_head; - str += if_head >> std::vector({if_true, if_merge}); - str += if_true >> if_merge; - str += if_merge >> std::vector({loop, merge}); - str += merge; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - if (is_shader) { - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Header block 3[%if_head] is contained in the loop construct " - "headed " - "by 2[%loop], but it's merge block 5[%if_merge] is not")); - } else { - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); - } -} - -TEST_P(ValidateCFG, SingleLatchBlockMultipleBranchesToLoopHeader) { - // This test case ensures we allow both branches of a loop latch block - // to go back to the loop header. It still counts as a single back edge. - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop", SpvOpBranchConditional); - Block latch("latch", SpvOpBranchConditional); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - loop.SetBody("OpLoopMerge %merge %latch None\n"); - } - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "loop", "latch", "merge") + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> std::vector({latch, merge}); - str += latch >> std::vector({loop, loop}); // This is the key - str += merge; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) - << str << getDiagnosticString(); -} - -TEST_P(ValidateCFG, SingleLatchBlockHeaderContinueTargetIsItselfGood) { - // This test case ensures we don't count a Continue Target from a loop - // header to itself as a self-loop when computing back edges. - // Also, it detects that there is an edge from %latch to the pseudo-exit - // node, rather than from %loop. In particular, it detects that we - // have used the *reverse* textual order of blocks when computing - // predecessor traversal roots. - bool is_shader = GetParam() == SpvCapabilityShader; - Block entry("entry"); - Block loop("loop"); - Block latch("latch"); - Block merge("merge", SpvOpReturn); - - entry.SetBody("%cond = OpSLessThan %boolt %one %two\n"); - if (is_shader) { - loop.SetBody("OpLoopMerge %merge %loop None\n"); - } - - std::string str = GetDefaultHeader(GetParam()) + - nameOps("entry", "loop", "latch", "merge") + - types_consts() + - "%func = OpFunction %voidt None %funct\n"; - - str += entry >> loop; - str += loop >> latch; - str += latch >> loop; - str += merge; - str += "OpFunctionEnd"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) - << str << getDiagnosticString(); -} - -// Unit test to check the case where a basic block is the entry block of 2 -// different constructs. In this case, the basic block is the entry block of a -// continue construct as well as a selection construct. See issue# 517 for more -// details. -TEST_F(ValidateCFG, BasicBlockIsEntryBlockOfTwoConstructsGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - %void = OpTypeVoid - %bool = OpTypeBool - %int = OpTypeInt 32 1 - %void_func = OpTypeFunction %void - %int_0 = OpConstant %int 0 - %testfun = OpFunction %void None %void_func - %label_1 = OpLabel - OpBranch %start - %start = OpLabel - %cond = OpSLessThan %bool %int_0 %int_0 - ; - ; Note: In this case, the "target" block is both the entry block of - ; the continue construct of the loop as well as the entry block of - ; the selection construct. - ; - OpLoopMerge %loop_merge %target None - OpBranchConditional %cond %target %loop_merge - %loop_merge = OpLabel - OpReturn - %target = OpLabel - OpSelectionMerge %selection_merge None - OpBranchConditional %cond %do_stuff %do_other_stuff - %do_other_stuff = OpLabel - OpBranch %selection_merge - %selection_merge = OpLabel - OpBranch %start - %do_stuff = OpLabel - OpBranch %selection_merge - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, OpReturnInNonVoidFunc) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - %int = OpTypeInt 32 1 - %int_func = OpTypeFunction %int - %testfun = OpFunction %int None %int_func - %label_1 = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpReturn can only be called from a function with void return type.\n" - " OpReturn")); -} - -TEST_F(ValidateCFG, StructuredCFGBranchIntoSelectionBody) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%entry = OpLabel -OpSelectionMerge %merge None -OpBranchConditional %true %then %merge -%merge = OpLabel -OpBranch %then -%then = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("branches to the selection construct, but not to the " - "selection header 6\n %7 = OpLabel")); -} - -TEST_F(ValidateCFG, SwitchDefaultOnly) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -OpSelectionMerge %7 None -OpSwitch %3 %7 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, SwitchSingleCase) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -OpSelectionMerge %7 None -OpSwitch %3 %7 0 %8 -%8 = OpLabel -OpBranch %7 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MultipleFallThroughBlocks) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %11 1 %12 -%10 = OpLabel -OpBranchConditional %6 %11 %12 -%11 = OpLabel -OpBranch %9 -%12 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Case construct that targets 10[%10] has branches to multiple other " - "case construct targets 12[%12] and 11[%11]\n %10 = OpLabel")); -} - -TEST_F(ValidateCFG, MultipleFallThroughToDefault) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %11 1 %12 -%10 = OpLabel -OpBranch %9 -%11 = OpLabel -OpBranch %10 -%12 = OpLabel -OpBranch %10 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Multiple case constructs have branches to the case construct " - "that targets 10[%10]\n %10 = OpLabel")); -} - -TEST_F(ValidateCFG, MultipleFallThroughToNonDefault) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %11 1 %12 -%10 = OpLabel -OpBranch %12 -%11 = OpLabel -OpBranch %12 -%12 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Multiple case constructs have branches to the case construct " - "that targets 12[%12]\n %12 = OpLabel")); -} - -TEST_F(ValidateCFG, DuplicateTargetWithFallThrough) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %10 1 %11 -%10 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, WrongOperandList) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %11 1 %12 -%10 = OpLabel -OpBranch %9 -%12 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Case construct that targets 12[%12] has branches to the case " - "construct that targets 11[%11], but does not immediately " - "precede it in the OpSwitch's target list\n" - " OpSwitch %uint_0 %10 0 %11 1 %12")); -} - -TEST_F(ValidateCFG, WrongOperandListThroughDefault) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %11 1 %12 -%10 = OpLabel -OpBranch %11 -%12 = OpLabel -OpBranch %10 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Case construct that targets 12[%12] has branches to the case " - "construct that targets 11[%11], but does not immediately " - "precede it in the OpSwitch's target list\n" - " OpSwitch %uint_0 %10 0 %11 1 %12")); -} - -TEST_F(ValidateCFG, WrongOperandListNotLast) { - std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpFunction %1 None %4 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %3 %10 0 %11 1 %12 2 %13 -%10 = OpLabel -OpBranch %9 -%12 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %9 -%13 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Case construct that targets 12[%12] has branches to the case " - "construct that targets 11[%11], but does not immediately " - "precede it in the OpSwitch's target list\n" - " OpSwitch %uint_0 %10 0 %11 1 %12 2 %13")); -} - -TEST_F(ValidateCFG, GoodUnreachableSwitch) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -%3 = OpTypeVoid -%4 = OpTypeFunction %3 -%5 = OpTypeBool -%6 = OpConstantTrue %5 -%7 = OpTypeInt 32 1 -%9 = OpConstant %7 0 -%2 = OpFunction %3 None %4 -%10 = OpLabel -OpSelectionMerge %11 None -OpBranchConditional %6 %12 %13 -%12 = OpLabel -OpReturn -%13 = OpLabel -OpReturn -%11 = OpLabel -OpSelectionMerge %14 None -OpSwitch %9 %14 0 %15 -%15 = OpLabel -OpBranch %14 -%14 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, InvalidCaseExit) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypeFunction %2 -%5 = OpConstant %3 0 -%1 = OpFunction %2 None %4 -%6 = OpLabel -OpSelectionMerge %7 None -OpSwitch %5 %7 0 %8 1 %9 -%8 = OpLabel -OpBranch %10 -%9 = OpLabel -OpBranch %10 -%10 = OpLabel -OpReturn -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Case construct that targets 8[%8] has invalid branch " - "to block 10[%10] (not another case construct, " - "corresponding merge, outer loop merge or outer loop " - "continue)")); -} - -TEST_F(ValidateCFG, GoodCaseExitsToOuterConstructs) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -OpBranch %2 -%2 = OpLabel -OpLoopMerge %7 %6 None -OpBranch %3 -%3 = OpLabel -OpSelectionMerge %5 None -OpSwitch %int0 %5 0 %4 -%4 = OpLabel -OpBranchConditional %true %6 %7 -%5 = OpLabel -OpBranchConditional %true %6 %7 -%6 = OpLabel -OpBranch %2 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, SwitchCaseOrderingBad1) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %default "default" -OpName %other "other" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpSwitch %undef %default 0 %other 1 %default -%default = OpLabel -OpBranch %other -%other = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Case construct that targets 1[%default] has branches to the " - "case construct that targets 2[%other], but does not " - "immediately precede it in the OpSwitch's target list")); -} - -TEST_F(ValidateCFG, SwitchCaseOrderingBad2) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %default "default" -OpName %other "other" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpSwitch %undef %default 0 %default 1 %other -%other = OpLabel -OpBranch %default -%default = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Case construct that targets 2[%other] has branches to the " - "case construct that targets 1[%default], but does not " - "immediately precede it in the OpSwitch's target list")); -} - -TEST_F(ValidateCFG, SwitchMultipleDefaultWithFallThroughGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %first "first" -OpName %second "second" -OpName %third "third" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpSwitch %undef %second 0 %first 1 %second 2 %third -%first = OpLabel -OpBranch %second -%second = OpLabel -OpBranch %third -%third = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, SwitchMultipleDefaultWithFallThroughBad) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %first "first" -OpName %second "second" -OpName %third "third" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpSwitch %undef %second 0 %second 1 %first 2 %third -%first = OpLabel -OpBranch %second -%second = OpLabel -OpBranch %third -%third = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); -} - -TEST_F(ValidateCFG, GoodUnreachableSelection) { - const std::string text = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%8 = OpTypeFunction %void -%bool = OpTypeBool -%false = OpConstantFalse %bool -%main = OpFunction %void None %8 -%15 = OpLabel -OpBranch %16 -%16 = OpLabel -OpLoopMerge %17 %18 None -OpBranch %19 -%19 = OpLabel -OpBranchConditional %false %21 %17 -%21 = OpLabel -OpSelectionMerge %22 None -OpBranchConditional %false %23 %22 -%23 = OpLabel -OpBranch %24 -%24 = OpLabel -OpLoopMerge %25 %26 None -OpBranch %27 -%27 = OpLabel -OpReturn -%26 = OpLabel -OpBranchConditional %false %24 %25 -%25 = OpLabel -OpSelectionMerge %28 None -OpBranchConditional %false %18 %28 -%28 = OpLabel -OpBranch %22 -%22 = OpLabel -OpBranch %18 -%18 = OpLabel -OpBranch %16 -%17 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, ShaderWithPhiPtr) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %void = OpTypeVoid - %5 = OpTypeFunction %void - %1 = OpFunction %void None %5 - %6 = OpLabel - %7 = OpVariable %_ptr_Function_bool Function - %8 = OpVariable %_ptr_Function_bool Function - %9 = OpUndef %bool - OpSelectionMerge %10 None - OpBranchConditional %9 %11 %10 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - %12 = OpPhi %_ptr_Function_bool %7 %6 %8 %11 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Using pointers with OpPhi requires capability " - "VariablePointers or VariablePointersStorageBuffer")); -} - -TEST_F(ValidateCFG, VarPtrShaderWithPhiPtr) { - const std::string text = R"( - OpCapability Shader - OpCapability VariablePointers - OpExtension "SPV_KHR_variable_pointers" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %void = OpTypeVoid - %5 = OpTypeFunction %void - %1 = OpFunction %void None %5 - %6 = OpLabel - %7 = OpVariable %_ptr_Function_bool Function - %8 = OpVariable %_ptr_Function_bool Function - %9 = OpUndef %bool - OpSelectionMerge %10 None - OpBranchConditional %9 %11 %10 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - %12 = OpPhi %_ptr_Function_bool %7 %6 %8 %11 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, VarPtrStgBufShaderWithPhiStgBufPtr) { - const std::string text = R"( - OpCapability Shader - OpCapability VariablePointersStorageBuffer - OpExtension "SPV_KHR_variable_pointers" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - %bool = OpTypeBool - %float = OpTypeFloat 32 -%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float - %7 = OpVariable %_ptr_StorageBuffer_float StorageBuffer - %8 = OpVariable %_ptr_StorageBuffer_float StorageBuffer - %void = OpTypeVoid - %5 = OpTypeFunction %void - %1 = OpFunction %void None %5 - %6 = OpLabel - %9 = OpUndef %bool - OpSelectionMerge %10 None - OpBranchConditional %9 %11 %10 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - %12 = OpPhi %_ptr_StorageBuffer_float %7 %6 %8 %11 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, KernelWithPhiPtr) { - const std::string text = R"( - OpCapability Kernel - OpCapability Addresses - OpMemoryModel Physical32 OpenCL - OpEntryPoint Kernel %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - %bool = OpTypeBool -%_ptr_Function_bool = OpTypePointer Function %bool - %void = OpTypeVoid - %5 = OpTypeFunction %void - %1 = OpFunction %void None %5 - %6 = OpLabel - %7 = OpVariable %_ptr_Function_bool Function - %8 = OpVariable %_ptr_Function_bool Function - %9 = OpUndef %bool - OpSelectionMerge %10 None - OpBranchConditional %9 %11 %10 - %11 = OpLabel - OpBranch %10 - %10 = OpLabel - %12 = OpPhi %_ptr_Function_bool %7 %6 %8 %11 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, SwitchTargetMustBeLabel) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "foo" - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %1 = OpFunction %void None %5 - %6 = OpLabel - %7 = OpCopyObject %uint %uint_0 - OpSelectionMerge %8 None - OpSwitch %uint_0 %8 0 %7 - %8 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("'Target Label' operands for OpSwitch must " - "be IDs of an OpLabel instruction")); -} - -TEST_F(ValidateCFG, BranchTargetMustBeLabel) { - const std::string text = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "foo" - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %1 = OpFunction %void None %5 - %2 = OpLabel - %7 = OpCopyObject %uint %uint_0 - OpBranch %7 - %8 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("'Target Label' operands for OpBranch must " - "be the ID of an OpLabel instruction")); -} - -TEST_F(ValidateCFG, ReachableOpUnreachableOneBlock) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, ReachableOpUnreachableOpBranch) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %block -%block = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, ReachableOpUnreachableOpBranchConditional) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %block None -OpBranchConditional %undef %block %unreachable -%block = OpLabel -OpReturn -%unreachable = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, ReachableOpUnreachableOpSwitch) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %block1 None -OpSwitch %undef %block1 0 %unreachable 1 %block2 -%block1 = OpLabel -OpReturn -%unreachable = OpLabel -OpUnreachable -%block2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, ReachableOpUnreachableLoop) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %unreachable %loop None -OpBranchConditional %undef %loop %unreachable -%unreachable = OpLabel -OpUnreachable -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, UnreachableLoopBadBackedge) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %2 "main" -OpExecutionMode %2 OriginUpperLeft -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%8 = OpTypeBool -%13 = OpConstantTrue %8 -%2 = OpFunction %4 None %5 -%14 = OpLabel -OpSelectionMerge %15 None -OpBranchConditional %13 %15 %15 -%16 = OpLabel -OpLoopMerge %17 %18 None -OpBranch %17 -%18 = OpLabel -OpBranch %17 -%17 = OpLabel -OpBranch %15 -%15 = OpLabel -OpReturn -OpFunctionEnd -)"; - - // The back-edge in this test is bad, but the validator fails to identify it - // because it is in an entirely unreachable section of code. Prior to #2488 - // this code failed an assert in Construct::blocks(). - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, OneContinueTwoBackedges) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %1 "main" -OpExecutionMode %1 LocalSize 1 1 1 -%void = OpTypeVoid -%bool = OpTypeBool -%true = OpConstantTrue %bool -%5 = OpTypeFunction %void -%1 = OpFunction %void None %5 -%6 = OpLabel -OpBranch %7 -%7 = OpLabel -OpLoopMerge %8 %9 None -OpBranch %10 -%10 = OpLabel -OpLoopMerge %11 %9 None -OpBranchConditional %true %11 %9 -%9 = OpLabel -OpBranchConditional %true %10 %7 -%11 = OpLabel -OpBranch %8 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 9 branches to the loop construct, but not " - "to the loop header 7")); -} - -TEST_F(ValidateCFG, LoopMergeMergeBlockNotLabel) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -OpLoopMerge %undef %2 None -OpBranchConditional %undef %2 %2 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Merge Block 1[%undef] must be an OpLabel")); -} - -TEST_F(ValidateCFG, LoopMergeContinueTargetNotLabel) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -OpLoopMerge %2 %undef None -OpBranchConditional %undef %2 %2 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Continue Target 1[%undef] must be an OpLabel")); -} - -TEST_F(ValidateCFG, LoopMergeMergeBlockContinueTargetSameLabel) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -OpLoopMerge %2 %2 None -OpBranchConditional %undef %2 %2 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Merge Block and Continue Target must be different ids")); -} - -TEST_F(ValidateCFG, LoopMergeUnrollAndDontUnroll) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%5 = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %2 %3 Unroll|DontUnroll -OpBranchConditional %undef %2 %3 -%3 = OpLabel -OpBranch %1 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Unroll and DontUnroll loop controls must not both be specified")); -} - -TEST_F(ValidateCFG, LoopMergePeelCountAndDontUnroll) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%5 = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %2 %3 DontUnroll|PeelCount 1 -OpBranchConditional %undef %2 %3 -%3 = OpLabel -OpBranch %1 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "PeelCount and DontUnroll loop controls must not both be specified")); -} - -TEST_F(ValidateCFG, LoopMergePartialCountAndDontUnroll) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%5 = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %2 %3 DontUnroll|PartialCount 1 -OpBranchConditional %undef %2 %3 -%3 = OpLabel -OpBranch %1 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("PartialCount and DontUnroll loop controls must not " - "both be specified")); -} - -TEST_F(ValidateCFG, LoopMergeIterationMultipleZero) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%5 = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %2 %3 IterationMultiple 0 -OpBranchConditional %undef %2 %3 -%3 = OpLabel -OpBranch %1 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "IterationMultiple loop control operand must be greater than zero")); -} - -TEST_F(ValidateCFG, LoopMergeIterationMultipleZeroMoreOperands) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %undef "undef" -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%5 = OpLabel -OpBranch %1 -%1 = OpLabel -OpLoopMerge %2 %3 MaxIterations|IterationMultiple 4 0 -OpBranchConditional %undef %2 %3 -%3 = OpLabel -OpBranch %1 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "IterationMultiple loop control operand must be greater than zero")); -} - -TEST_F(ValidateCFG, LoopMergeTargetsHeader) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%undef = OpUndef %bool -%void_fn = OpTypeFunction %void -%fn = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %loop %continue None -OpBranch %body -%continue = OpLabel -OpBranch %loop -%body = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Merge Block may not be the block containing the OpLoopMerge")); -} - -TEST_F(ValidateCFG, InvalidSelectionExit) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantTrue %3 -%5 = OpTypeFunction %2 -%1 = OpFunction %2 None %5 -%6 = OpLabel -OpSelectionMerge %7 None -OpBranchConditional %4 %7 %8 -%8 = OpLabel -OpSelectionMerge %9 None -OpBranchConditional %4 %10 %9 -%10 = OpLabel -OpBranch %7 -%9 = OpLabel -OpBranch %7 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 10[%10] exits the selection headed by " - "8[%8], but not via a structured exit")); -} - -TEST_F(ValidateCFG, InvalidLoopExit) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantTrue %3 -%5 = OpTypeFunction %2 -%1 = OpFunction %2 None %5 -%6 = OpLabel -OpSelectionMerge %7 None -OpBranchConditional %4 %7 %8 -%8 = OpLabel -OpLoopMerge %9 %10 None -OpBranchConditional %4 %9 %11 -%11 = OpLabel -OpBranchConditional %4 %7 %10 -%10 = OpLabel -OpBranch %8 -%9 = OpLabel -OpBranch %7 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 11[%11] exits the loop headed by " - "8[%8], but not via a structured exit")); -} - -TEST_F(ValidateCFG, InvalidContinueExit) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeBool -%4 = OpConstantTrue %3 -%5 = OpTypeFunction %2 -%1 = OpFunction %2 None %5 -%6 = OpLabel -OpSelectionMerge %7 None -OpBranchConditional %4 %7 %8 -%8 = OpLabel -OpLoopMerge %9 %10 None -OpBranchConditional %4 %9 %10 -%10 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranchConditional %4 %8 %7 -%9 = OpLabel -OpBranch %7 -%7 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 11[%11] exits the continue headed by " - "10[%10], but not via a structured exit")); -} - -TEST_F(ValidateCFG, InvalidSelectionExitBackedge) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpUndef %2 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -OpBranch %7 -%7 = OpLabel -OpLoopMerge %8 %9 None -OpBranchConditional %3 %8 %9 -%9 = OpLabel -OpSelectionMerge %10 None -OpBranchConditional %3 %11 %12 -%11 = OpLabel -OpBranch %13 -%12 = OpLabel -OpBranch %13 -%13 = OpLabel -OpBranch %7 -%10 = OpLabel -OpUnreachable -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 13[%13] exits the selection headed by " - "9[%9], but not via a structured exit")); -} - -TEST_F(ValidateCFG, BreakFromSwitch) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpTypeInt 32 0 -%4 = OpUndef %2 -%5 = OpUndef %3 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %5 %9 0 %10 -%10 = OpLabel -OpSelectionMerge %11 None -OpBranchConditional %4 %11 %12 -%12 = OpLabel -OpBranch %9 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, InvalidBreakFromSwitch) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpTypeInt 32 0 -%4 = OpUndef %2 -%5 = OpUndef %3 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %5 %9 0 %10 -%10 = OpLabel -OpSelectionMerge %11 None -OpSwitch %5 %11 0 %12 -%12 = OpLabel -OpBranch %9 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 12[%12] exits the selection headed by " - "10[%10], but not via a structured exit")); -} - -TEST_F(ValidateCFG, BreakToOuterSwitch) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpTypeInt 32 0 -%4 = OpUndef %2 -%5 = OpUndef %3 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -OpSelectionMerge %9 None -OpSwitch %5 %9 0 %10 -%10 = OpLabel -OpSelectionMerge %11 None -OpSwitch %5 %11 0 %12 -%12 = OpLabel -OpSelectionMerge %13 None -OpBranchConditional %4 %13 %14 -%14 = OpLabel -OpBranch %9 -%13 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 14[%14] exits the selection headed by " - "10[%10], but not via a structured exit")); -} - -TEST_F(ValidateCFG, BreakToOuterLoop) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeBool -%3 = OpUndef %2 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -OpBranch %7 -%7 = OpLabel -OpLoopMerge %8 %9 None -OpBranch %10 -%10 = OpLabel -OpLoopMerge %11 %12 None -OpBranch %13 -%13 = OpLabel -OpSelectionMerge %14 None -OpBranchConditional %3 %14 %15 -%15 = OpLabel -OpBranch %8 -%14 = OpLabel -OpBranch %12 -%12 = OpLabel -OpBranchConditional %3 %10 %11 -%11 = OpLabel -OpBranch %9 -%9 = OpLabel -OpBranchConditional %3 %7 %8 -%8 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("block 15[%15] exits the loop headed by " - "10[%10], but not via a structured exit")); -} - -TEST_F(ValidateCFG, ContinueFromNestedSelection) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%4 = OpFunction %void None %void_fn -%5 = OpLabel -OpBranch %48 -%48 = OpLabel -OpLoopMerge %47 %50 None -OpBranch %10 -%10 = OpLabel -OpLoopMerge %12 %37 None -OpBranchConditional %undef %11 %12 -%11 = OpLabel -OpSelectionMerge %31 None -OpBranchConditional %undef %30 %31 -%30 = OpLabel -OpSelectionMerge %38 None -OpBranchConditional %undef %36 %38 -%36 = OpLabel -OpBranch %38 -%38 = OpLabel -OpBranch %37 -%37 = OpLabel -OpBranch %10 -%31 = OpLabel -OpBranch %12 -%12 = OpLabel -OpSelectionMerge %55 None -OpBranchConditional %undef %47 %55 -%55 = OpLabel -OpBranch %47 -%50 = OpLabel -OpBranch %48 -%47 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeConditionalBranchBad) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranchConditional %undef %then %else -%then = OpLabel -OpReturn -%else = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured")); -} - -TEST_F(ValidateCFG, MissingMergeSwitchBad) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSwitch %undef %then 0 %else -%then = OpLabel -OpReturn -%else = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured")); -} - -TEST_F(ValidateCFG, MissingMergeSwitchBad2) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSwitch %undef %then 0 %then 1 %then 2 %else -%then = OpLabel -OpReturn -%else = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured")); -} - -TEST_F(ValidateCFG, MissingMergeOneBranchToMergeGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %b3 None -OpBranchConditional %undef %b1 %b2 -%b1 = OpLabel -OpBranchConditional %undef %b2 %b3 -%b2 = OpLabel -OpBranch %b3 -%b3 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeSameTargetConditionalBranchGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranchConditional %undef %then %then -%then = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeOneTargetSwitchGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%int = OpTypeInt 32 0 -%undef = OpUndef %int -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSwitch %undef %then 0 %then 1 %then -%then = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeOneUnseenTargetSwitchGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%int = OpTypeInt 32 0 -%undef_int = OpUndef %int -%bool = OpTypeBool -%undef_bool = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpBranchConditional %undef_bool %merge %b1 -%b1 = OpLabel -OpSwitch %undef_int %b2 0 %b2 1 %merge 2 %b2 -%b2 = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeLoopBreakGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %exit %continue None -OpBranch %body -%body = OpLabel -OpBranchConditional %undef %body2 %exit -%body2 = OpLabel -OpBranch %continue -%continue = OpLabel -OpBranch %loop -%exit = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeLoopContinueGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %exit %continue None -OpBranch %body -%body = OpLabel -OpBranchConditional %undef %body2 %continue -%body2 = OpLabel -OpBranch %continue -%continue = OpLabel -OpBranch %loop -%exit = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeSwitchBreakGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpSwitch %int_0 %merge 1 %b1 -%b1 = OpLabel -OpBranchConditional %undef %merge %b2 -%b2 = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeSwitchFallThroughGood) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpSwitch %int_0 %b1 1 %b2 -%b1 = OpLabel -OpBranchConditional %undef %b3 %b2 -%b2 = OpLabel -OpBranch %merge -%b3 = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateCFG, MissingMergeInALoopBad) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %exit %continue None -OpBranch %body -%body = OpLabel -OpBranchConditional %undef %b1 %b2 -%b1 = OpLabel -OpBranch %exit -%b2 = OpLabel -OpBranch %continue -%continue = OpLabel -OpBranch %loop -%exit = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured")); -} - -TEST_F(ValidateCFG, MissingMergeCrissCrossBad) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpSelectionMerge %merge None -OpBranchConditional %undef %b1 %b2 -%b1 = OpLabel -OpBranchConditional %undef %b3 %b4 -%b2 = OpLabel -OpBranchConditional %undef %b3 %b4 -%b3 = OpLabel -OpBranch %merge -%b4 = OpLabel -OpBranch %merge -%merge = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured")); -} - -TEST_F(ValidateCFG, ContinueCannotBeSelectionMergeTarget) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %loop "loop" -OpName %continue "continue" -OpName %body "body" -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %exit %continue None -OpBranch %body -%body = OpLabel -OpSelectionMerge %continue None -OpBranchConditional %undef %exit %continue -%continue = OpLabel -OpBranch %loop -%exit = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Header block 3[%body] is contained in the loop construct headed by " - "1[%loop], but it's merge block 2[%continue] is not")); -} - -TEST_F(ValidateCFG, ContinueCannotBeLoopMergeTarget) { - const std::string text = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpName %loop "loop" -OpName %continue "continue" -OpName %inner "inner" -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%bool = OpTypeBool -%undef = OpUndef %bool -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpBranch %loop -%loop = OpLabel -OpLoopMerge %exit %continue None -OpBranchConditional %undef %exit %inner -%inner = OpLabel -OpLoopMerge %continue %inner None -OpBranchConditional %undef %inner %continue -%continue = OpLabel -OpBranch %loop -%exit = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Header block 3[%inner] is contained in the loop construct headed by " - "1[%loop], but it's merge block 2[%continue] is not")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_code_generator.cpp b/3rdparty/spirv-tools/test/val/val_code_generator.cpp deleted file mode 100644 index 62aae9c41..000000000 --- a/3rdparty/spirv-tools/test/val/val_code_generator.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "test/val/val_code_generator.h" - -#include - -namespace spvtools { -namespace val { -namespace { - -std::string GetDefaultShaderCapabilities() { - return R"( -OpCapability Shader -OpCapability Geometry -OpCapability Tessellation -OpCapability Float64 -OpCapability Int64 -OpCapability MultiViewport -OpCapability SampleRateShading -)"; -} - -std::string GetWebGPUShaderCapabilities() { - return R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -)"; -} - -std::string GetDefaultShaderTypes() { - return R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%f64 = OpTypeFloat 64 -%i32 = OpTypeInt 32 1 -%i64 = OpTypeInt 64 1 -%u32 = OpTypeInt 32 0 -%u64 = OpTypeInt 64 0 -%f32vec2 = OpTypeVector %f32 2 -%f32vec3 = OpTypeVector %f32 3 -%f32vec4 = OpTypeVector %f32 4 -%f64vec2 = OpTypeVector %f64 2 -%f64vec3 = OpTypeVector %f64 3 -%f64vec4 = OpTypeVector %f64 4 -%u32vec2 = OpTypeVector %u32 2 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%u32vec4 = OpTypeVector %u32 4 -%u64vec2 = OpTypeVector %u64 2 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 -%f32_h = OpConstant %f32 0.5 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1 - -%u32arr2 = OpTypeArray %u32 %u32_2 -%u32arr3 = OpTypeArray %u32 %u32_3 -%u32arr4 = OpTypeArray %u32 %u32_4 -%u64arr2 = OpTypeArray %u64 %u32_2 -%u64arr3 = OpTypeArray %u64 %u32_3 -%u64arr4 = OpTypeArray %u64 %u32_4 -%f32arr2 = OpTypeArray %f32 %u32_2 -%f32arr3 = OpTypeArray %f32 %u32_3 -%f32arr4 = OpTypeArray %f32 %u32_4 -%f64arr2 = OpTypeArray %f64 %u32_2 -%f64arr3 = OpTypeArray %f64 %u32_3 -%f64arr4 = OpTypeArray %f64 %u32_4 - -%f32vec3arr3 = OpTypeArray %f32vec3 %u32_3 -%f32vec4arr3 = OpTypeArray %f32vec4 %u32_3 -%f64vec4arr3 = OpTypeArray %f64vec4 %u32_3 -)"; -} - -std::string GetWebGPUShaderTypes() { - return R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%f32vec2 = OpTypeVector %f32 2 -%f32vec3 = OpTypeVector %f32 3 -%f32vec4 = OpTypeVector %f32 4 -%u32vec2 = OpTypeVector %u32 2 -%u32vec3 = OpTypeVector %u32 3 -%u32vec4 = OpTypeVector %u32 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 -%f32_h = OpConstant %f32 0.5 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 - -%u32arr2 = OpTypeArray %u32 %u32_2 -%u32arr3 = OpTypeArray %u32 %u32_3 -%u32arr4 = OpTypeArray %u32 %u32_4 -%f32arr2 = OpTypeArray %f32 %u32_2 -%f32arr3 = OpTypeArray %f32 %u32_3 -%f32arr4 = OpTypeArray %f32 %u32_4 - -%f32vec3arr3 = OpTypeArray %f32vec3 %u32_3 -%f32vec4arr3 = OpTypeArray %f32vec4 %u32_3 -)"; -} - -} // namespace - -CodeGenerator CodeGenerator::GetDefaultShaderCodeGenerator() { - CodeGenerator generator; - generator.capabilities_ = GetDefaultShaderCapabilities(); - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - generator.types_ = GetDefaultShaderTypes(); - return generator; -} - -CodeGenerator CodeGenerator::GetWebGPUShaderCodeGenerator() { - CodeGenerator generator; - generator.capabilities_ = GetWebGPUShaderCapabilities(); - generator.memory_model_ = "OpMemoryModel Logical VulkanKHR\n"; - generator.extensions_ = "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"; - generator.types_ = GetWebGPUShaderTypes(); - return generator; -} - -std::string CodeGenerator::Build() const { - std::ostringstream ss; - - ss << capabilities_; - ss << extensions_; - ss << memory_model_; - - for (const EntryPoint& entry_point : entry_points_) { - ss << "OpEntryPoint " << entry_point.execution_model << " %" - << entry_point.name << " \"" << entry_point.name << "\" " - << entry_point.interfaces << "\n"; - } - - for (const EntryPoint& entry_point : entry_points_) { - ss << entry_point.execution_modes << "\n"; - } - - ss << before_types_; - ss << types_; - ss << after_types_; - - for (const EntryPoint& entry_point : entry_points_) { - ss << "\n"; - ss << "%" << entry_point.name << " = OpFunction %void None %func\n"; - ss << "%" << entry_point.name << "_entry = OpLabel\n"; - ss << entry_point.body; - ss << "\nOpReturn\nOpFunctionEnd\n"; - } - - ss << add_at_the_end_; - - return ss.str(); -} - -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_code_generator.h b/3rdparty/spirv-tools/test/val/val_code_generator.h deleted file mode 100644 index e580ddff7..000000000 --- a/3rdparty/spirv-tools/test/val/val_code_generator.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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. - -// Utility class used to generate SPIR-V code strings for tests - -#include -#include - -namespace spvtools { -namespace val { - -struct EntryPoint { - std::string name; - std::string execution_model; - std::string execution_modes; - std::string body; - std::string interfaces; -}; - -class CodeGenerator { - public: - static CodeGenerator GetDefaultShaderCodeGenerator(); - static CodeGenerator GetWebGPUShaderCodeGenerator(); - - std::string Build() const; - - std::vector entry_points_; - std::string capabilities_; - std::string extensions_; - std::string memory_model_; - std::string before_types_; - std::string types_; - std::string after_types_; - std::string add_at_the_end_; -}; - -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_composites_test.cpp b/3rdparty/spirv-tools/test/val/val_composites_test.cpp deleted file mode 100644 index e97056211..000000000 --- a/3rdparty/spirv-tools/test/val/val_composites_test.cpp +++ /dev/null @@ -1,1999 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; -using ::testing::Values; - -using ValidateComposites = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "Fragment") { - std::ostringstream ss; - ss << R"( -OpCapability Shader -OpCapability Float64 -)"; - - ss << capabilities_and_extensions; - ss << "OpMemoryModel Logical GLSL450\n"; - ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; - if (execution_model == "Fragment") { - ss << "OpExecutionMode %main OriginUpperLeft\n"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%f64 = OpTypeFloat 64 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%f32vec2 = OpTypeVector %f32 2 -%f32vec3 = OpTypeVector %f32 3 -%f32vec4 = OpTypeVector %f32 4 -%f64vec2 = OpTypeVector %f64 2 -%u32vec2 = OpTypeVector %u32 2 -%u32vec4 = OpTypeVector %u32 4 -%f64mat22 = OpTypeMatrix %f64vec2 2 -%f32mat22 = OpTypeMatrix %f32vec2 2 -%f32mat23 = OpTypeMatrix %f32vec2 3 -%f32mat32 = OpTypeMatrix %f32vec3 2 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 - -%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12 -%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 - -%f32vec2arr3 = OpTypeArray %f32vec2 %u32_3 -%f32vec2rarr = OpTypeRuntimeArray %f32vec2 - -%f32u32struct = OpTypeStruct %f32 %u32 -%big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2rarr %f32u32struct - -%ptr_big_struct = OpTypePointer Uniform %big_struct -%var_big_struct = OpVariable %ptr_big_struct Uniform - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -// Returns header for legacy tests taken from val_id_test.cpp. -std::string GetHeaderForTestsFromValId() { - return R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability Pipes -OpCapability LiteralSampler -OpCapability DeviceEnqueue -OpCapability Vector16 -OpCapability Int8 -OpCapability Int16 -OpCapability Int64 -OpCapability Float64 -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%int = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%mat4x3 = OpTypeMatrix %v3float 4 -%_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3 -%_ptr_Private_float = OpTypePointer Private %float -%my_matrix = OpVariable %_ptr_Private_mat4x3 Private -%my_float_var = OpVariable %_ptr_Private_float Private -%_ptr_Function_float = OpTypePointer Function %float -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_3 = OpConstant %int 3 -%int_5 = OpConstant %int 5 - -; Making the following nested structures. -; -; struct S { -; bool b; -; vec4 v[5]; -; int i; -; mat4x3 m[5]; -; } -; uniform blockName { -; S s; -; bool cond; -; RunTimeArray arr; -; } - -%f32arr = OpTypeRuntimeArray %float -%v4float = OpTypeVector %float 4 -%array5_mat4x3 = OpTypeArray %mat4x3 %int_5 -%array5_vec4 = OpTypeArray %v4float %int_5 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Function_vec4 = OpTypePointer Function %v4float -%_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float -%struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3 -%struct_blockName = OpTypeStruct %struct_s %int %f32arr -%_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName -%_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s -%_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3 -%_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3 -%_ptr_Uniform_v3float = OpTypePointer Uniform %v3float -%blockName_var = OpVariable %_ptr_Uniform_blockName Uniform -%spec_int = OpSpecConstant %int 2 -%func = OpFunction %void None %void_f -%my_label = OpLabel -)"; -} - -TEST_F(ValidateComposites, VectorExtractDynamicSuccess) { - const std::string body = R"( -%val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) { - const std::string body = R"( -%val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a scalar type")); -} - -TEST_F(ValidateComposites, VectorExtractDynamicNotVector) { - const std::string body = R"( -%val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Vector type to be OpTypeVector")); -} - -TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) { - const std::string body = R"( -%val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Vector component type to be equal to Result Type")); -} - -TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) { - const std::string body = R"( -%val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Index to be int scalar")); -} - -TEST_F(ValidateComposites, VectorInsertDynamicSuccess) { - const std::string body = R"( -%val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) { - const std::string body = R"( -%val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeVector")); -} - -TEST_F(ValidateComposites, VectorInsertDynamicNotVector) { - const std::string body = R"( -%val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Vector type to be equal to Result Type")); -} - -TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) { - const std::string body = R"( -%val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Component type to be equal to Result Type " - "component type")); -} - -TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) { - const std::string body = R"( -%val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Index to be int scalar")); -} - -TEST_F(ValidateComposites, CompositeConstructNotComposite) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a composite type")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorSuccess) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 -%val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0 -%val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12 -%val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected number of constituents to be at least 2")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%float] cannot be a " - "type")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Constituents to be scalars or vectors of the same " - "type as Result Type components")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Constituents to be scalars or vectors of the same " - "type as Result Type components")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of given components to be equal to the " - "size of Result Type vector")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of given components to be equal to the " - "size of Result Type vector")); -} - -TEST_F(ValidateComposites, CompositeConstructMatrixSuccess) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 -%val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of Constituents to be equal to the " - "number of columns of Result Type matrix")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of Constituents to be equal to the " - "number of columns of Result Type matrix")); -} - -TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Constituent type to be equal to the column type " - "Result Type matrix")); -} - -TEST_F(ValidateComposites, CompositeConstructArraySuccess) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of Constituents to be equal to the " - "number of elements of Result Type array")); -} - -TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of Constituents to be equal to the " - "number of elements of Result Type array")); -} - -TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Constituent type to be equal to the column type " - "Result Type array")); -} - -TEST_F(ValidateComposites, CompositeConstructStructSuccess) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32u32struct %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of Constituents to be equal to the " - "number of members of Result Type struct")); -} - -TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected total number of Constituents to be equal to the " - "number of members of Result Type struct")); -} - -TEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) { - const std::string body = R"( -%val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Constituent type to be equal to the " - "corresponding member type of Result Type struct")); -} - -TEST_F(ValidateComposites, CopyObjectSuccess) { - const std::string body = R"( -%val1 = OpCopyObject %f32 %f32_0 -%val2 = OpCopyObject %f32vec4 %f32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CopyObjectResultTypeNotType) { - const std::string body = R"( -%val1 = OpCopyObject %f32_0 %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 19[%float_0] is not a type id")); -} - -TEST_F(ValidateComposites, CopyObjectWrongOperandType) { - const std::string body = R"( -%val1 = OpCopyObject %f32 %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type and Operand type to be the same")); -} - -TEST_F(ValidateComposites, TransposeSuccess) { - const std::string body = R"( -%val1 = OpTranspose %f32mat32 %f32mat23_121212 -%val2 = OpTranspose %f32mat22 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, TransposeResultTypeNotMatrix) { - const std::string body = R"( -%val1 = OpTranspose %f32vec4 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a matrix type")); -} - -TEST_F(ValidateComposites, TransposeDifferentComponentTypes) { - const std::string body = R"( -%val1 = OpTranspose %f64mat22 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected component types of Matrix and Result Type to be " - "identical")); -} - -TEST_F(ValidateComposites, TransposeIncompatibleDimensions1) { - const std::string body = R"( -%val1 = OpTranspose %f32mat23 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected number of columns and the column size " - "of Matrix to be the reverse of those of Result Type")); -} - -TEST_F(ValidateComposites, TransposeIncompatibleDimensions2) { - const std::string body = R"( -%val1 = OpTranspose %f32mat32 %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected number of columns and the column size " - "of Matrix to be the reverse of those of Result Type")); -} - -TEST_F(ValidateComposites, TransposeIncompatibleDimensions3) { - const std::string body = R"( -%val1 = OpTranspose %f32mat23 %f32mat23_121212 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected number of columns and the column size " - "of Matrix to be the reverse of those of Result Type")); -} - -TEST_F(ValidateComposites, CompositeExtractSuccess) { - const std::string body = R"( -%val1 = OpCompositeExtract %f32 %f32vec4_0123 1 -%val2 = OpCompositeExtract %u32 %u32vec4_0123 0 -%val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1 -%val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0 -%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 -%val5 = OpCompositeExtract %f32vec2 %array 2 -%val6 = OpCompositeExtract %f32 %array 2 1 -%struct = OpLoad %big_struct %var_big_struct -%val7 = OpCompositeExtract %f32 %struct 0 -%val8 = OpCompositeExtract %f32vec4 %struct 1 -%val9 = OpCompositeExtract %f32 %struct 1 2 -%val10 = OpCompositeExtract %f32mat23 %struct 2 -%val11 = OpCompositeExtract %f32vec2 %struct 2 2 -%val12 = OpCompositeExtract %f32 %struct 2 2 1 -%val13 = OpCompositeExtract %f32vec2 %struct 3 2 -%val14 = OpCompositeExtract %f32 %struct 3 2 1 -%val15 = OpCompositeExtract %f32vec2 %struct 4 100 -%val16 = OpCompositeExtract %f32 %struct 4 1000 1 -%val17 = OpCompositeExtract %f32 %struct 5 0 -%val18 = OpCompositeExtract %u32 %struct 5 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CompositeExtractNotObject) { - const std::string body = R"( -%val1 = OpCompositeExtract %f32 %f32vec4 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 11[%v4float] cannot " - "be a type")); -} - -TEST_F(ValidateComposites, CompositeExtractNotComposite) { - const std::string body = R"( -%val1 = OpCompositeExtract %f32 %f32_1 0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Reached non-composite type while indexes still remain " - "to be traversed.")); -} - -TEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) { - const std::string body = R"( -%val1 = OpCompositeExtract %f32 %f32vec4_0123 4 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vector access is out of bounds, " - "vector size is 4, but access index is 4")); -} - -TEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) { - const std::string body = R"( -%val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Matrix access is out of bounds, " - "matrix has 3 columns, but access index is 3")); -} - -TEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) { - const std::string body = R"( -%val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vector access is out of bounds, " - "vector size is 2, but access index is 5")); -} - -TEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) { - const std::string body = R"( -%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 -%val1 = OpCompositeExtract %f32vec2 %array 3 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Array access is out of bounds, " - "array size is 3, but access index is 3")); -} - -TEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 6 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index is out of bounds, can not find index 6 in the " - "structure '37'. This structure has 6 members. " - "Largest valid index is 5.")); -} - -TEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 3 1 5 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vector access is out of bounds, " - "vector size is 2, but access index is 5")); -} - -TEST_F(ValidateComposites, CompositeExtractTooManyIndices) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 3 1 1 2 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Reached non-composite type while " - "indexes still remain to be traversed.")); -} - -TEST_F(ValidateComposites, CompositeExtractNoIndices) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %big_struct %struct -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected at least one index to OpCompositeExtract")); -} - -TEST_F(ValidateComposites, CompositeExtractWrongType1) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32vec2 %struct 3 1 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Result type (OpTypeVector) does not match the type that results " - "from indexing into the composite (OpTypeFloat).")); -} - -TEST_F(ValidateComposites, CompositeExtractWrongType2) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 3 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result type (OpTypeFloat) does not match the type " - "that results from indexing into the composite " - "(OpTypeVector).")); -} - -TEST_F(ValidateComposites, CompositeExtractWrongType3) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 2 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result type (OpTypeFloat) does not match the type " - "that results from indexing into the composite " - "(OpTypeVector).")); -} - -TEST_F(ValidateComposites, CompositeExtractWrongType4) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 4 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result type (OpTypeFloat) does not match the type " - "that results from indexing into the composite " - "(OpTypeVector).")); -} - -TEST_F(ValidateComposites, CompositeExtractWrongType5) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeExtract %f32 %struct 5 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Result type (OpTypeFloat) does not match the " - "type that results from indexing into the composite (OpTypeInt).")); -} - -TEST_F(ValidateComposites, CompositeInsertSuccess) { - const std::string body = R"( -%val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0 -%val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0 -%val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1 -%val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0 -%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 -%val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2 -%val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1 -%struct = OpLoad %big_struct %var_big_struct -%val7 = OpCompositeInsert %big_struct %f32_3 %struct 0 -%val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1 -%val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2 -%val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2 -%val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2 -%val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1 -%val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2 -%val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1 -%val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 100 -%val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 1000 1 -%val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0 -%val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) { - const std::string body = R"( -%val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Result Type must be the same as Composite type in " - "OpCompositeInsert yielding Result Id 5.")); -} - -TEST_F(ValidateComposites, CompositeInsertNotComposite) { - const std::string body = R"( -%val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Reached non-composite type while indexes still remain " - "to be traversed.")); -} - -TEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) { - const std::string body = R"( -%val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vector access is out of bounds, " - "vector size is 4, but access index is 4")); -} - -TEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) { - const std::string body = R"( -%val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Matrix access is out of bounds, " - "matrix has 3 columns, but access index is 3")); -} - -TEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) { - const std::string body = R"( -%val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vector access is out of bounds, " - "vector size is 2, but access index is 5")); -} - -TEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) { - const std::string body = R"( -%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 -%val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Array access is out of bounds, array " - "size is 3, but access index is 3")); -} - -TEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 6 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index is out of bounds, can not find index 6 in the " - "structure '37'. This structure has 6 members. " - "Largest valid index is 5.")); -} - -TEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Vector access is out of bounds, " - "vector size is 2, but access index is 5")); -} - -TEST_F(ValidateComposites, CompositeInsertTooManyIndices) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Reached non-composite type while indexes still remain " - "to be traversed.")); -} - -TEST_F(ValidateComposites, CompositeInsertWrongType1) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Object type (OpTypeVector) does not match the " - "type that results from indexing into the Composite " - "(OpTypeFloat).")); -} - -TEST_F(ValidateComposites, CompositeInsertWrongType2) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Object type (OpTypeFloat) does not match the type " - "that results from indexing into the Composite " - "(OpTypeVector).")); -} - -TEST_F(ValidateComposites, CompositeInsertWrongType3) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Object type (OpTypeFloat) does not match the type " - "that results from indexing into the Composite " - "(OpTypeVector).")); -} - -TEST_F(ValidateComposites, CompositeInsertWrongType4) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Object type (OpTypeFloat) does not match the type " - "that results from indexing into the Composite " - "(OpTypeVector).")); -} - -TEST_F(ValidateComposites, CompositeInsertWrongType5) { - const std::string body = R"( -%struct = OpLoad %big_struct %var_big_struct -%val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Object type (OpTypeFloat) does not match the type " - "that results from indexing into the Composite " - "(OpTypeInt).")); -} - -// Tests ported from val_id_test.cpp. - -// Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes. -TEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) { - int depth = 255; - std::string header = GetHeaderForTestsFromValId(); - header.erase(header.find("%func")); - std::ostringstream spirv; - spirv << header << std::endl; - - // Build nested structures. Struct 'i' contains struct 'i-1' - spirv << "%s_depth_1 = OpTypeStruct %float\n"; - for (int i = 2; i <= depth; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n"; - } - - // Define Pointer and Variable to use for CompositeExtract/Insert. - spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_" - << depth << "\n"; - spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n"; - - // Function Start - spirv << R"( - %func = OpFunction %void None %void_f - %my_label = OpLabel - )"; - - // OpCompositeExtract/Insert with 'n' indexes (n = depth) - spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl; - spirv << "%entry = OpCompositeExtract %float %deep"; - for (int i = 0; i < depth; ++i) { - spirv << " 0"; - } - spirv << std::endl; - spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth - << " %entry %deep"; - for (int i = 0; i < depth; ++i) { - spirv << " 0"; - } - spirv << std::endl; - - // Function end - spirv << R"( - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255. -TEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%entry = OpCompositeExtract %float %matrix"; - for (int i = 0; i < 256; ++i) { - spirv << " 0"; - } - spirv << R"( - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The number of indexes in OpCompositeExtract may not " - "exceed 255. Found 256 indexes.")); -} - -// Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255. -TEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix"; - for (int i = 0; i < 256; ++i) { - spirv << " 0"; - } - spirv << R"( - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The number of indexes in OpCompositeInsert may not " - "exceed 255. Found 256 indexes.")); -} - -// Invalid: In OpCompositeInsert, result type must be the same as composite type -TEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl; - spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1" - << std::endl; - spirv << R"(OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Result Type must be the same as Composite type")); -} - -// Invalid: No Indexes were passed to OpCompositeExtract. -TEST_F(ValidateComposites, CompositeExtractNoIndices2) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%float_entry = OpCompositeExtract %mat4x3 %matrix" << std::endl; - spirv << R"(OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected at least one index to OpCompositeExtract, zero found")); -} - -// Invalid: No Indexes were passed to OpCompositeExtract. -TEST_F(ValidateComposites, CompositeExtractNoIndicesWrongResultType) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%float_entry = OpCompositeExtract %float %matrix" << std::endl; - spirv << R"(OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected at least one index to OpCompositeExtract, zero found")); -} - -// Invalid: No Indices were passed to OpCompositeInsert, and the type of the -// Object argument matches the Composite type. -TEST_F(ValidateComposites, CompositeInsertMissingIndices) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix"; - spirv << R"( - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected at least one index to OpCompositeInsert, zero found")); -} - -// Invalid: No Indices were passed to OpCompositeInsert, but the type of the -// Object argument does not match the Composite type. -TEST_F(ValidateComposites, CompositeInsertMissingIndices2) { - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix"; - spirv << R"( - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected at least one index to OpCompositeInsert, zero found")); -} - -// Valid: Tests that we can index into Struct, Array, Matrix, and Vector! -TEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %ss = OpCompositeExtract %struct_s %myblock 0 - %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3 - %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1 - %sc = OpCompositeExtract %v3float %myblock 0 3 1 2 - %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 - ; - ; Now let's insert back at different levels... - ; - %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0 - %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3 - %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1 - %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2 - %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid. More indexes are provided than needed for OpCompositeExtract. -TEST_F(ValidateComposites, CompositeExtractReachedScalarBad) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Reached non-composite type while indexes still remain " - "to be traversed.")); -} - -// Invalid. More indexes are provided than needed for OpCompositeInsert. -TEST_F(ValidateComposites, CompositeInsertReachedScalarBad) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 - %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Reached non-composite type while indexes still remain " - "to be traversed.")); -} - -// Invalid. Result type doesn't match the type we get from indexing into -// the composite. -TEST_F(ValidateComposites, - CompositeExtractResultTypeDoesntMatchIndexedTypeBad) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %fl = OpCompositeExtract %int %myblock 0 3 1 2 0 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result type (OpTypeInt) does not match the type that " - "results from indexing into the composite " - "(OpTypeFloat).")); -} - -// Invalid. Given object type doesn't match the type we get from indexing into -// the composite. -TEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - // We are trying to insert an integer where we should be inserting a float. - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Object type (OpTypeInt) does not match the type " - "that results from indexing into the Composite " - "(OpTypeFloat).")); -} - -// Invalid. Index into a struct is larger than the number of struct members. -TEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) { - // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3. - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %ss = OpCompositeExtract %struct_s %myblock 3 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index is out of bounds, can not find index 3 in the " - "structure '25'. This structure has 3 members. " - "Largest valid index is 2.")); -} - -// Invalid. Index into a struct is larger than the number of struct members. -TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) { - // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3. - std::ostringstream spirv; - spirv << GetHeaderForTestsFromValId() << R"( - %myblock = OpLoad %struct_blockName %blockName_var - %ss = OpCompositeExtract %struct_s %myblock 0 - %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Index is out of bounds, can not find index 3 in the structure " - " '25'. This structure has 3 members. Largest valid index " - "is 2.")); -} - -// #1403: Ensure that the default spec constant value is not used to check the -// extract index. -TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) { - std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpDecorate %spec_const SpecId 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%spec_const = OpSpecConstant %uint 3 -%uint_array = OpTypeArray %uint %spec_const -%undef = OpUndef %uint_array -%voidf = OpTypeFunction %void -%func = OpFunction %void None %voidf -%1 = OpLabel -%2 = OpCompositeExtract %uint %undef 4 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// #1403: Ensure that spec constant ops do not produce false positives. -TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) { - std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpDecorate %spec_const SpecId 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%const = OpConstant %uint 1 -%spec_const = OpSpecConstant %uint 3 -%spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const -%uint_array = OpTypeArray %uint %spec_const_op -%undef = OpUndef %uint_array -%voidf = OpTypeFunction %void -%func = OpFunction %void None %voidf -%1 = OpLabel -%2 = OpCompositeExtract %uint %undef 4 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// #1403: Ensure that the default spec constant value is not used to check the -// size of the array for a composite construct. This code has limited actual -// value as it is incorrect unless the specialization constant is assigned the -// value of 2, but it is still a valid module. -TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) { - std::string spirv = R"( -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Logical OpenCL -OpDecorate %spec_const SpecId 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_0 = OpConstant %uint 0 -%spec_const = OpSpecConstant %uint 3 -%uint_array = OpTypeArray %uint %spec_const -%voidf = OpTypeFunction %void -%func = OpFunction %void None %voidf -%1 = OpLabel -%2 = OpCompositeConstruct %uint_array %uint_0 %uint_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateComposites, CoopMatConstantCompositeMismatchFail) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 - -%f32_1 = OpConstant %f32 1 - -%f16mat_1 = OpConstantComposite %f16mat %f32_1 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '11[%float_1]' type does " - "not match the Result Type '10[%10]'s component type.")); -} - -TEST_F(ValidateComposites, CoopMatCompositeConstructMismatchFail) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 - -%f32_1 = OpConstant %f32 1 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%f16mat_1 = OpCompositeConstruct %f16mat %f32_1 - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Constituent type to be equal to the component type")); -} - -TEST_F(ValidateComposites, ExtractDynamicLabelIndex) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%void_fn = OpTypeFunction %void -%float_0 = OpConstant %float 0 -%v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%func = OpFunction %void None %void_fn -%1 = OpLabel -%ex = OpVectorExtractDynamic %float %v4float_0 %v4float_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Index to be int scalar")); -} - -TEST_F(ValidateComposites, CopyLogicalSameType) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%struct = OpTypeStruct -%const_struct = OpConstantComposite %struct -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %struct %const_struct -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result Type must not equal the Operand type")); -} - -TEST_F(ValidateComposites, CopyLogicalSameStructDifferentId) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%struct1 = OpTypeStruct -%struct2 = OpTypeStruct -%const_struct = OpConstantComposite %struct1 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %struct2 %const_struct -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateComposites, CopyLogicalArrayDifferentLength) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%int_5 = OpConstant %int 5 -%array1 = OpTypeArray %int %int_4 -%array2 = OpTypeArray %int %int_5 -%const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %array2 %const_array -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result Type does not logically match the Operand type")); -} - -TEST_F(ValidateComposites, CopyLogicalArrayDifferentElement) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%array1 = OpTypeArray %int %int_4 -%array2 = OpTypeArray %float %int_4 -%const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %array2 %const_array -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result Type does not logically match the Operand type")); -} - -TEST_F(ValidateComposites, CopyLogicalArrayLogicallyMatchedElement) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -%inner1 = OpTypeArray %int %int_1 -%inner2 = OpTypeArray %int %int_1 -%array1 = OpTypeArray %inner1 %int_1 -%array2 = OpTypeArray %inner2 %int_1 -%const_inner = OpConstantComposite %inner1 %int_1 -%const_array = OpConstantComposite %array1 %const_inner -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %array2 %const_array -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateComposites, CopyLogicalStructDifferentNumberElements) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%struct1 = OpTypeStruct -%struct2 = OpTypeStruct %int -%const_struct = OpConstantComposite %struct1 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %struct2 %const_struct -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result Type does not logically match the Operand type")); -} - -TEST_F(ValidateComposites, CopyLogicalStructDifferentElement) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%int = OpTypeInt 32 1 -%int_0 = OpConstant %int 0 -%uint_0 = OpConstant %uint 0 -%struct1 = OpTypeStruct %int %uint -%struct2 = OpTypeStruct %int %int -%const_struct = OpConstantComposite %struct1 %int_0 %uint_0 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %struct2 %const_struct -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result Type does not logically match the Operand type")); -} - -TEST_F(ValidateComposites, CopyLogicalStructLogicallyMatch) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -%array1 = OpTypeArray %int %int_1 -%array2 = OpTypeArray %int %int_1 -%struct1 = OpTypeStruct %int %array1 -%struct2 = OpTypeStruct %int %array2 -%const_array = OpConstantComposite %array1 %int_1 -%const_struct = OpConstantComposite %struct1 %int_1 %const_array -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%copy = OpCopyLogical %struct2 %const_struct -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -using ValidateSmallComposites = spvtest::ValidateBase; - -CodeGenerator GetSmallCompositesCodeGenerator() { - CodeGenerator generator; - generator.capabilities_ = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer16BitAccess -OpCapability UniformAndStorageBuffer8BitAccess -)"; - generator.extensions_ = R"( -OpExtension "SPV_KHR_16bit_storage" -OpExtension "SPV_KHR_8bit_storage" -)"; - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - generator.before_types_ = R"( -OpDecorate %char_block Block -OpMemberDecorate %char_block 0 Offset 0 -OpDecorate %short_block Block -OpMemberDecorate %short_block 0 Offset 0 -OpDecorate %half_block Block -OpMemberDecorate %half_block 0 Offset 0 -)"; - generator.types_ = R"( -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%char = OpTypeInt 8 0 -%char2 = OpTypeVector %char 2 -%short = OpTypeInt 16 0 -%short2 = OpTypeVector %short 2 -%half = OpTypeFloat 16 -%half2 = OpTypeVector %half 2 -%char_block = OpTypeStruct %char2 -%short_block = OpTypeStruct %short2 -%half_block = OpTypeStruct %half2 -%ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block -%ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2 -%ptr_ssbo_char = OpTypePointer StorageBuffer %char -%ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block -%ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2 -%ptr_ssbo_short = OpTypePointer StorageBuffer %short -%ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block -%ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2 -%ptr_ssbo_half = OpTypePointer StorageBuffer %half -%void_fn = OpTypeFunction %void -%char_var = OpVariable %ptr_ssbo_char_block StorageBuffer -%short_var = OpVariable %ptr_ssbo_short_block StorageBuffer -%half_var = OpVariable %ptr_ssbo_half_block StorageBuffer -)"; - generator.after_types_ = R"( -%func = OpFunction %void None %void_fn -%entry = OpLabel -%char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0 -%ld_char2 = OpLoad %char2 %char2_gep -%char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0 -%ld_char = OpLoad %char %char_gep -%short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0 -%ld_short2 = OpLoad %short2 %short2_gep -%short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0 -%ld_short = OpLoad %short %short_gep -%half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0 -%ld_half2 = OpLoad %half2 %half2_gep -%half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0 -%ld_half = OpLoad %half %half_gep -)"; - generator.add_at_the_end_ = R"( -OpReturn -OpFunctionEnd -)"; - return generator; -} - -TEST_P(ValidateSmallComposites, VectorExtractDynamic) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = - "%inst = OpVectorExtractDynamic %" + type + " %ld_" + type + "2 %int_0\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Cannot extract from a vector of 8- or 16-bit types")); -} - -TEST_P(ValidateSmallComposites, VectorInsertDynamic) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = "%inst = OpVectorInsertDynamic %" + type + "2 %ld_" + - type + "2 %ld_" + type + " %int_0\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Cannot insert into a vector of 8- or 16-bit types")); -} - -TEST_P(ValidateSmallComposites, VectorShuffle) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = "%inst = OpVectorShuffle %" + type + "2 %ld_" + type + - "2 %ld_" + type + "2 0 0\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Cannot shuffle a vector of 8- or 16-bit types")); -} - -TEST_P(ValidateSmallComposites, CompositeConstruct) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = "%inst = OpCompositeConstruct %" + type + "2 %ld_" + type + - " %ld_" + type + "\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot create a composite containing 8- or 16-bit types")); -} - -TEST_P(ValidateSmallComposites, CompositeExtract) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = - "%inst = OpCompositeExtract %" + type + " %ld_" + type + "2 0\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot extract from a composite of 8- or 16-bit types")); -} - -TEST_P(ValidateSmallComposites, CompositeInsert) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = "%inst = OpCompositeInsert %" + type + "2 %ld_" + type + - " %ld_" + type + "2 0\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot insert into a composite of 8- or 16-bit types")); -} - -TEST_P(ValidateSmallComposites, CopyObject) { - std::string type = GetParam(); - CodeGenerator generator = GetSmallCompositesCodeGenerator(); - std::string inst = "%inst = OpCopyObject %" + type + "2 %ld_" + type + "2\n"; - generator.after_types_ += inst; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -INSTANTIATE_TEST_SUITE_P(SmallCompositeInstructions, ValidateSmallComposites, - Values("char", "short", "half")); - -TEST_F(ValidateComposites, HalfMatrixCannotTranspose) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -OpMemberDecorate %block 0 RowMajor -OpMemberDecorate %block 0 MatrixStride 8 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%float = OpTypeFloat 16 -%float2 = OpTypeVector %float 2 -%mat2x2 = OpTypeMatrix %float2 2 -%block = OpTypeStruct %mat2x2 -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%ptr_ssbo_mat2x2 = OpTypePointer StorageBuffer %mat2x2 -%var = OpVariable %ptr_ssbo_block StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -%gep = OpAccessChain %ptr_ssbo_mat2x2 %var %int_0 -%ld = OpLoad %mat2x2 %gep -%inst = OpTranspose %mat2x2 %ld -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Cannot transpose matrices of 16-bit floats")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_constants_test.cpp b/3rdparty/spirv-tools/test/val/val_constants_test.cpp deleted file mode 100644 index 301539d98..000000000 --- a/3rdparty/spirv-tools/test/val/val_constants_test.cpp +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright (c) 2019 Google LLC -// -// 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. - -// Test validation of constants. -// -// This file contains newer tests. Older tests may be in other files such as -// val_id_test.cpp. - -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Combine; -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Values; -using ::testing::ValuesIn; - -using ValidateConstant = spvtest::ValidateBase; - -#define kBasicTypes \ - "%bool = OpTypeBool " \ - "%uint = OpTypeInt 32 0 " \ - "%uint2 = OpTypeVector %uint 2 " \ - "%float = OpTypeFloat 32 " \ - "%_ptr_uint = OpTypePointer Workgroup %uint " \ - "%uint_0 = OpConstantNull %uint " \ - "%uint2_0 = OpConstantNull %uint " \ - "%float_0 = OpConstantNull %float " \ - "%false = OpConstantFalse %bool " \ - "%true = OpConstantTrue %bool " \ - "%null = OpConstantNull %_ptr_uint " - -#define kShaderPreamble \ - "OpCapability Shader\n" \ - "OpCapability Linkage\n" \ - "OpMemoryModel Logical Simple\n" - -#define kKernelPreamble \ - "OpCapability Kernel\n" \ - "OpCapability Linkage\n" \ - "OpCapability Addresses\n" \ - "OpMemoryModel Physical32 OpenCL\n" - -struct ConstantOpCase { - spv_target_env env; - std::string assembly; - bool expect_success; - std::string expect_err; -}; - -using ValidateConstantOp = spvtest::ValidateBase; - -TEST_P(ValidateConstantOp, Samples) { - const auto env = GetParam().env; - CompileSuccessfully(GetParam().assembly, env); - const auto result = ValidateInstructions(env); - if (GetParam().expect_success) { - EXPECT_EQ(SPV_SUCCESS, result); - EXPECT_THAT(getDiagnosticString(), Eq("")); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, result); - EXPECT_THAT(getDiagnosticString(), HasSubstr(GetParam().expect_err)); - } -} - -#define GOOD_SHADER_10(STR) \ - { SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, true, "" } -#define GOOD_KERNEL_10(STR) \ - { SPV_ENV_UNIVERSAL_1_0, kKernelPreamble kBasicTypes STR, true, "" } -INSTANTIATE_TEST_SUITE_P( - UniversalInShader, ValidateConstantOp, - ValuesIn(std::vector{ - // TODO(dneto): Conversions must change width. - GOOD_SHADER_10("%v = OpSpecConstantOp %uint SConvert %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %float FConvert %float_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint SNegate %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint Not %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalNot %true"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"), - GOOD_SHADER_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"), - GOOD_SHADER_10( - "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"), - })); - -INSTANTIATE_TEST_SUITE_P( - UniversalInKernel, ValidateConstantOp, - ValuesIn(std::vector{ - // TODO(dneto): Conversions must change width. - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SConvert %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FConvert %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SNegate %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Not %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalNot %true"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"), - })); - -INSTANTIATE_TEST_SUITE_P( - UConvert, ValidateConstantOp, - ValuesIn(std::vector{ - // TODO(dneto): Conversions must change width. - {SPV_ENV_UNIVERSAL_1_0, - kKernelPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - {SPV_ENV_UNIVERSAL_1_1, - kKernelPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - {SPV_ENV_UNIVERSAL_1_3, - kKernelPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - {SPV_ENV_UNIVERSAL_1_3, - kKernelPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - {SPV_ENV_UNIVERSAL_1_4, - kKernelPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - {SPV_ENV_UNIVERSAL_1_0, - kShaderPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - false, - "Prior to SPIR-V 1.4, specialization constant operation " - "UConvert requires Kernel capability"}, - {SPV_ENV_UNIVERSAL_1_1, - kShaderPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - false, - "Prior to SPIR-V 1.4, specialization constant operation " - "UConvert requires Kernel capability"}, - {SPV_ENV_UNIVERSAL_1_3, - kShaderPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - false, - "Prior to SPIR-V 1.4, specialization constant operation " - "UConvert requires Kernel capability"}, - {SPV_ENV_UNIVERSAL_1_3, - kShaderPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - false, - "Prior to SPIR-V 1.4, specialization constant operation " - "UConvert requires Kernel capability"}, - {SPV_ENV_UNIVERSAL_1_4, - kShaderPreamble kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - })); - -INSTANTIATE_TEST_SUITE_P( - KernelInKernel, ValidateConstantOp, - ValuesIn(std::vector{ - // TODO(dneto): Conversions must change width. - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UConvert %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Bitcast %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FNegate %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain " - "%null %uint_0"), - GOOD_KERNEL_10( - "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0"), - GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint " - "InBoundsPtrAccessChain %null %uint_0"), - })); - -#define BAD_SHADER_10(STR, NAME) \ - { \ - SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, false, \ - "Specialization constant operation " NAME \ - " requires Kernel capability" \ - } -INSTANTIATE_TEST_SUITE_P( - KernelInShader, ValidateConstantOp, - ValuesIn(std::vector{ - // TODO(dneto): Conversions must change width. - BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0", - "ConvertFToS"), - BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0", - "ConvertSToF"), - BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0", - "ConvertFToU"), - BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0", - "ConvertUToF"), - BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null", - "GenericCastToPtr"), - BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null", - "PtrCastToGeneric"), - BAD_SHADER_10("%v = OpSpecConstantOp %uint Bitcast %uint_0", "Bitcast"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FNegate %float_0", - "FNegate"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0", - "FAdd"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0", - "FSub"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0", - "FMul"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0", - "FDiv"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0", - "FRem"), - BAD_SHADER_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0", - "FMod"), - BAD_SHADER_10( - "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0", - "AccessChain"), - BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain " - "%null %uint_0", - "InBoundsAccessChain"), - BAD_SHADER_10( - "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0", - "PtrAccessChain"), - BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint " - "InBoundsPtrAccessChain %null %uint_0", - "InBoundsPtrAccessChain"), - })); - -INSTANTIATE_TEST_SUITE_P( - UConvertInAMD_gpu_shader_int16, ValidateConstantOp, - ValuesIn(std::vector{ - // SPV_AMD_gpu_shader_int16 should enable UConvert for OpSpecConstantOp - // https://github.com/KhronosGroup/glslang/issues/848 - {SPV_ENV_UNIVERSAL_1_0, - "OpCapability Shader " - "OpCapability Linkage ; So we don't need to define a function\n" - "OpExtension \"SPV_AMD_gpu_shader_int16\" " - "OpMemoryModel Logical Simple " kBasicTypes - "%v = OpSpecConstantOp %uint UConvert %uint_0", - true, ""}, - })); - -TEST_F(ValidateConstant, SpecConstantUConvert1p3Binary1p4EnvBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%int = OpTypeInt 32 0 -%int0 = OpConstant %int 0 -%const = OpSpecConstantOp %int UConvert %int0 -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Prior to SPIR-V 1.4, specialization constant operation UConvert " - "requires Kernel capability or extension SPV_AMD_gpu_shader_int16")); -} - -using SmallStorageConstants = spvtest::ValidateBase; - -CodeGenerator GetSmallStorageCodeGenerator() { - CodeGenerator generator; - generator.capabilities_ = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer16BitAccess -OpCapability StoragePushConstant16 -OpCapability StorageInputOutput16 -OpCapability UniformAndStorageBuffer8BitAccess -OpCapability StoragePushConstant8 -)"; - generator.extensions_ = R"( -OpExtension "SPV_KHR_16bit_storage" -OpExtension "SPV_KHR_8bit_storage" -)"; - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - generator.types_ = R"( -%short = OpTypeInt 16 0 -%short2 = OpTypeVector %short 2 -%char = OpTypeInt 8 0 -%char2 = OpTypeVector %char 2 -%half = OpTypeFloat 16 -%half2 = OpTypeVector %half 2 -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -)"; - return generator; -} - -TEST_P(SmallStorageConstants, SmallConstant) { - std::string constant = GetParam(); - CodeGenerator generator = GetSmallStorageCodeGenerator(); - generator.after_types_ += constant + "\n"; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Cannot form constants of 8- or 16-bit types")); -} - -// Constant composites would be caught through scalar constants. -INSTANTIATE_TEST_SUITE_P( - SmallConstants, SmallStorageConstants, - Values("%c = OpConstant %char 0", "%c = OpConstantNull %char2", - "%c = OpConstant %short 0", "%c = OpConstantNull %short", - "%c = OpConstant %half 0", "%c = OpConstantNull %half", - "%c = OpSpecConstant %char 0", "%c = OpSpecConstant %short 0", - "%c = OpSpecConstant %half 0", - "%c = OpSpecConstantOp %char SConvert %int_0", - "%c = OpSpecConstantOp %short SConvert %int_0", - "%c = OpSpecConstantOp %half FConvert %float_0")); - -TEST_F(ValidateConstant, NullPointerTo16BitStorageOk) { - std::string spirv = R"( -OpCapability Shader -OpCapability VariablePointersStorageBuffer -OpCapability UniformAndStorageBuffer16BitAccess -OpCapability Linkage -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -%half = OpTypeFloat 16 -%ptr_ssbo_half = OpTypePointer StorageBuffer %half -%null_ptr = OpConstantNull %ptr_ssbo_half -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateConstant, NullMatrix) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%float = OpTypeFloat 32 -%v2float = OpTypeVector %float 2 -%mat2x2 = OpTypeMatrix %v2float 2 -%null_vector = OpConstantNull %v2float -%null_matrix = OpConstantComposite %mat2x2 %null_vector %null_vector -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConstant, NullPhysicalStorageBuffer) { - std::string spirv = R"( -OpCapability Shader -OpCapability PhysicalStorageBufferAddresses -OpCapability Linkage -OpExtension "SPV_KHR_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpName %ptr "ptr" -%int = OpTypeInt 32 0 -%ptr = OpTypePointer PhysicalStorageBuffer %int -%null = OpConstantNull %ptr -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantNull Result Type '1[%ptr]' cannot have " - "a null value")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_conversion_test.cpp b/3rdparty/spirv-tools/test/val/val_conversion_test.cpp deleted file mode 100644 index 47e67938d..000000000 --- a/3rdparty/spirv-tools/test/val/val_conversion_test.cpp +++ /dev/null @@ -1,1721 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; -using ::testing::Values; - -using ValidateConversion = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& decorations = "", const std::string& types = "", - const std::string& variables = "") { - const std::string capabilities = - R"( -OpCapability Shader -OpCapability Int64 -OpCapability Float64)"; - - const std::string after_extension_before_decorations = - R"( -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft)"; - - const std::string after_decorations_before_types = - R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%f64 = OpTypeFloat 64 -%u64 = OpTypeInt 64 0 -%s64 = OpTypeInt 64 1 -%boolvec2 = OpTypeVector %bool 2 -%s32vec2 = OpTypeVector %s32 2 -%u32vec2 = OpTypeVector %u32 2 -%u64vec2 = OpTypeVector %u64 2 -%f32vec2 = OpTypeVector %f32 2 -%f64vec2 = OpTypeVector %f64 2 -%boolvec3 = OpTypeVector %bool 3 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%s32vec3 = OpTypeVector %s32 3 -%f32vec3 = OpTypeVector %f32 3 -%f64vec3 = OpTypeVector %f64 3 -%boolvec4 = OpTypeVector %bool 4 -%u32vec4 = OpTypeVector %u32 4 -%u64vec4 = OpTypeVector %u64 4 -%s32vec4 = OpTypeVector %s32 4 -%f32vec4 = OpTypeVector %f32 4 -%f64vec4 = OpTypeVector %f64 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 - -%s32_0 = OpConstant %s32 0 -%s32_1 = OpConstant %s32 1 -%s32_2 = OpConstant %s32 2 -%s32_3 = OpConstant %s32 3 -%s32_4 = OpConstant %s32 4 -%s32_m1 = OpConstant %s32 -1 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64_4 = OpConstant %f64 4 - -%s64_0 = OpConstant %s64 0 -%s64_1 = OpConstant %s64 1 -%s64_2 = OpConstant %s64 2 -%s64_3 = OpConstant %s64 3 -%s64_4 = OpConstant %s64 4 -%s64_m1 = OpConstant %s64 -1 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_4 = OpConstant %u64 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1 -%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2 -%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2 -%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3 -%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3 -%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4 - -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 -%f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4 - -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool - -%f32ptr_func = OpTypePointer Function %f32)"; - - const std::string after_variables_before_body = - R"( -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string after_body = - R"( -OpReturn -OpFunctionEnd)"; - - return capabilities + capabilities_and_extensions + - after_extension_before_decorations + decorations + - after_decorations_before_types + types + variables + - after_variables_before_body + body + after_body; -} - -std::string GenerateKernelCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - const std::string capabilities = - R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability GenericPointer -OpCapability Int64 -OpCapability Float64)"; - - const std::string after_extension_before_body = - R"( -OpMemoryModel Physical32 OpenCL -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%f64 = OpTypeFloat 64 -%u64 = OpTypeInt 64 0 -%boolvec2 = OpTypeVector %bool 2 -%u32vec2 = OpTypeVector %u32 2 -%u64vec2 = OpTypeVector %u64 2 -%f32vec2 = OpTypeVector %f32 2 -%f64vec2 = OpTypeVector %f64 2 -%boolvec3 = OpTypeVector %bool 3 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%f32vec3 = OpTypeVector %f32 3 -%f64vec3 = OpTypeVector %f64 3 -%boolvec4 = OpTypeVector %bool 4 -%u32vec4 = OpTypeVector %u32 4 -%u64vec4 = OpTypeVector %u64 4 -%f32vec4 = OpTypeVector %f32 4 -%f64vec4 = OpTypeVector %f64 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64_4 = OpConstant %f64 4 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_4 = OpConstant %u64 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 -%f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4 - -%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1 - -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool - -%f32ptr_func = OpTypePointer Function %f32 -%u32ptr_func = OpTypePointer Function %u32 -%f32ptr_gen = OpTypePointer Generic %f32 -%f32ptr_inp = OpTypePointer Input %f32 -%f32ptr_wg = OpTypePointer Workgroup %f32 -%f32ptr_cwg = OpTypePointer CrossWorkgroup %f32 - -%f32inp = OpVariable %f32ptr_inp Input - -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string after_body = - R"( -OpReturn -OpFunctionEnd)"; - - return capabilities + capabilities_and_extensions + - after_extension_before_body + body + after_body; -} - -TEST_F(ValidateConversion, ConvertFToUSuccess) { - const std::string body = R"( -%val1 = OpConvertFToU %u32 %f32_1 -%val2 = OpConvertFToU %u32 %f64_0 -%val3 = OpConvertFToU %u32vec2 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertFToUWrongResultType) { - const std::string body = R"( -%val = OpConvertFToU %s32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected unsigned int scalar or vector type as Result " - "Type: ConvertFToU")); -} - -TEST_F(ValidateConversion, ConvertFToUWrongInputType) { - const std::string body = R"( -%val = OpConvertFToU %u32 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input to be float scalar or vector: ConvertFToU")); -} - -TEST_F(ValidateConversion, ConvertFToUDifferentDimension) { - const std::string body = R"( -%val = OpConvertFToU %u32 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result " - "Type: ConvertFToU")); -} - -TEST_F(ValidateConversion, ConvertFToSSuccess) { - const std::string body = R"( -%val1 = OpConvertFToS %s32 %f32_1 -%val2 = OpConvertFToS %u32 %f64_0 -%val3 = OpConvertFToS %s32vec2 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertFToSWrongResultType) { - const std::string body = R"( -%val = OpConvertFToS %bool %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected int scalar or vector type as Result Type: ConvertFToS")); -} - -TEST_F(ValidateConversion, ConvertFToSWrongInputType) { - const std::string body = R"( -%val = OpConvertFToS %s32 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input to be float scalar or vector: ConvertFToS")); -} - -TEST_F(ValidateConversion, ConvertFToSDifferentDimension) { - const std::string body = R"( -%val = OpConvertFToS %u32 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result " - "Type: ConvertFToS")); -} - -TEST_F(ValidateConversion, ConvertSToFSuccess) { - const std::string body = R"( -%val1 = OpConvertSToF %f32 %u32_1 -%val2 = OpConvertSToF %f32 %s64_0 -%val3 = OpConvertSToF %f32vec2 %s32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertSToFWrongResultType) { - const std::string body = R"( -%val = OpConvertSToF %u32 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected float scalar or vector type as Result Type: ConvertSToF")); -} - -TEST_F(ValidateConversion, ConvertSToFWrongInputType) { - const std::string body = R"( -%val = OpConvertSToF %f32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input to be int scalar or vector: ConvertSToF")); -} - -TEST_F(ValidateConversion, ConvertSToFDifferentDimension) { - const std::string body = R"( -%val = OpConvertSToF %f32 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result " - "Type: ConvertSToF")); -} - -TEST_F(ValidateConversion, UConvertSuccess) { - const std::string body = R"( -%val1 = OpUConvert %u32 %u64_1 -%val2 = OpUConvert %u64 %s32_0 -%val3 = OpUConvert %u64vec2 %s32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, UConvertWrongResultType) { - const std::string body = R"( -%val = OpUConvert %s32 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected unsigned int scalar or vector type as Result " - "Type: UConvert")); -} - -TEST_F(ValidateConversion, UConvertWrongInputType) { - const std::string body = R"( -%val = OpUConvert %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be int scalar or vector: UConvert")); -} - -TEST_F(ValidateConversion, UConvertDifferentDimension) { - const std::string body = R"( -%val = OpUConvert %u32 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result " - "Type: UConvert")); -} - -TEST_F(ValidateConversion, UConvertSameBitWidth) { - const std::string body = R"( -%val = OpUConvert %u32 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have different bit width from " - "Result Type: UConvert")); -} - -TEST_F(ValidateConversion, SConvertSuccess) { - const std::string body = R"( -%val1 = OpSConvert %s32 %u64_1 -%val2 = OpSConvert %s64 %s32_0 -%val3 = OpSConvert %u64vec2 %s32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, SConvertWrongResultType) { - const std::string body = R"( -%val = OpSConvert %f32 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as Result Type: SConvert")); -} - -TEST_F(ValidateConversion, SConvertWrongInputType) { - const std::string body = R"( -%val = OpSConvert %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be int scalar or vector: SConvert")); -} - -TEST_F(ValidateConversion, SConvertDifferentDimension) { - const std::string body = R"( -%val = OpSConvert %s32 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result " - "Type: SConvert")); -} - -TEST_F(ValidateConversion, SConvertSameBitWidth) { - const std::string body = R"( -%val = OpSConvert %u32 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have different bit width from " - "Result Type: SConvert")); -} - -TEST_F(ValidateConversion, FConvertSuccess) { - const std::string body = R"( -%val1 = OpFConvert %f32 %f64_1 -%val2 = OpFConvert %f64 %f32_0 -%val3 = OpFConvert %f64vec2 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, FConvertWrongResultType) { - const std::string body = R"( -%val = OpFConvert %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected float scalar or vector type as Result Type: FConvert")); -} - -TEST_F(ValidateConversion, FConvertWrongInputType) { - const std::string body = R"( -%val = OpFConvert %f32 %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input to be float scalar or vector: FConvert")); -} - -TEST_F(ValidateConversion, FConvertDifferentDimension) { - const std::string body = R"( -%val = OpFConvert %f64 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result " - "Type: FConvert")); -} - -TEST_F(ValidateConversion, FConvertSameBitWidth) { - const std::string body = R"( -%val = OpFConvert %f32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have different bit width from " - "Result Type: FConvert")); -} - -TEST_F(ValidateConversion, QuantizeToF16Success) { - const std::string body = R"( -%val1 = OpQuantizeToF16 %f32 %f32_1 -%val2 = OpQuantizeToF16 %f32 %f32_0 -%val3 = OpQuantizeToF16 %f32vec2 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, QuantizeToF16WrongResultType) { - const std::string body = R"( -%val = OpQuantizeToF16 %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected 32-bit float scalar or vector type as Result Type: " - "QuantizeToF16")); -} - -TEST_F(ValidateConversion, QuantizeToF16WrongResultTypeBitWidth) { - const std::string body = R"( -%val = OpQuantizeToF16 %u64 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected 32-bit float scalar or vector type as Result Type: " - "QuantizeToF16")); -} - -TEST_F(ValidateConversion, QuantizeToF16WrongInputType) { - const std::string body = R"( -%val = OpQuantizeToF16 %f32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected input type to be equal to Result Type: QuantizeToF16")); -} - -TEST_F(ValidateConversion, ConvertPtrToUSuccess) { - const std::string body = R"( -%ptr = OpVariable %f32ptr_func Function -%val1 = OpConvertPtrToU %u32 %ptr -%val2 = OpConvertPtrToU %u64 %ptr -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertPtrToUWrongResultType) { - const std::string body = R"( -%ptr = OpVariable %f32ptr_func Function -%val = OpConvertPtrToU %f32 %ptr -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected unsigned int scalar type as Result Type: " - "ConvertPtrToU")); -} - -TEST_F(ValidateConversion, ConvertPtrToUNotPointer) { - const std::string body = R"( -%val = OpConvertPtrToU %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer: ConvertPtrToU")); -} - -TEST_F(ValidateConversion, SatConvertSToUSuccess) { - const std::string body = R"( -%val1 = OpSatConvertSToU %u32 %u64_2 -%val2 = OpSatConvertSToU %u64 %u32_1 -%val3 = OpSatConvertSToU %u64vec2 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, SatConvertSToUWrongResultType) { - const std::string body = R"( -%val = OpSatConvertSToU %f32 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar or vector type as Result Type: " - "SatConvertSToU")); -} - -TEST_F(ValidateConversion, SatConvertSToUWrongInputType) { - const std::string body = R"( -%val = OpSatConvertSToU %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected int scalar or vector as input: SatConvertSToU")); -} - -TEST_F(ValidateConversion, SatConvertSToUDifferentDimension) { - const std::string body = R"( -%val = OpSatConvertSToU %u32 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input to have the same dimension as Result Type: " - "SatConvertSToU")); -} - -TEST_F(ValidateConversion, ConvertUToPtrSuccess) { - const std::string body = R"( -%val1 = OpConvertUToPtr %f32ptr_func %u32_1 -%val2 = OpConvertUToPtr %f32ptr_func %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertUToPtrWrongResultType) { - const std::string body = R"( -%val = OpConvertUToPtr %f32 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a pointer: ConvertUToPtr")); -} - -TEST_F(ValidateConversion, ConvertUToPtrNotInt) { - const std::string body = R"( -%val = OpConvertUToPtr %f32ptr_func %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar as input: ConvertUToPtr")); -} - -TEST_F(ValidateConversion, ConvertUToPtrNotIntScalar) { - const std::string body = R"( -%val = OpConvertUToPtr %f32ptr_func %u32vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected int scalar as input: ConvertUToPtr")); -} - -TEST_F(ValidateConversion, PtrCastToGenericSuccess) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%val = OpPtrCastToGeneric %f32ptr_gen %ptr_func -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, PtrCastToGenericWrongResultType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%val = OpPtrCastToGeneric %f32 %ptr_func -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be a pointer: PtrCastToGeneric")); -} - -TEST_F(ValidateConversion, PtrCastToGenericWrongResultStorageClass) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%val = OpPtrCastToGeneric %f32ptr_func %ptr_func -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have storage class Generic: " - "PtrCastToGeneric")); -} - -TEST_F(ValidateConversion, PtrCastToGenericWrongInputType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%val = OpPtrCastToGeneric %f32ptr_gen %f32 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a " - "type")); -} - -TEST_F(ValidateConversion, PtrCastToGenericWrongInputStorageClass) { - const std::string body = R"( -%val = OpPtrCastToGeneric %f32ptr_gen %f32inp -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have storage class Workgroup, " - "CrossWorkgroup or Function: PtrCastToGeneric")); -} - -TEST_F(ValidateConversion, PtrCastToGenericPointToDifferentType) { - const std::string body = R"( -%ptr_func = OpVariable %u32ptr_func Function -%val = OpPtrCastToGeneric %f32ptr_gen %ptr_func -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input and Result Type to point to the same type: " - "PtrCastToGeneric")); -} - -TEST_F(ValidateConversion, GenericCastToPtrSuccess) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtr %f32ptr_func %ptr_gen -%ptr_wg = OpGenericCastToPtr %f32ptr_wg %ptr_gen -%ptr_cwg = OpGenericCastToPtr %f32ptr_cwg %ptr_gen -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, GenericCastToPtrWrongResultType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtr %f32 %ptr_gen -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be a pointer: GenericCastToPtr")); -} - -TEST_F(ValidateConversion, GenericCastToPtrWrongResultStorageClass) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtr %f32ptr_gen %ptr_gen -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have storage class Workgroup, " - "CrossWorkgroup or Function: GenericCastToPtr")); -} - -TEST_F(ValidateConversion, GenericCastToPtrWrongInputType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtr %f32ptr_func %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer: GenericCastToPtr")); -} - -TEST_F(ValidateConversion, GenericCastToPtrWrongInputStorageClass) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_func2 = OpGenericCastToPtr %f32ptr_func %ptr_func -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have storage class Generic: " - "GenericCastToPtr")); -} - -TEST_F(ValidateConversion, GenericCastToPtrPointToDifferentType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtr %u32ptr_func %ptr_gen -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input and Result Type to point to the same type: " - "GenericCastToPtr")); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitSuccess) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_gen Function -%ptr_wg = OpGenericCastToPtrExplicit %f32ptr_wg %ptr_gen Workgroup -%ptr_cwg = OpGenericCastToPtrExplicit %f32ptr_cwg %ptr_gen CrossWorkgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongResultType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtrExplicit %f32 %ptr_gen Function -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Result Type to be a pointer: GenericCastToPtrExplicit")); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitResultStorageClassDiffers) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_gen Workgroup -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be of target storage class: " - "GenericCastToPtrExplicit")); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongResultStorageClass) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_gen %ptr_gen Generic -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected target storage class to be Workgroup, " - "CrossWorkgroup or Function: GenericCastToPtrExplicit")); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongInputType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %f32_1 Function -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input to be a pointer: GenericCastToPtrExplicit")); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongInputStorageClass) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_func Function -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to have storage class Generic: " - "GenericCastToPtrExplicit")); -} - -TEST_F(ValidateConversion, GenericCastToPtrExplicitPointToDifferentType) { - const std::string body = R"( -%ptr_func = OpVariable %f32ptr_func Function -%ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func -%ptr_func2 = OpGenericCastToPtrExplicit %u32ptr_func %ptr_gen Function -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected input and Result Type to point to the same type: " - "GenericCastToPtrExplicit")); -} - -TEST_F(ValidateConversion, CoopMatConversionSuccess) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability Int16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%u16 = OpTypeInt 16 0 -%u32 = OpTypeInt 32 0 -%s16 = OpTypeInt 16 1 -%s32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 -%f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_8 %u32_8 -%u16mat = OpTypeCooperativeMatrixNV %u16 %subgroup %u32_8 %u32_8 -%u32mat = OpTypeCooperativeMatrixNV %u32 %subgroup %u32_8 %u32_8 -%s16mat = OpTypeCooperativeMatrixNV %s16 %subgroup %u32_8 %u32_8 -%s32mat = OpTypeCooperativeMatrixNV %s32 %subgroup %u32_8 %u32_8 - -%f16_1 = OpConstant %f16 1 -%f32_1 = OpConstant %f32 1 -%u16_1 = OpConstant %u16 1 -%u32_1 = OpConstant %u32 1 -%s16_1 = OpConstant %s16 1 -%s32_1 = OpConstant %s32 1 - -%f16mat_1 = OpConstantComposite %f16mat %f16_1 -%f32mat_1 = OpConstantComposite %f32mat %f32_1 -%u16mat_1 = OpConstantComposite %u16mat %u16_1 -%u32mat_1 = OpConstantComposite %u32mat %u32_1 -%s16mat_1 = OpConstantComposite %s16mat %s16_1 -%s32mat_1 = OpConstantComposite %s32mat %s32_1 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%val11 = OpConvertFToU %u16mat %f16mat_1 -%val12 = OpConvertFToU %u32mat %f16mat_1 -%val13 = OpConvertFToS %s16mat %f16mat_1 -%val14 = OpConvertFToS %s32mat %f16mat_1 -%val15 = OpFConvert %f32mat %f16mat_1 - -%val21 = OpConvertFToU %u16mat %f32mat_1 -%val22 = OpConvertFToU %u32mat %f32mat_1 -%val23 = OpConvertFToS %s16mat %f32mat_1 -%val24 = OpConvertFToS %s32mat %f32mat_1 -%val25 = OpFConvert %f16mat %f32mat_1 - -%val31 = OpConvertUToF %f16mat %u16mat_1 -%val32 = OpConvertUToF %f32mat %u16mat_1 -%val33 = OpUConvert %u32mat %u16mat_1 -%val34 = OpSConvert %s32mat %u16mat_1 - -%val41 = OpConvertSToF %f16mat %s16mat_1 -%val42 = OpConvertSToF %f32mat %s16mat_1 -%val43 = OpUConvert %u32mat %s16mat_1 -%val44 = OpSConvert %s32mat %s16mat_1 - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, CoopMatConversionShapesMismatchFail) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability Int16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%u16 = OpTypeInt 16 0 -%u32 = OpTypeInt 32 0 -%s16 = OpTypeInt 16 1 -%s32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%u32_4 = OpConstant %u32 4 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 -%f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_4 %u32_4 - -%f16_1 = OpConstant %f16 1 - -%f16mat_1 = OpConstantComposite %f16mat %f16_1 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%val15 = OpFConvert %f32mat %f16mat_1 - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected rows of Matrix type and Result Type to be identical")); -} - -TEST_F(ValidateConversion, CoopMatConversionShapesMismatchPass) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability Int16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%u16 = OpTypeInt 16 0 -%u32 = OpTypeInt 32 0 -%s16 = OpTypeInt 16 1 -%s32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%u32_4 = OpSpecConstant %u32 4 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 -%f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_4 %u32_4 - -%f16_1 = OpConstant %f16 1 - -%f16mat_1 = OpConstantComposite %f16mat %f16_1 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%val15 = OpFConvert %f32mat %f16mat_1 - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, BitcastSuccess) { - const std::string body = R"( -%ptr = OpVariable %f32ptr_func Function -%val1 = OpBitcast %u32 %ptr -%val2 = OpBitcast %u64 %ptr -%val3 = OpBitcast %f32ptr_func %u32_1 -%val4 = OpBitcast %f32ptr_wg %u64_1 -%val5 = OpBitcast %f32 %u32_1 -%val6 = OpBitcast %f32vec2 %u32vec2_12 -%val7 = OpBitcast %f32vec2 %u64_1 -%val8 = OpBitcast %f64 %u32vec2_12 -%val9 = OpBitcast %f32vec4 %f64vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, BitcastSuccessSPV1p5) { - const std::string body = R"( -%ptr = OpVariable %f32ptr_func Function -%val1 = OpBitcast %u32 %ptr -%val2 = OpBitcast %u64 %ptr -%val3 = OpBitcast %f32ptr_func %u32_1 -%val4 = OpBitcast %f32ptr_wg %u64_1 -%val5 = OpBitcast %f32 %u32_1 -%val6 = OpBitcast %f32vec2 %u32vec2_12 -%val7 = OpBitcast %f32vec2 %u64_1 -%val8 = OpBitcast %f64 %u32vec2_12 -%val9 = OpBitcast %f32vec4 %f64vec2_12 -%val10 = OpBitcast %u32ptr_func %u32vec2_01 -%val11 = OpBitcast %u32vec2 %ptr -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); -} - -TEST_F(ValidateConversion, BitcastSuccessPhysicalStorageBufferKHR) { - const std::string body = R"( -%ptr = OpVariable %f32ptr_func Function -%val1 = OpBitcast %u32 %ptr -%val2 = OpBitcast %u64 %ptr -%val3 = OpBitcast %f32ptr_func %u32_1 -%val4 = OpBitcast %f32ptr_wg %u64_1 -%val5 = OpBitcast %f32 %u32_1 -%val6 = OpBitcast %f32vec2 %u32vec2_12 -%val7 = OpBitcast %f32vec2 %u64_1 -%val8 = OpBitcast %f64 %u32vec2_12 -%val9 = OpBitcast %f32vec4 %f64vec2_12 -%val10 = OpBitcast %u32ptr_func %u32vec2_01 -%val11 = OpBitcast %u32vec2 %ptr -)"; - - CompileSuccessfully( - GenerateKernelCode(body, - "\nOpExtension \"SPV_KHR_physical_storage_buffer\"") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, BitcastInputHasNoType) { - const std::string body = R"( -%val = OpBitcast %u32 %f32 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a " - "type")); -} - -TEST_F(ValidateConversion, BitcastWrongResultType) { - const std::string body = R"( -%val = OpBitcast %bool %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be a pointer or int or float vector " - "or scalar type: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastWrongInputType) { - const std::string body = R"( -%val = OpBitcast %u32 %true -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer or int or float vector " - "or scalar: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongInputType) { - const std::string body = R"( -%val = OpBitcast %u32ptr_func %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer or int scalar if " - "Result Type is pointer: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongInputTypeSPV1p5) { - const std::string body = R"( -%val = OpBitcast %u32ptr_func %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer, int scalar or 32-bit " - "int vector if Result Type is pointer: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongInputTypePhysicalStorageBufferKHR) { - const std::string body = R"( -%val = OpBitcast %u32ptr_func %f32_1 -)"; - - CompileSuccessfully( - GenerateKernelCode(body, - "\nOpExtension \"SPV_KHR_physical_storage_buffer\"") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer, int scalar or 32-bit " - "int vector if Result Type is pointer: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongInputTypeIntVectorSPV1p5) { - const std::string body = R"( -%val = OpBitcast %u32ptr_func %u64vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer, int scalar or 32-bit " - "int vector if Result Type is pointer: Bitcast")); -} - -TEST_F(ValidateConversion, - BitcastPtrWrongInputTypeIntVectorPhysicalStorageBufferKHR) { - const std::string body = R"( -%val = OpBitcast %u32ptr_func %u64vec2_01 -)"; - - CompileSuccessfully( - GenerateKernelCode(body, - "\nOpExtension \"SPV_KHR_physical_storage_buffer\"") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected input to be a pointer, int scalar or 32-bit " - "int vector if Result Type is pointer: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongResultType) { - const std::string body = R"( -%val = OpBitcast %f32 %f32inp -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer can only be converted to another pointer or " - "int scalar: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongResultTypeSPV1p5) { - const std::string body = R"( -%val = OpBitcast %f32 %f32inp -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer can only be converted to another pointer, int " - "scalar or 32-bit int vector: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongResultTypePhysicalStorageBufferKHR) { - const std::string body = R"( -%val = OpBitcast %f32 %f32inp -)"; - - CompileSuccessfully( - GenerateKernelCode(body, - "\nOpExtension \"SPV_KHR_physical_storage_buffer\"") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer can only be converted to another pointer, int " - "scalar or 32-bit int vector: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastPtrWrongResultTypeIntVectorSPV1p5) { - const std::string body = R"( -%val = OpBitcast %u64vec2 %f32inp -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer can only be converted to another pointer, int " - "scalar or 32-bit int vector: Bitcast")); -} - -TEST_F(ValidateConversion, - BitcastPtrWrongResultTypeIntVectorPhysicalStorageBufferKHR) { - const std::string body = R"( -%val = OpBitcast %u64vec2 %f32inp -)"; - - CompileSuccessfully( - GenerateKernelCode(body, - "\nOpExtension \"SPV_KHR_physical_storage_buffer\"") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer can only be converted to another pointer, int " - "scalar or 32-bit int vector: Bitcast")); -} - -TEST_F(ValidateConversion, BitcastDifferentTotalBitWidth) { - const std::string body = R"( -%val = OpBitcast %f32 %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected input to have the same total bit width as Result Type: " - "Bitcast")); -} - -TEST_F(ValidateConversion, ConvertUToPtrInputIsAType) { - const std::string spirv = R"( -OpCapability Addresses -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer Function %int -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%1 = OpConvertUToPtr %ptr_int %int -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%uint] cannot be a " - "type")); -} - -TEST_F(ValidateConversion, ConvertUToPtrPSBSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%uint64 = OpTypeInt 64 0 -%u64_1 = OpConstant %uint64 1 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpConvertUToPtr %ptr %u64_1 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertUToPtrPSBStorageClass) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%uint64 = OpTypeInt 64 0 -%u64_1 = OpConstant %uint64 1 -%ptr = OpTypePointer Function %uint64 -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpConvertUToPtr %ptr %u64_1 -%val2 = OpConvertPtrToU %uint64 %val1 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer storage class must be " - "PhysicalStorageBufferEXT: ConvertUToPtr")); -} - -TEST_F(ValidateConversion, ConvertPtrToUPSBSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 RestrictPointerEXT -%uint64 = OpTypeInt 64 0 -%u64_1 = OpConstant %uint64 1 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -%val2 = OpLoad %ptr %val1 -%val3 = OpConvertPtrToU %uint64 %val2 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateConversion, ConvertPtrToUPSBStorageClass) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%uint64 = OpTypeInt 64 0 -%u64_1 = OpConstant %uint64 1 -%ptr = OpTypePointer Function %uint64 -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %ptr Function -%val2 = OpConvertPtrToU %uint64 %val1 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer storage class must be " - "PhysicalStorageBufferEXT: ConvertPtrToU")); -} - -using ValidateSmallConversions = spvtest::ValidateBase; - -CodeGenerator GetSmallConversionsCodeGenerator() { - CodeGenerator generator; - generator.capabilities_ = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer16BitAccess -OpCapability UniformAndStorageBuffer8BitAccess -)"; - generator.extensions_ = R"( -OpExtension "SPV_KHR_16bit_storage" -OpExtension "SPV_KHR_8bit_storage" -)"; - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - generator.before_types_ = R"( -OpDecorate %char_block Block -OpMemberDecorate %char_block 0 Offset 0 -OpDecorate %short_block Block -OpMemberDecorate %short_block 0 Offset 0 -OpDecorate %half_block Block -OpMemberDecorate %half_block 0 Offset 0 -OpDecorate %int_block Block -OpMemberDecorate %int_block 0 Offset 0 -OpDecorate %float_block Block -OpMemberDecorate %float_block 0 Offset 0 -)"; - generator.types_ = R"( -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int2 = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%float_0 = OpConstant %float 0 -%float2 = OpTypeVector %float 2 -%char = OpTypeInt 8 0 -%char2 = OpTypeVector %char 2 -%short = OpTypeInt 16 0 -%short2 = OpTypeVector %short 2 -%half = OpTypeFloat 16 -%half2 = OpTypeVector %half 2 -%char_block = OpTypeStruct %char2 -%short_block = OpTypeStruct %short2 -%half_block = OpTypeStruct %half2 -%int_block = OpTypeStruct %int2 -%float_block = OpTypeStruct %float2 -%ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block -%ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2 -%ptr_ssbo_char = OpTypePointer StorageBuffer %char -%ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block -%ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2 -%ptr_ssbo_short = OpTypePointer StorageBuffer %short -%ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block -%ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2 -%ptr_ssbo_half = OpTypePointer StorageBuffer %half -%ptr_ssbo_int_block = OpTypePointer StorageBuffer %int_block -%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_ssbo_float_block = OpTypePointer StorageBuffer %float_block -%ptr_ssbo_float2 = OpTypePointer StorageBuffer %float2 -%ptr_ssbo_float = OpTypePointer StorageBuffer %float -%void_fn = OpTypeFunction %void -%char_var = OpVariable %ptr_ssbo_char_block StorageBuffer -%short_var = OpVariable %ptr_ssbo_short_block StorageBuffer -%half_var = OpVariable %ptr_ssbo_half_block StorageBuffer -%int_var = OpVariable %ptr_ssbo_int_block StorageBuffer -%float_var = OpVariable %ptr_ssbo_float_block StorageBuffer -)"; - generator.after_types_ = R"( -%func = OpFunction %void None %void_fn -%entry = OpLabel -%char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0 -%ld_char2 = OpLoad %char2 %char2_gep -%char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0 -%ld_char = OpLoad %char %char_gep -%short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0 -%ld_short2 = OpLoad %short2 %short2_gep -%short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0 -%ld_short = OpLoad %short %short_gep -%half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0 -%ld_half2 = OpLoad %half2 %half2_gep -%half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0 -%ld_half = OpLoad %half %half_gep -%int2_gep = OpAccessChain %ptr_ssbo_int2 %int_var %int_0 -%ld_int2 = OpLoad %int2 %int2_gep -%int_gep = OpAccessChain %ptr_ssbo_int %int_var %int_0 %int_0 -%ld_int = OpLoad %int %int_gep -%float2_gep = OpAccessChain %ptr_ssbo_float2 %float_var %int_0 -%ld_float2 = OpLoad %float2 %float2_gep -%float_gep = OpAccessChain %ptr_ssbo_float %float_var %int_0 %int_0 -%ld_float = OpLoad %float %float_gep -)"; - generator.add_at_the_end_ = R"( -OpReturn -OpFunctionEnd -)"; - return generator; -} - -TEST_P(ValidateSmallConversions, Instruction) { - CodeGenerator generator = GetSmallConversionsCodeGenerator(); - generator.after_types_ += GetParam() + "\n"; - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "8- or 16-bit types can only be used with width-only conversions")); -} - -INSTANTIATE_TEST_SUITE_P(SmallConversionInstructions, ValidateSmallConversions, - Values("%inst = OpConvertFToU %char %ld_float", - "%inst = OpConvertFToU %char2 %ld_float2", - "%inst = OpConvertFToU %short %ld_float", - "%inst = OpConvertFToU %short2 %ld_float2", - "%inst = OpConvertFToU %int %ld_half", - "%inst = OpConvertFToU %int2 %ld_half2", - "%inst = OpConvertFToS %char %ld_float", - "%inst = OpConvertFToS %char2 %ld_float2", - "%inst = OpConvertFToS %short %ld_float", - "%inst = OpConvertFToS %short2 %ld_float2", - "%inst = OpConvertFToS %int %ld_half", - "%inst = OpConvertFToS %int2 %ld_half2", - "%inst = OpConvertSToF %float %ld_char", - "%inst = OpConvertSToF %float2 %ld_char2", - "%inst = OpConvertSToF %float %ld_short", - "%inst = OpConvertSToF %float2 %ld_short2", - "%inst = OpConvertSToF %half %ld_int", - "%inst = OpConvertSToF %half2 %ld_int2", - "%inst = OpConvertUToF %float %ld_char", - "%inst = OpConvertUToF %float2 %ld_char2", - "%inst = OpConvertUToF %float %ld_short", - "%inst = OpConvertUToF %float2 %ld_short2", - "%inst = OpConvertUToF %half %ld_int", - "%inst = OpConvertUToF %half2 %ld_int2", - "%inst = OpBitcast %half %ld_short", - "%inst = OpBitcast %half2 %ld_short2", - "%inst = OpBitcast %short %ld_half", - "%inst = OpBitcast %short2 %ld_half2")); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_data_test.cpp b/3rdparty/spirv-tools/test/val/val_data_test.cpp deleted file mode 100644 index 30afd03cd..000000000 --- a/3rdparty/spirv-tools/test/val/val_data_test.cpp +++ /dev/null @@ -1,949 +0,0 @@ -// 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. - -// Validation tests for Data Rules. - -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; - -using ValidateData = spvtest::ValidateBase>; - -std::string HeaderWith(std::string cap) { - return std::string("OpCapability Shader OpCapability Linkage OpCapability ") + - cap + " OpMemoryModel Logical GLSL450 "; -} - -std::string WebGPUHeaderWith(std::string cap) { - return R"( -OpCapability Shader -OpCapability )" + - cap + R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -)"; -} - -std::string webgpu_header = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -)"; - -std::string header = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_addresses = R"( - OpCapability Addresses - OpCapability Kernel - OpCapability GenericPointer - OpCapability Linkage - OpMemoryModel Physical32 OpenCL -)"; -std::string header_with_vec16_cap = R"( - OpCapability Shader - OpCapability Vector16 - OpCapability Linkage - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_int8 = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Int8 - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_int16 = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Int16 - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_int64 = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Int64 - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_float16 = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Float16 - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_float16_buffer = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Float16Buffer - OpMemoryModel Logical GLSL450 -)"; -std::string header_with_float64 = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Float64 - OpMemoryModel Logical GLSL450 -)"; - -std::string invalid_comp_error = "Illegal number of components"; -std::string missing_cap_error = "requires the Vector16 capability"; -std::string missing_int8_cap_error = "requires the Int8 capability"; -std::string missing_int16_cap_error = - "requires the Int16 capability," - " or an extension that explicitly enables 16-bit integers."; -std::string missing_int64_cap_error = "requires the Int64 capability"; -std::string missing_float16_cap_error = - "requires the Float16 or Float16Buffer capability," - " or an extension that explicitly enables 16-bit floating point."; -std::string missing_float64_cap_error = "requires the Float64 capability"; -std::string invalid_num_bits_error = "Invalid number of bits"; - -TEST_F(ValidateData, vec0) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 0 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error)); -} - -TEST_F(ValidateData, vec1) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 1 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error)); -} - -TEST_F(ValidateData, vec2) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 2 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, vec3) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, vec4) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, vec5) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 5 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error)); -} - -TEST_F(ValidateData, vec8) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 8 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error)); -} - -TEST_F(ValidateData, vec8_with_capability) { - std::string str = header_with_vec16_cap + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 8 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, vec16) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 8 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error)); -} - -TEST_F(ValidateData, vec16_with_capability) { - std::string str = header_with_vec16_cap + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 16 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, vec15) { - std::string str = header + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 15 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error)); -} - -TEST_F(ValidateData, int8_good) { - std::string str = header_with_int8 + "%2 = OpTypeInt 8 0"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, int8_bad) { - std::string str = header + "%2 = OpTypeInt 8 1"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int8_cap_error)); -} - -TEST_F(ValidateData, int8_with_storage_buffer_8bit_access_good) { - std::string str = HeaderWith( - "StorageBuffer8BitAccess " - "OpExtension \"SPV_KHR_8bit_storage\"") + - " %2 = OpTypeInt 8 0"; - CompileSuccessfully(str.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateData, int8_with_uniform_and_storage_buffer_8bit_access_good) { - std::string str = HeaderWith( - "UniformAndStorageBuffer8BitAccess " - "OpExtension \"SPV_KHR_8bit_storage\"") + - " %2 = OpTypeInt 8 0"; - CompileSuccessfully(str.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateData, int8_with_storage_push_constant_8_good) { - std::string str = HeaderWith( - "StoragePushConstant8 " - "OpExtension \"SPV_KHR_8bit_storage\"") + - " %2 = OpTypeInt 8 0"; - CompileSuccessfully(str.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateData, webgpu_int8_bad) { - std::string str = WebGPUHeaderWith("Int8") + "%2 = OpTypeInt 8 0"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Int8 is not allowed by WebGPU specification (or " - "requires extension)\n" - " OpCapability Int8\n")); -} - -TEST_F(ValidateData, int16_good) { - std::string str = header_with_int16 + "%2 = OpTypeInt 16 1"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, storage_uniform_buffer_block_16_good) { - std::string str = HeaderWith( - "StorageUniformBufferBlock16 " - "OpExtension \"SPV_KHR_16bit_storage\"") + - "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, storage_uniform_16_good) { - std::string str = - HeaderWith("StorageUniform16 OpExtension \"SPV_KHR_16bit_storage\"") + - "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, storage_push_constant_16_good) { - std::string str = HeaderWith( - "StoragePushConstant16 " - "OpExtension \"SPV_KHR_16bit_storage\"") + - "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, storage_input_output_16_good) { - std::string str = HeaderWith( - "StorageInputOutput16 " - "OpExtension \"SPV_KHR_16bit_storage\"") + - "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, amd_gpu_shader_half_float_fetch_16_good) { - std::string str = R"( - OpCapability Shader - OpCapability Linkage - OpExtension "SPV_AMD_gpu_shader_half_float_fetch" - OpMemoryModel Logical GLSL450 - %2 = OpTypeFloat 16)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, int16_bad) { - std::string str = header + "%2 = OpTypeInt 16 1"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error)); -} - -TEST_F(ValidateData, webgpu_int16_bad) { - std::string str = WebGPUHeaderWith("Int16") + "%2 = OpTypeInt 16 1"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Int16 is not allowed by WebGPU specification (or " - "requires extension)\n" - " OpCapability Int16\n")); -} - -TEST_F(ValidateData, webgpu_int32_good) { - std::string str = webgpu_header + R"( - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 - %void = OpTypeVoid -%func_t = OpTypeFunction %void - %func = OpFunction %void None %func_t - %1 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateData, int64_good) { - std::string str = header_with_int64 + "%2 = OpTypeInt 64 1"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, int64_bad) { - std::string str = header + "%2 = OpTypeInt 64 1"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error)); -} - -TEST_F(ValidateData, webgpu_int64_bad) { - std::string str = WebGPUHeaderWith("Int64") + "%2 = OpTypeInt 64 1"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Int64 is not allowed by WebGPU specification (or " - "requires extension)\n" - " OpCapability Int64\n")); -} - -// Number of bits in an integer may be only one of: {8,16,32,64} -TEST_F(ValidateData, int_invalid_num_bits) { - std::string str = header + "%2 = OpTypeInt 48 1"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error)); -} - -TEST_F(ValidateData, float16_good) { - std::string str = header_with_float16 + "%2 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, float16_buffer_good) { - std::string str = header_with_float16_buffer + "%2 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, float16_bad) { - std::string str = header + "%2 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error)); -} - -TEST_F(ValidateData, webgpu_float16_bad) { - std::string str = WebGPUHeaderWith("Float16") + "%2 = OpTypeFloat 16"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Float16 is not allowed by WebGPU specification (or " - "requires extension)\n" - " OpCapability Float16\n")); -} - -TEST_F(ValidateData, webgpu_float32_good) { - std::string str = webgpu_header + R"( - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft -%float_t = OpTypeFloat 32 - %void = OpTypeVoid - %func_t = OpTypeFunction %void - %func = OpFunction %void None %func_t - %1 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateData, float64_good) { - std::string str = header_with_float64 + "%2 = OpTypeFloat 64"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, float64_bad) { - std::string str = header + "%2 = OpTypeFloat 64"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error)); -} - -TEST_F(ValidateData, webgpu_float64_bad) { - std::string str = WebGPUHeaderWith("Float64") + "%2 = OpTypeFloat 64"; - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Float64 is not allowed by WebGPU specification (or " - "requires extension)\n" - " OpCapability Float64\n")); -} - -// Number of bits in a float may be only one of: {16,32,64} -TEST_F(ValidateData, float_invalid_num_bits) { - std::string str = header + "%2 = OpTypeFloat 48"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error)); -} - -TEST_F(ValidateData, matrix_data_type_float) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, ids_should_be_validated_before_data) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%mat33 = OpTypeMatrix %vec3 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 3[%3] has not been defined")); -} - -TEST_F(ValidateData, matrix_bad_column_type) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%mat33 = OpTypeMatrix %f32 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Columns in a matrix must be of type vector")); -} - -TEST_F(ValidateData, matrix_data_type_int) { - std::string str = header + R"( -%int32 = OpTypeInt 32 1 -%vec3 = OpTypeVector %int32 3 -%mat33 = OpTypeMatrix %vec3 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("can only be parameterized with floating-point types")); -} - -TEST_F(ValidateData, matrix_data_type_bool) { - std::string str = header + R"( -%boolt = OpTypeBool -%vec3 = OpTypeVector %boolt 3 -%mat33 = OpTypeMatrix %vec3 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("can only be parameterized with floating-point types")); -} - -TEST_F(ValidateData, matrix_with_0_columns) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 0 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("can only be parameterized as having only 2, 3, or 4 columns")); -} - -TEST_F(ValidateData, matrix_with_1_column) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 1 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("can only be parameterized as having only 2, 3, or 4 columns")); -} - -TEST_F(ValidateData, matrix_with_2_columns) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 2 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, matrix_with_3_columns) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 3 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, matrix_with_4_columns) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 4 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, matrix_with_5_column) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 5 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("can only be parameterized as having only 2, 3, or 4 columns")); -} - -TEST_F(ValidateData, specialize_int) { - std::string str = header + R"( -%i32 = OpTypeInt 32 1 -%len = OpSpecConstant %i32 2)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, specialize_float) { - std::string str = header + R"( -%f32 = OpTypeFloat 32 -%len = OpSpecConstant %f32 2)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, specialize_boolean) { - std::string str = header + R"( -%2 = OpTypeBool -%3 = OpSpecConstantTrue %2 -%4 = OpSpecConstantFalse %2)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, specialize_boolean_true_to_int) { - std::string str = header + R"( -%2 = OpTypeInt 32 1 -%3 = OpSpecConstantTrue %2)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantTrue Result Type '1[%int]' is not " - "a boolean type")); -} - -TEST_F(ValidateData, specialize_boolean_false_to_int) { - std::string str = header + R"( -%2 = OpTypeInt 32 1 -%4 = OpSpecConstantFalse %2)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantFalse Result Type '1[%int]' is not " - "a boolean type")); -} - -TEST_F(ValidateData, missing_forward_pointer_decl) { - std::string str = header_with_addresses + R"( -%uintt = OpTypeInt 32 0 -%3 = OpTypeStruct %fwd_ptrt %uintt -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 3[%3] requires a previous definition")); -} - -TEST_F(ValidateData, missing_forward_pointer_decl_self_reference) { - std::string str = header_with_addresses + R"( -%uintt = OpTypeInt 32 0 -%3 = OpTypeStruct %3 %uintt -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Operand 2[%_struct_2] requires a previous definition")); -} - -TEST_F(ValidateData, forward_pointer_missing_definition) { - std::string str = header_with_addresses + R"( -OpTypeForwardPointer %_ptr_Generic_struct_A Generic -%uintt = OpTypeInt 32 0 -%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("forward referenced IDs have not been defined")); -} - -TEST_F(ValidateData, forward_ref_bad_type) { - std::string str = header_with_addresses + R"( -OpTypeForwardPointer %_ptr_Generic_struct_A Generic -%uintt = OpTypeInt 32 0 -%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A -%_ptr_Generic_struct_A = OpTypeFloat 32 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer " - "type.\n OpTypeForwardPointer %float Generic\n")); -} - -TEST_F(ValidateData, forward_ref_points_to_non_struct) { - std::string str = header_with_addresses + R"( -OpTypeForwardPointer %_ptr_Generic_struct_A Generic -%uintt = OpTypeInt 32 0 -%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A -%_ptr_Generic_struct_A = OpTypePointer Generic %uintt -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Forward pointers must point to a structure")); -} - -TEST_F(ValidateData, struct_forward_pointer_good) { - std::string str = header_with_addresses + R"( -OpTypeForwardPointer %_ptr_Generic_struct_A Generic -%uintt = OpTypeInt 32 0 -%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A -%struct_C = OpTypeStruct %uintt %struct_B -%struct_A = OpTypeStruct %uintt %struct_C -%_ptr_Generic_struct_A = OpTypePointer Generic %struct_C -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateData, ext_16bit_storage_caps_allow_free_fp_rounding_mode) { - for (const char* cap : {"StorageUniform16", "StorageUniformBufferBlock16"}) { - for (const char* mode : {"RTE", "RTZ", "RTP", "RTN"}) { - std::string str = std::string(R"( - OpCapability Shader - OpCapability Linkage - OpCapability )") + - cap + R"( - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpExtension "SPV_KHR_variable_pointers" - OpExtension "SPV_KHR_16bit_storage" - OpMemoryModel Logical GLSL450 - OpDecorate %_ FPRoundingMode )" + mode + R"( - %half = OpTypeFloat 16 - %float = OpTypeFloat 32 - %float_1_25 = OpConstant %float 1.25 - %half_ptr = OpTypePointer StorageBuffer %half - %half_ptr_var = OpVariable %half_ptr StorageBuffer - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - %main_entry = OpLabel - %_ = OpFConvert %half %float_1_25 - OpStore %half_ptr_var %_ - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - } - } -} - -TEST_F(ValidateData, vulkan_disallow_free_fp_rounding_mode) { - for (const char* mode : {"RTE", "RTZ"}) { - for (const auto env : {SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) { - std::string str = std::string(R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpExtension "SPV_KHR_variable_pointers" - OpMemoryModel Logical GLSL450 - OpDecorate %_ FPRoundingMode )") + - mode + R"( - %half = OpTypeFloat 16 - %float = OpTypeFloat 32 - %float_1_25 = OpConstant %float 1.25 - %half_ptr = OpTypePointer StorageBuffer %half - %half_ptr_var = OpVariable %half_ptr StorageBuffer - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - %main_entry = OpLabel - %_ = OpFConvert %half %float_1_25 - OpStore %half_ptr_var %_ - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions(env)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Operand 2 of Decorate requires one of these capabilities: " - "StorageBuffer16BitAccess UniformAndStorageBuffer16BitAccess " - "StoragePushConstant16 StorageInputOutput16")); - } - } -} - -TEST_F(ValidateData, void_array) { - std::string str = header + R"( - %void = OpTypeVoid - %int = OpTypeInt 32 0 - %int_5 = OpConstant %int 5 - %array = OpTypeArray %void %int_5 - )"; - - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpTypeArray Element Type '1[%void]' is a void type.")); -} - -TEST_F(ValidateData, void_runtime_array) { - std::string str = header + R"( - %void = OpTypeVoid - %array = OpTypeRuntimeArray %void - )"; - - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '1[%void]' is a void type.")); -} - -TEST_F(ValidateData, vulkan_RTA_array_at_end_of_struct) { - std::string str = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft - OpDecorate %array_t ArrayStride 4 - OpMemberDecorate %struct_t 0 Offset 0 - OpMemberDecorate %struct_t 1 Offset 4 - OpDecorate %struct_t Block - %uint_t = OpTypeInt 32 0 - %array_t = OpTypeRuntimeArray %uint_t - %struct_t = OpTypeStruct %uint_t %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t - %2 = OpVariable %struct_ptr StorageBuffer - %void = OpTypeVoid - %func_t = OpTypeFunction %void - %func = OpFunction %void None %func_t - %1 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateData, vulkan_RTA_not_at_end_of_struct) { - std::string str = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft - OpDecorate %array_t ArrayStride 4 - OpMemberDecorate %struct_t 0 Offset 0 - OpMemberDecorate %struct_t 1 Offset 4 - OpDecorate %struct_t Block - %uint_t = OpTypeInt 32 0 - %array_t = OpTypeRuntimeArray %uint_t - %struct_t = OpTypeStruct %array_t %uint_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t - %2 = OpVariable %struct_ptr StorageBuffer - %void = OpTypeVoid - %func_t = OpTypeFunction %void - %func = OpFunction %void None %func_t - %1 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In Vulkan, OpTypeRuntimeArray must only be used for " - "the last member of an OpTypeStruct\n %_struct_3 = " - "OpTypeStruct %_runtimearr_uint %uint\n")); -} - -TEST_F(ValidateData, webgpu_RTA_array_at_end_of_struct) { - std::string str = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft - OpDecorate %array_t ArrayStride 4 - OpMemberDecorate %struct_t 0 Offset 0 - OpMemberDecorate %struct_t 1 Offset 4 - OpDecorate %struct_t Block - %uint_t = OpTypeInt 32 0 - %array_t = OpTypeRuntimeArray %uint_t - %struct_t = OpTypeStruct %uint_t %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t - %2 = OpVariable %struct_ptr StorageBuffer - %void = OpTypeVoid - %func_t = OpTypeFunction %void - %func = OpFunction %void None %func_t - %1 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateData, webgpu_RTA_not_at_end_of_struct) { - std::string str = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft - OpDecorate %array_t ArrayStride 4 - OpMemberDecorate %struct_t 0 Offset 0 - OpMemberDecorate %struct_t 1 Offset 4 - OpDecorate %struct_t Block - %uint_t = OpTypeInt 32 0 - %array_t = OpTypeRuntimeArray %uint_t - %struct_t = OpTypeStruct %array_t %uint_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t - %2 = OpVariable %struct_ptr StorageBuffer - %void = OpTypeVoid - %func_t = OpTypeFunction %void - %func = OpFunction %void None %func_t - %1 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In WebGPU, OpTypeRuntimeArray must only be used for " - "the last member of an OpTypeStruct\n %_struct_3 = " - "OpTypeStruct %_runtimearr_uint %uint\n")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_decoration_test.cpp b/3rdparty/spirv-tools/test/val/val_decoration_test.cpp deleted file mode 100644 index 256e115f5..000000000 --- a/3rdparty/spirv-tools/test/val/val_decoration_test.cpp +++ /dev/null @@ -1,7000 +0,0 @@ -// Copyright (c) 2017 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. - -// Validation tests for decorations - -#include -#include - -#include "gmock/gmock.h" -#include "source/val/decoration.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Combine; -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Values; - -struct TestResult { - TestResult(spv_result_t in_validation_result = SPV_SUCCESS, - const std::string& in_error_str = "") - : validation_result(in_validation_result), error_str(in_error_str) {} - spv_result_t validation_result; - const std::string error_str; -}; - -using ValidateDecorations = spvtest::ValidateBase; -using ValidateWebGPUCombineDecorationResult = - spvtest::ValidateBase>; - -TEST_F(ValidateDecorations, ValidateOpDecorateRegistration) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %1 ArrayStride 4 - OpDecorate %1 RelaxedPrecision - %2 = OpTypeFloat 32 - %1 = OpTypeRuntimeArray %2 - ; Since %1 is used first in Decoration, it gets id 1. -)"; - const uint32_t id = 1; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - // Must have 2 decorations. - EXPECT_THAT( - vstate_->id_decorations(id), - Eq(std::vector{Decoration(SpvDecorationArrayStride, {4}), - Decoration(SpvDecorationRelaxedPrecision)})); -} - -TEST_F(ValidateDecorations, ValidateOpMemberDecorateRegistration) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %_arr_double_uint_6 ArrayStride 4 - OpMemberDecorate %_struct_115 2 NonReadable - OpMemberDecorate %_struct_115 2 Offset 2 - OpDecorate %_struct_115 BufferBlock - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 - %uint_6 = OpConstant %uint 6 - %_arr_double_uint_6 = OpTypeArray %float %uint_6 - %_struct_115 = OpTypeStruct %float %float %_arr_double_uint_6 -)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - - // The array must have 1 decoration. - const uint32_t arr_id = 1; - EXPECT_THAT( - vstate_->id_decorations(arr_id), - Eq(std::vector{Decoration(SpvDecorationArrayStride, {4})})); - - // The struct must have 3 decorations. - const uint32_t struct_id = 2; - EXPECT_THAT( - vstate_->id_decorations(struct_id), - Eq(std::vector{Decoration(SpvDecorationNonReadable, {}, 2), - Decoration(SpvDecorationOffset, {2}, 2), - Decoration(SpvDecorationBufferBlock)})); -} - -TEST_F(ValidateDecorations, ValidateOpMemberDecorateOutOfBound) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "Main" - OpExecutionMode %1 OriginUpperLeft - OpMemberDecorate %_struct_2 1 RelaxedPrecision - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 - %_struct_2 = OpTypeStruct %float - %1 = OpFunction %void None %4 - %6 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index 1 provided in OpMemberDecorate for struct " - "2[%_struct_2] is out of bounds. The structure has 1 " - "members. Largest valid index is 0.")); -} - -TEST_F(ValidateDecorations, ValidateGroupDecorateRegistration) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %1 DescriptorSet 0 - OpDecorate %1 RelaxedPrecision - OpDecorate %1 Restrict - %1 = OpDecorationGroup - OpGroupDecorate %1 %2 %3 - OpGroupDecorate %1 %4 - %float = OpTypeFloat 32 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_9 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 - %2 = OpVariable %_ptr_Uniform__struct_9 Uniform - %_struct_10 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_10 = OpTypePointer Uniform %_struct_10 - %3 = OpVariable %_ptr_Uniform__struct_10 Uniform - %_struct_11 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_11 = OpTypePointer Uniform %_struct_11 - %4 = OpVariable %_ptr_Uniform__struct_11 Uniform - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - - // Decoration group has 3 decorations. - auto expected_decorations = - std::vector{Decoration(SpvDecorationDescriptorSet, {0}), - Decoration(SpvDecorationRelaxedPrecision), - Decoration(SpvDecorationRestrict)}; - - // Decoration group is applied to id 1, 2, 3, and 4. Note that id 1 (which is - // the decoration group id) also has all the decorations. - EXPECT_THAT(vstate_->id_decorations(1), Eq(expected_decorations)); - EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations)); - EXPECT_THAT(vstate_->id_decorations(3), Eq(expected_decorations)); - EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations)); -} - -TEST_F(ValidateDecorations, WebGPUOpDecorationGroupBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpDecorate %1 DescriptorSet 0 - OpDecorate %1 NonWritable - OpDecorate %1 Restrict - %1 = OpDecorationGroup - OpGroupDecorate %1 %2 %3 - OpGroupDecorate %1 %4 - %float = OpTypeFloat 32 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_9 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 - %2 = OpVariable %_ptr_Uniform__struct_9 Uniform - %_struct_10 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_10 = OpTypePointer Uniform %_struct_10 - %3 = OpVariable %_ptr_Uniform__struct_10 Uniform - %_struct_11 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_11 = OpTypePointer Uniform %_struct_11 - %4 = OpVariable %_ptr_Uniform__struct_11 Uniform - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpDecorationGroup is not allowed in the WebGPU " - "execution environment.\n %1 = OpDecorationGroup\n")); -} - -// For WebGPU, OpGroupDecorate does not have a test case, because it requires -// being preceded by OpDecorationGroup, which will cause a validation error. - -// For WebGPU, OpGroupMemberDecorate does not have a test case, because it -// requires being preceded by OpDecorationGroup, which will cause a validation -// error. - -TEST_F(ValidateDecorations, ValidateGroupMemberDecorateRegistration) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %1 Offset 3 - %1 = OpDecorationGroup - OpGroupMemberDecorate %1 %_struct_1 3 %_struct_2 3 %_struct_3 3 - %float = OpTypeFloat 32 -%_runtimearr = OpTypeRuntimeArray %float - %_struct_1 = OpTypeStruct %float %float %float %_runtimearr - %_struct_2 = OpTypeStruct %float %float %float %_runtimearr - %_struct_3 = OpTypeStruct %float %float %float %_runtimearr - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - // Decoration group has 1 decoration. - auto expected_decorations = - std::vector{Decoration(SpvDecorationOffset, {3}, 3)}; - - // Decoration group is applied to id 2, 3, and 4. - EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations)); - EXPECT_THAT(vstate_->id_decorations(3), Eq(expected_decorations)); - EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations)); -} - -TEST_F(ValidateDecorations, LinkageImportUsedForInitializedVariableBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %target LinkageAttributes "link_ptr" Import - %float = OpTypeFloat 32 - %_ptr_float = OpTypePointer Uniform %float - %zero = OpConstantNull %float - %target = OpVariable %_ptr_float Uniform %zero - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("A module-scope OpVariable with initialization value " - "cannot be marked with the Import Linkage Type.")); -} -TEST_F(ValidateDecorations, LinkageExportUsedForInitializedVariableGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %target LinkageAttributes "link_ptr" Export - %float = OpTypeFloat 32 - %_ptr_float = OpTypePointer Uniform %float - %zero = OpConstantNull %float - %target = OpVariable %_ptr_float Uniform %zero - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, StructAllMembersHaveBuiltInDecorationsGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpMemberDecorate %_struct_1 0 BuiltIn Position - OpMemberDecorate %_struct_1 1 BuiltIn Position - OpMemberDecorate %_struct_1 2 BuiltIn Position - OpMemberDecorate %_struct_1 3 BuiltIn Position - %float = OpTypeFloat 32 -%_runtimearr = OpTypeRuntimeArray %float - %_struct_1 = OpTypeStruct %float %float %float %_runtimearr - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, MixedBuiltInDecorationsBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpMemberDecorate %_struct_1 0 BuiltIn Position - OpMemberDecorate %_struct_1 1 BuiltIn Position - %float = OpTypeFloat 32 -%_runtimearr = OpTypeRuntimeArray %float - %_struct_1 = OpTypeStruct %float %float %float %_runtimearr - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("When BuiltIn decoration is applied to a structure-type " - "member, all members of that structure type must also be " - "decorated with BuiltIn (No allowed mixing of built-in " - "variables and non-built-in variables within a single " - "structure). Structure id 1 does not meet this requirement.")); -} - -TEST_F(ValidateDecorations, StructContainsBuiltInStructBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpMemberDecorate %_struct_1 0 BuiltIn Position - OpMemberDecorate %_struct_1 1 BuiltIn Position - OpMemberDecorate %_struct_1 2 BuiltIn Position - OpMemberDecorate %_struct_1 3 BuiltIn Position - %float = OpTypeFloat 32 -%_runtimearr = OpTypeRuntimeArray %float - %_struct_1 = OpTypeStruct %float %float %float %_runtimearr - %_struct_2 = OpTypeStruct %_struct_1 - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure 1[%_struct_1] contains members with " - "BuiltIn decoration. Therefore this structure may not " - "be contained as a member of another structure type. " - "Structure 4[%_struct_4] contains structure " - "1[%_struct_1].")); -} - -TEST_F(ValidateDecorations, StructContainsNonBuiltInStructGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - %float = OpTypeFloat 32 - %_struct_1 = OpTypeStruct %float - %_struct_2 = OpTypeStruct %_struct_1 - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, MultipleBuiltInObjectsConsumedByOpEntryPointBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Geometry - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %in_1 %in_2 - OpExecutionMode %main InputPoints - OpExecutionMode %main OutputPoints - OpMemberDecorate %struct_1 0 BuiltIn InvocationId - OpMemberDecorate %struct_2 0 BuiltIn Position - %int = OpTypeInt 32 1 - %void = OpTypeVoid - %func = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct_1 = OpTypeStruct %int - %struct_2 = OpTypeStruct %float -%ptr_builtin_1 = OpTypePointer Input %struct_1 -%ptr_builtin_2 = OpTypePointer Input %struct_2 -%in_1 = OpVariable %ptr_builtin_1 Input -%in_2 = OpVariable %ptr_builtin_2 Input - %main = OpFunction %void None %func - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("There must be at most one object per Storage Class " - "that can contain a structure type containing members " - "decorated with BuiltIn, consumed per entry-point.")); -} - -TEST_F(ValidateDecorations, - OneBuiltInObjectPerStorageClassConsumedByOpEntryPointGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Geometry - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %in_1 %out_1 - OpExecutionMode %main InputPoints - OpExecutionMode %main OutputPoints - OpMemberDecorate %struct_1 0 BuiltIn InvocationId - OpMemberDecorate %struct_2 0 BuiltIn Position - %int = OpTypeInt 32 1 - %void = OpTypeVoid - %func = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct_1 = OpTypeStruct %int - %struct_2 = OpTypeStruct %float -%ptr_builtin_1 = OpTypePointer Input %struct_1 -%ptr_builtin_2 = OpTypePointer Output %struct_2 -%in_1 = OpVariable %ptr_builtin_1 Input -%out_1 = OpVariable %ptr_builtin_2 Output - %main = OpFunction %void None %func - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, NoBuiltInObjectsConsumedByOpEntryPointGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Geometry - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %in_1 %out_1 - OpExecutionMode %main InputPoints - OpExecutionMode %main OutputPoints - %int = OpTypeInt 32 1 - %void = OpTypeVoid - %func = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct_1 = OpTypeStruct %int - %struct_2 = OpTypeStruct %float -%ptr_builtin_1 = OpTypePointer Input %struct_1 -%ptr_builtin_2 = OpTypePointer Output %struct_2 -%in_1 = OpVariable %ptr_builtin_1 Input -%out_1 = OpVariable %ptr_builtin_2 Output - %main = OpFunction %void None %func - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, EntryPointFunctionHasLinkageAttributeBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpDecorate %main LinkageAttributes "import_main" Import -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%main = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The LinkageAttributes Decoration (Linkage name: import_main) " - "cannot be applied to function id 1 because it is targeted by " - "an OpEntryPoint instruction.")); -} - -TEST_F(ValidateDecorations, FunctionDeclarationWithoutImportLinkageBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Function declaration (id 3) must have a LinkageAttributes " - "decoration with the Import Linkage type.")); -} - -TEST_F(ValidateDecorations, FunctionDeclarationWithImportLinkageGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %main LinkageAttributes "link_fn" Import - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, FunctionDeclarationWithExportLinkageBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %main LinkageAttributes "link_fn" Export - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Function declaration (id 1) must have a LinkageAttributes " - "decoration with the Import Linkage type.")); -} - -TEST_F(ValidateDecorations, FunctionDefinitionWithImportLinkageBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %main LinkageAttributes "link_fn" Import - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - %label = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Function definition (id 1) may not be decorated with " - "Import Linkage type.")); -} - -TEST_F(ValidateDecorations, FunctionDefinitionWithoutImportLinkageGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - %void = OpTypeVoid - %func = OpTypeFunction %void - %main = OpFunction %void None %func - %label = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, BuiltinVariablesGoodVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %_entryPointOutput Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%float_0 = OpConstant %float 0 -%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %3 -%5 = OpLabel -OpStore %_entryPointOutput %14 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); -} - -TEST_F(ValidateDecorations, BuiltinVariablesWithLocationDecorationVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %gl_FragCoord Location 0 -OpDecorate %_entryPointOutput Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%float_0 = OpConstant %float 0 -%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %3 -%5 = OpLabel -OpStore %_entryPointOutput %14 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("A BuiltIn variable (id 2) cannot have any Location or " - "Component decorations")); -} -TEST_F(ValidateDecorations, BuiltinVariablesWithComponentDecorationVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput -OpExecutionMode %main OriginUpperLeft -OpSource HLSL 500 -OpDecorate %gl_FragCoord BuiltIn FragCoord -OpDecorate %gl_FragCoord Component 0 -OpDecorate %_entryPointOutput Location 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%float_0 = OpConstant %float 0 -%14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_entryPointOutput = OpVariable %_ptr_Output_v4float Output -%main = OpFunction %void None %3 -%5 = OpLabel -OpStore %_entryPointOutput %14 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("A BuiltIn variable (id 2) cannot have any Location or " - "Component decorations")); -} - -// #version 440 -// #extension GL_EXT_nonuniform_qualifier : enable -// layout(binding = 1) uniform sampler2D s2d[]; -// layout(location = 0) in nonuniformEXT int i; -// void main() -// { -// vec4 v = texture(s2d[i], vec2(0.3)); -// } -TEST_F(ValidateDecorations, RuntimeArrayOfDescriptorSetsIsAllowed) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = R"( - OpCapability Shader - OpCapability ShaderNonUniformEXT - OpCapability RuntimeDescriptorArrayEXT - OpCapability SampledImageArrayNonUniformIndexingEXT - OpExtension "SPV_EXT_descriptor_indexing" - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %i - OpSource GLSL 440 - OpSourceExtension "GL_EXT_nonuniform_qualifier" - OpName %main "main" - OpName %v "v" - OpName %s2d "s2d" - OpName %i "i" - OpDecorate %s2d DescriptorSet 0 - OpDecorate %s2d Binding 1 - OpDecorate %i Location 0 - OpDecorate %i NonUniformEXT - OpDecorate %18 NonUniformEXT - OpDecorate %21 NonUniformEXT - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown - %11 = OpTypeSampledImage %10 -%_runtimearr_11 = OpTypeRuntimeArray %11 -%_ptr_Uniform__runtimearr_11 = OpTypePointer Uniform %_runtimearr_11 - %s2d = OpVariable %_ptr_Uniform__runtimearr_11 Uniform - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int - %i = OpVariable %_ptr_Input_int Input -%_ptr_Uniform_11 = OpTypePointer Uniform %11 - %v2float = OpTypeVector %float 2 -%float_0_300000012 = OpConstant %float 0.300000012 - %24 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012 - %float_0 = OpConstant %float 0 - %main = OpFunction %void None %3 - %5 = OpLabel - %v = OpVariable %_ptr_Function_v4float Function - %18 = OpLoad %int %i - %20 = OpAccessChain %_ptr_Uniform_11 %s2d %18 - %21 = OpLoad %11 %20 - %26 = OpImageSampleExplicitLod %v4float %21 %24 Lod %float_0 - OpStore %v %26 - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, BlockMissingOffsetBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be explicitly laid out with Offset decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockMissingOffsetBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be explicitly laid out with Offset decorations")); -} - -TEST_F(ValidateDecorations, BlockNestedStructMissingOffsetBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %S = OpTypeStruct %v3float %int - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be explicitly laid out with Offset decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockNestedStructMissingOffsetBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %S = OpTypeStruct %v3float %int - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be explicitly laid out with Offset decorations")); -} - -TEST_F(ValidateDecorations, BlockGLSLSharedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output Block - OpDecorate %Output GLSLShared - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLShared decoration")); -} - -TEST_F(ValidateDecorations, BufferBlockGLSLSharedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output BufferBlock - OpDecorate %Output GLSLShared - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLShared decoration")); -} - -TEST_F(ValidateDecorations, BlockNestedStructGLSLSharedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %S GLSLShared - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 1 - %S = OpTypeStruct %int - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLShared decoration")); -} - -TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLSharedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %S GLSLShared - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 1 - %S = OpTypeStruct %int - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLShared decoration")); -} - -TEST_F(ValidateDecorations, BlockGLSLPackedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output Block - OpDecorate %Output GLSLPacked - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLPacked decoration")); -} - -TEST_F(ValidateDecorations, BufferBlockGLSLPackedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output BufferBlock - OpDecorate %Output GLSLPacked - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLPacked decoration")); -} - -TEST_F(ValidateDecorations, BlockNestedStructGLSLPackedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %S GLSLPacked - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 1 - %S = OpTypeStruct %int - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLPacked decoration")); -} - -TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLPackedBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpDecorate %S GLSLPacked - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 1 - %S = OpTypeStruct %int - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must not use GLSLPacked decoration")); -} - -TEST_F(ValidateDecorations, BlockMissingArrayStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output Block - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 1 - %int_3 = OpConstant %int 3 - %array = OpTypeArray %float %int_3 - %Output = OpTypeStruct %array -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with ArrayStride decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockMissingArrayStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output BufferBlock - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 1 - %int_3 = OpConstant %int 3 - %array = OpTypeArray %float %int_3 - %Output = OpTypeStruct %array -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with ArrayStride decorations")); -} - -TEST_F(ValidateDecorations, BlockNestedStructMissingArrayStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 1 - %int_3 = OpConstant %int 3 - %array = OpTypeArray %float %int_3 - %S = OpTypeStruct %array - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with ArrayStride decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockNestedStructMissingArrayStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %int = OpTypeInt 32 1 - %int_3 = OpConstant %int 3 - %array = OpTypeArray %float %int_3 - %S = OpTypeStruct %array - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with ArrayStride decorations")); -} - -TEST_F(ValidateDecorations, BlockMissingMatrixStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output Block - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %matrix = OpTypeMatrix %v3float 4 - %Output = OpTypeStruct %matrix -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with MatrixStride decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output BufferBlock - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %matrix = OpTypeMatrix %v3float 4 - %Output = OpTypeStruct %matrix -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with MatrixStride decorations")); -} - -TEST_F(ValidateDecorations, BlockMissingMatrixStrideArrayBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output Block - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %matrix = OpTypeMatrix %v3float 4 - %int = OpTypeInt 32 1 - %int_3 = OpConstant %int 3 - %array = OpTypeArray %matrix %int_3 - %Output = OpTypeStruct %matrix -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with MatrixStride decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideArrayBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %Output BufferBlock - OpMemberDecorate %Output 0 Offset 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %matrix = OpTypeMatrix %v3float 4 - %int = OpTypeInt 32 1 - %int_3 = OpConstant %int 3 - %array = OpTypeArray %matrix %int_3 - %Output = OpTypeStruct %matrix -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with MatrixStride decorations")); -} - -TEST_F(ValidateDecorations, BlockNestedStructMissingMatrixStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %v4float = OpTypeVector %float 4 - %matrix = OpTypeMatrix %v3float 4 - %S = OpTypeStruct %matrix - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with MatrixStride decorations")); -} - -TEST_F(ValidateDecorations, BufferBlockNestedStructMissingMatrixStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 16 - OpMemberDecorate %Output 2 Offset 32 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %v4float = OpTypeVector %float 4 - %matrix = OpTypeMatrix %v3float 4 - %S = OpTypeStruct %matrix - %Output = OpTypeStruct %float %v4float %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("must be explicitly laid out with MatrixStride decorations")); -} - -TEST_F(ValidateDecorations, BlockStandardUniformBufferLayout) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %F 0 Offset 0 - OpMemberDecorate %F 1 Offset 8 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48 - OpMemberDecorate %O 0 Offset 0 - OpMemberDecorate %O 1 Offset 16 - OpMemberDecorate %O 2 Offset 32 - OpMemberDecorate %O 3 Offset 64 - OpMemberDecorate %O 4 ColMajor - OpMemberDecorate %O 4 Offset 80 - OpMemberDecorate %O 4 MatrixStride 16 - OpDecorate %_arr_O_uint_2 ArrayStride 176 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 8 - OpMemberDecorate %Output 2 Offset 16 - OpMemberDecorate %Output 3 Offset 32 - OpMemberDecorate %Output 4 Offset 48 - OpMemberDecorate %Output 5 Offset 64 - OpMemberDecorate %Output 6 ColMajor - OpMemberDecorate %Output 6 Offset 96 - OpMemberDecorate %Output 6 MatrixStride 16 - OpMemberDecorate %Output 7 Offset 128 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %uint = OpTypeInt 32 0 - %v2uint = OpTypeVector %uint 2 - %F = OpTypeStruct %int %v2uint - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 -%mat2v3float = OpTypeMatrix %v3float 2 - %v3uint = OpTypeVector %uint 3 -%mat3v3float = OpTypeMatrix %v3float 3 -%_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2 - %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2 -%_arr_O_uint_2 = OpTypeArray %O %uint_2 - %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2 -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, BlockLayoutPermitsTightVec3ScalarPackingGood) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 12 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %v3float %float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, BlockCantAppearWithinABlockBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 16 - OpMemberDecorate %S2 0 Offset 0 - OpMemberDecorate %S2 1 Offset 12 - OpDecorate %S Block - OpDecorate %S2 Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %S2 = OpTypeStruct %float %float - %S = OpTypeStruct %float %S2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("rules: A Block or BufferBlock cannot be nested within " - "another Block or BufferBlock.")); -} - -TEST_F(ValidateDecorations, BufferblockCantAppearWithinABufferblockBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 16 - OpMemberDecorate %S2 0 Offset 0 - OpMemberDecorate %S2 1 Offset 16 - OpMemberDecorate %S3 0 Offset 0 - OpMemberDecorate %S3 1 Offset 12 - OpDecorate %S BufferBlock - OpDecorate %S3 BufferBlock - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %S3 = OpTypeStruct %float %float - %S2 = OpTypeStruct %float %S3 - %S = OpTypeStruct %float %S2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("rules: A Block or BufferBlock cannot be nested within " - "another Block or BufferBlock.")); -} - -TEST_F(ValidateDecorations, BufferblockCantAppearWithinABlockBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 16 - OpMemberDecorate %S2 0 Offset 0 - OpMemberDecorate %S2 1 Offset 16 - OpMemberDecorate %S3 0 Offset 0 - OpMemberDecorate %S3 1 Offset 12 - OpDecorate %S Block - OpDecorate %S3 BufferBlock - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %S3 = OpTypeStruct %float %float - %S2 = OpTypeStruct %float %S3 - %S = OpTypeStruct %float %S2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("rules: A Block or BufferBlock cannot be nested within " - "another Block or BufferBlock.")); -} - -TEST_F(ValidateDecorations, BlockCantAppearWithinABufferblockBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 16 - OpMemberDecorate %S2 0 Offset 0 - OpMemberDecorate %S2 1 Offset 16 - OpMemberDecorate %S3 0 Offset 0 - OpMemberDecorate %S3 1 Offset 16 - OpMemberDecorate %S4 0 Offset 0 - OpMemberDecorate %S4 1 Offset 12 - OpDecorate %S BufferBlock - OpDecorate %S4 Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %S4 = OpTypeStruct %float %float - %S3 = OpTypeStruct %float %S4 - %S2 = OpTypeStruct %float %S3 - %S = OpTypeStruct %float %S2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("rules: A Block or BufferBlock cannot be nested within " - "another Block or BufferBlock.")); -} - -TEST_F(ValidateDecorations, BlockLayoutForbidsTightScalarVec3PackingBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Structure id 2 decorated as Block for variable in Uniform " - "storage class must follow standard uniform buffer layout " - "rules: member 1 at offset 4 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood) { - // Same as previous test, but with explicit option to relax block layout. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad) { - // Same as previous test, but with the vector not aligned to its scalar - // element. Use offset 5 instead of a multiple of 4. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 5 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 2 decorated as Block for variable in Uniform storage " - "class must follow relaxed uniform buffer layout rules: member 1 at " - "offset 5 is not aligned to scalar element size 4")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good) { - // Same as previous test, but with Vulkan 1.1. Vulkan 1.1 included - // VK_KHR_relaxed_block_layout in core. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood) { - // Same as previous test, but with scalar block layout. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood) { - // The array at offset 4 is ok with scalar block layout. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - OpDecorate %arr_float ArrayStride 4 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 - %float = OpTypeFloat 32 - %arr_float = OpTypeArray %float %uint_3 - %S = OpTypeStruct %float %arr_float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood) { - // The array at offset 4 is ok with scalar block layout, even though - // its elements are vec3. - // This is the same as the previous case, but the array elements are vec3 - // instead of float. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - OpDecorate %arr_vec3 ArrayStride 12 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 - %float = OpTypeFloat 32 - %vec3 = OpTypeVector %float 3 - %arr_vec3 = OpTypeArray %vec3 %uint_3 - %S = OpTypeStruct %float %arr_vec3 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, - BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood) { - // Scalar block layout permits the struct at offset 4, even though - // it contains a vector with base alignment 8 and scalar alignment 4. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpMemberDecorate %st 0 Offset 0 - OpMemberDecorate %st 1 Offset 8 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %vec2 = OpTypeVector %float 2 - %st = OpTypeStruct %vec2 %float - %S = OpTypeStruct %float %st -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F( - ValidateDecorations, - BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood) { - // Scalar block layout permits fields in what would normally be the padding at - // the end of a struct. - std::string spirv = R"( - OpCapability Shader - OpCapability Float64 - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %st 0 Offset 0 - OpMemberDecorate %st 1 Offset 8 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 12 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %double = OpTypeFloat 64 - %st = OpTypeStruct %double %float - %S = OpTypeStruct %st %float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F( - ValidateDecorations, - BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood) { - // Same as previous, but set relaxed block layout first. Scalar layout always - // wins. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %vec4 = OpTypeVector %float 4 - %S = OpTypeStruct %float %vec4 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F( - ValidateDecorations, - BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood) { - // Same as previous, but set scalar block layout first. Scalar layout always - // wins. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %vec4 = OpTypeVector %float 4 - %S = OpTypeStruct %float %vec4 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true); - spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, BufferBlock16bitStandardStorageBufferLayout) { - std::string spirv = R"( - OpCapability Shader - OpCapability StorageUniform16 - OpExtension "SPV_KHR_16bit_storage" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpDecorate %f32arr ArrayStride 4 - OpDecorate %f16arr ArrayStride 2 - OpMemberDecorate %SSBO32 0 Offset 0 - OpMemberDecorate %SSBO16 0 Offset 0 - OpDecorate %SSBO32 BufferBlock - OpDecorate %SSBO16 BufferBlock - %void = OpTypeVoid - %voidf = OpTypeFunction %void - %u32 = OpTypeInt 32 0 - %i32 = OpTypeInt 32 1 - %f32 = OpTypeFloat 32 - %uvec3 = OpTypeVector %u32 3 - %c_i32_32 = OpConstant %i32 32 -%c_i32_128 = OpConstant %i32 128 - %f32arr = OpTypeArray %f32 %c_i32_128 - %f16 = OpTypeFloat 16 - %f16arr = OpTypeArray %f16 %c_i32_128 - %SSBO32 = OpTypeStruct %f32arr - %SSBO16 = OpTypeStruct %f16arr -%_ptr_Uniform_SSBO32 = OpTypePointer Uniform %SSBO32 - %varSSBO32 = OpVariable %_ptr_Uniform_SSBO32 Uniform -%_ptr_Uniform_SSBO16 = OpTypePointer Uniform %SSBO16 - %varSSBO16 = OpVariable %_ptr_Uniform_SSBO16 Uniform - %main = OpFunction %void None %voidf - %label = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, BlockArrayExtendedAlignmentGood) { - // For uniform buffer, Array base alignment is 16, and ArrayStride - // must be a multiple of 16. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 16 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_PushConstant_S = OpTypePointer PushConstant %S - %u = OpVariable %_ptr_PushConstant_S PushConstant - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, BlockArrayBaseAlignmentBad) { - // For uniform buffer, Array base alignment is 16. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 8 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %u = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 3 decorated as Block for variable in Uniform " - "storage class must follow standard uniform buffer layout rules: " - "member 1 at offset 8 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithRelaxedLayoutStillBad) { - // For uniform buffer, Array base alignment is 16, and ArrayStride - // must be a multiple of 16. This case uses relaxed block layout. Relaxed - // layout only relaxes rules for vector alignment, not array alignment. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %u DescriptorSet 0 - OpDecorate %u Binding 0 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 8 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %u = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 4 decorated as Block for variable in Uniform " - "storage class must follow standard uniform buffer layout rules: " - "member 1 at offset 8 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithVulkan1_1StillBad) { - // Same as previous test, but with Vulkan 1.1, which includes - // VK_KHR_relaxed_block_layout in core. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %u DescriptorSet 0 - OpDecorate %u Binding 0 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 8 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %u = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 4 decorated as Block for variable in Uniform " - "storage class must follow relaxed uniform buffer layout rules: " - "member 1 at offset 8 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, - BlockArrayBaseAlignmentWithBlockStandardLayoutGood) { - // Same as previous test, but with VK_KHR_uniform_buffer_standard_layout - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %u DescriptorSet 0 - OpDecorate %u Binding 0 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 8 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_Uniform_S = OpTypePointer Uniform %S - %u = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetUniformBufferStandardLayout(getValidatorOptions(), - true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, VulkanBufferBlockOnStorageBufferBad) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct BufferBlock - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In Vulkan, BufferBlock is disallowed on variables in " - "the StorageBuffer storage class")); -} - -TEST_F(ValidateDecorations, PushConstantArrayBaseAlignmentGood) { - // Tests https://github.com/KhronosGroup/SPIRV-Tools/issues/1664 - // From GLSL vertex shader: - // #version 450 - // layout(push_constant) uniform S { vec2 v; float arr[2]; } u; - // void main() { } - - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 4 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 8 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_PushConstant_S = OpTypePointer PushConstant %S - %u = OpVariable %_ptr_PushConstant_S PushConstant - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, PushConstantArrayBadAlignmentBad) { - // Like the previous test, but with offset 7 instead of 8. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 4 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 7 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_PushConstant_S = OpTypePointer PushConstant %S - %u = OpVariable %_ptr_PushConstant_S PushConstant - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 3 decorated as Block for variable in PushConstant " - "storage class must follow standard storage buffer layout rules: " - "member 1 at offset 7 is not aligned to 4")); -} - -TEST_F(ValidateDecorations, - PushConstantLayoutPermitsTightVec3ScalarPackingGood) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 12 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %v3float %float -%_ptr_PushConstant_S = OpTypePointer PushConstant %S - %B = OpVariable %_ptr_PushConstant_S PushConstant - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, - PushConstantLayoutForbidsTightScalarVec3PackingBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666 - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer PushConstant %S - %B = OpVariable %_ptr_Uniform_S PushConstant - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 2 decorated as Block for variable in PushConstant " - "storage class must follow standard storage buffer layout " - "rules: member 1 at offset 4 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, PushConstantMissingBlockGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %pc = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, VulkanPushConstantMissingBlockBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %pc = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("PushConstant id '2' is missing Block decoration.\n" - "From Vulkan spec, section 14.5.1:\n" - "Such variables must be identified with a Block " - "decoration")); -} - -TEST_F(ValidateDecorations, MultiplePushConstantsSingleEntryPointGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %ptr_float = OpTypePointer PushConstant %float - %pc1 = OpVariable %ptr PushConstant - %pc2 = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpAccessChain %ptr_float %pc1 %int_0 - %3 = OpLoad %float %2 - %4 = OpAccessChain %ptr_float %pc2 %int_0 - %5 = OpLoad %float %4 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, - VulkanMultiplePushConstantsDifferentEntryPointGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "func1" - OpEntryPoint Fragment %2 "func2" - OpExecutionMode %2 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %ptr_float = OpTypePointer PushConstant %float - %pc1 = OpVariable %ptr PushConstant - %pc2 = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label1 = OpLabel - %3 = OpAccessChain %ptr_float %pc1 %int_0 - %4 = OpLoad %float %3 - OpReturn - OpFunctionEnd - - %2 = OpFunction %void None %voidfn - %label2 = OpLabel - %5 = OpAccessChain %ptr_float %pc2 %int_0 - %6 = OpLoad %float %5 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, - VulkanMultiplePushConstantsUnusedSingleEntryPointGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %ptr_float = OpTypePointer PushConstant %float - %pc1 = OpVariable %ptr PushConstant - %pc2 = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, VulkanMultiplePushConstantsSingleEntryPointBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %ptr_float = OpTypePointer PushConstant %float - %pc1 = OpVariable %ptr PushConstant - %pc2 = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpAccessChain %ptr_float %pc1 %int_0 - %3 = OpLoad %float %2 - %4 = OpAccessChain %ptr_float %pc2 %int_0 - %5 = OpLoad %float %4 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Entry point id '1' uses more than one PushConstant interface.\n" - "From Vulkan spec, section 14.5.1:\n" - "There must be no more than one push constant block " - "statically used per shader entry point.")); -} - -TEST_F(ValidateDecorations, - VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "func1" - OpEntryPoint Fragment %2 "func2" - OpExecutionMode %2 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %ptr_float = OpTypePointer PushConstant %float - %pc1 = OpVariable %ptr PushConstant - %pc2 = OpVariable %ptr PushConstant - - %sub1 = OpFunction %void None %voidfn - %label_sub1 = OpLabel - %3 = OpAccessChain %ptr_float %pc1 %int_0 - %4 = OpLoad %float %3 - OpReturn - OpFunctionEnd - - %sub2 = OpFunction %void None %voidfn - %label_sub2 = OpLabel - %5 = OpAccessChain %ptr_float %pc2 %int_0 - %6 = OpLoad %float %5 - OpReturn - OpFunctionEnd - - %1 = OpFunction %void None %voidfn - %label1 = OpLabel - %call1 = OpFunctionCall %void %sub1 - OpReturn - OpFunctionEnd - - %2 = OpFunction %void None %voidfn - %label2 = OpLabel - %call2 = OpFunctionCall %void %sub2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, - VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %ptr_float = OpTypePointer PushConstant %float - %pc1 = OpVariable %ptr PushConstant - %pc2 = OpVariable %ptr PushConstant - - %sub1 = OpFunction %void None %voidfn - %label_sub1 = OpLabel - %3 = OpAccessChain %ptr_float %pc1 %int_0 - %4 = OpLoad %float %3 - OpReturn - OpFunctionEnd - - %sub2 = OpFunction %void None %voidfn - %label_sub2 = OpLabel - %5 = OpAccessChain %ptr_float %pc2 %int_0 - %6 = OpLoad %float %5 - OpReturn - OpFunctionEnd - - %1 = OpFunction %void None %voidfn - %label1 = OpLabel - %call1 = OpFunctionCall %void %sub1 - %call2 = OpFunctionCall %void %sub2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Entry point id '1' uses more than one PushConstant interface.\n" - "From Vulkan spec, section 14.5.1:\n" - "There must be no more than one push constant block " - "statically used per shader entry point.")); -} - -TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer Uniform %struct -%ptr_float = OpTypePointer Uniform %float - %var = OpVariable %ptr Uniform - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpAccessChain %ptr_float %var %int_0 - %3 = OpLoad %float %2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Uniform id '3' is missing DescriptorSet decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - OpDecorate %var DescriptorSet 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer Uniform %struct -%ptr_float = OpTypePointer Uniform %float - %var = OpVariable %ptr Uniform - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpAccessChain %ptr_float %var %int_0 - %3 = OpLoad %float %2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Uniform id '3' is missing Binding decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %sampler = OpTypeSampler - %ptr = OpTypePointer UniformConstant %sampler - %var = OpVariable %ptr UniformConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpLoad %sampler %var - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("UniformConstant id '2' is missing DescriptorSet decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %var DescriptorSet 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %sampler = OpTypeSampler - %ptr = OpTypePointer UniformConstant %sampler - %var = OpVariable %ptr UniformConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpLoad %sampler %var - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("UniformConstant id '2' is missing Binding decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer -%ptr_float = OpTypePointer StorageBuffer %float - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpAccessChain %ptr_float %var %int_0 - %3 = OpLoad %float %2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpDecorate %var DescriptorSet 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer -%ptr_float = OpTypePointer StorageBuffer %float - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %2 = OpAccessChain %ptr_float %var %int_0 - %3 = OpLoad %float %2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("StorageBuffer id '3' is missing Binding decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, - VulkanStorageBufferMissingDescriptorSetSubFunctionBad) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer -%ptr_float = OpTypePointer StorageBuffer %float - %int = OpTypeInt 32 0 - %int_0 = OpConstant %int 0 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - %call = OpFunctionCall %void %2 - OpReturn - OpFunctionEnd - %2 = OpFunction %void None %voidfn - %label2 = OpLabel - %3 = OpAccessChain %ptr_float %var %int_0 - %4 = OpLoad %float %3 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n" - "From Vulkan spec, section 14.5.2:\n" - "These variables must have DescriptorSet and Binding " - "decorations specified")); -} - -TEST_F(ValidateDecorations, - VulkanStorageBufferMissingDescriptorAndBindingUnusedGood) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer Uniform %struct - %var = OpVariable %ptr Uniform - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, UniformMissingBindingGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - OpDecorate %var DescriptorSet 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer Uniform %struct - %var = OpVariable %ptr Uniform - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %sampler = OpTypeSampler - %ptr = OpTypePointer UniformConstant %sampler - %var = OpVariable %ptr UniformConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, UniformConstantMissingBindingGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %var DescriptorSet 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %sampler = OpTypeSampler - %ptr = OpTypePointer UniformConstant %sampler - %var = OpVariable %ptr UniformConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct BufferBlock - OpDecorate %var Binding 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, StorageBufferMissingBindingGood) { - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct BufferBlock - OpDecorate %var DescriptorSet 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer StorageBuffer %struct - %var = OpVariable %ptr StorageBuffer - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood) { - // Spot check buffer rules when using StorageBuffer storage class with Block - // decoration. - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 4 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 8 - OpDecorate %S Block - OpDecorate %u DescriptorSet 0 - OpDecorate %u Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_Uniform_S = OpTypePointer StorageBuffer %S - %u = OpVariable %_ptr_Uniform_S StorageBuffer - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBadAlignmentBad) { - // Like the previous test, but with offset 7. - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpDecorate %_arr_float_uint_2 ArrayStride 4 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 7 - OpDecorate %S Block - OpDecorate %u DescriptorSet 0 - OpDecorate %u Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %S = OpTypeStruct %v2float %_arr_float_uint_2 -%_ptr_Uniform_S = OpTypePointer StorageBuffer %S - %u = OpVariable %_ptr_Uniform_S StorageBuffer - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 3 decorated as Block for variable in StorageBuffer " - "storage class must follow standard storage buffer layout rules: " - "member 1 at offset 7 is not aligned to 4")); -} - -TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayout) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %F 0 Offset 0 - OpMemberDecorate %F 1 Offset 8 - OpDecorate %_arr_float_uint_2 ArrayStride 4 - OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48 - OpMemberDecorate %O 0 Offset 0 - OpMemberDecorate %O 1 Offset 16 - OpMemberDecorate %O 2 Offset 24 - OpMemberDecorate %O 3 Offset 32 - OpMemberDecorate %O 4 ColMajor - OpMemberDecorate %O 4 Offset 48 - OpMemberDecorate %O 4 MatrixStride 16 - OpDecorate %_arr_O_uint_2 ArrayStride 144 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 8 - OpMemberDecorate %Output 2 Offset 16 - OpMemberDecorate %Output 3 Offset 32 - OpMemberDecorate %Output 4 Offset 48 - OpMemberDecorate %Output 5 Offset 52 - OpMemberDecorate %Output 6 ColMajor - OpMemberDecorate %Output 6 Offset 64 - OpMemberDecorate %Output 6 MatrixStride 16 - OpMemberDecorate %Output 7 Offset 96 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %uint = OpTypeInt 32 0 - %v2uint = OpTypeVector %uint 2 - %F = OpTypeStruct %int %v2uint - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 -%mat2v3float = OpTypeMatrix %v3float 2 - %v3uint = OpTypeVector %uint 3 -%mat3v3float = OpTypeMatrix %v3float 3 -%_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2 - %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2 -%_arr_O_uint_2 = OpTypeArray %O %uint_2 - %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2 -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, - StorageBufferLayoutPermitsTightVec3ScalarPackingGood) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666 - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 12 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %v3float %float -%_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S - %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, - StorageBufferLayoutForbidsTightScalarVec3PackingBad) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666 - std::string spirv = R"( - OpCapability Shader - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S - %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 2 decorated as Block for variable in StorageBuffer " - "storage class must follow standard storage buffer layout " - "rules: member 1 at offset 4 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, - BlockStandardUniformBufferLayoutIncorrectOffset0Bad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %F 0 Offset 0 - OpMemberDecorate %F 1 Offset 8 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48 - OpMemberDecorate %O 0 Offset 0 - OpMemberDecorate %O 1 Offset 16 - OpMemberDecorate %O 2 Offset 24 - OpMemberDecorate %O 3 Offset 33 - OpMemberDecorate %O 4 ColMajor - OpMemberDecorate %O 4 Offset 80 - OpMemberDecorate %O 4 MatrixStride 16 - OpDecorate %_arr_O_uint_2 ArrayStride 176 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 8 - OpMemberDecorate %Output 2 Offset 16 - OpMemberDecorate %Output 3 Offset 32 - OpMemberDecorate %Output 4 Offset 48 - OpMemberDecorate %Output 5 Offset 64 - OpMemberDecorate %Output 6 ColMajor - OpMemberDecorate %Output 6 Offset 96 - OpMemberDecorate %Output 6 MatrixStride 16 - OpMemberDecorate %Output 7 Offset 128 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %uint = OpTypeInt 32 0 - %v2uint = OpTypeVector %uint 2 - %F = OpTypeStruct %int %v2uint - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 -%mat2v3float = OpTypeMatrix %v3float 2 - %v3uint = OpTypeVector %uint 3 -%mat3v3float = OpTypeMatrix %v3float 3 -%_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2 - %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2 -%_arr_O_uint_2 = OpTypeArray %O %uint_2 - %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2 -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Structure id 6 decorated as Block for variable in Uniform " - "storage class must follow standard uniform buffer layout " - "rules: member 2 at offset 152 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, - BlockStandardUniformBufferLayoutIncorrectOffset1Bad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %F 0 Offset 0 - OpMemberDecorate %F 1 Offset 8 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48 - OpMemberDecorate %O 0 Offset 0 - OpMemberDecorate %O 1 Offset 16 - OpMemberDecorate %O 2 Offset 32 - OpMemberDecorate %O 3 Offset 64 - OpMemberDecorate %O 4 ColMajor - OpMemberDecorate %O 4 Offset 80 - OpMemberDecorate %O 4 MatrixStride 16 - OpDecorate %_arr_O_uint_2 ArrayStride 176 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 8 - OpMemberDecorate %Output 2 Offset 16 - OpMemberDecorate %Output 3 Offset 32 - OpMemberDecorate %Output 4 Offset 48 - OpMemberDecorate %Output 5 Offset 71 - OpMemberDecorate %Output 6 ColMajor - OpMemberDecorate %Output 6 Offset 96 - OpMemberDecorate %Output 6 MatrixStride 16 - OpMemberDecorate %Output 7 Offset 128 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %uint = OpTypeInt 32 0 - %v2uint = OpTypeVector %uint 2 - %F = OpTypeStruct %int %v2uint - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 -%mat2v3float = OpTypeMatrix %v3float 2 - %v3uint = OpTypeVector %uint 3 -%mat3v3float = OpTypeMatrix %v3float 3 -%_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2 - %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2 -%_arr_O_uint_2 = OpTypeArray %O %uint_2 - %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2 -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Structure id 8 decorated as Block for variable in Uniform " - "storage class must follow standard uniform buffer layout " - "rules: member 5 at offset 71 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, BlockUniformBufferLayoutIncorrectArrayStrideBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %F 0 Offset 0 - OpMemberDecorate %F 1 Offset 8 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 49 - OpMemberDecorate %O 0 Offset 0 - OpMemberDecorate %O 1 Offset 16 - OpMemberDecorate %O 2 Offset 32 - OpMemberDecorate %O 3 Offset 64 - OpMemberDecorate %O 4 ColMajor - OpMemberDecorate %O 4 Offset 80 - OpMemberDecorate %O 4 MatrixStride 16 - OpDecorate %_arr_O_uint_2 ArrayStride 176 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 8 - OpMemberDecorate %Output 2 Offset 16 - OpMemberDecorate %Output 3 Offset 32 - OpMemberDecorate %Output 4 Offset 48 - OpMemberDecorate %Output 5 Offset 64 - OpMemberDecorate %Output 6 ColMajor - OpMemberDecorate %Output 6 Offset 96 - OpMemberDecorate %Output 6 MatrixStride 16 - OpMemberDecorate %Output 7 Offset 128 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %v3float = OpTypeVector %float 3 - %int = OpTypeInt 32 1 - %uint = OpTypeInt 32 0 - %v2uint = OpTypeVector %uint 2 - %F = OpTypeStruct %int %v2uint - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 -%mat2v3float = OpTypeMatrix %v3float 2 - %v3uint = OpTypeVector %uint 3 -%mat3v3float = OpTypeMatrix %v3float 3 -%_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2 - %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2 -%_arr_O_uint_2 = OpTypeArray %O %uint_2 - %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2 -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 6 decorated as Block for variable in Uniform storage " - "class must follow standard uniform buffer layout rules: member 4 " - "contains " - "an array with stride 49 not satisfying alignment to 16")); -} - -TEST_F(ValidateDecorations, - BufferBlockStandardStorageBufferLayoutImproperStraddleBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 8 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %Output = OpTypeStruct %float %v3float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Structure id 3 decorated as BufferBlock for variable in " - "Uniform storage class must follow standard storage buffer " - "layout rules: member 1 at offset 8 is not aligned to 16")); -} - -TEST_F(ValidateDecorations, - BlockUniformBufferLayoutOffsetInsideArrayPaddingBad) { - // In this case the 2nd member fits entirely within the padding. - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpDecorate %_arr_float_uint_2 ArrayStride 16 - OpMemberDecorate %Output 0 Offset 0 - OpMemberDecorate %Output 1 Offset 20 - OpDecorate %Output Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 - %v2uint = OpTypeVector %uint 2 - %uint_2 = OpConstant %uint 2 -%_arr_float_uint_2 = OpTypeArray %float %uint_2 - %Output = OpTypeStruct %_arr_float_uint_2 %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 4 decorated as Block for variable in Uniform storage " - "class must follow standard uniform buffer layout rules: member 1 at " - "offset 20 overlaps previous member ending at offset 31")); -} - -TEST_F(ValidateDecorations, - BlockUniformBufferLayoutOffsetInsideStructPaddingBad) { - // In this case the 2nd member fits entirely within the padding. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpMemberDecorate %_struct_6 0 Offset 0 - OpMemberDecorate %_struct_2 0 Offset 0 - OpMemberDecorate %_struct_2 1 Offset 4 - OpDecorate %_struct_2 Block - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 - %_struct_6 = OpTypeStruct %float - %_struct_2 = OpTypeStruct %_struct_6 %float -%_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2 - %8 = OpVariable %_ptr_Uniform__struct_2 Uniform - %1 = OpFunction %void None %4 - %9 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 3 decorated as Block for variable in Uniform storage " - "class must follow standard uniform buffer layout rules: member 1 at " - "offset 4 overlaps previous member ending at offset 15")); -} - -TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodUniversal1_0) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpMemberDecorate %Outer 0 Offset 4 - OpMemberDecorate %Outer 1 Offset 0 - OpDecorate %Outer Block - OpDecorate %O DescriptorSet 0 - OpDecorate %O Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %Outer = OpTypeStruct %uint %uint -%_ptr_Uniform_Outer = OpTypePointer Uniform %Outer - %O = OpVariable %_ptr_Uniform_Outer Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0)); -} - -TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodOpenGL4_5) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpMemberDecorate %Outer 0 Offset 4 - OpMemberDecorate %Outer 1 Offset 0 - OpDecorate %Outer Block - OpDecorate %O DescriptorSet 0 - OpDecorate %O Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %Outer = OpTypeStruct %uint %uint -%_ptr_Uniform_Outer = OpTypePointer Uniform %Outer - %O = OpVariable %_ptr_Uniform_Outer Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_OPENGL_4_5)); -} - -TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodVulkan1_1) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpMemberDecorate %Outer 0 Offset 4 - OpMemberDecorate %Outer 1 Offset 0 - OpDecorate %Outer Block - OpDecorate %O DescriptorSet 0 - OpDecorate %O Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %Outer = OpTypeStruct %uint %uint -%_ptr_Uniform_Outer = OpTypePointer Uniform %Outer - %O = OpVariable %_ptr_Uniform_Outer Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)) - << getDiagnosticString(); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, BlockLayoutOffsetOverlapBad) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpMemberDecorate %Outer 0 Offset 0 - OpMemberDecorate %Outer 1 Offset 16 - OpMemberDecorate %Inner 0 Offset 0 - OpMemberDecorate %Inner 1 Offset 16 - OpDecorate %Outer Block - OpDecorate %O DescriptorSet 0 - OpDecorate %O Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %Inner = OpTypeStruct %uint %uint - %Outer = OpTypeStruct %Inner %uint -%_ptr_Uniform_Outer = OpTypePointer Uniform %Outer - %O = OpVariable %_ptr_Uniform_Outer Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 3 decorated as Block for variable in Uniform storage " - "class must follow standard uniform buffer layout rules: member 1 at " - "offset 16 overlaps previous member ending at offset 31")); -} - -TEST_F(ValidateDecorations, BufferBlockEmptyStruct) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpMemberDecorate %Output 0 Offset 0 - OpDecorate %Output BufferBlock - %void = OpTypeVoid - %3 = OpTypeFunction %void - %S = OpTypeStruct - %Output = OpTypeStruct %S -%_ptr_Uniform_Output = OpTypePointer Uniform %Output - %dataOutput = OpVariable %_ptr_Uniform_Output Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, RowMajorMatrixTightPackingGood) { - // Row major matrix rule: - // A row-major matrix of C columns has a base alignment equal to - // the base alignment of a vector of C matrix components. - // Note: The "matrix component" is the scalar element type. - - // The matrix has 3 columns and 2 rows (C=3, R=2). - // So the base alignment of b is the same as a vector of 3 floats, which is 16 - // bytes. The matrix consists of two of these, and therefore occupies 2 x 16 - // bytes, or 32 bytes. - // - // So the offsets can be: - // a -> 0 - // b -> 16 - // c -> 48 - // d -> 60 ; d fits at bytes 12-15 after offset of c. Tight (vec3;float) - // packing - - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpSource GLSL 450 - OpMemberDecorate %_struct_2 0 Offset 0 - OpMemberDecorate %_struct_2 1 RowMajor - OpMemberDecorate %_struct_2 1 Offset 16 - OpMemberDecorate %_struct_2 1 MatrixStride 16 - OpMemberDecorate %_struct_2 2 Offset 48 - OpMemberDecorate %_struct_2 3 Offset 60 - OpDecorate %_struct_2 Block - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%mat3v2float = OpTypeMatrix %v2float 3 - %v3float = OpTypeVector %float 3 - %_struct_2 = OpTypeStruct %v4float %mat3v2float %v3float %float -%_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2 - %3 = OpVariable %_ptr_Uniform__struct_2 Uniform - %1 = OpFunction %void None %5 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixTightPackingGood) { - // Like the previous case, but we have an array of arrays of matrices. - // The RowMajor decoration goes on the struct member (surprisingly). - - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpSource GLSL 450 - OpMemberDecorate %_struct_2 0 Offset 0 - OpMemberDecorate %_struct_2 1 RowMajor - OpMemberDecorate %_struct_2 1 Offset 16 - OpMemberDecorate %_struct_2 1 MatrixStride 16 - OpMemberDecorate %_struct_2 2 Offset 80 - OpMemberDecorate %_struct_2 3 Offset 92 - OpDecorate %arr_mat ArrayStride 32 - OpDecorate %arr_arr_mat ArrayStride 32 - OpDecorate %_struct_2 Block - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%mat3v2float = OpTypeMatrix %v2float 3 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 - %arr_mat = OpTypeArray %mat3v2float %uint_1 -%arr_arr_mat = OpTypeArray %arr_mat %uint_2 - %v3float = OpTypeVector %float 3 - %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float -%_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2 - %3 = OpVariable %_ptr_Uniform__struct_2 Uniform - %1 = OpFunction %void None %5 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()) - << getDiagnosticString(); -} - -TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixNextMemberOverlapsBad) { - // Like the previous case, but the offset of member 2 overlaps the matrix. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpSource GLSL 450 - OpMemberDecorate %_struct_2 0 Offset 0 - OpMemberDecorate %_struct_2 1 RowMajor - OpMemberDecorate %_struct_2 1 Offset 16 - OpMemberDecorate %_struct_2 1 MatrixStride 16 - OpMemberDecorate %_struct_2 2 Offset 64 - OpMemberDecorate %_struct_2 3 Offset 92 - OpDecorate %arr_mat ArrayStride 32 - OpDecorate %arr_arr_mat ArrayStride 32 - OpDecorate %_struct_2 Block - OpDecorate %3 DescriptorSet 0 - OpDecorate %3 Binding 0 - %void = OpTypeVoid - %5 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %v2float = OpTypeVector %float 2 -%mat3v2float = OpTypeMatrix %v2float 3 -%uint = OpTypeInt 32 0 -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 - %arr_mat = OpTypeArray %mat3v2float %uint_1 -%arr_arr_mat = OpTypeArray %arr_mat %uint_2 - %v3float = OpTypeVector %float 3 - %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float -%_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2 - %3 = OpVariable %_ptr_Uniform__struct_2 Uniform - %1 = OpFunction %void None %5 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 2 decorated as Block for variable in Uniform storage " - "class must follow standard uniform buffer layout rules: member 2 at " - "offset 64 overlaps previous member ending at offset 79")); -} - -TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGood) { - // Original GLSL - - // #version 450 - // layout (set=0,binding=0) buffer S { - // uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12 - // uint i; // Can have offset 60 = 3x16 + 12 - // } B; - // void main() {} - - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpDecorate %_arr_v3uint_uint_2 ArrayStride 16 - OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32 - OpMemberDecorate %_struct_4 0 Offset 0 - OpMemberDecorate %_struct_4 1 Offset 60 - OpDecorate %_struct_4 BufferBlock - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - %void = OpTypeVoid - %7 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 - %uint_2 = OpConstant %uint 2 -%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2 -%_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2 - %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 - %5 = OpVariable %_ptr_Uniform__struct_4 Uniform - %1 = OpFunction %void None %7 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad) { - // Like previous but, the offset of the second member is too small. - - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpDecorate %_arr_v3uint_uint_2 ArrayStride 16 - OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32 - OpMemberDecorate %_struct_4 0 Offset 0 - OpMemberDecorate %_struct_4 1 Offset 56 - OpDecorate %_struct_4 BufferBlock - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - %void = OpTypeVoid - %7 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 - %uint_2 = OpConstant %uint 2 -%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2 -%_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2 - %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 - %5 = OpVariable %_ptr_Uniform__struct_4 Uniform - %1 = OpFunction %void None %7 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure id 4 decorated as BufferBlock for variable " - "in Uniform storage class must follow standard storage " - "buffer layout rules: member 1 at offset 56 overlaps " - "previous member ending at offset 59")); -} - -TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood) { - // Like the corresponding buffer block case, but the array padding must - // count for the last element as well, and so the offset of the second - // member must be at least 64. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpDecorate %_arr_v3uint_uint_2 ArrayStride 16 - OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32 - OpMemberDecorate %_struct_4 0 Offset 0 - OpMemberDecorate %_struct_4 1 Offset 64 - OpDecorate %_struct_4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - %void = OpTypeVoid - %7 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 - %uint_2 = OpConstant %uint 2 -%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2 -%_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2 - %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 - %5 = OpVariable %_ptr_Uniform__struct_4 Uniform - %1 = OpFunction %void None %7 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) { - // Like previous but, the offset of the second member is too small. - - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpDecorate %_arr_v3uint_uint_2 ArrayStride 16 - OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32 - OpMemberDecorate %_struct_4 0 Offset 0 - OpMemberDecorate %_struct_4 1 Offset 60 - OpDecorate %_struct_4 Block - OpDecorate %5 DescriptorSet 0 - OpDecorate %5 Binding 0 - %void = OpTypeVoid - %7 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 - %uint_2 = OpConstant %uint 2 -%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2 -%_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2 - %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 - %5 = OpVariable %_ptr_Uniform__struct_4 Uniform - %1 = OpFunction %void None %7 - %12 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure id 4 decorated as Block for variable in Uniform storage " - "class must follow standard uniform buffer layout rules: member 1 at " - "offset 60 overlaps previous member ending at offset 63")); -} - -TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout) { - // Checks that block layout is not verified in skipping block layout mode. - // Even for obviously wrong layout. - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 3 ; wrong alignment - OpMemberDecorate %S 1 Offset 3 ; same offset as before! - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetSkipBlockLayout(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" %var -OpExecutionMode %1 OriginUpperLeft -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr_int_Workgroup = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int_Workgroup Workgroup -%func_ty = OpTypeFunction %void -%1 = OpFunction %void None %func_ty -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpEntryPoint interfaces must be OpVariables with " - "Storage Class of Input(1) or Output(3). Found Storage " - "Class 4 for Entry Point id 1.")); -} - -TEST_F(ValidateDecorations, VulkanMemoryModelNonCoherent) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical VulkanKHR -OpDecorate %1 Coherent -%2 = OpTypeInt 32 0 -%3 = OpTypePointer StorageBuffer %2 -%1 = OpVariable %3 StorageBuffer -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Coherent decoration targeting 1[%1] is " - "banned when using the Vulkan memory model.")); -} - -TEST_F(ValidateDecorations, VulkanMemoryModelNoCoherentMember) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpMemberDecorate %1 0 Coherent -%2 = OpTypeInt 32 0 -%1 = OpTypeStruct %2 %2 -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Coherent decoration targeting 1[%_struct_1] (member index 0) " - "is banned when using the Vulkan memory model.")); -} - -TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical VulkanKHR -OpDecorate %1 Volatile -%2 = OpTypeInt 32 0 -%3 = OpTypePointer StorageBuffer %2 -%1 = OpVariable %3 StorageBuffer -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Volatile decoration targeting 1[%1] is banned when " - "using the Vulkan memory model.")); -} - -TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatileMember) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpMemberDecorate %1 1 Volatile -%2 = OpTypeInt 32 0 -%1 = OpTypeStruct %2 %2 -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Volatile decoration targeting 1[%_struct_1] (member " - "index 1) is banned when using the Vulkan memory " - "model.")); -} - -TEST_F(ValidateDecorations, FPRoundingModeGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%float_1_25 = OpConstant %float 1.25 -%half_ptr = OpTypePointer StorageBuffer %half -%half_ptr_var = OpVariable %half_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %half %float_1_25 -OpStore %half_ptr_var %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, FPRoundingModeVectorGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%v2half = OpTypeVector %half 2 -%v2float = OpTypeVector %float 2 -%float_1_25 = OpConstant %float 1.25 -%floats = OpConstantComposite %v2float %float_1_25 %float_1_25 -%halfs_ptr = OpTypePointer StorageBuffer %v2half -%halfs_ptr_var = OpVariable %halfs_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %v2half %floats -OpStore %halfs_ptr_var %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, FPRoundingModeNotOpFConvert) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%short = OpTypeInt 16 1 -%int = OpTypeInt 32 1 -%int_17 = OpConstant %int 17 -%short_ptr = OpTypePointer StorageBuffer %short -%short_ptr_var = OpVariable %short_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpSConvert %short %int_17 -OpStore %short_ptr_var %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("FPRoundingMode decoration can be applied only to a " - "width-only conversion instruction for floating-point " - "object.")); -} - -TEST_F(ValidateDecorations, FPRoundingModeNoOpStoreGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%float_1_25 = OpConstant %float 1.25 -%half_ptr = OpTypePointer StorageBuffer %half -%half_ptr_var = OpVariable %half_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %half %float_1_25 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, FPRoundingModeFConvert64to16Good) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpCapability Float64 -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%half = OpTypeFloat 16 -%double = OpTypeFloat 64 -%double_1_25 = OpConstant %double 1.25 -%half_ptr = OpTypePointer StorageBuffer %half -%half_ptr_var = OpVariable %half_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %half %double_1_25 -OpStore %half_ptr_var %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, FPRoundingModeNotStoreInFloat16) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpCapability Float64 -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%float = OpTypeFloat 32 -%double = OpTypeFloat 64 -%double_1_25 = OpConstant %double 1.25 -%float_ptr = OpTypePointer StorageBuffer %float -%float_ptr_var = OpVariable %float_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %float %double_1_25 -OpStore %float_ptr_var %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("FPRoundingMode decoration can be applied only to the " - "Object operand of an OpStore storing through a " - "pointer to a 16-bit floating-point scalar or vector object.")); -} - -TEST_F(ValidateDecorations, FPRoundingModeMultipleOpStoreGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%float_1_25 = OpConstant %float 1.25 -%half_ptr = OpTypePointer StorageBuffer %half -%half_ptr_var_0 = OpVariable %half_ptr StorageBuffer -%half_ptr_var_1 = OpVariable %half_ptr StorageBuffer -%half_ptr_var_2 = OpVariable %half_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %half %float_1_25 -OpStore %half_ptr_var_0 %_ -OpStore %half_ptr_var_1 %_ -OpStore %half_ptr_var_2 %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, FPRoundingModeMultipleUsesBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%float_1_25 = OpConstant %float 1.25 -%half_ptr = OpTypePointer StorageBuffer %half -%half_ptr_var_0 = OpVariable %half_ptr StorageBuffer -%half_ptr_var_1 = OpVariable %half_ptr StorageBuffer -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%_ = OpFConvert %half %float_1_25 -OpStore %half_ptr_var_0 %_ -%result = OpFAdd %half %_ %_ -OpStore %half_ptr_var_1 %_ -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("FPRoundingMode decoration can be applied only to the " - "Object operand of an OpStore.")); -} - -TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpDecorationGroup -OpGroupDecorate %1 %1 -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpGroupDecorate may not target OpDecorationGroup " - "'1[%1]'")); -} - -TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup2) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%1 = OpDecorationGroup -OpGroupDecorate %1 %2 %1 -%2 = OpTypeVoid -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpGroupDecorate may not target OpDecorationGroup " - "'1[%1]'")); -} - -TEST_F(ValidateDecorations, RecurseThroughRuntimeArray) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %outer Block -OpMemberDecorate %inner 0 Offset 0 -OpMemberDecorate %inner 1 Offset 1 -OpDecorate %runtime ArrayStride 16 -OpMemberDecorate %outer 0 Offset 0 -%int = OpTypeInt 32 0 -%inner = OpTypeStruct %int %int -%runtime = OpTypeRuntimeArray %inner -%outer = OpTypeStruct %runtime -%outer_ptr = OpTypePointer Uniform %outer -%var = OpVariable %outer_ptr Uniform -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Structure id 2 decorated as Block for variable in Uniform " - "storage class must follow standard uniform buffer layout " - "rules: member 1 at offset 1 is not aligned to 4")); -} - -TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpMemberDecorate %struct 1 Offset 16 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%empty = OpTypeStruct -%struct = OpTypeStruct %float %empty -%ptr_struct_ubo = OpTypePointer Uniform %struct -%var = OpVariable %ptr_struct_ubo Uniform -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Uniform and UniformId decorations - -TEST_F(ValidateDecorations, UniformDecorationGood) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %int0 Uniform -OpDecorate %var Uniform -OpDecorate %val Uniform -%void = OpTypeVoid -%int = OpTypeInt 32 1 -%int0 = OpConstantNull %int -%intptr = OpTypePointer Private %int -%var = OpVariable %intptr Private -%fn = OpTypeFunction %void -%main = OpFunction %void None %fn -%entry = OpLabel -%val = OpLoad %int %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -// Returns SPIR-V assembly for a shader that uses a given decoration -// instruction. -std::string ShaderWithUniformLikeDecoration(const std::string& inst) { - return std::string(R"( -OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpName %subgroupscope "subgroupscope" -OpName %call "call" -OpName %myfunc "myfunc" -OpName %int0 "int0" -OpName %float0 "float0" -OpName %fn "fn" -)") + inst + - R"( -%void = OpTypeVoid -%float = OpTypeFloat 32 -%int = OpTypeInt 32 1 -%int0 = OpConstantNull %int -%int_99 = OpConstant %int 99 -%subgroupscope = OpConstant %int 3 -%float0 = OpConstantNull %float -%fn = OpTypeFunction %void -%myfunc = OpFunction %void None %fn -%myfuncentry = OpLabel -OpReturn -OpFunctionEnd -%main = OpFunction %void None %fn -%entry = OpLabel -%call = OpFunctionCall %void %myfunc -OpReturn -OpFunctionEnd -)"; -} - -TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13Bad) { - const std::string spirv = ShaderWithUniformLikeDecoration( - "OpDecorateId %int0 UniformId %subgroupscope"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_WRONG_VERSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires SPIR-V version 1.4 or later\n" - " OpDecorateId %int0 UniformId %subgroupscope")) - << spirv; -} - -TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13BadTargetV14) { - const std::string spirv = ShaderWithUniformLikeDecoration( - "OpDecorateId %int0 UniformId %subgroupscope"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_WRONG_VERSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires SPIR-V version 1.4 or later")); -} - -TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV14Good) { - const std::string spirv = ShaderWithUniformLikeDecoration( - "OpDecorateId %int0 UniformId %subgroupscope"); - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, UniformDecorationTargetsTypeBad) { - const std::string spirv = - ShaderWithUniformLikeDecoration("OpDecorate %fn Uniform"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Uniform decoration applied to a non-object")); - EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void")); -} - -TEST_F(ValidateDecorations, UniformIdDecorationTargetsTypeBad) { - const std::string spirv = ShaderWithUniformLikeDecoration( - "OpDecorateId %fn UniformId %subgroupscope"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("UniformId decoration applied to a non-object")); - EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void")); -} - -TEST_F(ValidateDecorations, UniformDecorationTargetsVoidValueBad) { - const std::string spirv = - ShaderWithUniformLikeDecoration("OpDecorate %call Uniform"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Uniform decoration applied to a value with void type\n" - " %call = OpFunctionCall %void %myfunc")); -} - -TEST_F(ValidateDecorations, UniformIdDecorationTargetsVoidValueBad) { - const std::string spirv = ShaderWithUniformLikeDecoration( - "OpDecorateId %call UniformId %subgroupscope"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)) - << spirv; - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("UniformId decoration applied to a value with void type\n" - " %call = OpFunctionCall %void %myfunc")); -} - -TEST_F(ValidateDecorations, - UniformDecorationWithScopeIdV14IdIsFloatValueIsBad) { - const std::string spirv = - ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %float0"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ConstantNull: expected scope to be a 32-bit int")); -} - -TEST_F(ValidateDecorations, - UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad) { - const std::string spirv = - ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int_99"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid scope value:\n %int_99 = OpConstant %int 99\n")); -} - -TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) { - const std::string spirv = - ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int0"); - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(": in Vulkan environment Execution Scope is limited to " - "Workgroup and Subgroup")); -} - -TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad) { - const std::string spirv = - ShaderWithUniformLikeDecoration("OpDecorateId %int0 Uniform"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Decorations that don't take ID parameters may not be " - "used with OpDecorateId\n" - " OpDecorateId %int0 Uniform")); -} - -TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad) { - const std::string spirv = ShaderWithUniformLikeDecoration( - "OpDecorate %int0 UniformId %subgroupscope"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Decorations taking ID parameters may not be used with OpDecorateId\n" - " OpDecorate %int0 UniformId %subgroupscope")); -} - -TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID '2', member '0' decorated with Offset multiple " - "times is not allowed.")); -} - -TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %array ArrayStride 4 - OpDecorate %array ArrayStride 4 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 - %uint_4 = OpConstant %uint 4 - %array = OpTypeArray %float %uint_4 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID '2' decorated with ArrayStride multiple " - "times is not allowed.")); -} - -TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - OpMemberDecorate %struct 0 ColMajor - OpMemberDecorate %struct 0 MatrixStride 16 - OpMemberDecorate %struct 0 MatrixStride 16 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %fvec4 = OpTypeVector %float 4 - %fmat4 = OpTypeMatrix %fvec4 4 - %struct = OpTypeStruct %fmat4 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID '2', member '0' decorated with MatrixStride " - "multiple times is not allowed.")); -} - -TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - OpMemberDecorate %struct 0 MatrixStride 16 - OpMemberDecorate %struct 0 RowMajor - OpMemberDecorate %struct 0 RowMajor - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %fvec4 = OpTypeVector %float 4 - %fmat4 = OpTypeMatrix %fvec4 4 - %struct = OpTypeStruct %fmat4 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID '2', member '0' decorated with RowMajor multiple " - "times is not allowed.")); -} - -TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - OpMemberDecorate %struct 0 MatrixStride 16 - OpMemberDecorate %struct 0 ColMajor - OpMemberDecorate %struct 0 ColMajor - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %fvec4 = OpTypeVector %float 4 - %fmat4 = OpTypeMatrix %fvec4 4 - %struct = OpTypeStruct %fmat4 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID '2', member '0' decorated with ColMajor multiple " - "times is not allowed.")); -} - -TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpMemberDecorate %struct 0 Offset 0 - OpMemberDecorate %struct 0 MatrixStride 16 - OpMemberDecorate %struct 0 ColMajor - OpMemberDecorate %struct 0 RowMajor - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %fvec4 = OpTypeVector %float 4 - %fmat4 = OpTypeMatrix %fvec4 4 - %struct = OpTypeStruct %fmat4 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID '2', member '0' decorated with both RowMajor and " - "ColMajor is not allowed.")); -} - -TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpDecorate %struct BufferBlock - OpMemberDecorate %struct 0 Offset 0 - OpMemberDecorate %struct 0 MatrixStride 16 - OpMemberDecorate %struct 0 RowMajor - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %fvec4 = OpTypeVector %float 4 - %fmat4 = OpTypeMatrix %fvec4 4 - %struct = OpTypeStruct %fmat4 - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ID '2' decorated with both BufferBlock and Block is not allowed.")); -} - -std::string MakeIntegerShader( - const std::string& decoration, const std::string& inst, - const std::string& extension = - "OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") { - return R"( -OpCapability Shader -OpCapability Linkage -)" + extension + - R"( -%glsl = OpExtInstImport "GLSL.std.450" -%opencl = OpExtInstImport "OpenCL.std" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpName %entry "entry" -)" + decoration + - R"( - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %int = OpTypeInt 32 1 - %zero = OpConstantNull %int - %float = OpTypeFloat 32 - %float0 = OpConstantNull %float - %main = OpFunction %void None %voidfn - %entry = OpLabel -)" + inst + - R"( -OpReturn -OpFunctionEnd)"; -} - -// NoSignedWrap - -TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) { - std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", ""); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid")); -} - -TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) { - std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", ""); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NoSignedWrap decoration may not be applied to Label")); -} - -TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpIAdd %int %zero %zero", ""); - - CompileSuccessfully(spirv); - EXPECT_NE(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions: " - "SPV_KHR_no_integer_wrap_decoration")); -} - -TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpIAdd %int %zero %zero", ""); - - CompileSuccessfully(spirv); - EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions: " - "SPV_KHR_no_integer_wrap_decoration")); -} - -TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpIAdd %int %zero %zero", ""); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapIAddGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpIAdd %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapISubGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpISub %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapIMulGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpIMul %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) { - std::string spirv = - MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpShiftLeftLogical %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpSNegate %int %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapSRemBad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpSRem %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NoSignedWrap decoration may not be applied to SRem")); -} - -TEST_F(ValidateDecorations, NoSignedWrapFAddBad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpFAdd %float %float0 %float0"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NoSignedWrap decoration may not be applied to FAdd")); -} - -TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) { - std::string spirv = - MakeIntegerShader("OpDecorate %val NoSignedWrap", - "%val = OpExtInst %int %opencl s_abs %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) { - std::string spirv = MakeIntegerShader( - "OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -// TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit -// "OpExtInst for instruction numbers specified in the extended -// instruction-set specifications as accepting this decoration." - -// NoUnignedWrap - -TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) { - std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", ""); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) { - std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", ""); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("NoUnsignedWrap decoration may not be applied to Label")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpIAdd %int %zero %zero", ""); - - CompileSuccessfully(spirv); - EXPECT_NE(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions: " - "SPV_KHR_no_integer_wrap_decoration")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpIAdd %int %zero %zero", ""); - - CompileSuccessfully(spirv); - EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions: " - "SPV_KHR_no_integer_wrap_decoration")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpIAdd %int %zero %zero", ""); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpIAdd %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpISub %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpIMul %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) { - std::string spirv = - MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpShiftLeftLogical %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpSNegate %int %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpSRem %int %zero %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("NoUnsignedWrap decoration may not be applied to SRem")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) { - std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpFAdd %float %float0 %float0"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) { - std::string spirv = - MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpExtInst %int %opencl s_abs %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) { - std::string spirv = - MakeIntegerShader("OpDecorate %val NoUnsignedWrap", - "%val = OpExtInst %int %glsl SAbs %zero"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, AliasedandRestrictBad) { - const std::string body = R"( -OpCapability Shader -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpSource GLSL 430 -OpMemberDecorate %Output 0 Offset 0 -OpDecorate %Output BufferBlock -OpDecorate %dataOutput Restrict -OpDecorate %dataOutput Aliased -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%Output = OpTypeStruct %float -%_ptr_Uniform_Output = OpTypePointer Uniform %Output -%dataOutput = OpVariable %_ptr_Uniform_Output Uniform -%main = OpFunction %void None %3 -%5 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("decorated with both Aliased and Restrict is not allowed")); -} - -// TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit -// "OpExtInst for instruction numbers specified in the extended -// instruction-set specifications as accepting this decoration." - -TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 RestrictPointerEXT -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("expected AliasedPointerEXT or RestrictPointerEXT for " - "PhysicalStorageBufferEXT pointer")); -} - -TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 RestrictPointerEXT -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("can't specify both AliasedPointerEXT and RestrictPointerEXT " - "for PhysicalStorageBufferEXT pointer")); -} - -TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %fparam Restrict -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%fnptr = OpTypeFunction %void %ptr -%main = OpFunction %void None %voidfn -%entry = OpLabel -OpReturn -OpFunctionEnd -%fn = OpFunction %void None %fnptr -%fparam = OpFunctionParameter %ptr -%lab = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%fnptr = OpTypeFunction %void %ptr -%main = OpFunction %void None %voidfn -%entry = OpLabel -OpReturn -OpFunctionEnd -%fn = OpFunction %void None %fnptr -%fparam = OpFunctionParameter %ptr -%lab = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("expected Aliased or Restrict for " - "PhysicalStorageBufferEXT pointer")); -} - -TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %fparam Restrict -OpDecorate %fparam Aliased -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%fnptr = OpTypeFunction %void %ptr -%main = OpFunction %void None %voidfn -%entry = OpLabel -OpReturn -OpFunctionEnd -%fn = OpFunction %void None %fnptr -%fparam = OpFunctionParameter %ptr -%lab = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("can't specify both Aliased and Restrict for " - "PhysicalStorageBufferEXT pointer")); -} - -TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess) { - std::string spirv = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_EXT_physical_storage_buffer" -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_KHR_variable_pointers" -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %_ FPRoundingMode RTE -OpDecorate %half_ptr_var AliasedPointerEXT -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%float_1_25 = OpConstant %float 1.25 -%half_ptr = OpTypePointer PhysicalStorageBufferEXT %half -%half_pptr_f = OpTypePointer Function %half_ptr -%void = OpTypeVoid -%func = OpTypeFunction %void -%main = OpFunction %void None %func -%main_entry = OpLabel -%half_ptr_var = OpVariable %half_pptr_f Function -%val1 = OpLoad %half_ptr %half_ptr_var -%_ = OpFConvert %half %float_1_25 -OpStore %val1 %_ Aligned 2 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateDecorations, InvalidStraddle) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpMemberDecorate %inner_struct 0 Offset 0 -OpMemberDecorate %inner_struct 1 Offset 4 -OpDecorate %outer_struct Block -OpMemberDecorate %outer_struct 0 Offset 0 -OpMemberDecorate %outer_struct 1 Offset 8 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%float2 = OpTypeVector %float 2 -%inner_struct = OpTypeStruct %float %float2 -%outer_struct = OpTypeStruct %float2 %inner_struct -%ptr_ssbo_outer = OpTypePointer StorageBuffer %outer_struct -%var = OpVariable %ptr_ssbo_outer StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure id 2 decorated as Block for variable in " - "StorageBuffer storage class must follow relaxed " - "storage buffer layout rules: member 1 is an " - "improperly straddling vector at offset 12")); -} - -TEST_F(ValidateDecorations, DescriptorArray) { - const std::string spirv = R"( -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpMemberDecorate %struct 1 Offset 1 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%int = OpTypeInt 32 0 -%int_2 = OpConstant %int 2 -%float2 = OpTypeVector %float 2 -%struct = OpTypeStruct %float %float2 -%struct_array = OpTypeArray %struct %int_2 -%ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array -%var = OpVariable %ptr_ssbo_array StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure id 2 decorated as Block for variable in " - "StorageBuffer storage class must follow standard " - "storage buffer layout rules: member 1 at offset 1 is " - "not aligned to 8")); -} - -TEST_F(ValidateDecorations, DescriptorRuntimeArray) { - const std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpMemberDecorate %struct 1 Offset 1 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%float = OpTypeFloat 32 -%int = OpTypeInt 32 0 -%float2 = OpTypeVector %float 2 -%struct = OpTypeStruct %float %float2 -%struct_array = OpTypeRuntimeArray %struct -%ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array -%var = OpVariable %ptr_ssbo_array StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure id 2 decorated as Block for variable in " - "StorageBuffer storage class must follow standard " - "storage buffer layout rules: member 1 at offset 1 is " - "not aligned to 8")); -} - -TEST_F(ValidateDecorations, MultiDimensionalArray) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %array_4 ArrayStride 4 -OpDecorate %array_3 ArrayStride 48 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_3 = OpConstant %int 3 -%int_4 = OpConstant %int 4 -%array_4 = OpTypeArray %int %int_4 -%array_3 = OpTypeArray %array_4 %int_3 -%struct = OpTypeStruct %array_3 -%ptr_struct = OpTypePointer Uniform %struct -%var = OpVariable %ptr_struct Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure id 2 decorated as Block for variable in " - "Uniform storage class must follow standard uniform " - "buffer layout rules: member 0 contains an array with " - "stride 4 not satisfying alignment to 16")); -} - -TEST_F(ValidateDecorations, ImproperStraddleInArray) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %array ArrayStride 24 -OpMemberDecorate %inner 0 Offset 0 -OpMemberDecorate %inner 1 Offset 4 -OpMemberDecorate %inner 2 Offset 12 -OpMemberDecorate %inner 3 Offset 16 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_2 = OpConstant %int 2 -%int2 = OpTypeVector %int 2 -%inner = OpTypeStruct %int %int2 %int %int -%array = OpTypeArray %inner %int_2 -%struct = OpTypeStruct %array -%ptr_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_struct StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structure id 4 decorated as Block for variable in " - "StorageBuffer storage class must follow relaxed " - "storage buffer layout rules: member 1 is an " - "improperly straddling vector at offset 28")); -} - -TEST_F(ValidateDecorations, LargeArray) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %array ArrayStride 24 -OpMemberDecorate %inner 0 Offset 0 -OpMemberDecorate %inner 1 Offset 8 -OpMemberDecorate %inner 2 Offset 16 -OpMemberDecorate %inner 3 Offset 20 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_2000000 = OpConstant %int 2000000 -%int2 = OpTypeVector %int 2 -%inner = OpTypeStruct %int %int2 %int %int -%array = OpTypeArray %inner %int_2000000 -%struct = OpTypeStruct %array -%ptr_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_struct StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -// NonWritable - -// Returns a SPIR-V shader module with variables in various storage classes, -// parameterizable by which ID should be decorated as NonWritable. -std::string ShaderWithNonWritableTarget(const std::string& target, - bool member_decorate = false) { - const std::string decoration_inst = - std::string(member_decorate ? "OpMemberDecorate " : "OpDecorate ") + - target + (member_decorate ? " 0" : ""); - - return std::string(R"( - OpCapability Shader - OpCapability RuntimeDescriptorArrayEXT - OpExtension "SPV_EXT_descriptor_indexing" - OpExtension "SPV_KHR_storage_buffer_storage_class" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpName %label "label" - OpName %param_f "param_f" - OpName %param_p "param_p" - OpName %_ptr_imstor "_ptr_imstor" - OpName %_ptr_imsam "_ptr_imsam" - OpName %var_wg "var_wg" - OpName %var_imsam "var_imsam" - OpName %var_priv "var_priv" - OpName %var_func "var_func" - OpName %simple_struct "simple_struct" - - OpDecorate %struct_b Block - OpDecorate %struct_b_rtarr Block - OpMemberDecorate %struct_b 0 Offset 0 - OpMemberDecorate %struct_b_rtarr 0 Offset 0 - OpDecorate %rtarr ArrayStride 4 -)") + decoration_inst + - - R"( NonWritable - - %void = OpTypeVoid - %void_fn = OpTypeFunction %void - %float = OpTypeFloat 32 - %float_0 = OpConstant %float 0 - %int = OpTypeInt 32 0 - %int_2 = OpConstant %int 2 - %struct_b = OpTypeStruct %float - %rtarr = OpTypeRuntimeArray %float -%struct_b_rtarr = OpTypeStruct %rtarr -%simple_struct = OpTypeStruct %float - ; storage image - %imstor = OpTypeImage %float 2D 0 0 0 2 R32f - ; sampled image - %imsam = OpTypeImage %float 2D 0 0 0 1 R32f -%array_imstor = OpTypeArray %imstor %int_2 -%rta_imstor = OpTypeRuntimeArray %imstor - -%_ptr_Uniform_stb = OpTypePointer Uniform %struct_b -%_ptr_StorageBuffer_stb = OpTypePointer StorageBuffer %struct_b -%_ptr_StorageBuffer_stb_rtarr = OpTypePointer StorageBuffer %struct_b_rtarr -%_ptr_Workgroup = OpTypePointer Workgroup %float -%_ptr_Private = OpTypePointer Private %float -%_ptr_Function = OpTypePointer Function %float -%_ptr_imstor = OpTypePointer UniformConstant %imstor -%_ptr_imsam = OpTypePointer UniformConstant %imsam -%_ptr_array_imstor = OpTypePointer UniformConstant %array_imstor -%_ptr_rta_imstor = OpTypePointer UniformConstant %rta_imstor - -%extra_fn = OpTypeFunction %void %float %_ptr_Private %_ptr_imstor - -%var_ubo = OpVariable %_ptr_Uniform_stb Uniform -%var_ssbo_sb = OpVariable %_ptr_StorageBuffer_stb StorageBuffer -%var_ssbo_sb_rtarr = OpVariable %_ptr_StorageBuffer_stb_rtarr StorageBuffer -%var_wg = OpVariable %_ptr_Workgroup Workgroup -%var_priv = OpVariable %_ptr_Private Private -%var_imstor = OpVariable %_ptr_imstor UniformConstant -%var_imsam = OpVariable %_ptr_imsam UniformConstant -%var_array_imstor = OpVariable %_ptr_array_imstor UniformConstant -%var_rta_imstor = OpVariable %_ptr_rta_imstor UniformConstant - - %helper = OpFunction %void None %extra_fn - %param_f = OpFunctionParameter %float - %param_p = OpFunctionParameter %_ptr_Private - %param_pimstor = OpFunctionParameter %_ptr_imstor -%helper_label = OpLabel -%helper_func_var = OpVariable %_ptr_Function Function - OpReturn - OpFunctionEnd - - %main = OpFunction %void None %void_fn - %label = OpLabel -%var_func = OpVariable %_ptr_Function Function - OpReturn - OpFunctionEnd -)"; -} - -TEST_F(ValidateDecorations, NonWritableLabelTargetBad) { - std::string spirv = ShaderWithNonWritableTarget("%label"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration must be a " - "memory object declaration (a variable or a function " - "parameter)\n %label = OpLabel")); -} - -TEST_F(ValidateDecorations, NonWritableTypeTargetBad) { - std::string spirv = ShaderWithNonWritableTarget("%void"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration must be a " - "memory object declaration (a variable or a function " - "parameter)\n %void = OpTypeVoid")); -} - -TEST_F(ValidateDecorations, NonWritableValueTargetBad) { - std::string spirv = ShaderWithNonWritableTarget("%float_0"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration must be a " - "memory object declaration (a variable or a function " - "parameter)\n %float_0 = OpConstant %float 0")); -} - -TEST_F(ValidateDecorations, NonWritableValueParamBad) { - std::string spirv = ShaderWithNonWritableTarget("%param_f"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %param_f = OpFunctionParameter %float")); -} - -TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad) { - std::string spirv = ShaderWithNonWritableTarget("%param_p"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %param_p = OpFunctionParameter %_ptr_Private_float")); -} - -TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood) { - std::string spirv = ShaderWithNonWritableTarget("%param_pimstor"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableVarStorageImageGood) { - std::string spirv = ShaderWithNonWritableTarget("%var_imstor"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableVarSampledImageBad) { - std::string spirv = ShaderWithNonWritableTarget("%var_imsam"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_imsam")); -} - -TEST_F(ValidateDecorations, NonWritableVarUboGood) { - std::string spirv = ShaderWithNonWritableTarget("%var_ubo"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpDecorate %struct_bb BufferBlock -OpMemberDecorate %struct_bb 0 Offset 0 -OpDecorate %var_ssbo_u NonWritable -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%float = OpTypeFloat 32 -%struct_bb = OpTypeStruct %float -%_ptr_Uniform_stbb = OpTypePointer Uniform %struct_bb -%var_ssbo_u = OpVariable %_ptr_Uniform_stbb Uniform -%main = OpFunction %void None %void_fn -%label = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood) { - std::string spirv = ShaderWithNonWritableTarget("%var_ssbo_sb"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood) { - std::string spirv = ShaderWithNonWritableTarget("%struct_b_rtarr", true); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableMemberOfStructGood) { - std::string spirv = ShaderWithNonWritableTarget("%simple_struct", true); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad) { - std::string spirv = ShaderWithNonWritableTarget("%var_wg"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_wg")); -} - -TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad) { - std::string spirv = ShaderWithNonWritableTarget("%var_wg"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, storage " - "buffer, or variable in Private or Function storage " - "class\n %var_wg")); -} - -TEST_F(ValidateDecorations, NonWritableVarPrivateBad) { - std::string spirv = ShaderWithNonWritableTarget("%var_priv"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_priv")); -} - -TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad) { - std::string spirv = ShaderWithNonWritableTarget("%var_priv"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_priv")); -} - -TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good) { - std::string spirv = ShaderWithNonWritableTarget("%var_priv"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad) { - std::string spirv = ShaderWithNonWritableTarget("%var_priv"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_priv")); -} - -TEST_F(ValidateDecorations, NonWritableVarFunctionBad) { - std::string spirv = ShaderWithNonWritableTarget("%var_func"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_func")); -} - -TEST_F(ValidateDecorations, NonWritableArrayGood) { - std::string spirv = ShaderWithNonWritableTarget("%var_array_imstor"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood) { - std::string spirv = ShaderWithNonWritableTarget("%var_rta_imstor"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateWebGPUCombineDecorationResult, Decorate) { - const char* const decoration = std::get<0>(GetParam()); - const TestResult& test_result = std::get<1>(GetParam()); - - CodeGenerator generator = CodeGenerator::GetWebGPUShaderCodeGenerator(); - generator.before_types_ = "OpDecorate %u32 "; - generator.before_types_ += decoration; - generator.before_types_ += "\n"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Vertex"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - if (test_result.error_str != "") { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } -} - -TEST_P(ValidateWebGPUCombineDecorationResult, DecorateMember) { - const char* const decoration = std::get<0>(GetParam()); - const TestResult& test_result = std::get<1>(GetParam()); - - CodeGenerator generator = CodeGenerator::GetWebGPUShaderCodeGenerator(); - generator.before_types_ = "OpMemberDecorate %struct_type 0 "; - generator.before_types_ += decoration; - generator.before_types_ += "\n"; - - generator.after_types_ = "%struct_type = OpTypeStruct %u32\n"; - - EntryPoint entry_point; - entry_point.name = "main"; - entry_point.execution_model = "Vertex"; - generator.entry_points_.push_back(std::move(entry_point)); - - CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0); - ASSERT_EQ(test_result.validation_result, - ValidateInstructions(SPV_ENV_WEBGPU_0)); - if (!test_result.error_str.empty()) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); - } -} - -INSTANTIATE_TEST_SUITE_P( - DecorationCapabilityFailure, ValidateWebGPUCombineDecorationResult, - Combine(Values("CPacked", "Patch", "Sample", "Constant", - "SaturatedConversion", "NonUniformEXT"), - Values(TestResult(SPV_ERROR_INVALID_CAPABILITY, - "requires one of these capabilities")))); - -INSTANTIATE_TEST_SUITE_P( - DecorationWhitelistFailure, ValidateWebGPUCombineDecorationResult, - Combine(Values("RelaxedPrecision", "BufferBlock", "GLSLShared", - "GLSLPacked", "Invariant", "Volatile", "Coherent"), - Values(TestResult( - SPV_ERROR_INVALID_ID, - "is not valid for the WebGPU execution environment.")))); - -TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) { - std::string spirv = ShaderWithNonWritableTarget("%var_func"); - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_func")); -} - -TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good) { - std::string spirv = ShaderWithNonWritableTarget("%var_func"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad) { - std::string spirv = ShaderWithNonWritableTarget("%var_func"); - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of NonWritable decoration is invalid: must " - "point to a storage image, uniform block, or storage " - "buffer\n %var_func")); -} - -TEST_F(ValidateDecorations, BufferBlockV13ValV14Good) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 BufferBlock -%1 = OpTypeStruct -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateDecorations, BufferBlockV14Bad) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -OpDecorate %1 BufferBlock -%1 = OpTypeStruct -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_WRONG_VERSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("2nd operand of Decorate: operand BufferBlock(3) " - "requires SPIR-V version 1.3 or earlier")); -} - -// Component - -TEST_F(ValidateDecorations, ComponentDecorationBadTarget) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpDecorate %t Component 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%t = OpTypeVector %float 2 -%main = OpFunction %void None %3 -%5 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of Component decoration must be " - "a memory object declaration")); -} - -TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpDecorate %v Component 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%t = OpTypeVector %float 2 -%ptr_private = OpTypePointer Private %t -%v = OpVariable %ptr_private Private -%main = OpFunction %void None %3 -%5 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target of Component decoration is invalid: must " - "point to a Storage Class of Input(1) or Output(3)")); -} - -TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = R"( -OpCapability Shader -OpCapability Matrix -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpDecorate %v Component 0 -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%vtype = OpTypeVector %float 4 -%t = OpTypeMatrix %vtype 4 -%ptr_input = OpTypePointer Input %t -%v = OpVariable %ptr_input Input -%main = OpFunction %void None %3 -%5 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Component decoration specified for type")); - EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector")); -} - -std::string ShaderWithComponentDecoration(const std::string& type, - const std::string& decoration) { - return R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %entryPointOutput -OpExecutionMode %main OriginUpperLeft -OpDecorate %entryPointOutput Location 0 -OpDecorate %entryPointOutput )" + - decoration + R"( -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%uint_2 = OpConstant %uint 2 -%arr_v3float_uint_2 = OpTypeArray %v3float %uint_2 -%float_0 = OpConstant %float 0 -%_ptr_Output_type = OpTypePointer Output %)" + type + R"( -%entryPointOutput = OpVariable %_ptr_Output_type Output -%main = OpFunction %void None %3 -%5 = OpLabel -OpReturn -OpFunctionEnd -)"; -} - -TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("uint", "Component 0"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("uint", "Component 1"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("uint", "Component 2"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("uint", "Component 3"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("uint", "Component 4"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Sequence of components starting with 4 " - "and ending with 4 gets larger than 3")); -} - -TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Sequence of components starting with 1 " - "and ending with 4 gets larger than 3")); -} - -TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Sequence of components starting with 3 " - "and ending with 6 gets larger than 3")); -} - -TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = - ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = - ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2"); - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Sequence of components starting with 2 " - "and ending with 4 gets larger than 3")); -} - -TEST_F(ValidateDecorations, ComponentDecorationBlockGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" %9 %12 -OpExecutionMode %4 OriginUpperLeft -OpDecorate %9 Location 0 -OpMemberDecorate %block 0 Location 2 -OpMemberDecorate %block 0 Component 1 -OpDecorate %block Block -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%float = OpTypeFloat 32 -%vec3 = OpTypeVector %float 3 -%8 = OpTypePointer Output %vec3 -%9 = OpVariable %8 Output -%block = OpTypeStruct %vec3 -%11 = OpTypePointer Input %block -%12 = OpVariable %11 Input -%int = OpTypeInt 32 1 -%14 = OpConstant %int 0 -%15 = OpTypePointer Input %vec3 -%4 = OpFunction %2 None %3 -%5 = OpLabel -%16 = OpAccessChain %15 %12 %14 -%17 = OpLoad %vec3 %16 -OpStore %9 %17 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan) { - const spv_target_env env = SPV_ENV_VULKAN_1_0; - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %4 "main" %9 %12 -OpExecutionMode %4 OriginUpperLeft -OpDecorate %9 Location 0 -OpMemberDecorate %block 0 Location 2 -OpMemberDecorate %block 0 Component 2 -OpDecorate %block Block -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%float = OpTypeFloat 32 -%vec3 = OpTypeVector %float 3 -%8 = OpTypePointer Output %vec3 -%9 = OpVariable %8 Output -%block = OpTypeStruct %vec3 -%11 = OpTypePointer Input %block -%12 = OpVariable %11 Input -%int = OpTypeInt 32 1 -%14 = OpConstant %int 0 -%15 = OpTypePointer Input %vec3 -%4 = OpFunction %2 None %3 -%5 = OpLabel -%16 = OpAccessChain %15 %12 %14 -%17 = OpLoad %vec3 %16 -OpStore %9 %17 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, env); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Sequence of components starting with 2 " - "and ending with 4 gets larger than 3")); -} - -TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - - OpDecorate %param_f Component 0 - - %void = OpTypeVoid - %void_fn = OpTypeFunction %void - %float = OpTypeFloat 32 - %float_0 = OpConstant %float 0 - %int = OpTypeInt 32 0 - %int_2 = OpConstant %int 2 - %struct_b = OpTypeStruct %float - -%extra_fn = OpTypeFunction %void %float - - %helper = OpFunction %void None %extra_fn - %param_f = OpFunctionParameter %float -%helper_label = OpLabel - OpReturn - OpFunctionEnd - - %main = OpFunction %void None %void_fn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateDecorations, VulkanStorageBufferBlock) { - const std::string spirv = R"( -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%ptr_ssbo = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) { - const std::string spirv = R"( -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%ptr_ssbo = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables " - "must be identified with a Block decoration")); -} - -TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) { - const std::string spirv = R"( -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_4 = OpConstant %uint 4 -%struct = OpTypeStruct %uint -%array = OpTypeArray %struct %uint_4 -%ptr_ssbo = OpTypePointer StorageBuffer %array -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables " - "must be identified with a Block decoration")); -} - -TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) { - const std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_EXT_descriptor_indexing" -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%array = OpTypeRuntimeArray %struct -%ptr_ssbo = OpTypePointer StorageBuffer %array -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables " - "must be identified with a Block decoration")); -} - -TEST_F(ValidateDecorations, VulkanUniformBlock) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%ptr_ubo = OpTypePointer Uniform %struct -%var = OpVariable %ptr_ubo Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateDecorations, VulkanUniformBufferBlock) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct BufferBlock -OpMemberDecorate %struct 0 Offset 0 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%ptr_ubo = OpTypePointer Uniform %struct -%var = OpVariable %ptr_ubo Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0)); -} - -TEST_F(ValidateDecorations, VulkanUniformMissingBlock) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%ptr_ubo = OpTypePointer Uniform %struct -%var = OpVariable %ptr_ubo Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be " - "identified with a Block or BufferBlock decoration")); -} - -TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_4 = OpConstant %uint 4 -%struct = OpTypeStruct %uint -%array = OpTypeArray %struct %uint_4 -%ptr_ubo = OpTypePointer Uniform %array -%var = OpVariable %ptr_ubo Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be " - "identified with a Block or BufferBlock decoration")); -} - -TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) { - const std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%struct = OpTypeStruct %uint -%array = OpTypeRuntimeArray %struct -%ptr_ubo = OpTypePointer Uniform %array -%var = OpVariable %ptr_ubo Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be " - "identified with a Block or BufferBlock decoration")); -} - -TEST_F(ValidateDecorations, VulkanArrayStrideZero) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %array ArrayStride 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%array = OpTypeArray %int %int_4 -%struct = OpTypeStruct %array -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_ssbo_struct StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("contains an array with stride 0")); -} - -TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %inner ArrayStride 4 -OpDecorate %outer ArrayStride 4 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%inner = OpTypeArray %int %int_4 -%outer = OpTypeArray %inner %int_4 -%struct = OpTypeStruct %outer -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_ssbo_struct StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "contains an array with stride 4, but with an element size of 16")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_derivatives_test.cpp b/3rdparty/spirv-tools/test/val/val_derivatives_test.cpp deleted file mode 100644 index 606abb93d..000000000 --- a/3rdparty/spirv-tools/test/val/val_derivatives_test.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2017 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateDerivatives = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "Fragment") { - std::stringstream ss; - ss << R"( -OpCapability Shader -OpCapability DerivativeControl -)"; - - ss << capabilities_and_extensions; - ss << "OpMemoryModel Logical GLSL450\n"; - ss << "OpEntryPoint " << execution_model << " %main \"main\"" - << " %f32_var_input" - << " %f32vec4_var_input" - << "\n"; - if (execution_model == "Fragment") { - ss << "OpExecutionMode %main OriginUpperLeft\n"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%f32vec4 = OpTypeVector %f32 4 - -%f32_ptr_input = OpTypePointer Input %f32 -%f32_var_input = OpVariable %f32_ptr_input Input - -%f32vec4_ptr_input = OpTypePointer Input %f32vec4 -%f32vec4_var_input = OpVariable %f32vec4_ptr_input Input -)"; - - if (capabilities_and_extensions.find("OpCapability Float16") != - std::string::npos) { - ss << "%f16 = OpTypeFloat 16\n" - << "%f16vec4 = OpTypeVector %f16 4\n" - << "%f16_0 = OpConstantNull %f16\n" - << "%f16vec4_0 = OpConstantNull %f16vec4\n"; - } - - ss << R"( -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -TEST_F(ValidateDerivatives, ScalarSuccess) { - const std::string body = R"( -%f32_var = OpLoad %f32 %f32_var_input -%val1 = OpDPdx %f32 %f32_var -%val2 = OpDPdy %f32 %f32_var -%val3 = OpFwidth %f32 %f32_var -%val4 = OpDPdxFine %f32 %f32_var -%val5 = OpDPdyFine %f32 %f32_var -%val6 = OpFwidthFine %f32 %f32_var -%val7 = OpDPdxCoarse %f32 %f32_var -%val8 = OpDPdyCoarse %f32 %f32_var -%val9 = OpFwidthCoarse %f32 %f32_var -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateDerivatives, VectorSuccess) { - const std::string body = R"( -%f32vec4_var = OpLoad %f32vec4 %f32vec4_var_input -%val1 = OpDPdx %f32vec4 %f32vec4_var -%val2 = OpDPdy %f32vec4 %f32vec4_var -%val3 = OpFwidth %f32vec4 %f32vec4_var -%val4 = OpDPdxFine %f32vec4 %f32vec4_var -%val5 = OpDPdyFine %f32vec4 %f32vec4_var -%val6 = OpFwidthFine %f32vec4 %f32vec4_var -%val7 = OpDPdxCoarse %f32vec4 %f32vec4_var -%val8 = OpDPdyCoarse %f32vec4 %f32vec4_var -%val9 = OpFwidthCoarse %f32vec4 %f32vec4_var -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateDerivatives, OpDPdxWrongResultType) { - const std::string body = R"( -%f32_var = OpLoad %f32 %f32_var_input -%val1 = OpDPdx %u32 %f32vec4 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 10[%v4float] cannot " - "be a type")); -} - -TEST_F(ValidateDerivatives, OpDPdxWrongPType) { - const std::string body = R"( -%f32vec4_var = OpLoad %f32vec4 %f32vec4_var_input -%val1 = OpDPdx %f32 %f32vec4_var -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected P type and Result Type to be the same: " - "DPdx")); -} - -TEST_F(ValidateDerivatives, OpDPdxWrongExecutionModel) { - const std::string body = R"( -%f32vec4_var = OpLoad %f32vec4 %f32vec4_var_input -%val1 = OpDPdx %f32vec4 %f32vec4_var -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Derivative instructions require Fragment or GLCompute " - "execution model: DPdx")); -} - -using ValidateHalfDerivatives = spvtest::ValidateBase; - -TEST_P(ValidateHalfDerivatives, ScalarFailure) { - const std::string op = GetParam(); - const std::string body = "%val = " + op + " %f16 %f16_0\n"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability Float16\n").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result type component width must be 32 bits")); -} - -TEST_P(ValidateHalfDerivatives, VectorFailure) { - const std::string op = GetParam(); - const std::string body = "%val = " + op + " %f16vec4 %f16vec4_0\n"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability Float16\n").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result type component width must be 32 bits")); -} - -INSTANTIATE_TEST_SUITE_P(HalfDerivatives, ValidateHalfDerivatives, - ::testing::Values("OpDPdx", "OpDPdy", "OpFwidth", - "OpDPdxFine", "OpDPdyFine", - "OpFwidthFine", "OpDPdxCoarse", - "OpDPdyCoarse", "OpFwidthCoarse")); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_entry_point.cpp b/3rdparty/spirv-tools/test/val/val_entry_point.cpp deleted file mode 100644 index f28cf5d19..000000000 --- a/3rdparty/spirv-tools/test/val/val_entry_point.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2019 Samsung 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; - -using ValidateEntryPoints = spvtest::ValidateBase; - -TEST_F(ValidateEntryPoints, DuplicateEntryPoints) { - const std::string body = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %3 "foo" -OpEntryPoint GLCompute %4 "foo" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%20 = OpLabel -OpReturn -OpFunctionEnd -%4 = OpFunction %1 None %2 -%21 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Entry points cannot share the same name")); -} - -TEST_F(ValidateEntryPoints, UniqueEntryPoints) { - const std::string body = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %3 "foo" -OpEntryPoint GLCompute %4 "foo2" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%20 = OpLabel -OpReturn -OpFunctionEnd -%4 = OpFunction %1 None %2 -%21 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -} // namespace -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_explicit_reserved_test.cpp b/3rdparty/spirv-tools/test/val/val_explicit_reserved_test.cpp deleted file mode 100644 index f01e933fa..000000000 --- a/3rdparty/spirv-tools/test/val/val_explicit_reserved_test.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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. - -// Validation tests for illegal instructions - -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; - -using ReservedSamplingInstTest = spvtest::ValidateBase; - -// Generate a shader for use with validation tests for sparse sampling -// instructions. -std::string ShaderAssembly(const std::string& instruction_under_test) { - std::ostringstream os; - os << R"( OpCapability Shader - OpCapability SparseResidency - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - OpSource GLSL 450 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - %void = OpTypeVoid - %4 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %float_0 = OpConstant %float 0 - %8 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 - %9 = OpTypeImage %float 2D 0 0 0 1 Unknown - %10 = OpTypeSampledImage %9 -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %2 = OpVariable %_ptr_UniformConstant_10 UniformConstant - %v2float = OpTypeVector %float 2 - %13 = OpConstantComposite %v2float %float_0 %float_0 - %int = OpTypeInt 32 1 - %_struct_15 = OpTypeStruct %int %v4float - %1 = OpFunction %void None %4 - %16 = OpLabel - %17 = OpLoad %10 %2 -)" << instruction_under_test - << R"( - OpReturn - OpFunctionEnd -)"; - - return os.str(); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjImplicitLod) { - const std::string input = ShaderAssembly( - "%result = OpImageSparseSampleProjImplicitLod %_struct_15 %17 %13"); - CompileSuccessfully(input); - - EXPECT_THAT(ValidateInstructions(), Eq(SPV_ERROR_INVALID_BINARY)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid Opcode name 'OpImageSparseSampleProjImplicitLod'")); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjExplicitLod) { - const std::string input = ShaderAssembly( - "%result = OpImageSparseSampleProjExplicitLod %_struct_15 %17 %13 Lod " - "%float_0\n"); - CompileSuccessfully(input); - - EXPECT_THAT(ValidateInstructions(), Eq(SPV_ERROR_INVALID_BINARY)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid Opcode name 'OpImageSparseSampleProjExplicitLod'")); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefImplicitLod) { - const std::string input = ShaderAssembly( - "%result = OpImageSparseSampleProjDrefImplicitLod %_struct_15 %17 %13 " - "%float_0\n"); - CompileSuccessfully(input); - - EXPECT_THAT(ValidateInstructions(), Eq(SPV_ERROR_INVALID_BINARY)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Invalid Opcode name 'OpImageSparseSampleProjDrefImplicitLod'")); -} - -TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefExplicitLod) { - const std::string input = ShaderAssembly( - "%result = OpImageSparseSampleProjDrefExplicitLod %_struct_15 %17 %13 " - "%float_0 Lod " - "%float_0\n"); - CompileSuccessfully(input); - - EXPECT_THAT(ValidateInstructions(), Eq(SPV_ERROR_INVALID_BINARY)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Invalid Opcode name 'OpImageSparseSampleProjDrefExplicitLod'")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_ext_inst_test.cpp b/3rdparty/spirv-tools/test/val/val_ext_inst_test.cpp deleted file mode 100644 index 67df43d13..000000000 --- a/3rdparty/spirv-tools/test/val/val_ext_inst_test.cpp +++ /dev/null @@ -1,5853 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests validation rules of GLSL.450.std and OpenCL.std extended instructions. -// Doesn't test OpenCL.std vector size 2, 3, 4, 8 or 16 rules (not supported -// by standard SPIR-V). - -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateExtInst = spvtest::ValidateBase; -using ValidateGlslStd450SqrtLike = spvtest::ValidateBase; -using ValidateGlslStd450FMinLike = spvtest::ValidateBase; -using ValidateGlslStd450FClampLike = spvtest::ValidateBase; -using ValidateGlslStd450SAbsLike = spvtest::ValidateBase; -using ValidateGlslStd450UMinLike = spvtest::ValidateBase; -using ValidateGlslStd450UClampLike = spvtest::ValidateBase; -using ValidateGlslStd450SinLike = spvtest::ValidateBase; -using ValidateGlslStd450PowLike = spvtest::ValidateBase; -using ValidateGlslStd450Pack = spvtest::ValidateBase; -using ValidateGlslStd450Unpack = spvtest::ValidateBase; -using ValidateOpenCLStdSqrtLike = spvtest::ValidateBase; -using ValidateOpenCLStdFMinLike = spvtest::ValidateBase; -using ValidateOpenCLStdFClampLike = spvtest::ValidateBase; -using ValidateOpenCLStdSAbsLike = spvtest::ValidateBase; -using ValidateOpenCLStdUMinLike = spvtest::ValidateBase; -using ValidateOpenCLStdUClampLike = spvtest::ValidateBase; -using ValidateOpenCLStdUMul24Like = spvtest::ValidateBase; -using ValidateOpenCLStdUMad24Like = spvtest::ValidateBase; -using ValidateOpenCLStdLengthLike = spvtest::ValidateBase; -using ValidateOpenCLStdDistanceLike = spvtest::ValidateBase; -using ValidateOpenCLStdNormalizeLike = spvtest::ValidateBase; -using ValidateOpenCLStdVStoreHalfLike = spvtest::ValidateBase; -using ValidateOpenCLStdVLoadHalfLike = spvtest::ValidateBase; -using ValidateOpenCLStdFractLike = spvtest::ValidateBase; -using ValidateOpenCLStdFrexpLike = spvtest::ValidateBase; -using ValidateOpenCLStdLdexpLike = spvtest::ValidateBase; -using ValidateOpenCLStdUpsampleLike = spvtest::ValidateBase; - -// Returns number of components in Pack/Unpack extended instructions. -// |ext_inst_name| is expected to be of the format "PackHalf2x16". -// Number of components is assumed to be single-digit. -uint32_t GetPackedNumComponents(const std::string& ext_inst_name) { - const size_t x_index = ext_inst_name.find_last_of('x'); - const std::string num_components_str = - ext_inst_name.substr(x_index - 1, x_index); - return uint32_t(std::stoul(num_components_str)); -} - -// Returns packed bit width in Pack/Unpack extended instructions. -// |ext_inst_name| is expected to be of the format "PackHalf2x16". -uint32_t GetPackedBitWidth(const std::string& ext_inst_name) { - const size_t x_index = ext_inst_name.find_last_of('x'); - const std::string packed_bit_width_str = ext_inst_name.substr(x_index + 1); - return uint32_t(std::stoul(packed_bit_width_str)); -} - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "Fragment") { - std::ostringstream ss; - ss << R"( -OpCapability Shader -OpCapability Float16 -OpCapability Float64 -OpCapability Int16 -OpCapability Int64 -)"; - - ss << capabilities_and_extensions; - ss << "%extinst = OpExtInstImport \"GLSL.std.450\"\n"; - ss << "OpMemoryModel Logical GLSL450\n"; - ss << "OpEntryPoint " << execution_model << " %main \"main\"" - << " %f32_output" - << " %f32vec2_output" - << " %u32_output" - << " %u32vec2_output" - << " %u64_output" - << " %f32_input" - << " %f32vec2_input" - << " %u32_input" - << " %u32vec2_input" - << " %u64_input" - << "\n"; - if (execution_model == "Fragment") { - ss << "OpExecutionMode %main OriginUpperLeft\n"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%f64 = OpTypeFloat 64 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%u64 = OpTypeInt 64 0 -%s64 = OpTypeInt 64 1 -%u16 = OpTypeInt 16 0 -%s16 = OpTypeInt 16 1 -%f32vec2 = OpTypeVector %f32 2 -%f32vec3 = OpTypeVector %f32 3 -%f32vec4 = OpTypeVector %f32 4 -%f64vec2 = OpTypeVector %f64 2 -%f64vec3 = OpTypeVector %f64 3 -%f64vec4 = OpTypeVector %f64 4 -%u32vec2 = OpTypeVector %u32 2 -%u32vec3 = OpTypeVector %u32 3 -%s32vec2 = OpTypeVector %s32 2 -%u32vec4 = OpTypeVector %u32 4 -%s32vec4 = OpTypeVector %s32 4 -%u64vec2 = OpTypeVector %u64 2 -%s64vec2 = OpTypeVector %s64 2 -%f64mat22 = OpTypeMatrix %f64vec2 2 -%f32mat22 = OpTypeMatrix %f32vec2 2 -%f32mat23 = OpTypeMatrix %f32vec2 3 -%f32mat32 = OpTypeMatrix %f32vec3 2 -%f32mat33 = OpTypeMatrix %f32vec3 3 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 -%f32_h = OpConstant %f32 0.5 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 - -%f16_0 = OpConstant %f16 0 -%f16_1 = OpConstant %f16 1 -%f16_h = OpConstant %f16 0.5 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 - -%s32_0 = OpConstant %s32 0 -%s32_1 = OpConstant %s32 1 -%s32_2 = OpConstant %s32 2 -%s32_3 = OpConstant %s32 3 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 - -%s64_0 = OpConstant %s64 0 -%s64_1 = OpConstant %s64 1 -%s64_2 = OpConstant %s64 2 -%s64_3 = OpConstant %s64 3 - -%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1 -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 - -%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 - -%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 - -%s64vec2_01 = OpConstantComposite %s64vec2 %s64_0 %s64_1 -%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1 - -%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12 -%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 - -%f32_ptr_output = OpTypePointer Output %f32 -%f32vec2_ptr_output = OpTypePointer Output %f32vec2 - -%u32_ptr_output = OpTypePointer Output %u32 -%u32vec2_ptr_output = OpTypePointer Output %u32vec2 - -%u64_ptr_output = OpTypePointer Output %u64 - -%f32_output = OpVariable %f32_ptr_output Output -%f32vec2_output = OpVariable %f32vec2_ptr_output Output - -%u32_output = OpVariable %u32_ptr_output Output -%u32vec2_output = OpVariable %u32vec2_ptr_output Output - -%u64_output = OpVariable %u64_ptr_output Output - -%f32_ptr_input = OpTypePointer Input %f32 -%f32vec2_ptr_input = OpTypePointer Input %f32vec2 - -%u32_ptr_input = OpTypePointer Input %u32 -%u32vec2_ptr_input = OpTypePointer Input %u32vec2 - -%u64_ptr_input = OpTypePointer Input %u64 - -%f32_input = OpVariable %f32_ptr_input Input -%f32vec2_input = OpVariable %f32vec2_ptr_input Input - -%u32_input = OpVariable %u32_ptr_input Input -%u32vec2_input = OpVariable %u32vec2_ptr_input Input - -%u64_input = OpVariable %u64_ptr_input Input - -%struct_f16_u16 = OpTypeStruct %f16 %u16 -%struct_f32_f32 = OpTypeStruct %f32 %f32 -%struct_f32_f32_f32 = OpTypeStruct %f32 %f32 %f32 -%struct_f32_u32 = OpTypeStruct %f32 %u32 -%struct_f32_u32_f32 = OpTypeStruct %f32 %u32 %f32 -%struct_u32_f32 = OpTypeStruct %u32 %f32 -%struct_u32_u32 = OpTypeStruct %u32 %u32 -%struct_f32_f64 = OpTypeStruct %f32 %f64 -%struct_f32vec2_f32vec2 = OpTypeStruct %f32vec2 %f32vec2 -%struct_f32vec2_u32vec2 = OpTypeStruct %f32vec2 %u32vec2 - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -std::string GenerateKernelCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& memory_model = "Physical32") { - std::ostringstream ss; - ss << R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability GenericPointer -OpCapability Int8 -OpCapability Int16 -OpCapability Int64 -OpCapability Float16 -OpCapability Float64 -OpCapability Vector16 -OpCapability Matrix -)"; - - ss << capabilities_and_extensions; - ss << "%extinst = OpExtInstImport \"OpenCL.std\"\n"; - ss << "OpMemoryModel " << memory_model << " OpenCL\n"; - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f16 = OpTypeFloat 16 -%f32 = OpTypeFloat 32 -%f64 = OpTypeFloat 64 -%u32 = OpTypeInt 32 0 -%u64 = OpTypeInt 64 0 -%u16 = OpTypeInt 16 0 -%u8 = OpTypeInt 8 0 -%f32vec2 = OpTypeVector %f32 2 -%f32vec3 = OpTypeVector %f32 3 -%f32vec4 = OpTypeVector %f32 4 -%f32vec8 = OpTypeVector %f32 8 -%f16vec8 = OpTypeVector %f16 8 -%f32vec16 = OpTypeVector %f32 16 -%f64vec2 = OpTypeVector %f64 2 -%f64vec3 = OpTypeVector %f64 3 -%f64vec4 = OpTypeVector %f64 4 -%u32vec2 = OpTypeVector %u32 2 -%u32vec3 = OpTypeVector %u32 3 -%u32vec4 = OpTypeVector %u32 4 -%u32vec8 = OpTypeVector %u32 8 -%u64vec2 = OpTypeVector %u64 2 -%f64mat22 = OpTypeMatrix %f64vec2 2 -%f32mat22 = OpTypeMatrix %f32vec2 2 -%f32mat23 = OpTypeMatrix %f32vec2 3 -%f32mat32 = OpTypeMatrix %f32vec3 2 -%f32mat33 = OpTypeMatrix %f32vec3 3 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 -%f32_h = OpConstant %f32 0.5 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 -%f32vec8_01010101 = OpConstantComposite %f32vec8 %f32_0 %f32_1 %f32_0 %f32_1 %f32_0 %f32_1 %f32_0 %f32_1 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 - -%f16_0 = OpConstant %f16 0 -%f16_1 = OpConstant %f16 1 - -%u8_0 = OpConstant %u8 0 -%u8_1 = OpConstant %u8 1 -%u8_2 = OpConstant %u8 2 -%u8_3 = OpConstant %u8 3 - -%u16_0 = OpConstant %u16 0 -%u16_1 = OpConstant %u16 1 -%u16_2 = OpConstant %u16 2 -%u16_3 = OpConstant %u16 3 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_256 = OpConstant %u32 256 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_256 = OpConstant %u64 256 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 - -%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1 - -%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12 -%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 - -%struct_f32_f32 = OpTypeStruct %f32 %f32 -%struct_f32_f32_f32 = OpTypeStruct %f32 %f32 %f32 -%struct_f32_u32 = OpTypeStruct %f32 %u32 -%struct_f32_u32_f32 = OpTypeStruct %f32 %u32 %f32 -%struct_u32_f32 = OpTypeStruct %u32 %f32 -%struct_u32_u32 = OpTypeStruct %u32 %u32 -%struct_f32_f64 = OpTypeStruct %f32 %f64 -%struct_f32vec2_f32vec2 = OpTypeStruct %f32vec2 %f32vec2 -%struct_f32vec2_u32vec2 = OpTypeStruct %f32vec2 %u32vec2 - -%f16vec8_ptr_workgroup = OpTypePointer Workgroup %f16vec8 -%f16vec8_workgroup = OpVariable %f16vec8_ptr_workgroup Workgroup -%f16_ptr_workgroup = OpTypePointer Workgroup %f16 - -%u32vec8_ptr_workgroup = OpTypePointer Workgroup %u32vec8 -%u32vec8_workgroup = OpVariable %u32vec8_ptr_workgroup Workgroup -%u32_ptr_workgroup = OpTypePointer Workgroup %u32 - -%f32vec8_ptr_workgroup = OpTypePointer Workgroup %f32vec8 -%f32vec8_workgroup = OpVariable %f32vec8_ptr_workgroup Workgroup -%f32_ptr_workgroup = OpTypePointer Workgroup %f32 - -%u32arr = OpTypeArray %u32 %u32_256 -%u32arr_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %u32arr -%u32arr_cross_workgroup = OpVariable %u32arr_ptr_cross_workgroup CrossWorkgroup -%u32_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %u32 - -%f32arr = OpTypeArray %f32 %u32_256 -%f32arr_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %f32arr -%f32arr_cross_workgroup = OpVariable %f32arr_ptr_cross_workgroup CrossWorkgroup -%f32_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %f32 - -%f32vec2arr = OpTypeArray %f32vec2 %u32_256 -%f32vec2arr_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %f32vec2arr -%f32vec2arr_cross_workgroup = OpVariable %f32vec2arr_ptr_cross_workgroup CrossWorkgroup -%f32vec2_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %f32vec2 - -%struct_arr = OpTypeArray %struct_f32_f32 %u32_256 -%struct_arr_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %struct_arr -%struct_arr_cross_workgroup = OpVariable %struct_arr_ptr_cross_workgroup CrossWorkgroup -%struct_ptr_cross_workgroup = OpTypePointer CrossWorkgroup %struct_f32_f32 - -%f16vec8_ptr_uniform_constant = OpTypePointer UniformConstant %f16vec8 -%f16vec8_uniform_constant = OpVariable %f16vec8_ptr_uniform_constant UniformConstant -%f16_ptr_uniform_constant = OpTypePointer UniformConstant %f16 - -%u32vec8_ptr_uniform_constant = OpTypePointer UniformConstant %u32vec8 -%u32vec8_uniform_constant = OpVariable %u32vec8_ptr_uniform_constant UniformConstant -%u32_ptr_uniform_constant = OpTypePointer UniformConstant %u32 - -%f32vec8_ptr_uniform_constant = OpTypePointer UniformConstant %f32vec8 -%f32vec8_uniform_constant = OpVariable %f32vec8_ptr_uniform_constant UniformConstant -%f32_ptr_uniform_constant = OpTypePointer UniformConstant %f32 - -%f16vec8_ptr_input = OpTypePointer Input %f16vec8 -%f16vec8_input = OpVariable %f16vec8_ptr_input Input -%f16_ptr_input = OpTypePointer Input %f16 - -%u32vec8_ptr_input = OpTypePointer Input %u32vec8 -%u32vec8_input = OpVariable %u32vec8_ptr_input Input -%u32_ptr_input = OpTypePointer Input %u32 - -%f32_ptr_generic = OpTypePointer Generic %f32 -%u32_ptr_generic = OpTypePointer Generic %u32 - -%f32_ptr_function = OpTypePointer Function %f32 -%f32vec2_ptr_function = OpTypePointer Function %f32vec2 -%u32_ptr_function = OpTypePointer Function %u32 -%u64_ptr_function = OpTypePointer Function %u64 -%u32vec2_ptr_function = OpTypePointer Function %u32vec2 - -%u8arr = OpTypeArray %u8 %u32_256 -%u8arr_ptr_uniform_constant = OpTypePointer UniformConstant %u8arr -%u8arr_uniform_constant = OpVariable %u8arr_ptr_uniform_constant UniformConstant -%u8_ptr_uniform_constant = OpTypePointer UniformConstant %u8 -%u8_ptr_generic = OpTypePointer Generic %u8 - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -TEST_P(ValidateGlslStd450SqrtLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32_0\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01\n"; - ss << "%val3 = OpExtInst %f64 %extinst " << ext_inst_name << " %f64_0\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450SqrtLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a float scalar " - "or vector type")); -} - -TEST_P(ValidateGlslStd450SqrtLike, IntOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllSqrtLike, ValidateGlslStd450SqrtLike, - ::testing::ValuesIn(std::vector{ - "Round", - "RoundEven", - "FAbs", - "Trunc", - "FSign", - "Floor", - "Ceil", - "Fract", - "Sqrt", - "InverseSqrt", - "Normalize", - })); - -TEST_P(ValidateGlslStd450FMinLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %f32vec2_12\n"; - ss << "%val3 = OpExtInst %f64 %extinst " << ext_inst_name - << " %f64_0 %f64_0\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450FMinLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a float scalar " - "or vector type")); -} - -TEST_P(ValidateGlslStd450FMinLike, IntOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateGlslStd450FMinLike, IntOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllFMinLike, ValidateGlslStd450FMinLike, - ::testing::ValuesIn(std::vector{ - "FMin", - "FMax", - "Step", - "Reflect", - "NMin", - "NMax", - })); - -TEST_P(ValidateGlslStd450FClampLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1 %f32_2\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %f32vec2_01 %f32vec2_12\n"; - ss << "%val3 = OpExtInst %f64 %extinst " << ext_inst_name - << " %f64_0 %f64_0 %f64_1\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450FClampLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32_0 %f32_1 %f32_2\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a float scalar " - "or vector type")); -} - -TEST_P(ValidateGlslStd450FClampLike, IntOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateGlslStd450FClampLike, IntOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateGlslStd450FClampLike, IntOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f32_1 %f32_0 %u32_2\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllFClampLike, ValidateGlslStd450FClampLike, - ::testing::ValuesIn(std::vector{ - "FClamp", - "FMix", - "SmoothStep", - "Fma", - "FaceForward", - "NClamp", - })); - -TEST_P(ValidateGlslStd450SAbsLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %s32 %extinst " << ext_inst_name << " %u32_1\n"; - ss << "%val2 = OpExtInst %s32 %extinst " << ext_inst_name << " %s32_1\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name << " %u32_1\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name << " %s32_1\n"; - ss << "%val5 = OpExtInst %s32vec2 %extinst " << ext_inst_name - << " %s32vec2_01\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %s32vec2_01\n"; - ss << "%val8 = OpExtInst %s32vec2 %extinst " << ext_inst_name - << " %u32vec2_01\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450SAbsLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be an int scalar " - "or vector type")); -} - -TEST_P(ValidateGlslStd450SAbsLike, FloatOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + " %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to be int scalars or " - "vectors")); -} - -TEST_P(ValidateGlslStd450SAbsLike, WrongDimOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + " %s32vec2_01\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same dimension as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450SAbsLike, WrongBitWidthOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s64 %extinst " + ext_inst_name + " %s32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same bit width as " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllSAbsLike, ValidateGlslStd450SAbsLike, - ::testing::ValuesIn(std::vector{ - "SAbs", - "SSign", - "FindILsb", - "FindUMsb", - "FindSMsb", - })); - -TEST_F(ValidateExtInst, FindUMsbNot32Bit) { - const std::string body = R"( -%val1 = OpExtInst %s64 %extinst FindUMsb %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FindUMsb: this instruction is currently " - "limited to 32-bit width components")); -} - -TEST_F(ValidateExtInst, FindSMsbNot32Bit) { - const std::string body = R"( -%val1 = OpExtInst %s64 %extinst FindSMsb %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FindSMsb: this instruction is currently " - "limited to 32-bit width components")); -} - -TEST_P(ValidateGlslStd450UMinLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %s32 %extinst " << ext_inst_name - << " %u32_1 %s32_2\n"; - ss << "%val2 = OpExtInst %s32 %extinst " << ext_inst_name - << " %s32_1 %u32_2\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %s32_2\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name - << " %s32_1 %u32_2\n"; - ss << "%val5 = OpExtInst %s32vec2 %extinst " << ext_inst_name - << " %s32vec2_01 %u32vec2_01\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %s32vec2_01\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %s32vec2_01 %u32vec2_01\n"; - ss << "%val8 = OpExtInst %s32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %s32vec2_01\n"; - ss << "%val9 = OpExtInst %s64 %extinst " << ext_inst_name - << " %u64_1 %s64_0\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450UMinLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0 %u32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be an int scalar " - "or vector type")); -} - -TEST_P(ValidateGlslStd450UMinLike, FloatOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + " %f32_0 %u32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to be int scalars or " - "vectors")); -} - -TEST_P(ValidateGlslStd450UMinLike, FloatOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + " %u32_0 %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to be int scalars or " - "vectors")); -} - -TEST_P(ValidateGlslStd450UMinLike, WrongDimOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %s32vec2_01 %s32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same dimension as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UMinLike, WrongDimOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %s32_0 %s32vec2_01\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same dimension as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UMinLike, WrongBitWidthOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s64 %extinst " + ext_inst_name + " %s32_0 %s64_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same bit width as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UMinLike, WrongBitWidthOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %s64 %extinst " + ext_inst_name + " %s64_0 %s32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same bit width as " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUMinLike, ValidateGlslStd450UMinLike, - ::testing::ValuesIn(std::vector{ - "UMin", - "SMin", - "UMax", - "SMax", - })); - -TEST_P(ValidateGlslStd450UClampLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %s32 %extinst " << ext_inst_name - << " %s32_0 %u32_1 %s32_2\n"; - ss << "%val2 = OpExtInst %s32 %extinst " << ext_inst_name - << " %u32_0 %s32_1 %u32_2\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name - << " %s32_0 %u32_1 %s32_2\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %s32_1 %u32_2\n"; - ss << "%val5 = OpExtInst %s32vec2 %extinst " << ext_inst_name - << " %s32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %s32vec2_01 %s32vec2_12\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %s32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val8 = OpExtInst %s32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %s32vec2_01 %s32vec2_12\n"; - ss << "%val9 = OpExtInst %s64 %extinst " << ext_inst_name - << " %u64_1 %s64_0 %s64_1\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450UClampLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be an int scalar " - "or vector type")); -} - -TEST_P(ValidateGlslStd450UClampLike, FloatOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to be int scalars or " - "vectors")); -} - -TEST_P(ValidateGlslStd450UClampLike, FloatOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to be int scalars or " - "vectors")); -} - -TEST_P(ValidateGlslStd450UClampLike, FloatOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to be int scalars or " - "vectors")); -} - -TEST_P(ValidateGlslStd450UClampLike, WrongDimOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %s32vec2_01 %s32_0 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same dimension as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UClampLike, WrongDimOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %s32_0 %s32vec2_01 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same dimension as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UClampLike, WrongDimOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s32 %extinst " + ext_inst_name + - " %s32_0 %u32_1 %s32vec2_01\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same dimension as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UClampLike, WrongBitWidthOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s64 %extinst " + ext_inst_name + - " %s32_0 %s64_0 %s64_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same bit width as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UClampLike, WrongBitWidthOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s64 %extinst " + ext_inst_name + - " %s64_0 %s32_0 %s64_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same bit width as " - "Result Type")); -} - -TEST_P(ValidateGlslStd450UClampLike, WrongBitWidthOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %s64 %extinst " + ext_inst_name + - " %s64_0 %s64_0 %s32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected all operands to have the same bit width as " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUClampLike, ValidateGlslStd450UClampLike, - ::testing::ValuesIn(std::vector{ - "UClamp", - "SClamp", - })); - -TEST_P(ValidateGlslStd450SinLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32_0\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450SinLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a 16 or 32-bit scalar " - "or vector float type")); -} - -TEST_P(ValidateGlslStd450SinLike, F64ResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f64 %extinst " + ext_inst_name + " %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a 16 or 32-bit scalar " - "or vector float type")); -} - -TEST_P(ValidateGlslStd450SinLike, IntOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllSinLike, ValidateGlslStd450SinLike, - ::testing::ValuesIn(std::vector{ - "Radians", - "Degrees", - "Sin", - "Cos", - "Tan", - "Asin", - "Acos", - "Atan", - "Sinh", - "Cosh", - "Tanh", - "Asinh", - "Acosh", - "Atanh", - "Exp", - "Exp2", - "Log", - "Log2", - })); - -TEST_P(ValidateGlslStd450PowLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_1 %f32_1\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %f32vec2_12\n"; - CompileSuccessfully(GenerateShaderCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450PowLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_1 %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a 16 or 32-bit scalar " - "or vector float type")); -} - -TEST_P(ValidateGlslStd450PowLike, F64ResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f64 %extinst " + ext_inst_name + " %f32_1 %f32_0\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected Result Type to be a 16 or 32-bit scalar " - "or vector float type")); -} - -TEST_P(ValidateGlslStd450PowLike, IntOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateGlslStd450PowLike, IntOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllPowLike, ValidateGlslStd450PowLike, - ::testing::ValuesIn(std::vector{ - "Atan2", - "Pow", - })); - -TEST_F(ValidateExtInst, GlslStd450DeterminantSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Determinant %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450DeterminantIncompatibleResultType) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst Determinant %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Determinant: " - "expected operand X component type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450DeterminantNotMatrix) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Determinant %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Determinant: " - "expected operand X to be a square matrix")); -} - -TEST_F(ValidateExtInst, GlslStd450DeterminantMatrixNotSquare) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Determinant %f32mat23_121212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Determinant: " - "expected operand X to be a square matrix")); -} - -TEST_F(ValidateExtInst, GlslStd450MatrixInverseSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32mat22 %extinst MatrixInverse %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450MatrixInverseIncompatibleResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32mat33 %extinst MatrixInverse %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 MatrixInverse: " - "expected operand X type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450MatrixInverseNotMatrix) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst MatrixInverse %f32mat22_1212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 MatrixInverse: " - "expected Result Type to be a square matrix")); -} - -TEST_F(ValidateExtInst, GlslStd450MatrixInverseMatrixNotSquare) { - const std::string body = R"( -%val1 = OpExtInst %f32mat23 %extinst MatrixInverse %f32mat23_121212 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 MatrixInverse: " - "expected Result Type to be a square matrix")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Modf %f32_h %f32_output -%val2 = OpExtInst %f32vec2 %extinst Modf %f32vec2_01 %f32vec2_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450ModfIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst Modf %f32_h %f32_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Modf: " - "expected Result Type to be a scalar or vector " - "float type")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfXNotOfResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Modf %f64_0 %f32_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Modf: " - "expected operand X type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfINotPointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Modf %f32_h %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Modf: " - "expected operand I to be a pointer")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfIDataNotOfResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Modf %f32_h %f32vec2_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Modf: " - "expected operand I data type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfStructSuccess) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_f32 %extinst ModfStruct %f32_h -%val2 = OpExtInst %struct_f32vec2_f32vec2 %extinst ModfStruct %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450ModfStructResultTypeNotStruct) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst ModfStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 ModfStruct: " - "expected Result Type to be a struct with two " - "identical scalar or vector float type members")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfStructResultTypeStructWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_f32_f32 %extinst ModfStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 ModfStruct: " - "expected Result Type to be a struct with two " - "identical scalar or vector float type members")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfStructResultTypeStructWrongFirstMember) { - const std::string body = R"( -%val1 = OpExtInst %struct_u32_f32 %extinst ModfStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 ModfStruct: " - "expected Result Type to be a struct with two " - "identical scalar or vector float type members")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfStructResultTypeStructMembersNotEqual) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_f64 %extinst ModfStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 ModfStruct: " - "expected Result Type to be a struct with two " - "identical scalar or vector float type members")); -} - -TEST_F(ValidateExtInst, GlslStd450ModfStructXWrongType) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_f32 %extinst ModfStruct %f64_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 ModfStruct: " - "expected operand X type to be equal to members of " - "Result Type struct")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Frexp %f32_h %u32_output -%val2 = OpExtInst %f32vec2 %extinst Frexp %f32vec2_01 %u32vec2_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst Frexp %f32_h %u32_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Frexp: " - "expected Result Type to be a scalar or vector " - "float type")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpWrongXType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Frexp %u32_1 %u32_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Frexp: " - "expected operand X type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpExpNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Frexp %f32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Frexp: " - "expected operand Exp to be a pointer")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpExpNotInt32Pointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Frexp %f32_1 %f32_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Frexp: " - "expected operand Exp data type to be a 32-bit int " - "scalar or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpExpWrongComponentNumber) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Frexp %f32vec2_01 %u32_output -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Frexp: " - "expected operand Exp data type to have the same " - "component number as Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450LdexpSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Ldexp %f32_h %u32_2 -%val2 = OpExtInst %f32vec2 %extinst Ldexp %f32vec2_01 %u32vec2_12 -%val3 = OpExtInst %f32 %extinst Ldexp %f32_h %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450LdexpIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst Ldexp %f32_h %u32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Ldexp: " - "expected Result Type to be a scalar or vector " - "float type")); -} - -TEST_F(ValidateExtInst, GlslStd450LdexpWrongXType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Ldexp %u32_1 %u32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Ldexp: " - "expected operand X type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450LdexpFloatExp) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Ldexp %f32_1 %f32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Ldexp: " - "expected operand Exp to be a 32-bit int scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450LdexpExpWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Ldexp %f32vec2_12 %u32_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Ldexp: " - "expected operand Exp to have the same component " - "number as Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpStructSuccess) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_u32 %extinst FrexpStruct %f32_h -%val2 = OpExtInst %struct_f32vec2_u32vec2 %extinst FrexpStruct %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpStructResultTypeNotStruct) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst FrexpStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FrexpStruct: " - "expected Result Type to be a struct with two members, " - "first member a float scalar or vector, second member " - "a 32-bit int scalar or vector with the same number of " - "components as the first member")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpStructResultTypeStructWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_u32_f32 %extinst FrexpStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FrexpStruct: " - "expected Result Type to be a struct with two members, " - "first member a float scalar or vector, second member " - "a 32-bit int scalar or vector with the same number of " - "components as the first member")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpStructResultTypeStructWrongMember1) { - const std::string body = R"( -%val1 = OpExtInst %struct_u32_u32 %extinst FrexpStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FrexpStruct: " - "expected Result Type to be a struct with two members, " - "first member a float scalar or vector, second member " - "a 32-bit int scalar or vector with the same number of " - "components as the first member")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpStructResultTypeStructWrongMember2) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_f32 %extinst FrexpStruct %f32_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FrexpStruct: " - "expected Result Type to be a struct with two members, " - "first member a float scalar or vector, second member " - "a 32-bit int scalar or vector with the same number of " - "components as the first member")); -} - -TEST_F(ValidateExtInst, GlslStd450FrexpStructXWrongType) { - const std::string body = R"( -%val1 = OpExtInst %struct_f32_u32 %extinst FrexpStruct %f64_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FrexpStruct: " - "expected operand X type to be equal to the first " - "member of Result Type struct")); -} - -TEST_F(ValidateExtInst, - GlslStd450FrexpStructResultTypeStructRightInt16Member2) { - const std::string body = R"( -%val1 = OpExtInst %struct_f16_u16 %extinst FrexpStruct %f16_h -)"; - - const std::string extension = R"( -OpExtension "SPV_AMD_gpu_shader_int16" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extension)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, - GlslStd450FrexpStructResultTypeStructWrongInt16Member2) { - const std::string body = R"( -%val1 = OpExtInst %struct_f16_u16 %extinst FrexpStruct %f16_h -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 FrexpStruct: " - "expected Result Type to be a struct with two members, " - "first member a float scalar or vector, second member " - "a 32-bit int scalar or vector with the same number of " - "components as the first member")); -} - -TEST_P(ValidateGlslStd450Pack, Success) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string vec_str = - num_components == 2 ? " %f32vec2_01\n" : " %f32vec4_0123\n"; - - std::ostringstream body; - body << "%val1 = OpExtInst %u" << total_bit_width << " %extinst " - << ext_inst_name << vec_str; - body << "%val2 = OpExtInst %s" << total_bit_width << " %extinst " - << ext_inst_name << vec_str; - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450Pack, Float32ResultType) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string vec_str = - num_components == 2 ? " %f32vec2_01\n" : " %f32vec4_0123\n"; - - std::ostringstream body; - body << "%val1 = OpExtInst %f" << total_bit_width << " %extinst " - << ext_inst_name << vec_str; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected Result Type to be " << total_bit_width - << "-bit int scalar type"; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Pack, Int16ResultType) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string vec_str = - num_components == 2 ? " %f32vec2_01\n" : " %f32vec4_0123\n"; - - std::ostringstream body; - body << "%val1 = OpExtInst %u16 %extinst " << ext_inst_name << vec_str; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected Result Type to be " << total_bit_width - << "-bit int scalar type"; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Pack, VNotVector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - - std::ostringstream body; - body << "%val1 = OpExtInst %u" << total_bit_width << " %extinst " - << ext_inst_name << " %f32_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected operand V to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Pack, VNotFloatVector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string vec_str = - num_components == 2 ? " %u32vec2_01\n" : " %u32vec4_0123\n"; - - std::ostringstream body; - body << "%val1 = OpExtInst %u" << total_bit_width << " %extinst " - << ext_inst_name << vec_str; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected operand V to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Pack, VNotFloat32Vector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string vec_str = - num_components == 2 ? " %f64vec2_01\n" : " %f64vec4_0123\n"; - - std::ostringstream body; - body << "%val1 = OpExtInst %u" << total_bit_width << " %extinst " - << ext_inst_name << vec_str; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected operand V to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Pack, VWrongSizeVector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string vec_str = - num_components == 4 ? " %f32vec2_01\n" : " %f32vec4_0123\n"; - - std::ostringstream body; - body << "%val1 = OpExtInst %u" << total_bit_width << " %extinst " - << ext_inst_name << vec_str; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected operand V to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -INSTANTIATE_TEST_SUITE_P(AllPack, ValidateGlslStd450Pack, - ::testing::ValuesIn(std::vector{ - "PackSnorm4x8", - "PackUnorm4x8", - "PackSnorm2x16", - "PackUnorm2x16", - "PackHalf2x16", - })); - -TEST_F(ValidateExtInst, PackDouble2x32Success) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst PackDouble2x32 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, PackDouble2x32Float32ResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst PackDouble2x32 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 PackDouble2x32: expected Result Type to " - "be 64-bit float scalar type")); -} - -TEST_F(ValidateExtInst, PackDouble2x32Int64ResultType) { - const std::string body = R"( -%val1 = OpExtInst %u64 %extinst PackDouble2x32 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 PackDouble2x32: expected Result Type to " - "be 64-bit float scalar type")); -} - -TEST_F(ValidateExtInst, PackDouble2x32VNotVector) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst PackDouble2x32 %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 PackDouble2x32: expected operand V to be " - "a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, PackDouble2x32VNotIntVector) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst PackDouble2x32 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 PackDouble2x32: expected operand V to be " - "a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, PackDouble2x32VNotInt32Vector) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst PackDouble2x32 %u64vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 PackDouble2x32: expected operand V to be " - "a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, PackDouble2x32VWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst PackDouble2x32 %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 PackDouble2x32: expected operand V to be " - "a 32-bit int vector of size 2")); -} - -TEST_P(ValidateGlslStd450Unpack, Success) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string result_type_str = - num_components == 2 ? "%f32vec2" : " %f32vec4"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %u" << total_bit_width << "_1\n"; - body << "%val2 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %s" << total_bit_width << "_1\n"; - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateGlslStd450Unpack, ResultTypeNotVector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string result_type_str = "%f32"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %u" << total_bit_width << "_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected Result Type to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Unpack, ResultTypeNotFloatVector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string result_type_str = - num_components == 2 ? "%u32vec2" : " %u32vec4"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %u" << total_bit_width << "_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected Result Type to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Unpack, ResultTypeNotFloat32Vector) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string result_type_str = - num_components == 2 ? "%f64vec2" : " %f64vec4"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %u" << total_bit_width << "_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected Result Type to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Unpack, ResultTypeWrongSize) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string result_type_str = - num_components == 4 ? "%f32vec2" : " %f32vec4"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %u" << total_bit_width << "_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected Result Type to be a 32-bit float vector of size " - << num_components; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Unpack, ResultPNotInt) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const std::string result_type_str = - num_components == 2 ? "%f32vec2" : " %f32vec4"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %f" << total_bit_width << "_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected operand P to be a " << total_bit_width - << "-bit int scalar"; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -TEST_P(ValidateGlslStd450Unpack, ResultPWrongBitWidth) { - const std::string ext_inst_name = GetParam(); - const uint32_t num_components = GetPackedNumComponents(ext_inst_name); - const uint32_t packed_bit_width = GetPackedBitWidth(ext_inst_name); - const uint32_t total_bit_width = num_components * packed_bit_width; - const uint32_t wrong_bit_width = total_bit_width == 32 ? 64 : 32; - const std::string result_type_str = - num_components == 2 ? "%f32vec2" : " %f32vec4"; - - std::ostringstream body; - body << "%val1 = OpExtInst " << result_type_str << " %extinst " - << ext_inst_name << " %u" << wrong_bit_width << "_1\n"; - - std::ostringstream expected; - expected << "GLSL.std.450 " << ext_inst_name - << ": expected operand P to be a " << total_bit_width - << "-bit int scalar"; - - CompileSuccessfully(GenerateShaderCode(body.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected.str())); -} - -INSTANTIATE_TEST_SUITE_P(AllUnpack, ValidateGlslStd450Unpack, - ::testing::ValuesIn(std::vector{ - "UnpackSnorm4x8", - "UnpackUnorm4x8", - "UnpackSnorm2x16", - "UnpackUnorm2x16", - "UnpackHalf2x16", - })); - -TEST_F(ValidateExtInst, UnpackDouble2x32Success) { - const std::string body = R"( -%val1 = OpExtInst %u32vec2 %extinst UnpackDouble2x32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, UnpackDouble2x32ResultTypeNotVector) { - const std::string body = R"( -%val1 = OpExtInst %u64 %extinst UnpackDouble2x32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 UnpackDouble2x32: expected Result Type " - "to be a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, UnpackDouble2x32ResultTypeNotIntVector) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst UnpackDouble2x32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 UnpackDouble2x32: expected Result Type " - "to be a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, UnpackDouble2x32ResultTypeNotInt32Vector) { - const std::string body = R"( -%val1 = OpExtInst %u64vec2 %extinst UnpackDouble2x32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 UnpackDouble2x32: expected Result Type " - "to be a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, UnpackDouble2x32ResultTypeWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %u32vec4 %extinst UnpackDouble2x32 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 UnpackDouble2x32: expected Result Type " - "to be a 32-bit int vector of size 2")); -} - -TEST_F(ValidateExtInst, UnpackDouble2x32VNotFloat) { - const std::string body = R"( -%val1 = OpExtInst %u32vec2 %extinst UnpackDouble2x32 %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 UnpackDouble2x32: expected operand V to " - "be a 64-bit float scalar")); -} - -TEST_F(ValidateExtInst, UnpackDouble2x32VNotFloat64) { - const std::string body = R"( -%val1 = OpExtInst %u32vec2 %extinst UnpackDouble2x32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 UnpackDouble2x32: expected operand V to " - "be a 64-bit float scalar")); -} - -TEST_F(ValidateExtInst, GlslStd450LengthSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Length %f32_1 -%val2 = OpExtInst %f32 %extinst Length %f32vec2_01 -%val3 = OpExtInst %f32 %extinst Length %f32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450LengthIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst Length %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Length: " - "expected Result Type to be a float scalar type")); -} - -TEST_F(ValidateExtInst, GlslStd450LengthIntX) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Length %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Length: " - "expected operand X to be of float scalar or " - "vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450LengthDifferentType) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst Length %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Length: " - "expected operand X component type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Distance %f32_0 %f32_1 -%val2 = OpExtInst %f32 %extinst Distance %f32vec2_01 %f32vec2_12 -%val3 = OpExtInst %f32 %extinst Distance %f32vec4_0123 %f32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst Distance %f32vec2_01 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Distance: " - "expected Result Type to be a float scalar type")); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceIntP0) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Distance %u32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Distance: " - "expected operand P0 to be of float scalar or " - "vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceF64VectorP0) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Distance %f64vec2_01 %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Distance: " - "expected operand P0 component type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceIntP1) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Distance %f32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Distance: " - "expected operand P1 to be of float scalar or " - "vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceF64VectorP1) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Distance %f32vec2_12 %f64vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Distance: " - "expected operand P1 component type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450DistanceDifferentSize) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Distance %f32vec2_01 %f32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Distance: " - "expected operands P0 and P1 to have the same number " - "of components")); -} - -TEST_F(ValidateExtInst, GlslStd450CrossSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst Cross %f32vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450CrossIntVectorResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32vec3 %extinst Cross %f32vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Cross: " - "expected Result Type to be a float vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450CrossResultTypeWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Cross %f32vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Cross: " - "expected Result Type to have 3 components")); -} - -TEST_F(ValidateExtInst, GlslStd450CrossXWrongType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst Cross %f64vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Cross: " - "expected operand X type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450CrossYWrongType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst Cross %f32vec3_123 %f64vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Cross: " - "expected operand Y type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450RefractSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst Refract %f32_1 %f32_1 %f32_1 -%val2 = OpExtInst %f32vec2 %extinst Refract %f32vec2_01 %f32vec2_01 %f16_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450RefractIntVectorResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32vec2 %extinst Refract %f32vec2_01 %f32vec2_01 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Refract: " - "expected Result Type to be a float scalar or " - "vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450RefractIntVectorI) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Refract %u32vec2_01 %f32vec2_01 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Refract: " - "expected operand I to be of type equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450RefractIntVectorN) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Refract %f32vec2_01 %u32vec2_01 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Refract: " - "expected operand N to be of type equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450RefractIntEta) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Refract %f32vec2_01 %f32vec2_01 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Refract: " - "expected operand Eta to be a float scalar")); -} - -TEST_F(ValidateExtInst, GlslStd450RefractFloat64Eta) { - // SPIR-V issue 337: Eta can be 64-bit float scalar. - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Refract %f32vec2_01 %f32vec2_01 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateExtInst, GlslStd450RefractVectorEta) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst Refract %f32vec2_01 %f32vec2_01 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 Refract: " - "expected operand Eta to be a float scalar")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32_input -%val2 = OpExtInst %f32vec2 %extinst InterpolateAtCentroid %f32vec2_input -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidNoCapability) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32_input -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid requires " - "capability InterpolationFunction")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst InterpolateAtCentroid %f32_input -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid: " - "expected Result Type to be a 32-bit float scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidF64ResultType) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst InterpolateAtCentroid %f32_input -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid: " - "expected Result Type to be a 32-bit float scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid: " - "expected Interpolant to be a pointer")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidWrongDataType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32vec2_input -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid: " - "expected Interpolant data type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidWrongStorageClass) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32_output -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid: " - "expected Interpolant storage class to be Input")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidWrongExecutionModel) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32_input -)"; - - CompileSuccessfully(GenerateShaderCode( - body, "OpCapability InterpolationFunction\n", "Vertex")); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtCentroid requires " - "Fragment execution model")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_input %u32_1 -%val2 = OpExtInst %f32vec2 %extinst InterpolateAtSample %f32vec2_input %u32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleNoCapability) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_input %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample requires " - "capability InterpolationFunction")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst InterpolateAtSample %f32_input %u32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Result Type to be a 32-bit float scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleF64ResultType) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst InterpolateAtSample %f32_input %u32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Result Type to be a 32-bit float scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_1 %u32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Interpolant to be a pointer")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleWrongDataType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32vec2_input %u32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Interpolant data type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleWrongStorageClass) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_output %u32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Interpolant storage class to be Input")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleFloatSample) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_input %f32_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Sample to be 32-bit integer")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleU64Sample) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_input %u64_1 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample: " - "expected Sample to be 32-bit integer")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleWrongExecutionModel) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_input %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode( - body, "OpCapability InterpolationFunction\n", "Vertex")); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtSample requires " - "Fragment execution model")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f32vec2_01 -%val2 = OpExtInst %f32vec2 %extinst InterpolateAtOffset %f32vec2_input %f32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetNoCapability) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset requires " - "capability InterpolationFunction")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst InterpolateAtOffset %f32_input %f32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Result Type to be a 32-bit float scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetF64ResultType) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst InterpolateAtOffset %f32_input %f32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Result Type to be a 32-bit float scalar " - "or vector type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_1 %f32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Interpolant to be a pointer")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetWrongDataType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32vec2_input %f32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Interpolant data type to be equal to " - "Result Type")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetWrongStorageClass) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_output %f32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Interpolant storage class to be Input")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetOffsetNotVector) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f32_0 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Offset to be a vector of 2 32-bit floats")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetOffsetNotVector2) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f32vec3_012 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Offset to be a vector of 2 32-bit floats")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetOffsetNotFloatVector) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %u32vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Offset to be a vector of 2 32-bit floats")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetOffsetNotFloat32Vector) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f64vec2_01 -)"; - - CompileSuccessfully( - GenerateShaderCode(body, "OpCapability InterpolationFunction\n")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset: " - "expected Offset to be a vector of 2 32-bit floats")); -} - -TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetWrongExecutionModel) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode( - body, "OpCapability InterpolationFunction\n", "Vertex")); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("GLSL.std.450 InterpolateAtOffset requires " - "Fragment execution model")); -} - -TEST_P(ValidateOpenCLStdSqrtLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32_0\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01\n"; - ss << "%val3 = OpExtInst %f32vec4 %extinst " << ext_inst_name - << " %f32vec4_0123\n"; - ss << "%val4 = OpExtInst %f64 %extinst " << ext_inst_name << " %f64_0\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdSqrtLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float scalar " - "or vector type")); -} - -TEST_P(ValidateOpenCLStdSqrtLike, IntOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P( - AllSqrtLike, ValidateOpenCLStdSqrtLike, - ::testing::ValuesIn(std::vector{ - "acos", "acosh", "acospi", "asin", - "asinh", "asinpi", "atan", "atanh", - "atanpi", "cbrt", "ceil", "cos", - "cosh", "cospi", "erfc", "erf", - "exp", "exp2", "exp10", "expm1", - "fabs", "floor", "log", "log2", - "log10", "log1p", "logb", "rint", - "round", "rsqrt", "sin", "sinh", - "sinpi", "sqrt", "tan", "tanh", - "tanpi", "tgamma", "trunc", "half_cos", - "half_exp", "half_exp2", "half_exp10", "half_log", - "half_log2", "half_log10", "half_recip", "half_rsqrt", - "half_sin", "half_sqrt", "half_tan", "lgamma", - "native_cos", "native_exp", "native_exp2", "native_exp10", - "native_log", "native_log2", "native_log10", "native_recip", - "native_rsqrt", "native_sin", "native_sqrt", "native_tan", - "degrees", "radians", "sign", - })); - -TEST_P(ValidateOpenCLStdFMinLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %f32vec2_12\n"; - ss << "%val3 = OpExtInst %f64 %extinst " << ext_inst_name - << " %f64_0 %f64_0\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdFMinLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float scalar " - "or vector type")); -} - -TEST_P(ValidateOpenCLStdFMinLike, IntOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateOpenCLStdFMinLike, IntOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllFMinLike, ValidateOpenCLStdFMinLike, - ::testing::ValuesIn(std::vector{ - "atan2", "atan2pi", "copysign", - "fdim", "fmax", "fmin", - "fmod", "maxmag", "minmag", - "hypot", "nextafter", "pow", - "powr", "remainder", "half_divide", - "half_powr", "native_divide", "native_powr", - "step", "fmax_common", "fmin_common", - })); - -TEST_P(ValidateOpenCLStdFClampLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1 %f32_2\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %f32vec2_01 %f32vec2_12\n"; - ss << "%val3 = OpExtInst %f64 %extinst " << ext_inst_name - << " %f64_0 %f64_0 %f64_1\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdFClampLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32_0 %f32_1 %f32_2\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float scalar " - "or vector type")); -} - -TEST_P(ValidateOpenCLStdFClampLike, IntOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateOpenCLStdFClampLike, IntOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -TEST_P(ValidateOpenCLStdFClampLike, IntOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f32_1 %f32_0 %u32_2\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllFClampLike, ValidateOpenCLStdFClampLike, - ::testing::ValuesIn(std::vector{ - "fma", - "mad", - "fclamp", - "mix", - "smoothstep", - })); - -TEST_P(ValidateOpenCLStdSAbsLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name << " %u32_1\n"; - ss << "%val2 = OpExtInst %u32 %extinst " << ext_inst_name << " %u32_1\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name << " %u32_1\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name << " %u32_1\n"; - ss << "%val5 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01\n"; - ss << "%val8 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdSAbsLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be an int scalar " - "or vector type")); -} - -TEST_P(ValidateOpenCLStdSAbsLike, FloatOperand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdSAbsLike, U64Operand) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u64_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllSAbsLike, ValidateOpenCLStdSAbsLike, - ::testing::ValuesIn(std::vector{ - "s_abs", - "clz", - "ctz", - "popcount", - "u_abs", - })); - -TEST_P(ValidateOpenCLStdUMinLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val2 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val5 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val8 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val9 = OpExtInst %u64 %extinst " << ext_inst_name - << " %u64_1 %u64_0\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdUMinLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0 %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be an int scalar " - "or vector type")); -} - -TEST_P(ValidateOpenCLStdUMinLike, FloatOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0 %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMinLike, FloatOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u32_0 %f32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMinLike, U64Operand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u64_0 %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMinLike, U64Operand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u32_0 %u64_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUMinLike, ValidateOpenCLStdUMinLike, - ::testing::ValuesIn(std::vector{ - "s_max", - "u_max", - "s_min", - "u_min", - "s_abs_diff", - "s_add_sat", - "u_add_sat", - "s_mul_hi", - "rotate", - "s_sub_sat", - "u_sub_sat", - "s_hadd", - "u_hadd", - "s_rhadd", - "u_rhadd", - "u_abs_diff", - "u_mul_hi", - })); - -TEST_P(ValidateOpenCLStdUClampLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val2 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val5 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val8 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val9 = OpExtInst %u64 %extinst " << ext_inst_name - << " %u64_1 %u64_0 %u64_1\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdUClampLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be an int scalar " - "or vector type")); -} - -TEST_P(ValidateOpenCLStdUClampLike, FloatOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUClampLike, FloatOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUClampLike, FloatOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUClampLike, U64Operand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUClampLike, U64Operand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUClampLike, U64Operand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUClampLike, ValidateOpenCLStdUClampLike, - ::testing::ValuesIn(std::vector{ - "s_clamp", - "u_clamp", - "s_mad_hi", - "u_mad_sat", - "s_mad_sat", - "u_mad_hi", - })); - -// ------------------------------------------------------------- -TEST_P(ValidateOpenCLStdUMul24Like, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val2 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val5 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - ss << "%val8 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdUMul24Like, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32_0 %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": expected Result Type to be a 32-bit int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdUMul24Like, U64ResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u64 %extinst " + ext_inst_name + " %u64_0 %u64_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": expected Result Type to be a 32-bit int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdUMul24Like, FloatOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_0 %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMul24Like, FloatOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u32_0 %f32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMul24Like, U64Operand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u64_0 %u32_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMul24Like, U64Operand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %u32_0 %u64_0\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUMul24Like, ValidateOpenCLStdUMul24Like, - ::testing::ValuesIn(std::vector{ - "s_mul24", - "u_mul24", - })); - -TEST_P(ValidateOpenCLStdUMad24Like, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val2 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val3 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val4 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u32_0 %u32_1 %u32_2\n"; - ss << "%val5 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val6 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val7 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - ss << "%val8 = OpExtInst %u32vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01 %u32vec2_12\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdUMad24Like, FloatResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": expected Result Type to be a 32-bit int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, U64ResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u64 %extinst " + ext_inst_name + - " %u64_0 %u64_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": expected Result Type to be a 32-bit int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, FloatOperand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, FloatOperand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, FloatOperand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, U64Operand1) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32_0 %u32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, U64Operand2) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %f32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdUMad24Like, U64Operand3) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %u32_0 %u32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected types of all operands to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUMad24Like, ValidateOpenCLStdUMad24Like, - ::testing::ValuesIn(std::vector{ - "s_mad24", - "u_mad24", - })); - -TEST_F(ValidateExtInst, OpenCLStdCrossSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst cross %f32vec3_012 %f32vec3_123 -%val2 = OpExtInst %f32vec4 %extinst cross %f32vec4_0123 %f32vec4_0123 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdCrossIntVectorResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32vec3 %extinst cross %f32vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std cross: " - "expected Result Type to be a float vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdCrossResultTypeWrongSize) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst cross %f32vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std cross: " - "expected Result Type to have 3 or 4 components")); -} - -TEST_F(ValidateExtInst, OpenCLStdCrossXWrongType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst cross %f64vec3_012 %f32vec3_123 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std cross: " - "expected operand X type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdCrossYWrongType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst cross %f32vec3_123 %f64vec3_012 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std cross: " - "expected operand Y type to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdLengthLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32vec2_01\n"; - ss << "%val2 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32vec4_0123\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdLengthLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32vec2_01\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected Result Type to be a float scalar type")); -} - -TEST_P(ValidateOpenCLStdLengthLike, IntX) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + " %u32vec2_01\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand P to be a float scalar or vector")); -} - -TEST_P(ValidateOpenCLStdLengthLike, VectorTooBig) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f32vec8_01010101\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand P to have no more than 4 components")); -} - -TEST_P(ValidateOpenCLStdLengthLike, DifferentType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f64 %extinst " + ext_inst_name + " %f32vec2_01\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand P component type to be equal to " - "Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllLengthLike, ValidateOpenCLStdLengthLike, - ::testing::ValuesIn(std::vector{ - "length", - "fast_length", - })); - -TEST_P(ValidateOpenCLStdDistanceLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32vec2_01 %f32vec2_01\n"; - ss << "%val2 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32vec4_0123 %f32vec4_1234\n"; - ss << "%val3 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdDistanceLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + - " %f32vec2_01 %f32vec2_12\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected Result Type to be a float scalar type")); -} - -TEST_P(ValidateOpenCLStdDistanceLike, IntP0) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %u32vec2_01 %f32vec2_12\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand P0 to be of float scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdDistanceLike, VectorTooBig) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f32vec8_01010101 %f32vec8_01010101\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand P0 to have no more than 4 components")); -} - -TEST_P(ValidateOpenCLStdDistanceLike, F64P0) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32 %extinst " + ext_inst_name + - " %f64vec2_01 %f32vec2_12\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": " - "expected operand P0 component type to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdDistanceLike, DifferentOperands) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f64 %extinst " + ext_inst_name + - " %f64vec2_01 %f32vec2_12\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operands P0 and P1 to be of the same type")); -} - -INSTANTIATE_TEST_SUITE_P(AllDistanceLike, ValidateOpenCLStdDistanceLike, - ::testing::ValuesIn(std::vector{ - "distance", - "fast_distance", - })); - -TEST_P(ValidateOpenCLStdNormalizeLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01\n"; - ss << "%val2 = OpExtInst %f32vec4 %extinst " << ext_inst_name - << " %f32vec4_0123\n"; - ss << "%val3 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32_2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdNormalizeLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %u32 %extinst " + ext_inst_name + " %f32_2\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected Result Type to be a float scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdNormalizeLike, VectorTooBig) { - const std::string ext_inst_name = GetParam(); - const std::string body = "%val1 = OpExtInst %f32vec8 %extinst " + - ext_inst_name + " %f32vec8_01010101\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected Result Type to have no more than 4 components")); -} - -TEST_P(ValidateOpenCLStdNormalizeLike, DifferentType) { - const std::string ext_inst_name = GetParam(); - const std::string body = - "%val1 = OpExtInst %f64vec2 %extinst " + ext_inst_name + " %f32vec2_01\n"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand P type to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllNormalizeLike, ValidateOpenCLStdNormalizeLike, - ::testing::ValuesIn(std::vector{ - "normalize", - "fast_normalize", - })); - -TEST_F(ValidateExtInst, OpenCLStdBitselectSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst bitselect %f32_2 %f32_1 %f32_1 -%val2 = OpExtInst %f32vec4 %extinst bitselect %f32vec4_0123 %f32vec4_1234 %f32vec4_0123 -%val3 = OpExtInst %u32 %extinst bitselect %u32_2 %u32_1 %u32_1 -%val4 = OpExtInst %u32vec4 %extinst bitselect %u32vec4_0123 %u32vec4_0123 %u32vec4_0123 -%val5 = OpExtInst %u64 %extinst bitselect %u64_2 %u64_1 %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdBitselectWrongResultType) { - const std::string body = R"( -%val3 = OpExtInst %struct_f32_f32 %extinst bitselect %u32_2 %u32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std bitselect: " - "expected Result Type to be an int or float scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdBitselectAWrongType) { - const std::string body = R"( -%val3 = OpExtInst %u32 %extinst bitselect %f32_2 %u32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std bitselect: " - "expected types of all operands to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdBitselectBWrongType) { - const std::string body = R"( -%val3 = OpExtInst %u32 %extinst bitselect %u32_2 %f32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std bitselect: " - "expected types of all operands to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdBitselectCWrongType) { - const std::string body = R"( -%val3 = OpExtInst %u32 %extinst bitselect %u32_2 %u32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std bitselect: " - "expected types of all operands to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst select %f32_2 %f32_1 %u32_1 -%val2 = OpExtInst %f32vec4 %extinst select %f32vec4_0123 %f32vec4_1234 %u32vec4_0123 -%val3 = OpExtInst %u32 %extinst select %u32_2 %u32_1 %u32_1 -%val4 = OpExtInst %u32vec4 %extinst select %u32vec4_0123 %u32vec4_0123 %u32vec4_0123 -%val5 = OpExtInst %u64 %extinst select %u64_2 %u64_1 %u64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectWrongResultType) { - const std::string body = R"( -%val3 = OpExtInst %struct_f32_f32 %extinst select %u32_2 %u32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std select: " - "expected Result Type to be an int or float scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectAWrongType) { - const std::string body = R"( -%val3 = OpExtInst %u32 %extinst select %f32_2 %u32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std select: " - "expected operand A type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectBWrongType) { - const std::string body = R"( -%val3 = OpExtInst %u32 %extinst select %u32_2 %f32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std select: " - "expected operand B type to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectCWrongType) { - const std::string body = R"( -%val3 = OpExtInst %f32 %extinst select %f32_2 %f32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std select: " - "expected operand C to be an int scalar or vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectCWrongComponentNumber) { - const std::string body = R"( -%val3 = OpExtInst %f32vec2 %extinst select %f32vec2_12 %f32vec2_01 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std select: " - "expected operand C to have the same number of " - "components as Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdSelectCWrongBitWidth) { - const std::string body = R"( -%val3 = OpExtInst %f32vec2 %extinst select %f32vec2_12 %f32vec2_01 %u64vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std select: " - "expected operand C to have the same bit width as Result Type")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, SuccessPhysical32) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_1 %u32_1 %ptr" << rounding_mode << "\n"; - ss << "%val2 = OpExtInst %void %extinst " << ext_inst_name - << " %f64_0 %u32_2 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - ss << "%val2 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec4_0123 %u32_0 %ptr" << rounding_mode << "\n"; - ss << "%val3 = OpExtInst %void %extinst " << ext_inst_name - << " %f64vec2_01 %u32_2 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, SuccessPhysical64) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_1 %u64_1 %ptr" << rounding_mode << "\n"; - ss << "%val2 = OpExtInst %void %extinst " << ext_inst_name - << " %f64_0 %u64_2 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u64_1 %ptr" << rounding_mode << "\n"; - ss << "%val2 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec4_0123 %u64_0 %ptr" << rounding_mode << "\n"; - ss << "%val3 = OpExtInst %void %extinst " << ext_inst_name - << " %f64vec2_01 %u64_2 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, NonVoidResultType) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_1 %u32_1 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be void")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, WrongDataType) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f64vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Data to be a 32 or 64-bit float scalar")); - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f64_0 %u32_1 %ptr" << rounding_mode << "\n"; - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Data to be a 32 or 64-bit float vector")); - } -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, AddressingModelLogical) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_0 %u32_1 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Logical")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - " can only be used with physical addressing models")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, OffsetNotSizeT) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_0 %u32_1 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": " - "expected operand Offset to be of type size_t (64-bit integer " - "for the addressing model used in the module)")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, PNotPointer) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_0 %u32_1 %f16_ptr_workgroup" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %f16_ptr_workgroup" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 89[%_ptr_Workgroup_half] cannot be a type")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, ConstPointer) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_uniform_constant " - "%f16vec8_uniform_constant %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_0 %u32_1 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand P storage class to be Generic, " - "CrossWorkgroup, Workgroup or Function")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, PDataTypeInt) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %u32_ptr_workgroup %u32vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_0 %u32_1 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand P data type to be 16-bit float scalar")); -} - -TEST_P(ValidateOpenCLStdVStoreHalfLike, PDataTypeFloat32) { - const std::string ext_inst_name = GetParam(); - const std::string rounding_mode = - ext_inst_name.substr(ext_inst_name.length() - 2) == "_r" ? " RTE" : ""; - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - if (std::string::npos == ext_inst_name.find("halfn")) { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32_0 %u32_1 %ptr" << rounding_mode << "\n"; - } else { - ss << "%val1 = OpExtInst %void %extinst " << ext_inst_name - << " %f32vec2_01 %u32_1 %ptr" << rounding_mode << "\n"; - } - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand P data type to be 16-bit float scalar")); -} - -INSTANTIATE_TEST_SUITE_P(AllVStoreHalfLike, ValidateOpenCLStdVStoreHalfLike, - ::testing::ValuesIn(std::vector{ - "vstore_half", - "vstore_half_r", - "vstore_halfn", - "vstore_halfn_r", - "vstorea_halfn", - "vstorea_halfn_r", - })); - -TEST_P(ValidateOpenCLStdVLoadHalfLike, SuccessPhysical32) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %ptr 2\n"; - ss << "%val2 = OpExtInst %f32vec3 %extinst " << ext_inst_name - << " %u32_1 %ptr 3\n"; - ss << "%val3 = OpExtInst %f32vec4 %extinst " << ext_inst_name - << " %u32_1 %ptr 4\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, SuccessPhysical64) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u64_1 %ptr 2\n"; - ss << "%val2 = OpExtInst %f32vec3 %extinst " << ext_inst_name - << " %u64_1 %ptr 3\n"; - ss << "%val3 = OpExtInst %f32vec4 %extinst " << ext_inst_name - << " %u64_1 %ptr 4\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, ResultTypeNotFloatVector) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %u32_1 %ptr 1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float vector type")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, AddressingModelLogical) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Logical")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - " can only be used with physical addressing models")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, OffsetNotSizeT) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u64_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand Offset to be of type size_t (32-bit " - "integer for the addressing model used in the module)")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, PNotPointer) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %f16_ptr_workgroup 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 89[%_ptr_Workgroup_half] cannot be a type")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, OffsetWrongStorageType) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_input %f16vec8_input %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand P storage class to be UniformConstant, " - "Generic, CrossWorkgroup, Workgroup or Function")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, PDataTypeInt) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %u32_ptr_workgroup %u32vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand P data type to be 16-bit float scalar")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, PDataTypeFloat32) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected operand P data type to be 16-bit float scalar")); -} - -TEST_P(ValidateOpenCLStdVLoadHalfLike, WrongN) { - const std::string ext_inst_name = GetParam(); - - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_workgroup %f16vec8_workgroup %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %u32_1 %ptr 3\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected literal N to be equal to the number of " - "components of Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllVLoadHalfLike, ValidateOpenCLStdVLoadHalfLike, - ::testing::ValuesIn(std::vector{ - "vload_halfn", - "vloada_halfn", - })); - -TEST_F(ValidateExtInst, VLoadNSuccessFloatPhysical32) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst vloadn %u32_1 %ptr 2\n"; - ss << "%val2 = OpExtInst %f32vec3 %extinst vloadn %u32_1 %ptr 3\n"; - ss << "%val3 = OpExtInst %f32vec4 %extinst vloadn %u32_1 %ptr 4\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VLoadNSuccessIntPhysical32) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %u32_ptr_uniform_constant " - "%u32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %u32vec2 %extinst vloadn %u32_1 %ptr 2\n"; - ss << "%val2 = OpExtInst %u32vec3 %extinst vloadn %u32_1 %ptr 3\n"; - ss << "%val3 = OpExtInst %u32vec4 %extinst vloadn %u32_1 %ptr 4\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VLoadNSuccessFloatPhysical64) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst vloadn %u64_1 %ptr 2\n"; - ss << "%val2 = OpExtInst %f32vec3 %extinst vloadn %u64_1 %ptr 3\n"; - ss << "%val3 = OpExtInst %f32vec4 %extinst vloadn %u64_1 %ptr 4\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VLoadNSuccessIntPhysical64) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %u32_ptr_uniform_constant " - "%u32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %u32vec2 %extinst vloadn %u64_1 %ptr 2\n"; - ss << "%val2 = OpExtInst %u32vec3 %extinst vloadn %u64_1 %ptr 3\n"; - ss << "%val3 = OpExtInst %u32vec4 %extinst vloadn %u64_1 %ptr 4\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VLoadNWrongResultType) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vloadn %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std vloadn: " - "expected Result Type to be an int or float vector type")); -} - -TEST_F(ValidateExtInst, VLoadNAddressingModelLogical) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst vloadn %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Logical")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vloadn can only be used with physical " - "addressing models")); -} - -TEST_F(ValidateExtInst, VLoadNOffsetNotSizeT) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst vloadn %u64_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std vloadn: expected operand Offset to be of type size_t " - "(32-bit integer for the addressing model used in the module)")); -} - -TEST_F(ValidateExtInst, VLoadNPNotPointer) { - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32vec2 %extinst vloadn %u32_1 " - "%f32_ptr_uniform_constant 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 120[%_ptr_UniformConstant_float] cannot be a " - "type")); -} - -TEST_F(ValidateExtInst, VLoadNWrongStorageClass) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %u32_ptr_input %u32vec8_input %u32_1\n"; - ss << "%val1 = OpExtInst %u32vec2 %extinst vloadn %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vloadn: expected operand P storage class " - "to be UniformConstant, Generic, CrossWorkgroup, " - "Workgroup or Function")); -} - -TEST_F(ValidateExtInst, VLoadNWrongComponentType) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %u32vec2 %extinst vloadn %u32_1 %ptr 2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vloadn: expected operand P data type to be " - "equal to component type of Result Type")); -} - -TEST_F(ValidateExtInst, VLoadNWrongN) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst vloadn %u32_1 %ptr 3\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vloadn: expected literal N to be equal to " - "the number of components of Result Type")); -} - -TEST_F(ValidateExtInst, VLoadHalfSuccessPhysical32) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_uniform_constant " - "%f16vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u32_1 %ptr\n"; - ss << "%val2 = OpExtInst %f64 %extinst vload_half %u32_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VLoadHalfSuccessPhysical64) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_uniform_constant " - "%f16vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u64_1 %ptr\n"; - ss << "%val2 = OpExtInst %f64 %extinst vload_half %u64_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VLoadHalfWrongResultType) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_uniform_constant " - "%f16vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %u32 %extinst vload_half %u32_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vload_half: " - "expected Result Type to be a float scalar type")); -} - -TEST_F(ValidateExtInst, VLoadHalfAddressingModelLogical) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_uniform_constant " - "%f16vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u32_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Logical")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vload_half can only be used with physical " - "addressing models")); -} - -TEST_F(ValidateExtInst, VLoadHalfOffsetNotSizeT) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_uniform_constant " - "%f16vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u64_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std vload_half: expected operand Offset to be of type size_t " - "(32-bit integer for the addressing model used in the module)")); -} - -TEST_F(ValidateExtInst, VLoadHalfPNotPointer) { - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u32_1 " - "%f16_ptr_uniform_constant\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 114[%_ptr_UniformConstant_half] cannot be a " - "type")); -} - -TEST_F(ValidateExtInst, VLoadHalfWrongStorageClass) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f16_ptr_input %f16vec8_input %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u32_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std vload_half: expected operand P storage class to be " - "UniformConstant, Generic, CrossWorkgroup, Workgroup or Function")); -} - -TEST_F(ValidateExtInst, VLoadHalfPDataTypeInt) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %u32_ptr_uniform_constant " - "%u32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u32_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vload_half: expected operand P data type " - "to be 16-bit float scalar")); -} - -TEST_F(ValidateExtInst, VLoadHalfPDataTypeFloat32) { - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst vload_half %u32_1 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vload_half: expected operand P data type " - "to be 16-bit float scalar")); -} - -TEST_F(ValidateExtInst, VStoreNSuccessFloatPhysical32) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32vec2_01 %u32_1 %ptr_g\n"; - ss << "%val2 = OpExtInst %void %extinst vstoren %f32vec4_0123 %u32_1 " - "%ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VStoreNSuccessFloatPhysical64) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32vec2_01 %u64_1 %ptr_g\n"; - ss << "%val2 = OpExtInst %void %extinst vstoren %f32vec4_0123 %u64_1 " - "%ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VStoreNSuccessIntPhysical32) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %u32_ptr_workgroup %u32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %u32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %u32vec2_01 %u32_1 %ptr_g\n"; - ss << "%val2 = OpExtInst %void %extinst vstoren %u32vec4_0123 %u32_1 " - "%ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VStoreNSuccessIntPhysical64) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %u32_ptr_workgroup %u32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %u32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %u32vec2_01 %u64_1 %ptr_g\n"; - ss << "%val2 = OpExtInst %void %extinst vstoren %u32vec4_0123 %u64_1 " - "%ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, VStoreNResultTypeNotVoid) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %f32 %extinst vstoren %f32vec2_01 %u32_1 %ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vstoren: expected Result Type to be void")); -} - -TEST_F(ValidateExtInst, VStoreNDataWrongType) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32_1 %u32_1 %ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std vstoren: expected Data to be an int or float vector")); -} - -TEST_F(ValidateExtInst, VStoreNAddressingModelLogical) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32vec2_01 %u32_1 %ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Logical")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vstoren can only be used with physical " - "addressing models")); -} - -TEST_F(ValidateExtInst, VStoreNOffsetNotSizeT) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32vec2_01 %u32_1 %ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str(), "", "Physical64")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std vstoren: expected operand Offset to be of type size_t " - "(64-bit integer for the addressing model used in the module)")); -} - -TEST_F(ValidateExtInst, VStoreNPNotPointer) { - std::ostringstream ss; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32vec2_01 %u32_1 " - "%f32_ptr_generic\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 127[%_ptr_Generic_float] cannot be a type")); -} - -TEST_F(ValidateExtInst, VStoreNWrongStorageClass) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %f32vec2_01 %u32_1 %ptr_w\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std vstoren: expected operand P storage class " - "to be Generic, CrossWorkgroup, Workgroup or Function")); -} - -TEST_F(ValidateExtInst, VStorePWrongDataType) { - std::ostringstream ss; - ss << "%ptr_w = OpAccessChain %f32_ptr_workgroup %f32vec8_workgroup %u32_1\n"; - ss << "%ptr_g = OpPtrCastToGeneric %f32_ptr_generic %ptr_w\n"; - ss << "%val1 = OpExtInst %void %extinst vstoren %u32vec2_01 %u32_1 %ptr_g\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std vstoren: expected operand P data type to " - "be equal to the type of operand Data components")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle %f32vec4_0123 %u32vec2_01 -%val2 = OpExtInst %f32vec4 %extinst shuffle %f32vec4_0123 %u32vec4_0123 -%val3 = OpExtInst %u32vec2 %extinst shuffle %u32vec4_0123 %u32vec2_01 -%val4 = OpExtInst %u32vec4 %extinst shuffle %u32vec4_0123 %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleWrongResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst shuffle %f32vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected Result Type to be an int or float vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleResultTypeInvalidNumComponents) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst shuffle %f32vec4_0123 %u32vec3_012 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected Result Type to have 2, 4, 8 or 16 components")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleXWrongType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle %f32_0 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected operand X to be an int or float vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleXInvalidNumComponents) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle %f32vec3_012 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected operand X to have 2, 4, 8 or 16 components")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleXInvalidComponentType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle %f64vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std shuffle: " - "expected operand X and Result Type to have equal component types")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleShuffleMaskNotIntVector) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle %f32vec4_0123 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected operand Shuffle Mask to be an int vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleShuffleMaskInvalidNumComponents) { - const std::string body = R"( -%val1 = OpExtInst %f32vec4 %extinst shuffle %f32vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected operand Shuffle Mask to have the same number " - "of components as Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffleShuffleMaskInvalidBitWidth) { - const std::string body = R"( -%val1 = OpExtInst %f64vec2 %extinst shuffle %f64vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle: " - "expected operand Shuffle Mask components to have the " - "same bit width as Result Type components")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2Success) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle2 %f32vec4_0123 %f32vec4_0123 %u32vec2_01 -%val2 = OpExtInst %f32vec4 %extinst shuffle2 %f32vec4_0123 %f32vec4_0123 %u32vec4_0123 -%val3 = OpExtInst %u32vec2 %extinst shuffle2 %u32vec4_0123 %u32vec4_0123 %u32vec2_01 -%val4 = OpExtInst %u32vec4 %extinst shuffle2 %u32vec4_0123 %u32vec4_0123 %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2WrongResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst shuffle2 %f32vec4_0123 %f32vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected Result Type to be an int or float vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2ResultTypeInvalidNumComponents) { - const std::string body = R"( -%val1 = OpExtInst %f32vec3 %extinst shuffle2 %f32vec4_0123 %f32vec4_0123 %u32vec3_012 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected Result Type to have 2, 4, 8 or 16 components")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2XWrongType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle2 %f32_0 %f32_0 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected operand X to be an int or float vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2YTypeDifferentFromX) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle2 %f32vec2_01 %f32vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected operands X and Y to be of the same type")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2XInvalidNumComponents) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle2 %f32vec3_012 %f32vec3_012 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected operand X to have 2, 4, 8 or 16 components")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2XInvalidComponentType) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle2 %f64vec4_0123 %f64vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std shuffle2: " - "expected operand X and Result Type to have equal component types")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2ShuffleMaskNotIntVector) { - const std::string body = R"( -%val1 = OpExtInst %f32vec2 %extinst shuffle2 %f32vec4_0123 %f32vec4_0123 %f32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected operand Shuffle Mask to be an int vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2ShuffleMaskInvalidNumComponents) { - const std::string body = R"( -%val1 = OpExtInst %f32vec4 %extinst shuffle2 %f32vec4_0123 %f32vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected operand Shuffle Mask to have the same number " - "of components as Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdShuffle2ShuffleMaskInvalidBitWidth) { - const std::string body = R"( -%val1 = OpExtInst %f64vec2 %extinst shuffle2 %f64vec4_0123 %f64vec4_0123 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std shuffle2: " - "expected operand Shuffle Mask components to have the " - "same bit width as Result Type components")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrintfSuccess) { - const std::string body = R"( -%format = OpAccessChain %u8_ptr_uniform_constant %u8arr_uniform_constant %u32_0 -%val1 = OpExtInst %u32 %extinst printf %format %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdPrintfBoolResultType) { - const std::string body = R"( -%format = OpAccessChain %u8_ptr_uniform_constant %u8arr_uniform_constant %u32_0 -%val1 = OpExtInst %bool %extinst printf %format %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std printf: expected Result Type to be a 32-bit int type")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrintfU64ResultType) { - const std::string body = R"( -%format = OpAccessChain %u8_ptr_uniform_constant %u8arr_uniform_constant %u32_0 -%val1 = OpExtInst %u64 %extinst printf %format %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std printf: expected Result Type to be a 32-bit int type")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrintfFormatNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst printf %u8_ptr_uniform_constant %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 137[%_ptr_UniformConstant_uchar] cannot be a " - "type")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrintfFormatNotUniformConstStorageClass) { - const std::string body = R"( -%format_const = OpAccessChain %u8_ptr_uniform_constant %u8arr_uniform_constant %u32_0 -%format = OpBitcast %u8_ptr_generic %format_const -%val1 = OpExtInst %u32 %extinst printf %format %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std printf: expected Format storage class to " - "be UniformConstant")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrintfFormatNotU8Pointer) { - const std::string body = R"( -%format = OpAccessChain %u32_ptr_uniform_constant %u32vec8_uniform_constant %u32_0 -%val1 = OpExtInst %u32 %extinst printf %format %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std printf: expected Format data type to be 8-bit int")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchU32Success) { - const std::string body = R"( -%ptr = OpAccessChain %u32_ptr_cross_workgroup %u32arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchU32Physical64Success) { - const std::string body = R"( -%ptr = OpAccessChain %u32_ptr_cross_workgroup %u32arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u64_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body, "", "Physical64")); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchF32Success) { - const std::string body = R"( -%ptr = OpAccessChain %f32_ptr_cross_workgroup %f32arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchF32Vec2Success) { - const std::string body = R"( -%ptr = OpAccessChain %f32vec2_ptr_cross_workgroup %f32vec2arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchResultTypeNotVoid) { - const std::string body = R"( -%ptr = OpAccessChain %u32_ptr_cross_workgroup %u32arr_cross_workgroup %u32_0 -%val1 = OpExtInst %u32 %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std prefetch: expected Result Type to be void")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchPtrNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %void %extinst prefetch %u32_ptr_cross_workgroup %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 99[%_ptr_CrossWorkgroup_uint] cannot be a " - "type")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchPtrNotCrossWorkgroup) { - const std::string body = R"( -%ptr = OpAccessChain %u8_ptr_uniform_constant %u8arr_uniform_constant %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std prefetch: expected operand Ptr storage " - "class to be CrossWorkgroup")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchInvalidDataType) { - const std::string body = R"( -%ptr = OpAccessChain %struct_ptr_cross_workgroup %struct_arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std prefetch: expected Ptr data type to be int " - "or float scalar or vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchAddressingModelLogical) { - const std::string body = R"( -%ptr = OpAccessChain %u32_ptr_cross_workgroup %u32arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body, "", "Logical")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std prefetch can only be used with physical " - "addressing models")); -} - -TEST_F(ValidateExtInst, OpenCLStdPrefetchNumElementsNotSizeT) { - const std::string body = R"( -%ptr = OpAccessChain %f32_ptr_cross_workgroup %f32arr_cross_workgroup %u32_0 -%val1 = OpExtInst %void %extinst prefetch %ptr %u32_256 -)"; - - CompileSuccessfully(GenerateKernelCode(body, "", "Physical64")); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std prefetch: expected operand Num Elements to " - "be of type size_t (64-bit integer for the addressing " - "model used in the module)")); -} - -TEST_P(ValidateOpenCLStdFractLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_f32 = OpVariable %f32_ptr_function Function\n"; - ss << "%var_f32vec2 = OpVariable %f32vec2_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %var_f32\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %var_f32vec2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdFractLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_f32 = OpVariable %f32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %f32_0 %var_f32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdFractLike, XWrongType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_f32 = OpVariable %f32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f64_0 %var_f32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected type of operand X to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdFractLike, NotPointer) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_f32 = OpVariable %f32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected the last operand to be a pointer")); -} - -TEST_P(ValidateOpenCLStdFractLike, PointerInvalidStorageClass) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32_0 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected storage class of the pointer to be " - "Generic, CrossWorkgroup, Workgroup or Function")); -} - -TEST_P(ValidateOpenCLStdFractLike, PointerWrongDataType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_u32 = OpVariable %u32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %var_u32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": expected data type of the pointer to be equal to Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllFractLike, ValidateOpenCLStdFractLike, - ::testing::ValuesIn(std::vector{ - "fract", - "modf", - "sincos", - })); - -TEST_F(ValidateExtInst, OpenCLStdRemquoSuccess) { - const std::string body = R"( -%var_u32 = OpVariable %u32_ptr_function Function -%var_u32vec2 = OpVariable %u32vec2_ptr_function Function -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %f32_2 %var_u32 -%val2 = OpExtInst %f32vec2 %extinst remquo %f32vec2_01 %f32vec2_12 %var_u32vec2 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoIntResultType) { - const std::string body = R"( -%var_u32 = OpVariable %u32_ptr_function Function -%val1 = OpExtInst %u32 %extinst remquo %f32_3 %f32_2 %var_u32 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected Result Type to be a float scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoXWrongType) { - const std::string body = R"( -%var_u32 = OpVariable %f32_ptr_function Function -%val1 = OpExtInst %f32 %extinst remquo %u32_3 %f32_2 %var_u32 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected type of operand X to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoYWrongType) { - const std::string body = R"( -%var_u32 = OpVariable %f32_ptr_function Function -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %u32_2 %var_u32 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected type of operand Y to be equal to Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoNotPointer) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %f32_2 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected the last operand to be a pointer")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoPointerWrongStorageClass) { - const std::string body = R"( -%ptr = OpAccessChain %f32_ptr_uniform_constant %f32vec8_uniform_constant %u32_1 -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %f32_2 %ptr -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected storage class of the pointer to be Generic, " - "CrossWorkgroup, Workgroup or Function")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoPointerWrongDataType) { - const std::string body = R"( -%var_f32 = OpVariable %f32_ptr_function Function -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %f32_2 %var_f32 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected data type of the pointer to be a 32-bit int " - "scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoPointerWrongDataTypeWidth) { - const std::string body = R"( -%var_u64 = OpVariable %u64_ptr_function Function -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %f32_2 %var_u64 -)"; - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected data type of the pointer to be a 32-bit int " - "scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdRemquoPointerWrongNumberOfComponents) { - const std::string body = R"( -%var_u32vec2 = OpVariable %u32vec2_ptr_function Function -%val1 = OpExtInst %f32 %extinst remquo %f32_3 %f32_2 %var_u32vec2 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std remquo: " - "expected data type of the pointer to have the same number " - "of components as Result Type")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_u32 = OpVariable %u32_ptr_function Function\n"; - ss << "%var_u32vec2 = OpVariable %u32vec2_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %var_u32\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %var_u32vec2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdFrexpLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_u32 = OpVariable %u32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %f32_0 %var_u32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, XWrongType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_u32 = OpVariable %u32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f64_0 %var_u32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected type of operand X to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, NotPointer) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected the last operand to be a pointer")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, PointerInvalidStorageClass) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%ptr = OpAccessChain %f32_ptr_uniform_constant " - "%f32vec8_uniform_constant %u32_1\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name << " %f32_0 %ptr\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected storage class of the pointer to be " - "Generic, CrossWorkgroup, Workgroup or Function")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, PointerDataTypeFloat) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_f32 = OpVariable %f32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %var_f32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected data type of the pointer to be a 32-bit " - "int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, PointerDataTypeU64) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_u64 = OpVariable %u64_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %var_u64\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected data type of the pointer to be a 32-bit " - "int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdFrexpLike, PointerDataTypeDiffSize) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%var_u32 = OpVariable %u32_ptr_function Function\n"; - ss << "%val1 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_01 %var_u32\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected data type of the pointer to have the same " - "number of components as Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllFrexpLike, ValidateOpenCLStdFrexpLike, - ::testing::ValuesIn(std::vector{ - "frexp", - "lgamma_r", - })); - -TEST_F(ValidateExtInst, OpenCLStdIlogbSuccess) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst ilogb %f32_3 -%val2 = OpExtInst %u32vec2 %extinst ilogb %f32vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdIlogbFloatResultType) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst ilogb %f32_3 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std ilogb: " - "expected Result Type to be a 32-bit int scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdIlogbIntX) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst ilogb %u32_3 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std ilogb: " - "expected operand X to be a float scalar or vector")); -} - -TEST_F(ValidateExtInst, OpenCLStdIlogbDiffSize) { - const std::string body = R"( -%val2 = OpExtInst %u32vec2 %extinst ilogb %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std ilogb: " - "expected operand X to have the same number of " - "components as Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdNanSuccess) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst nan %u32_3 -%val2 = OpExtInst %f32vec2 %extinst nan %u32vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtInst, OpenCLStdNanIntResultType) { - const std::string body = R"( -%val1 = OpExtInst %u32 %extinst nan %u32_3 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std nan: " - "expected Result Type to be a float scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdNanFloatNancode) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst nan %f32_3 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std nan: " - "expected Nancode to be an int scalar or vector type")); -} - -TEST_F(ValidateExtInst, OpenCLStdNanFloatDiffSize) { - const std::string body = R"( -%val1 = OpExtInst %f32 %extinst nan %u32vec2_12 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std nan: " - "expected Nancode to have the same number of " - "components as Result Type")); -} - -TEST_F(ValidateExtInst, OpenCLStdNanFloatDiffBitWidth) { - const std::string body = R"( -%val1 = OpExtInst %f64 %extinst nan %u32_2 -)"; - - CompileSuccessfully(GenerateKernelCode(body)); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std nan: " - "expected Nancode to have the same bit width as Result Type")); -} - -TEST_P(ValidateOpenCLStdLdexpLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %u32_1\n"; - ss << "%val2 = OpExtInst %f32vec2 %extinst " << ext_inst_name - << " %f32vec2_12 %u32vec2_12\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdLdexpLike, IntResultType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u32 %extinst " << ext_inst_name - << " %f32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be a float scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdLdexpLike, XWrongType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %u32_0 %u32_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected type of operand X to be equal to Result Type")); -} - -TEST_P(ValidateOpenCLStdLdexpLike, ExponentNotInt) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %f32_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected the exponent to be a 32-bit int scalar or vector")); -} - -TEST_P(ValidateOpenCLStdLdexpLike, ExponentNotInt32) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %u64_1\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected the exponent to be a 32-bit int scalar or vector")); -} - -TEST_P(ValidateOpenCLStdLdexpLike, ExponentWrongSize) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f32 %extinst " << ext_inst_name - << " %f32_0 %u32vec2_01\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected the exponent to have the same number of " - "components as Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllLdexpLike, ValidateOpenCLStdLdexpLike, - ::testing::ValuesIn(std::vector{ - "ldexp", - "pown", - "rootn", - })); - -TEST_P(ValidateOpenCLStdUpsampleLike, Success) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u16 %extinst " << ext_inst_name << " %u8_1 %u8_2\n"; - ss << "%val2 = OpExtInst %u32 %extinst " << ext_inst_name - << " %u16_1 %u16_2\n"; - ss << "%val3 = OpExtInst %u64 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - ss << "%val4 = OpExtInst %u64vec2 %extinst " << ext_inst_name - << " %u32vec2_01 %u32vec2_01\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateOpenCLStdUpsampleLike, FloatResultType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %f64 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Result Type to be an int scalar or vector type")); -} - -TEST_P(ValidateOpenCLStdUpsampleLike, InvalidResultTypeBitWidth) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u8 %extinst " << ext_inst_name << " %u8_1 %u8_2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpenCL.std " + ext_inst_name + - ": expected bit width of Result Type components to be 16, 32 or 64")); -} - -TEST_P(ValidateOpenCLStdUpsampleLike, LoHiDiffType) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u64 %extinst " << ext_inst_name - << " %u32_1 %u16_2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Hi and Lo operands to have the same type")); -} - -TEST_P(ValidateOpenCLStdUpsampleLike, DiffNumberOfComponents) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u64vec2 %extinst " << ext_inst_name - << " %u32_1 %u32_2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected Hi and Lo operands to have the same number " - "of components as Result Type")); -} - -TEST_P(ValidateOpenCLStdUpsampleLike, HiLoWrongBitWidth) { - const std::string ext_inst_name = GetParam(); - std::ostringstream ss; - ss << "%val1 = OpExtInst %u64 %extinst " << ext_inst_name - << " %u16_1 %u16_2\n"; - - CompileSuccessfully(GenerateKernelCode(ss.str())); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpenCL.std " + ext_inst_name + - ": expected bit width of components of Hi and Lo operands to " - "be half of the bit width of components of Result Type")); -} - -INSTANTIATE_TEST_SUITE_P(AllUpsampleLike, ValidateOpenCLStdUpsampleLike, - ::testing::ValuesIn(std::vector{ - "u_upsample", - "s_upsample", - })); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_extensions_test.cpp b/3rdparty/spirv-tools/test/val/val_extensions_test.cpp deleted file mode 100644 index 682c32143..000000000 --- a/3rdparty/spirv-tools/test/val/val_extensions_test.cpp +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for OpExtension validator rules. - -#include -#include - -#include "gmock/gmock.h" -#include "source/enum_string_mapping.h" -#include "source/extensions.h" -#include "source/spirv_target_env.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; -using ::testing::Values; -using ::testing::ValuesIn; - -using ValidateKnownExtensions = spvtest::ValidateBase; -using ValidateUnknownExtensions = spvtest::ValidateBase; -using ValidateExtensionCapabilities = spvtest::ValidateBase; - -// Returns expected error string if |extension| is not recognized. -std::string GetErrorString(const std::string& extension) { - return "Found unrecognized extension " + extension; -} - -INSTANTIATE_TEST_SUITE_P( - ExpectSuccess, ValidateKnownExtensions, - Values( - // Match the order as published on the SPIR-V Registry. - "SPV_AMD_shader_explicit_vertex_parameter", - "SPV_AMD_shader_trinary_minmax", "SPV_AMD_gcn_shader", - "SPV_KHR_shader_ballot", "SPV_AMD_shader_ballot", - "SPV_AMD_gpu_shader_half_float", "SPV_KHR_shader_draw_parameters", - "SPV_KHR_subgroup_vote", "SPV_KHR_16bit_storage", - "SPV_KHR_device_group", "SPV_KHR_multiview", - "SPV_NVX_multiview_per_view_attributes", "SPV_NV_viewport_array2", - "SPV_NV_stereo_view_rendering", "SPV_NV_sample_mask_override_coverage", - "SPV_NV_geometry_shader_passthrough", "SPV_AMD_texture_gather_bias_lod", - "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_variable_pointers", - "SPV_AMD_gpu_shader_int16", "SPV_KHR_post_depth_coverage", - "SPV_KHR_shader_atomic_counter_ops", "SPV_EXT_shader_stencil_export", - "SPV_EXT_shader_viewport_index_layer", - "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_fragment_mask", - "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", - "SPV_NV_shader_subgroup_partitioned", "SPV_EXT_descriptor_indexing")); - -INSTANTIATE_TEST_SUITE_P(FailSilently, ValidateUnknownExtensions, - Values("ERROR_unknown_extension", "SPV_KHR_", - "SPV_KHR_shader_ballot_ERROR")); - -TEST_P(ValidateKnownExtensions, ExpectSuccess) { - const std::string extension = GetParam(); - const std::string str = - "OpCapability Shader\nOpCapability Linkage\nOpExtension \"" + extension + - "\"\nOpMemoryModel Logical GLSL450"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Not(HasSubstr(GetErrorString(extension)))); -} - -TEST_P(ValidateUnknownExtensions, FailSilently) { - const std::string extension = GetParam(); - const std::string str = - "OpCapability Shader\nOpCapability Linkage\nOpExtension \"" + extension + - "\"\nOpMemoryModel Logical GLSL450"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(extension))); -} - -TEST_F(ValidateUnknownExtensions, HitMaxNumOfWarnings) { - const std::string str = - std::string("OpCapability Shader\n") + "OpCapability Linkage\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" + - "OpMemoryModel Logical GLSL450"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Other warnings have been suppressed.")); -} - -TEST_F(ValidateExtensionCapabilities, DeclCapabilitySuccess) { - const std::string str = - "OpCapability Shader\nOpCapability Linkage\nOpCapability DeviceGroup\n" - "OpExtension \"SPV_KHR_device_group\"" - "\nOpMemoryModel Logical GLSL450"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateExtensionCapabilities, DeclCapabilityFailure) { - const std::string str = - "OpCapability Shader\nOpCapability Linkage\nOpCapability DeviceGroup\n" - "\nOpMemoryModel Logical GLSL450"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("1st operand of Capability")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("requires one of these extensions")); - EXPECT_THAT(getDiagnosticString(), HasSubstr("SPV_KHR_device_group")); -} - -using ValidateAMDShaderBallotCapabilities = spvtest::ValidateBase; - -// Returns a vector of strings for the prefix of a SPIR-V assembly shader -// that can use the group instructions introduced by SPV_AMD_shader_ballot. -std::vector ShaderPartsForAMDShaderBallot() { - return std::vector{R"( - OpCapability Shader - OpCapability Linkage - )", - R"( - OpMemoryModel Logical GLSL450 - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %scope = OpConstant %uint 3 - %uint_const = OpConstant %uint 42 - %int_const = OpConstant %uint 45 - %float_const = OpConstant %float 3.5 - - %void = OpTypeVoid - %fn_ty = OpTypeFunction %void - %fn = OpFunction %void None %fn_ty - %entry = OpLabel - )"}; -} - -// Returns a list of SPIR-V assembly strings, where each uses only types -// and IDs that can fit with a shader made from parts from the result -// of ShaderPartsForAMDShaderBallot. -std::vector AMDShaderBallotGroupInstructions() { - return std::vector{ - "%iadd_reduce = OpGroupIAddNonUniformAMD %uint %scope Reduce %uint_const", - "%iadd_iscan = OpGroupIAddNonUniformAMD %uint %scope InclusiveScan " - "%uint_const", - "%iadd_escan = OpGroupIAddNonUniformAMD %uint %scope ExclusiveScan " - "%uint_const", - - "%fadd_reduce = OpGroupFAddNonUniformAMD %float %scope Reduce " - "%float_const", - "%fadd_iscan = OpGroupFAddNonUniformAMD %float %scope InclusiveScan " - "%float_const", - "%fadd_escan = OpGroupFAddNonUniformAMD %float %scope ExclusiveScan " - "%float_const", - - "%fmin_reduce = OpGroupFMinNonUniformAMD %float %scope Reduce " - "%float_const", - "%fmin_iscan = OpGroupFMinNonUniformAMD %float %scope InclusiveScan " - "%float_const", - "%fmin_escan = OpGroupFMinNonUniformAMD %float %scope ExclusiveScan " - "%float_const", - - "%umin_reduce = OpGroupUMinNonUniformAMD %uint %scope Reduce %uint_const", - "%umin_iscan = OpGroupUMinNonUniformAMD %uint %scope InclusiveScan " - "%uint_const", - "%umin_escan = OpGroupUMinNonUniformAMD %uint %scope ExclusiveScan " - "%uint_const", - - "%smin_reduce = OpGroupUMinNonUniformAMD %int %scope Reduce %int_const", - "%smin_iscan = OpGroupUMinNonUniformAMD %int %scope InclusiveScan " - "%int_const", - "%smin_escan = OpGroupUMinNonUniformAMD %int %scope ExclusiveScan " - "%int_const", - - "%fmax_reduce = OpGroupFMaxNonUniformAMD %float %scope Reduce " - "%float_const", - "%fmax_iscan = OpGroupFMaxNonUniformAMD %float %scope InclusiveScan " - "%float_const", - "%fmax_escan = OpGroupFMaxNonUniformAMD %float %scope ExclusiveScan " - "%float_const", - - "%umax_reduce = OpGroupUMaxNonUniformAMD %uint %scope Reduce %uint_const", - "%umax_iscan = OpGroupUMaxNonUniformAMD %uint %scope InclusiveScan " - "%uint_const", - "%umax_escan = OpGroupUMaxNonUniformAMD %uint %scope ExclusiveScan " - "%uint_const", - - "%smax_reduce = OpGroupUMaxNonUniformAMD %int %scope Reduce %int_const", - "%smax_iscan = OpGroupUMaxNonUniformAMD %int %scope InclusiveScan " - "%int_const", - "%smax_escan = OpGroupUMaxNonUniformAMD %int %scope ExclusiveScan " - "%int_const"}; -} - -TEST_P(ValidateAMDShaderBallotCapabilities, ExpectSuccess) { - // Succeed because the module specifies the SPV_AMD_shader_ballot extension. - auto parts = ShaderPartsForAMDShaderBallot(); - - const std::string assembly = - parts[0] + "OpExtension \"SPV_AMD_shader_ballot\"\n" + parts[1] + - GetParam() + "\nOpReturn OpFunctionEnd"; - - CompileSuccessfully(assembly.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -INSTANTIATE_TEST_SUITE_P(ExpectSuccess, ValidateAMDShaderBallotCapabilities, - ValuesIn(AMDShaderBallotGroupInstructions())); - -TEST_P(ValidateAMDShaderBallotCapabilities, ExpectFailure) { - // Fail because the module does not specify the SPV_AMD_shader_ballot - // extension. - auto parts = ShaderPartsForAMDShaderBallot(); - - const std::string assembly = - parts[0] + parts[1] + GetParam() + "\nOpReturn OpFunctionEnd"; - - CompileSuccessfully(assembly.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - - // Make sure we get an appropriate error message. - // Find just the opcode name, skipping over the "Op" part. - auto prefix_with_opcode = GetParam().substr(GetParam().find("Group")); - auto opcode = prefix_with_opcode.substr(0, prefix_with_opcode.find(' ')); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr(std::string("Opcode " + opcode + - " requires one of these capabilities: Groups"))); -} - -INSTANTIATE_TEST_SUITE_P(ExpectFailure, ValidateAMDShaderBallotCapabilities, - ValuesIn(AMDShaderBallotGroupInstructions())); - -struct ExtIntoCoreCase { - const char* ext; - const char* cap; - const char* builtin; - spv_target_env env; - bool success; -}; - -using ValidateExtIntoCore = spvtest::ValidateBase; - -// Make sure that we don't panic about missing extensions for using -// functionalities that introduced in extensions but became core SPIR-V later. - -TEST_P(ValidateExtIntoCore, DoNotAskForExtensionInLaterVersion) { - const std::string code = std::string(R"( - OpCapability Shader - OpCapability )") + - GetParam().cap + R"( - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %builtin - OpDecorate %builtin BuiltIn )" + GetParam().builtin + R"( - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int - %builtin = OpVariable %_ptr_Input_int Input - %main = OpFunction %void None %3 - %5 = OpLabel - %18 = OpLoad %int %builtin - OpReturn - OpFunctionEnd)"; - - CompileSuccessfully(code.c_str(), GetParam().env); - if (GetParam().success) { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(GetParam().env)) - << getDiagnosticString(); - } else { - ASSERT_NE(SPV_SUCCESS, ValidateInstructions(GetParam().env)) - << " in " << spvTargetEnvDescription(GetParam().env) << ":\n" - << code; - const std::string message = getDiagnosticString(); - if (spvIsVulkanEnv(GetParam().env)) { - EXPECT_THAT(message, HasSubstr(std::string(GetParam().cap) + - " is not allowed by Vulkan")); - EXPECT_THAT(message, HasSubstr(std::string("or requires extension"))); - } else { - EXPECT_THAT(message, - HasSubstr(std::string("requires one of these extensions: ") + - GetParam().ext)); - } - } -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P( - KHR_extensions, ValidateExtIntoCore, - ValuesIn(std::vector{ - // SPV_KHR_shader_draw_parameters became core SPIR-V 1.3 - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_3, true}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_2, false}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_1, false}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_0, false}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_VULKAN_1_1, true}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_VULKAN_1_0, false}, - - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseInstance", SPV_ENV_UNIVERSAL_1_3, true}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseInstance", SPV_ENV_VULKAN_1_0, false}, - - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "DrawIndex", SPV_ENV_UNIVERSAL_1_3, true}, - {"SPV_KHR_shader_draw_parameters", "DrawParameters", "DrawIndex", SPV_ENV_UNIVERSAL_1_1, false}, - - // SPV_KHR_multiview became core SPIR-V 1.3 - {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_3, true}, - {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_2, false}, - {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_1, false}, - {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_0, false}, - {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_VULKAN_1_1, true}, - {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_VULKAN_1_0, false}, - - // SPV_KHR_device_group became core SPIR-V 1.3 - {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_3, true}, - {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_2, false}, - {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_1, false}, - {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_0, false}, - {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_VULKAN_1_1, true}, - {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_VULKAN_1_0, false}, - })); -// clang-format on - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_fixtures.h b/3rdparty/spirv-tools/test/val/val_fixtures.h deleted file mode 100644 index 5635c7813..000000000 --- a/3rdparty/spirv-tools/test/val/val_fixtures.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Common validation fixtures for unit tests - -#ifndef TEST_VAL_VAL_FIXTURES_H_ -#define TEST_VAL_VAL_FIXTURES_H_ - -#include -#include - -#include "source/val/validation_state.h" -#include "spirv-tools/libspirv.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" - -namespace spvtest { - -template -class ValidateBase : public ::testing::Test, - public ::testing::WithParamInterface { - public: - ValidateBase(); - - virtual void TearDown(); - - // Returns the a spv_const_binary struct - spv_const_binary get_const_binary(); - - // Assembles the given SPIR-V text, checks that it fails to assemble, - // and returns resulting diagnostic. No internal state is updated. - std::string CompileFailure(std::string code, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0); - - // Checks that 'code' is valid SPIR-V text representation and stores the - // binary version for further method calls. - void CompileSuccessfully(std::string code, - spv_target_env env = SPV_ENV_UNIVERSAL_1_0); - - // Overwrites the word at index 'index' with the given word. - // For testing purposes, it is often useful to be able to manipulate the - // assembled binary before running the validator on it. - // This function overwrites the word at the given index with a new word. - void OverwriteAssembledBinary(uint32_t index, uint32_t word); - - // Performs validation on the SPIR-V code. - spv_result_t ValidateInstructions(spv_target_env env = SPV_ENV_UNIVERSAL_1_0); - - // Performs validation. Returns the status and stores validation state into - // the vstate_ member. - spv_result_t ValidateAndRetrieveValidationState( - spv_target_env env = SPV_ENV_UNIVERSAL_1_0); - - // Destroys the stored binary. - void DestroyBinary() { - spvBinaryDestroy(binary_); - binary_ = nullptr; - } - - // Destroys the stored diagnostic. - void DestroyDiagnostic() { - spvDiagnosticDestroy(diagnostic_); - diagnostic_ = nullptr; - } - - std::string getDiagnosticString(); - spv_position_t getErrorPosition(); - spv_validator_options getValidatorOptions(); - - spv_binary binary_; - spv_diagnostic diagnostic_; - spv_validator_options options_; - std::unique_ptr vstate_; -}; - -template -ValidateBase::ValidateBase() : binary_(nullptr), diagnostic_(nullptr) { - // Initialize to default command line options. Different tests can then - // specialize specific options as necessary. - options_ = spvValidatorOptionsCreate(); -} - -template -spv_const_binary ValidateBase::get_const_binary() { - return spv_const_binary(binary_); -} - -template -void ValidateBase::TearDown() { - if (diagnostic_) { - spvDiagnosticPrint(diagnostic_); - } - DestroyBinary(); - DestroyDiagnostic(); - spvValidatorOptionsDestroy(options_); -} - -template -std::string ValidateBase::CompileFailure(std::string code, - spv_target_env env) { - spv_diagnostic diagnostic = nullptr; - EXPECT_NE(SPV_SUCCESS, - spvTextToBinary(ScopedContext(env).context, code.c_str(), - code.size(), &binary_, &diagnostic)); - std::string result(diagnostic->error); - spvDiagnosticDestroy(diagnostic); - return result; -} - -template -void ValidateBase::CompileSuccessfully(std::string code, - spv_target_env env) { - DestroyBinary(); - spv_diagnostic diagnostic = nullptr; - ScopedContext context(env); - auto status = spvTextToBinary(context.context, code.c_str(), code.size(), - &binary_, &diagnostic); - EXPECT_EQ(SPV_SUCCESS, status) - << "ERROR: " << diagnostic->error - << "\nSPIR-V could not be compiled into binary:\n" - << code; - ASSERT_EQ(SPV_SUCCESS, status); - spvDiagnosticDestroy(diagnostic); -} - -template -void ValidateBase::OverwriteAssembledBinary(uint32_t index, uint32_t word) { - ASSERT_TRUE(index < binary_->wordCount) - << "OverwriteAssembledBinary: The given index is larger than the binary " - "word count."; - binary_->code[index] = word; -} - -template -spv_result_t ValidateBase::ValidateInstructions(spv_target_env env) { - DestroyDiagnostic(); - if (binary_ == nullptr) { - fprintf(stderr, - "ERROR: Attempting to validate a null binary, did you forget to " - "call CompileSuccessfully?"); - fflush(stderr); - } - assert(binary_ != nullptr); - return spvValidateWithOptions(ScopedContext(env).context, options_, - get_const_binary(), &diagnostic_); -} - -template -spv_result_t ValidateBase::ValidateAndRetrieveValidationState( - spv_target_env env) { - DestroyDiagnostic(); - return spvtools::val::ValidateBinaryAndKeepValidationState( - ScopedContext(env).context, options_, get_const_binary()->code, - get_const_binary()->wordCount, &diagnostic_, &vstate_); -} - -template -std::string ValidateBase::getDiagnosticString() { - return diagnostic_ == nullptr ? std::string() - : std::string(diagnostic_->error); -} - -template -spv_validator_options ValidateBase::getValidatorOptions() { - return options_; -} - -template -spv_position_t ValidateBase::getErrorPosition() { - return diagnostic_ == nullptr ? spv_position_t() : diagnostic_->position; -} - -} // namespace spvtest - -#endif // TEST_VAL_VAL_FIXTURES_H_ diff --git a/3rdparty/spirv-tools/test/val/val_function_test.cpp b/3rdparty/spirv-tools/test/val/val_function_test.cpp deleted file mode 100644 index af0199a60..000000000 --- a/3rdparty/spirv-tools/test/val/val_function_test.cpp +++ /dev/null @@ -1,843 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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 "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Combine; -using ::testing::HasSubstr; -using ::testing::Values; - -using ValidateFunctionCall = spvtest::ValidateBase; - -std::string GenerateShader(const std::string& storage_class, - const std::string& capabilities, - const std::string& extensions) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability AtomicStorage -)" + capabilities + R"( -OpExtension "SPV_KHR_storage_buffer_storage_class" -)" + - extensions + R"( -OpMemoryModel Logical GLSL450 -OpName %var "var" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr = OpTypePointer )" + storage_class + R"( %int -%caller_ty = OpTypeFunction %void -%callee_ty = OpTypeFunction %void %ptr -)"; - - if (storage_class != "Function") { - spirv += "%var = OpVariable %ptr " + storage_class; - } - - spirv += R"( -%caller = OpFunction %void None %caller_ty -%1 = OpLabel -)"; - - if (storage_class == "Function") { - spirv += "%var = OpVariable %ptr Function"; - } - - spirv += R"( -%call = OpFunctionCall %void %callee %var -OpReturn -OpFunctionEnd -%callee = OpFunction %void None %callee_ty -%param = OpFunctionParameter %ptr -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - return spirv; -} - -std::string GenerateShaderParameter(const std::string& storage_class, - const std::string& capabilities, - const std::string& extensions) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability AtomicStorage -)" + capabilities + R"( -OpExtension "SPV_KHR_storage_buffer_storage_class" -)" + - extensions + R"( -OpMemoryModel Logical GLSL450 -OpName %p "p" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%ptr = OpTypePointer )" + storage_class + R"( %int -%func_ty = OpTypeFunction %void %ptr -%caller = OpFunction %void None %func_ty -%p = OpFunctionParameter %ptr -%1 = OpLabel -%call = OpFunctionCall %void %callee %p -OpReturn -OpFunctionEnd -%callee = OpFunction %void None %func_ty -%param = OpFunctionParameter %ptr -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - return spirv; -} - -std::string GenerateShaderAccessChain(const std::string& storage_class, - const std::string& capabilities, - const std::string& extensions) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability AtomicStorage -)" + capabilities + R"( -OpExtension "SPV_KHR_storage_buffer_storage_class" -)" + - extensions + R"( -OpMemoryModel Logical GLSL450 -OpName %var "var" -OpName %gep "gep" -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int2 = OpTypeVector %int 2 -%int_0 = OpConstant %int 0 -%ptr = OpTypePointer )" + storage_class + R"( %int2 -%ptr2 = OpTypePointer )" + - storage_class + R"( %int -%caller_ty = OpTypeFunction %void -%callee_ty = OpTypeFunction %void %ptr2 -)"; - - if (storage_class != "Function") { - spirv += "%var = OpVariable %ptr " + storage_class; - } - - spirv += R"( -%caller = OpFunction %void None %caller_ty -%1 = OpLabel -)"; - - if (storage_class == "Function") { - spirv += "%var = OpVariable %ptr Function"; - } - - spirv += R"( -%gep = OpAccessChain %ptr2 %var %int_0 -%call = OpFunctionCall %void %callee %gep -OpReturn -OpFunctionEnd -%callee = OpFunction %void None %callee_ty -%param = OpFunctionParameter %ptr2 -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - - return spirv; -} - -TEST_P(ValidateFunctionCall, VariableNoVariablePointers) { - const std::string storage_class = GetParam(); - - std::string spirv = GenerateShader(storage_class, "", ""); - - const std::vector valid_storage_classes = { - "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"}; - bool valid = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - if (valid) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - if (storage_class == "StorageBuffer") { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("StorageBuffer pointer operand 1[%var] requires a " - "variable pointers capability")); - } else { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 1[%var]")); - } - } -} - -TEST_P(ValidateFunctionCall, VariableVariablePointersStorageClass) { - const std::string storage_class = GetParam(); - - std::string spirv = GenerateShader( - storage_class, "OpCapability VariablePointersStorageBuffer", - "OpExtension \"SPV_KHR_variable_pointers\""); - - const std::vector valid_storage_classes = { - "UniformConstant", "Function", "Private", - "Workgroup", "StorageBuffer", "AtomicCounter"}; - bool valid = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - if (valid) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 1[%var]")); - } -} - -TEST_P(ValidateFunctionCall, VariableVariablePointers) { - const std::string storage_class = GetParam(); - - std::string spirv = - GenerateShader(storage_class, "OpCapability VariablePointers", - "OpExtension \"SPV_KHR_variable_pointers\""); - - const std::vector valid_storage_classes = { - "UniformConstant", "Function", "Private", - "Workgroup", "StorageBuffer", "AtomicCounter"}; - bool valid = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - if (valid) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 1[%var]")); - } -} - -TEST_P(ValidateFunctionCall, ParameterNoVariablePointers) { - const std::string storage_class = GetParam(); - - std::string spirv = GenerateShaderParameter(storage_class, "", ""); - - const std::vector valid_storage_classes = { - "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"}; - bool valid = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - if (valid) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - if (storage_class == "StorageBuffer") { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("StorageBuffer pointer operand 1[%p] requires a " - "variable pointers capability")); - } else { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 1[%p]")); - } - } -} - -TEST_P(ValidateFunctionCall, ParameterVariablePointersStorageBuffer) { - const std::string storage_class = GetParam(); - - std::string spirv = GenerateShaderParameter( - storage_class, "OpCapability VariablePointersStorageBuffer", - "OpExtension \"SPV_KHR_variable_pointers\""); - - const std::vector valid_storage_classes = { - "UniformConstant", "Function", "Private", - "Workgroup", "StorageBuffer", "AtomicCounter"}; - bool valid = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - if (valid) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 1[%p]")); - } -} - -TEST_P(ValidateFunctionCall, ParameterVariablePointers) { - const std::string storage_class = GetParam(); - - std::string spirv = - GenerateShaderParameter(storage_class, "OpCapability VariablePointers", - "OpExtension \"SPV_KHR_variable_pointers\""); - - const std::vector valid_storage_classes = { - "UniformConstant", "Function", "Private", - "Workgroup", "StorageBuffer", "AtomicCounter"}; - bool valid = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - if (valid) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 1[%p]")); - } -} - -TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) { - const std::string storage_class = GetParam(); - - std::string spirv = GenerateShaderAccessChain(storage_class, "", ""); - - const std::vector valid_storage_classes = { - "Function", "Private", "Workgroup", "AtomicCounter"}; - bool valid_sc = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - - CompileSuccessfully(spirv); - spv_result_t expected_result = - storage_class == "UniformConstant" ? SPV_SUCCESS : SPV_ERROR_INVALID_ID; - EXPECT_EQ(expected_result, ValidateInstructions()); - if (valid_sc) { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Pointer operand 2[%gep] must be a memory object declaration")); - } else { - if (storage_class == "StorageBuffer") { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("StorageBuffer pointer operand 2[%gep] requires a " - "variable pointers capability")); - } else if (storage_class != "UniformConstant") { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 2[%gep]")); - } - } -} - -TEST_P(ValidateFunctionCall, - NonMemoryObjectDeclarationVariablePointersStorageBuffer) { - const std::string storage_class = GetParam(); - - std::string spirv = GenerateShaderAccessChain( - storage_class, "OpCapability VariablePointersStorageBuffer", - "OpExtension \"SPV_KHR_variable_pointers\""); - - const std::vector valid_storage_classes = { - "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"}; - bool valid_sc = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - bool validate = - storage_class == "StorageBuffer" || storage_class == "UniformConstant"; - - CompileSuccessfully(spirv); - if (validate) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - if (valid_sc) { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Pointer operand 2[%gep] must be a memory object declaration")); - } else { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 2[%gep]")); - } - } -} - -TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationVariablePointers) { - const std::string storage_class = GetParam(); - - std::string spirv = - GenerateShaderAccessChain(storage_class, "OpCapability VariablePointers", - "OpExtension \"SPV_KHR_variable_pointers\""); - - const std::vector valid_storage_classes = { - "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"}; - bool valid_sc = - std::find(valid_storage_classes.begin(), valid_storage_classes.end(), - storage_class) != valid_storage_classes.end(); - bool validate = storage_class == "StorageBuffer" || - storage_class == "Workgroup" || - storage_class == "UniformConstant"; - - CompileSuccessfully(spirv); - if (validate) { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - if (valid_sc) { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Pointer operand 2[%gep] must be a memory object declaration")); - } else { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Invalid storage class for pointer operand 2[%gep]")); - } - } -} - -TEST_F(ValidateFunctionCall, LogicallyMatchingPointers) { - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %_struct_3 = OpTypeStruct %int -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 - %void = OpTypeVoid - %14 = OpTypeFunction %void - %_struct_15 = OpTypeStruct %int -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 - %18 = OpTypeFunction %void %_ptr_Function__struct_15 - %2 = OpVariable %_ptr_Uniform__struct_5 Uniform - %1 = OpFunction %void None %14 - %19 = OpLabel - %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0 - %21 = OpFunctionCall %void %22 %20 - OpReturn - OpFunctionEnd - %22 = OpFunction %void None %18 - %23 = OpFunctionParameter %_ptr_Function__struct_15 - %24 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateFunctionCall, LogicallyMatchingPointersNestedStruct) { - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpMemberDecorate %_struct_4 0 Offset 0 - OpDecorate %_runtimearr__struct_4 ArrayStride 4 - OpMemberDecorate %_struct_6 0 Offset 0 - OpDecorate %_struct_6 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %_struct_3 = OpTypeStruct %int - %_struct_4 = OpTypeStruct %_struct_3 -%_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4 - %_struct_6 = OpTypeStruct %_runtimearr__struct_4 -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 - %void = OpTypeVoid - %13 = OpTypeFunction %void - %_struct_14 = OpTypeStruct %int - %_struct_15 = OpTypeStruct %_struct_14 -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 - %18 = OpTypeFunction %void %_ptr_Function__struct_15 - %2 = OpVariable %_ptr_Uniform__struct_6 Uniform - %1 = OpFunction %void None %13 - %19 = OpLabel - %20 = OpVariable %_ptr_Function__struct_15 Function - %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0 - %22 = OpFunctionCall %void %23 %21 - OpReturn - OpFunctionEnd - %23 = OpFunction %void None %18 - %24 = OpFunctionParameter %_ptr_Function__struct_15 - %25 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateFunctionCall, LogicallyMatchingPointersNestedArray) { - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpDecorate %_arr_int_uint_10 ArrayStride 4 - OpMemberDecorate %_struct_4 0 Offset 0 - OpDecorate %_runtimearr__struct_4 ArrayStride 40 - OpMemberDecorate %_struct_6 0 Offset 0 - OpDecorate %_struct_6 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_10 = OpConstant %uint 10 -%_arr_int_uint_10 = OpTypeArray %int %uint_10 - %_struct_4 = OpTypeStruct %_arr_int_uint_10 -%_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4 - %_struct_6 = OpTypeStruct %_runtimearr__struct_4 -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 - %void = OpTypeVoid - %14 = OpTypeFunction %void -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 -%_arr_int_uint_10_0 = OpTypeArray %int %uint_10 - %_struct_17 = OpTypeStruct %_arr_int_uint_10_0 -%_ptr_Function__struct_17 = OpTypePointer Function %_struct_17 - %19 = OpTypeFunction %void %_ptr_Function__struct_17 - %2 = OpVariable %_ptr_Uniform__struct_6 Uniform - %1 = OpFunction %void None %14 - %20 = OpLabel - %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0 - %22 = OpFunctionCall %void %23 %21 - OpReturn - OpFunctionEnd - %23 = OpFunction %void None %19 - %24 = OpFunctionParameter %_ptr_Function__struct_17 - %25 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateFunctionCall, LogicallyMismatchedPointersMissingMember) { - // Validation should fail because the formal parameter type has two members, - // while the actual parameter only has 1. - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %_struct_3 = OpTypeStruct %int -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 - %void = OpTypeVoid - %14 = OpTypeFunction %void - %_struct_15 = OpTypeStruct %int %int -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 - %18 = OpTypeFunction %void %_ptr_Function__struct_15 - %2 = OpVariable %_ptr_Uniform__struct_5 Uniform - %1 = OpFunction %void None %14 - %19 = OpLabel - %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0 - %21 = OpFunctionCall %void %22 %20 - OpReturn - OpFunctionEnd - %22 = OpFunction %void None %18 - %23 = OpFunctionParameter %_ptr_Function__struct_15 - %24 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument ")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("type does not match Function ")); -} - -TEST_F(ValidateFunctionCall, LogicallyMismatchedPointersDifferentMemberType) { - // Validation should fail because the formal parameter has a member that is - // a different type than the actual parameter. - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %_struct_3 = OpTypeStruct %uint -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 - %void = OpTypeVoid - %14 = OpTypeFunction %void - %_struct_15 = OpTypeStruct %int -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 - %18 = OpTypeFunction %void %_ptr_Function__struct_15 - %2 = OpVariable %_ptr_Uniform__struct_5 Uniform - %1 = OpFunction %void None %14 - %19 = OpLabel - %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0 - %21 = OpFunctionCall %void %22 %20 - OpReturn - OpFunctionEnd - %22 = OpFunction %void None %18 - %23 = OpFunctionParameter %_ptr_Function__struct_15 - %24 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument ")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("type does not match Function ")); -} - -TEST_F(ValidateFunctionCall, - LogicallyMismatchedPointersIncompatableDecorations) { - // Validation should fail because the formal parameter has an incompatible - // decoration. - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 Block - OpMemberDecorate %_struct_15 0 NonWritable - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %_struct_3 = OpTypeStruct %int -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_StorageBuffer__struct_5 = OpTypePointer StorageBuffer %_struct_5 - %void = OpTypeVoid - %14 = OpTypeFunction %void - %_struct_15 = OpTypeStruct %int -%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15 -%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3 - %18 = OpTypeFunction %void %_ptr_Function__struct_15 - %2 = OpVariable %_ptr_StorageBuffer__struct_5 StorageBuffer - %1 = OpFunction %void None %14 - %19 = OpLabel - %20 = OpAccessChain %_ptr_StorageBuffer__struct_3 %2 %int_0 %uint_0 - %21 = OpFunctionCall %void %22 %20 - OpReturn - OpFunctionEnd - %22 = OpFunction %void None %18 - %23 = OpFunctionParameter %_ptr_Function__struct_15 - %24 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument ")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("type does not match Function ")); -} - -TEST_F(ValidateFunctionCall, - LogicallyMismatchedPointersIncompatableDecorations2) { - // Validation should fail because the formal parameter has an incompatible - // decoration. - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpMemberDecorate %_struct_3 0 Offset 0 - OpDecorate %_runtimearr__struct_3 ArrayStride 4 - OpMemberDecorate %_struct_5 0 Offset 0 - OpDecorate %_struct_5 BufferBlock - OpDecorate %_ptr_Uniform__struct_3 ArrayStride 4 - OpDecorate %_ptr_Uniform__struct_3_0 ArrayStride 8 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %_struct_3 = OpTypeStruct %int -%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 - %_struct_5 = OpTypeStruct %_runtimearr__struct_3 -%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 - %void = OpTypeVoid - %14 = OpTypeFunction %void -%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 -%_ptr_Uniform__struct_3_0 = OpTypePointer Uniform %_struct_3 - %18 = OpTypeFunction %void %_ptr_Uniform__struct_3_0 - %2 = OpVariable %_ptr_Uniform__struct_5 Uniform - %1 = OpFunction %void None %14 - %19 = OpLabel - %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0 - %21 = OpFunctionCall %void %22 %20 - OpReturn - OpFunctionEnd - %22 = OpFunction %void None %18 - %23 = OpFunctionParameter %_ptr_Uniform__struct_3_0 - %24 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument ")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("type does not match Function ")); -} - -TEST_F(ValidateFunctionCall, LogicallyMismatchedPointersArraySize) { - // Validation should fail because the formal parameter array has a different - // number of element than the actual parameter. - std::string spirv = - R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %1 "main" - OpExecutionMode %1 LocalSize 1 1 1 - OpSource HLSL 600 - OpDecorate %2 DescriptorSet 0 - OpDecorate %2 Binding 0 - OpDecorate %_arr_int_uint_10 ArrayStride 4 - OpMemberDecorate %_struct_4 0 Offset 0 - OpDecorate %_runtimearr__struct_4 ArrayStride 40 - OpMemberDecorate %_struct_6 0 Offset 0 - OpDecorate %_struct_6 BufferBlock - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 - %uint_5 = OpConstant %uint 5 - %uint_10 = OpConstant %uint 10 -%_arr_int_uint_10 = OpTypeArray %int %uint_10 - %_struct_4 = OpTypeStruct %_arr_int_uint_10 -%_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4 - %_struct_6 = OpTypeStruct %_runtimearr__struct_4 -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 - %void = OpTypeVoid - %14 = OpTypeFunction %void -%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 -%_arr_int_uint_5 = OpTypeArray %int %uint_5 - %_struct_17 = OpTypeStruct %_arr_int_uint_5 -%_ptr_Function__struct_17 = OpTypePointer Function %_struct_17 - %19 = OpTypeFunction %void %_ptr_Function__struct_17 - %2 = OpVariable %_ptr_Uniform__struct_6 Uniform - %1 = OpFunction %void None %14 - %20 = OpLabel - %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0 - %22 = OpFunctionCall %void %23 %21 - OpReturn - OpFunctionEnd - %23 = OpFunction %void None %19 - %24 = OpFunctionParameter %_ptr_Function__struct_17 - %25 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument ")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("type does not match Function ")); -} - -INSTANTIATE_TEST_SUITE_P(StorageClass, ValidateFunctionCall, - Values("UniformConstant", "Input", "Uniform", "Output", - "Workgroup", "Private", "Function", - "PushConstant", "Image", "StorageBuffer", - "AtomicCounter")); -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_id_test.cpp b/3rdparty/spirv-tools/test/val/val_id_test.cpp deleted file mode 100644 index 019d91ad7..000000000 --- a/3rdparty/spirv-tools/test/val/val_id_test.cpp +++ /dev/null @@ -1,6577 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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 "gmock/gmock.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -// NOTE: The tests in this file are ONLY testing ID usage, there for the input -// SPIR-V does not follow the logical layout rules from the spec in all cases in -// order to makes the tests smaller. Validation of the whole module is handled -// in stages, ID validation is only one of these stages. All validation stages -// are stand alone. - -namespace spvtools { -namespace val { -namespace { - -using spvtest::ScopedContext; -using ::testing::HasSubstr; -using ::testing::ValuesIn; - -using ValidateIdWithMessage = spvtest::ValidateBase; - -std::string kOpCapabilitySetupWithoutVector16 = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Addresses - OpCapability Int8 - OpCapability Int16 - OpCapability Int64 - OpCapability Float64 - OpCapability LiteralSampler - OpCapability Pipes - OpCapability DeviceEnqueue -)"; - -std::string kOpCapabilitySetup = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Addresses - OpCapability Int8 - OpCapability Int16 - OpCapability Int64 - OpCapability Float64 - OpCapability LiteralSampler - OpCapability Pipes - OpCapability DeviceEnqueue - OpCapability Vector16 -)"; - -std::string kOpVariablePtrSetUp = R"( - OpCapability VariablePointers - OpExtension "SPV_KHR_variable_pointers" -)"; - -std::string kGLSL450MemoryModel = - kOpCapabilitySetup + kOpVariablePtrSetUp + R"( - OpMemoryModel Logical GLSL450 -)"; - -std::string kGLSL450MemoryModelWithoutVector16 = - kOpCapabilitySetupWithoutVector16 + kOpVariablePtrSetUp + R"( - OpMemoryModel Logical GLSL450 -)"; - -std::string kNoKernelGLSL450MemoryModel = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Addresses - OpCapability Int8 - OpCapability Int16 - OpCapability Int64 - OpCapability Float64 - OpMemoryModel Logical GLSL450 -)"; - -std::string kOpenCLMemoryModel32 = R"( - OpCapability Addresses - OpCapability Linkage - OpCapability Kernel -%1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical32 OpenCL -)"; - -std::string kOpenCLMemoryModel64 = R"( - OpCapability Addresses - OpCapability Linkage - OpCapability Kernel - OpCapability Int64 -%1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Physical64 OpenCL -)"; - -std::string sampledImageSetup = R"( - %void = OpTypeVoid - %typeFuncVoid = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %image_type = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_img = OpTypePointer UniformConstant %image_type - %tex = OpVariable %_ptr_UniformConstant_img UniformConstant - %sampler_type = OpTypeSampler -%_ptr_UniformConstant_sam = OpTypePointer UniformConstant %sampler_type - %s = OpVariable %_ptr_UniformConstant_sam UniformConstant - %sampled_image_type = OpTypeSampledImage %image_type - %v2float = OpTypeVector %float 2 - %float_1 = OpConstant %float 1 - %float_2 = OpConstant %float 2 - %const_vec_1_1 = OpConstantComposite %v2float %float_1 %float_1 - %const_vec_2_2 = OpConstantComposite %v2float %float_2 %float_2 - %bool_type = OpTypeBool - %spec_true = OpSpecConstantTrue %bool_type - %main = OpFunction %void None %typeFuncVoid - %label_1 = OpLabel - %image_inst = OpLoad %image_type %tex - %sampler_inst = OpLoad %sampler_type %s -)"; - -std::string BranchConditionalSetup = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 140 - OpName %main "main" - - ; type definitions - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - - ; constants - %true = OpConstantTrue %bool - %i0 = OpConstant %int 0 - %i1 = OpConstant %int 1 - %f0 = OpConstant %float 0 - %f1 = OpConstant %float 1 - - - ; main function header - %void = OpTypeVoid - %voidfunc = OpTypeFunction %void - %main = OpFunction %void None %voidfunc - %lmain = OpLabel -)"; - -std::string BranchConditionalTail = R"( - %target_t = OpLabel - OpNop - OpBranch %end - %target_f = OpLabel - OpNop - OpBranch %end - - %end = OpLabel - - OpReturn - OpFunctionEnd -)"; - -// TODO: OpUndef - -TEST_F(ValidateIdWithMessage, OpName) { - std::string spirv = kGLSL450MemoryModel + R"( - OpName %2 "name" -%1 = OpTypeInt 32 0 -%2 = OpTypePointer UniformConstant %1 -%3 = OpVariable %2 UniformConstant)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpMemberNameGood) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberName %2 0 "foo" -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpMemberNameTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberName %1 0 "foo" -%1 = OpTypeInt 32 0)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpMemberName Type '1[%uint]' is not a struct type.")); -} -TEST_F(ValidateIdWithMessage, OpMemberNameMemberBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberName %1 1 "foo" -%2 = OpTypeInt 32 0 -%1 = OpTypeStruct %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpMemberName Member '1[%_struct_1]' index is larger " - "than Type '1[%_struct_1]'s member count.")); -} - -TEST_F(ValidateIdWithMessage, OpLineGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpString "/path/to/source.file" - OpLine %1 0 0 -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Input %2 -%4 = OpVariable %3 Input)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpLineFileBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeInt 32 0 - OpLine %1 0 0 - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpLine Target '1[%uint]' is not an OpString.")); -} - -TEST_F(ValidateIdWithMessage, OpDecorateGood) { - std::string spirv = kGLSL450MemoryModel + R"( - OpDecorate %2 GLSLShared -%1 = OpTypeInt 64 0 -%2 = OpTypeStruct %1 %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpDecorateBad) { - std::string spirv = kGLSL450MemoryModel + R"( -OpDecorate %1 GLSLShared)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("forward referenced IDs have not been defined")); -} - -TEST_F(ValidateIdWithMessage, OpMemberDecorateGood) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %2 0 RelaxedPrecision -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct %1 %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpMemberDecorateBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 RelaxedPrecision -%1 = OpTypeInt 32 0)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpMemberDecorate Structure type '1[%uint]' is " - "not a struct type.")); -} -TEST_F(ValidateIdWithMessage, OpMemberDecorateMemberBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 3 RelaxedPrecision -%int = OpTypeInt 32 0 -%1 = OpTypeStruct %int %int)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index 3 provided in OpMemberDecorate for struct " - "1[%_struct_1] is out of bounds. The structure has 2 " - "members. Largest valid index is 1.")); -} - -TEST_F(ValidateIdWithMessage, OpGroupDecorateGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpDecorationGroup - OpDecorate %1 RelaxedPrecision - OpDecorate %1 GLSLShared - OpGroupDecorate %1 %3 %4 -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 42 -%4 = OpConstant %2 23)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpDecorationGroupBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpDecorationGroup - OpDecorate %1 RelaxedPrecision - OpDecorate %1 GLSLShared - OpMemberDecorate %1 0 Constant - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result id of OpDecorationGroup can only " - "be targeted by OpName, OpGroupDecorate, " - "OpDecorate, OpDecorateId, and OpGroupMemberDecorate")); -} -TEST_F(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpGroupDecorate %1 %2 %3 -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 42)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpGroupDecorate Decoration group '1[%1]' is not " - "a decoration group.")); -} -TEST_F(ValidateIdWithMessage, OpGroupDecorateTargetBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpDecorationGroup - OpDecorate %1 RelaxedPrecision - OpDecorate %1 GLSLShared - OpGroupDecorate %1 %3 -%2 = OpTypeInt 32 0)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("forward referenced IDs have not been defined")); -} -TEST_F(ValidateIdWithMessage, OpGroupMemberDecorateDecorationGroupBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpGroupMemberDecorate %1 %2 0 -%2 = OpTypeInt 32 0)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpGroupMemberDecorate Decoration group '1[%1]' " - "is not a decoration group.")); -} -TEST_F(ValidateIdWithMessage, OpGroupMemberDecorateIdNotStructBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpDecorationGroup - OpGroupMemberDecorate %1 %2 0 -%2 = OpTypeInt 32 0)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpGroupMemberDecorate Structure type '2[%uint]' " - "is not a struct type.")); -} -TEST_F(ValidateIdWithMessage, OpGroupMemberDecorateIndexOutOfBoundBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpDecorate %1 Offset 0 - %1 = OpDecorationGroup - OpGroupMemberDecorate %1 %struct 3 -%float = OpTypeFloat 32 -%struct = OpTypeStruct %float %float %float -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index 3 provided in OpGroupMemberDecorate for struct " - " 2[%_struct_2] is out of bounds. The structure " - "has 3 members. Largest valid index is 2.")); -} - -// TODO: OpExtInst - -TEST_F(ValidateIdWithMessage, OpEntryPointGood) { - std::string spirv = kGLSL450MemoryModel + R"( - OpEntryPoint GLCompute %3 "" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpEntryPointFunctionBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpEntryPoint GLCompute %1 "" -%1 = OpTypeVoid)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpEntryPoint Entry Point '1[%void]' is not a " - "function.")); -} -TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpEntryPoint GLCompute %3 "" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpEntryPoint Entry Point '1[%1]'s function " - "parameter count is not zero")); -} -TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpEntryPoint GLCompute %3 "" -%1 = OpTypeInt 32 0 -%ret = OpConstant %1 0 -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturnValue %ret - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpEntryPoint Entry Point '1[%1]'s function " - "return type is not void.")); -} - -TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Geometry - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %ptr_builtin_1 - OpExecutionMode %main InputPoints - OpExecutionMode %main OutputPoints - OpMemberDecorate %struct_1 0 BuiltIn InvocationId - %int = OpTypeInt 32 1 - %void = OpTypeVoid - %func = OpTypeFunction %void - %struct_1 = OpTypeStruct %int -%ptr_builtin_1 = OpTypePointer Input %struct_1 - %main = OpFunction %void None %func - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Interfaces passed to OpEntryPoint must be of type " - "OpTypeVariable. Found OpTypePointer.")); -} - -TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceStorageClassBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability Geometry - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %in_1 - OpExecutionMode %main InputPoints - OpExecutionMode %main OutputPoints - OpMemberDecorate %struct_1 0 BuiltIn InvocationId - %int = OpTypeInt 32 1 - %void = OpTypeVoid - %func = OpTypeFunction %void - %struct_1 = OpTypeStruct %int -%ptr_builtin_1 = OpTypePointer Uniform %struct_1 - %in_1 = OpVariable %ptr_builtin_1 Uniform - %main = OpFunction %void None %func - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpEntryPoint interfaces must be OpVariables with " - "Storage Class of Input(1) or Output(3). Found Storage " - "Class 2 for Entry Point id 1.")); -} - -TEST_F(ValidateIdWithMessage, OpExecutionModeGood) { - std::string spirv = kGLSL450MemoryModel + R"( - OpEntryPoint GLCompute %3 "" - OpExecutionMode %3 LocalSize 1 1 1 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) { - std::string spirv = kGLSL450MemoryModel + R"( - OpExecutionMode %3 LocalSize 1 1 1 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpExecutionMode Entry Point '1[%1]' is not the " - "Entry Point operand of an OpEntryPoint.")); -} - -TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointBad) { - std::string spirv = kGLSL450MemoryModel + R"( - OpEntryPoint GLCompute %3 "" %a - OpExecutionMode %a LocalSize 1 1 1 -%void = OpTypeVoid -%ptr = OpTypePointer Input %void -%a = OpVariable %ptr Input -%2 = OpTypeFunction %void -%3 = OpFunction %void None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpExecutionMode Entry Point '2[%2]' is not the " - "Entry Point operand of an OpEntryPoint.")); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorFloat) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorInt) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeVector %1 4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorUInt) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 64 0 -%2 = OpTypeVector %1 4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorBool) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeBool -%2 = OpTypeVector %1 4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypePointer UniformConstant %1 -%3 = OpTypeVector %2 4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpTypeVector Component Type " - "'2[%_ptr_UniformConstant_float]' is not a scalar type.")); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountLessThanTwoBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Illegal number of components (1) for TypeVector\n %v1float = " - "OpTypeVector %float 1\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountGreaterThanFourBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Illegal number of components (5) for TypeVector\n %v5float = " - "OpTypeVector %float 5\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountEightWithoutVector16Bad) { - std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 8)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Having 8 components for TypeVector requires the Vector16 " - "capability\n %v8float = OpTypeVector %float 8\n")); -} - -TEST_F(ValidateIdWithMessage, - OpTypeVectorColumnCountSixteenWithoutVector16Bad) { - std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 16)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Having 16 components for TypeVector requires the Vector16 " - "capability\n %v16float = OpTypeVector %float 16\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountOfEightWithVector16Good) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 8)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, - OpTypeVectorColumnCountOfSixteenWithVector16Good) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 16)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeMatrixGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 2 -%3 = OpTypeMatrix %2 3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnTypeNonVectorBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeMatrix %1 3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("olumns in a matrix must be of type vector.\n %mat3float = " - "OpTypeMatrix %float 3\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeMatrixVectorTypeNonFloatBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 16 0 -%2 = OpTypeVector %1 2 -%3 = OpTypeMatrix %2 2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Matrix types can only be parameterized with floating-point " - "types.\n %mat2v2ushort = OpTypeMatrix %v2ushort 2\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnCountLessThanTwoBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 2 -%3 = OpTypeMatrix %2 1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Matrix types can only be parameterized as having only 2, 3, " - "or 4 columns.\n %mat1v2float = OpTypeMatrix %v2float 1\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnCountGreaterThanFourBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 2 -%3 = OpTypeMatrix %2 8)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Matrix types can only be parameterized as having only 2, 3, " - "or 4 columns.\n %mat8v2float = OpTypeMatrix %v2float 8\n")); -} - -TEST_F(ValidateIdWithMessage, OpTypeSamplerGood) { - // In Rev31, OpTypeSampler takes no arguments. - std::string spirv = kGLSL450MemoryModel + R"( -%s = OpTypeSampler)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeArrayGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 1 -%3 = OpTypeArray %1 %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeArrayElementTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 1 -%3 = OpTypeArray %2 %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeArray Element Type '2[%uint_1]' is not a " - "type.")); -} - -// Signed or unsigned. -enum Signed { kSigned, kUnsigned }; - -// Creates an assembly module declaring OpTypeArray with the given length. -std::string MakeArrayLength(const std::string& len, Signed isSigned, int width, - int max_int_width = 64, - bool use_vulkan_memory_model = false) { - std::ostringstream ss; - ss << R"( - OpCapability Shader - )"; - if (use_vulkan_memory_model) { - ss << " OpCapability VulkanMemoryModel\n"; - } - if (width == 16) { - ss << " OpCapability Int16\n"; - } - if (max_int_width > 32) { - ss << "\n OpCapability Int64\n"; - } - if (use_vulkan_memory_model) { - ss << " OpExtension \"SPV_KHR_vulkan_memory_model\"\n"; - ss << "OpMemoryModel Logical Vulkan\n"; - } else { - ss << "OpMemoryModel Logical GLSL450\n"; - } - ss << "OpEntryPoint GLCompute %main \"main\"\n"; - ss << "OpExecutionMode %main LocalSize 1 1 1\n"; - ss << " %t = OpTypeInt " << width << (isSigned == kSigned ? " 1" : " 0"); - ss << " %l = OpConstant %t " << len; - ss << " %a = OpTypeArray %t %l"; - ss << " %void = OpTypeVoid \n" - " %voidfn = OpTypeFunction %void \n" - " %main = OpFunction %void None %voidfn \n" - " %entry = OpLabel\n" - " OpReturn\n" - " OpFunctionEnd\n"; - return ss.str(); -} - -// Tests OpTypeArray. Parameter is the width (in bits) of the array-length's -// type. -class OpTypeArrayLengthTest - : public spvtest::TextToBinaryTestBase<::testing::TestWithParam> { - protected: - OpTypeArrayLengthTest() - : env_(SPV_ENV_UNIVERSAL_1_0), - position_(spv_position_t{0, 0, 0}), - diagnostic_(spvDiagnosticCreate(&position_, "")) {} - - ~OpTypeArrayLengthTest() { spvDiagnosticDestroy(diagnostic_); } - - // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint(). - spv_result_t Val(const SpirvVector& v, const std::string& expected_err = "") { - spv_const_binary_t cbinary{v.data(), v.size()}; - spvDiagnosticDestroy(diagnostic_); - diagnostic_ = nullptr; - const auto status = - spvValidate(ScopedContext(env_).context, &cbinary, &diagnostic_); - if (status != SPV_SUCCESS) { - spvDiagnosticPrint(diagnostic_); - EXPECT_THAT(std::string(diagnostic_->error), - testing::ContainsRegex(expected_err)); - } - return status; - } - - protected: - spv_target_env env_; - - private: - spv_position_t position_; // For creating diagnostic_. - spv_diagnostic diagnostic_; -}; - -TEST_P(OpTypeArrayLengthTest, LengthPositiveSmall) { - const int width = GetParam(); - EXPECT_EQ(SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("1", kSigned, width)))); - EXPECT_EQ(SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned, width)))); - EXPECT_EQ(SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("2", kSigned, width)))); - EXPECT_EQ(SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned, width)))); - EXPECT_EQ(SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("55", kSigned, width)))); - EXPECT_EQ(SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned, width)))); - const std::string fpad(width / 4 - 1, 'F'); - EXPECT_EQ( - SPV_SUCCESS, - Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad, kSigned, width)))) - << MakeArrayLength("0x7" + fpad, kSigned, width); -} - -TEST_P(OpTypeArrayLengthTest, LengthZero) { - const int width = GetParam(); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width)), - "OpTypeArray Length '3\\[%.*\\]' default value must be at " - "least 1.")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width)), - "OpTypeArray Length '3\\[%.*\\]' default value must be at " - "least 1.")); -} - -TEST_P(OpTypeArrayLengthTest, LengthNegative) { - const int width = GetParam(); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width)), - "OpTypeArray Length '3\\[%.*\\]' default value must be at " - "least 1.")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width)), - "OpTypeArray Length '3\\[%.*\\]' default value must be at " - "least 1.")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width)), - "OpTypeArray Length '3\\[%.*\\]' default value must be at " - "least 1.")); - const std::string neg_max = "0x8" + std::string(width / 4 - 1, '0'); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width)), - "OpTypeArray Length '3\\[%.*\\]' default value must be at " - "least 1.")); -} - -// Returns the string form of an integer of the form 0x80....0 of the -// given bit width. -std::string big_num_ending_0(int bit_width) { - return "0x8" + std::string(bit_width / 4 - 1, '0'); -} - -// Returns the string form of an integer of the form 0x80..001 of the -// given bit width. -std::string big_num_ending_1(int bit_width) { - return "0x8" + std::string(bit_width / 4 - 2, '0') + "1"; -} - -TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding0InVulkan) { - env_ = SPV_ENV_VULKAN_1_0; - const int width = GetParam(); - for (int max_int_width : {32, 64}) { - if (width > max_int_width) { - // Not valid to even make the OpConstant in this case. - continue; - } - const auto module = CompileSuccessfully(MakeArrayLength( - big_num_ending_0(width), kUnsigned, width, max_int_width)); - EXPECT_EQ(SPV_SUCCESS, Val(module)); - } -} - -TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding1InVulkan) { - env_ = SPV_ENV_VULKAN_1_0; - const int width = GetParam(); - for (int max_int_width : {32, 64}) { - if (width > max_int_width) { - // Not valid to even make the OpConstant in this case. - continue; - } - const auto module = CompileSuccessfully(MakeArrayLength( - big_num_ending_1(width), kUnsigned, width, max_int_width)); - EXPECT_EQ(SPV_SUCCESS, Val(module)); - } -} - -TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding0InWebGPU) { - env_ = SPV_ENV_WEBGPU_0; - const int width = GetParam(); - // WebGPU only has 32 bit integers. - if (width != 32) return; - const int max_int_width = 32; - const auto module = CompileSuccessfully(MakeArrayLength( - big_num_ending_0(width), kUnsigned, width, max_int_width, true)); - EXPECT_EQ(SPV_SUCCESS, Val(module)); -} - -TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding1InWebGPU) { - env_ = SPV_ENV_WEBGPU_0; - const int width = GetParam(); - // WebGPU only has 32 bit integers. - if (width != 32) return; - const int max_int_width = 32; - const auto module = CompileSuccessfully(MakeArrayLength( - big_num_ending_1(width), kUnsigned, width, max_int_width, true)); - EXPECT_EQ(SPV_ERROR_INVALID_ID, - Val(module, - "OpTypeArray Length '3\\[%.*\\]' size exceeds max value " - "2147483648 permitted by WebGPU: got 2147483649")); -} - -// The only valid widths for integers are 8, 16, 32, and 64. -// Since the Int8 capability requires the Kernel capability, and the Kernel -// capability prohibits usage of signed integers, we can skip 8-bit integers -// here since the purpose of these tests is to check the validity of -// OpTypeArray, not OpTypeInt. -INSTANTIATE_TEST_SUITE_P(Widths, OpTypeArrayLengthTest, - ValuesIn(std::vector{16, 32, 64})); - -TEST_F(ValidateIdWithMessage, OpTypeArrayLengthNull) { - std::string spirv = kGLSL450MemoryModel + R"( -%i32 = OpTypeInt 32 0 -%len = OpConstantNull %i32 -%ary = OpTypeArray %i32 %len)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeArray Length '2[%2]' default value must be at least 1.")); -} - -TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) { - std::string spirv = kGLSL450MemoryModel + R"( -%i32 = OpTypeInt 32 0 -%len = OpSpecConstant %i32 2 -%ary = OpTypeArray %i32 %len)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConstOp) { - std::string spirv = kGLSL450MemoryModel + R"( -%i32 = OpTypeInt 32 0 -%c1 = OpConstant %i32 1 -%c2 = OpConstant %i32 2 -%len = OpSpecConstantOp %i32 IAdd %c1 %c2 -%ary = OpTypeArray %i32 %len)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeRuntimeArray %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 0 -%3 = OpTypeRuntimeArray %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpTypeRuntimeArray Element Type '2[%uint_0]' is not a " - "type.")); -} -// TODO: Object of this type can only be created with OpVariable using the -// Unifrom Storage Class - -TEST_F(ValidateIdWithMessage, OpTypeStructGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFloat 64 -%3 = OpTypePointer Input %1 -%4 = OpTypeStruct %1 %2 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpTypeStructMemberTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFloat 64 -%3 = OpConstant %2 0.0 -%4 = OpTypeStruct %1 %2 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeStruct Member Type '3[%double_0]' is not " - "a type.")); -} - -TEST_F(ValidateIdWithMessage, OpTypeStructOpaqueTypeBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - %1 = OpTypeSampler - %2 = OpTypeStruct %1 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeStruct must not contain an opaque type")); -} - -TEST_F(ValidateIdWithMessage, OpTypePointerGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypePointer Input %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpTypePointerBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 0 -%3 = OpTypePointer Input %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypePointer Type '2[%uint_0]' is not a " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpTypeFunctionGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 0 -%3 = OpTypeFunction %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeFunction Return Type '2[%uint_0]' is not " - "a type.")); -} -TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 %2 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpTypeFunction Parameter Type '3[%uint_0]' is not a " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterTypeVoidBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%4 = OpTypeFunction %1 %2 %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeFunction Parameter Type '1[%void]' cannot " - "be OpTypeVoid.")); -} - -TEST_F(ValidateIdWithMessage, OpTypePipeGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 16 -%3 = OpTypePipe ReadOnly)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpConstantTrueGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeBool -%2 = OpConstantTrue %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantTrueBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpConstantTrue %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantTrue Result Type '1[%void]' is not a boolean " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantFalseGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeBool -%2 = OpConstantTrue %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantFalseBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpConstantFalse %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantFalse Result Type '1[%void]' is not a boolean " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpConstant !1 !0)"; - // The expected failure code is implementation dependent (currently - // INVALID_BINARY because the binary parser catches these cases) and may - // change over time, but this must always fail. - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpConstant %1 3.14 -%4 = OpConstantComposite %2 %3 %3 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorWithUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpConstant %1 3.14 -%9 = OpUndef %1 -%4 = OpConstantComposite %2 %3 %3 %3 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpConstant %1 3.14 -%4 = OpConstantComposite %1 %3 %3 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantComposite Result Type '1[%float]' is not a " - "composite type.")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%4 = OpTypeInt 32 0 -%3 = OpConstant %1 3.14 -%5 = OpConstant %4 42 ; bad type for constant value -%6 = OpConstantComposite %2 %3 %5 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '5[%uint_42]'s type " - "does not match Result Type '2[%v4float]'s vector " - "element type.")); -} -TEST_F(ValidateIdWithMessage, - OpConstantCompositeVectorConstituentUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%4 = OpTypeInt 32 0 -%3 = OpConstant %1 3.14 -%5 = OpUndef %4 ; bad type for undef value -%6 = OpConstantComposite %2 %3 %5 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '5[%5]'s type does not " - "match Result Type '2[%v4float]'s vector element type.")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeMatrix %2 4 - %4 = OpConstant %1 1.0 - %5 = OpConstant %1 0.0 - %6 = OpConstantComposite %2 %4 %5 %5 %5 - %7 = OpConstantComposite %2 %5 %4 %5 %5 - %8 = OpConstantComposite %2 %5 %5 %4 %5 - %9 = OpConstantComposite %2 %5 %5 %5 %4 -%10 = OpConstantComposite %3 %6 %7 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeMatrix %2 4 - %4 = OpConstant %1 1.0 - %5 = OpConstant %1 0.0 - %6 = OpConstantComposite %2 %4 %5 %5 %5 - %7 = OpConstantComposite %2 %5 %4 %5 %5 - %8 = OpConstantComposite %2 %5 %5 %4 %5 - %9 = OpUndef %2 -%10 = OpConstantComposite %3 %6 %7 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 -%11 = OpTypeVector %1 3 - %3 = OpTypeMatrix %2 4 - %4 = OpConstant %1 1.0 - %5 = OpConstant %1 0.0 - %6 = OpConstantComposite %2 %4 %5 %5 %5 - %7 = OpConstantComposite %2 %5 %4 %5 %5 - %8 = OpConstantComposite %2 %5 %5 %4 %5 - %9 = OpConstantComposite %11 %5 %5 %5 -%10 = OpConstantComposite %3 %6 %7 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '10[%10]' vector " - "component count does not match Result Type " - "'4[%mat4v4float]'s vector component count.")); -} -TEST_F(ValidateIdWithMessage, - OpConstantCompositeMatrixConstituentUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 -%11 = OpTypeVector %1 3 - %3 = OpTypeMatrix %2 4 - %4 = OpConstant %1 1.0 - %5 = OpConstant %1 0.0 - %6 = OpConstantComposite %2 %4 %5 %5 %5 - %7 = OpConstantComposite %2 %5 %4 %5 %5 - %8 = OpConstantComposite %2 %5 %5 %4 %5 - %9 = OpUndef %11 -%10 = OpConstantComposite %3 %6 %7 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '10[%10]' vector " - "component count does not match Result Type " - "'4[%mat4v4float]'s vector component count.")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%4 = OpConstantComposite %3 %2 %2 %2 %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayWithUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%9 = OpUndef %1 -%3 = OpTypeArray %1 %2 -%4 = OpConstantComposite %3 %2 %2 %2 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%4 = OpConstantComposite %3 %2 %2 %2 %1)"; // Uses a type as operand - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%uint] cannot be a " - "type")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%4 = OpTypePointer Uniform %1 -%5 = OpVariable %4 Uniform -%6 = OpConstantComposite %3 %2 %2 %2 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '5[%5]' is not a " - "constant or undef.")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%5 = OpTypeFloat 32 -%6 = OpConstant %5 3.14 ; bad type for const value -%4 = OpConstantComposite %3 %2 %2 %2 %6)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent " - "'5[%float_3_1400001]'s type does not match Result " - "Type '3[%_arr_uint_uint_4]'s array element " - "type.")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%5 = OpTypeFloat 32 -%6 = OpUndef %5 ; bad type for undef -%4 = OpConstantComposite %3 %2 %2 %2 %6)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent " - "'5[%5]'s type does not match Result " - "Type '3[%_arr_uint_uint_4]'s array element " - "type.")); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeStructGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpConstant %1 42 -%5 = OpConstant %2 4300000000 -%6 = OpConstantComposite %3 %4 %4 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeStructUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpConstant %1 42 -%5 = OpUndef %2 -%6 = OpConstantComposite %3 %4 %4 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpConstant %1 42 -%5 = OpConstant %2 4300000000 -%6 = OpConstantComposite %3 %4 %5 %4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent " - "'5[%ulong_4300000000]' type does not match the " - "Result Type '3[%_struct_3]'s member type.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpConstant %1 42 -%5 = OpUndef %2 -%6 = OpConstantComposite %3 %4 %5 %4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantComposite Constituent '5[%5]' type " - "does not match the Result Type '3[%_struct_3]'s " - "member type.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantSamplerGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%float = OpTypeFloat 32 -%samplerType = OpTypeSampler -%3 = OpConstantSampler %samplerType ClampToEdge 0 Nearest)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpConstantSampler %1 Clamp 0 Nearest)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpConstantSampler Result Type '1[%float]' is not a sampler " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantNullGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeBool - %2 = OpConstantNull %1 - %3 = OpTypeInt 32 0 - %4 = OpConstantNull %3 - %5 = OpTypeFloat 32 - %6 = OpConstantNull %5 - %7 = OpTypePointer UniformConstant %3 - %8 = OpConstantNull %7 - %9 = OpTypeEvent -%10 = OpConstantNull %9 -%11 = OpTypeDeviceEvent -%12 = OpConstantNull %11 -%13 = OpTypeReserveId -%14 = OpConstantNull %13 -%15 = OpTypeQueue -%16 = OpConstantNull %15 -%17 = OpTypeVector %5 2 -%18 = OpConstantNull %17 -%19 = OpTypeMatrix %17 2 -%20 = OpConstantNull %19 -%25 = OpConstant %3 8 -%21 = OpTypeArray %3 %25 -%22 = OpConstantNull %21 -%23 = OpTypeStruct %3 %5 %1 -%24 = OpConstantNull %23 -%26 = OpTypeArray %17 %25 -%27 = OpConstantNull %26 -%28 = OpTypeStruct %7 %26 %26 %1 -%29 = OpConstantNull %28 -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpConstantNullBasicBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpConstantNull %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpConstantNull Result Type '1[%void]' cannot have a null " - "value.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantNullArrayBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%2 = OpTypeInt 32 0 -%3 = OpTypeSampler -%4 = OpConstant %2 4 -%5 = OpTypeArray %3 %4 -%6 = OpConstantNull %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpConstantNull Result Type '4[%_arr_2_uint_4]' cannot have a " - "null value.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantNullStructBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%2 = OpTypeSampler -%3 = OpTypeStruct %2 %2 -%4 = OpConstantNull %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpConstantNull Result Type '2[%_struct_2]' " - "cannot have a null value.")); -} - -TEST_F(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%bool = OpTypeBool -%array = OpTypeRuntimeArray %bool -%null = OpConstantNull %array)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpConstantNull Result Type '2[%_runtimearr_bool]' cannot have " - "a null value.")); -} - -TEST_F(ValidateIdWithMessage, OpSpecConstantTrueGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeBool -%2 = OpSpecConstantTrue %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpSpecConstantTrueBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpSpecConstantTrue %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantTrue Result Type '1[%void]' is not " - "a boolean type")); -} - -TEST_F(ValidateIdWithMessage, OpSpecConstantFalseGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeBool -%2 = OpSpecConstantFalse %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpSpecConstantFalseBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpSpecConstantFalse %1)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpSpecConstantFalse Result Type '1[%void]' is not " - "a boolean type")); -} - -TEST_F(ValidateIdWithMessage, OpSpecConstantGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpSpecConstant %1 42)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpSpecConstantBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpSpecConstant !1 !4)"; - // The expected failure code is implementation dependent (currently - // INVALID_BINARY because the binary parser catches these cases) and may - // change over time, but this must always fail. - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Type Id 1 is not a scalar numeric type")); -} - -// Valid: SpecConstantComposite specializes to a vector. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpSpecConstant %1 3.14 -%4 = OpConstant %1 3.14 -%5 = OpSpecConstantComposite %2 %3 %3 %4 %4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Valid: Vector of floats and Undefs. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorWithUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpSpecConstant %1 3.14 -%5 = OpConstant %1 3.14 -%9 = OpUndef %1 -%4 = OpSpecConstantComposite %2 %3 %5 %3 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: result type is float. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpSpecConstant %1 3.14 -%4 = OpSpecConstantComposite %1 %3 %3 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a composite type")); -} - -// Invalid: Vector contains a mix of Int and Float. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%4 = OpTypeInt 32 0 -%3 = OpSpecConstant %1 3.14 -%5 = OpConstant %4 42 ; bad type for constant value -%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent " - "'5[%uint_42]'s type does not match Result Type " - "'2[%v4float]'s vector element type.")); -} - -// Invalid: Constituent is not a constant -TEST_F(ValidateIdWithMessage, - OpSpecConstantCompositeVectorConstituentNotConstantBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%3 = OpTypeInt 32 0 -%4 = OpSpecConstant %1 3.14 -%5 = OpTypePointer Uniform %1 -%6 = OpVariable %5 Uniform -%7 = OpSpecConstantComposite %2 %6 %4 %4 %4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '6[%6]' is " - "not a constant or undef.")); -} - -// Invalid: Vector contains a mix of Undef-int and Float. -TEST_F(ValidateIdWithMessage, - OpSpecConstantCompositeVectorConstituentUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 4 -%4 = OpTypeInt 32 0 -%3 = OpSpecConstant %1 3.14 -%5 = OpUndef %4 ; bad type for undef value -%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '5[%5]'s " - "type does not match Result Type '2[%v4float]'s " - "vector element type.")); -} - -// Invalid: Vector expects 3 components, but 4 specified. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorNumComponentsBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeVector %1 3 -%3 = OpConstant %1 3.14 -%5 = OpSpecConstant %1 4.0 -%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent count does " - "not match Result Type '2[%v3float]'s vector " - "component count.")); -} - -// Valid: 4x4 matrix of floats -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeMatrix %2 4 - %4 = OpConstant %1 1.0 - %5 = OpSpecConstant %1 0.0 - %6 = OpSpecConstantComposite %2 %4 %5 %5 %5 - %7 = OpSpecConstantComposite %2 %5 %4 %5 %5 - %8 = OpSpecConstantComposite %2 %5 %5 %4 %5 - %9 = OpSpecConstantComposite %2 %5 %5 %5 %4 -%10 = OpSpecConstantComposite %3 %6 %7 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Valid: Matrix in which one column is Undef -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeMatrix %2 4 - %4 = OpConstant %1 1.0 - %5 = OpSpecConstant %1 0.0 - %6 = OpSpecConstantComposite %2 %4 %5 %5 %5 - %7 = OpSpecConstantComposite %2 %5 %4 %5 %5 - %8 = OpSpecConstantComposite %2 %5 %5 %4 %5 - %9 = OpUndef %2 -%10 = OpSpecConstantComposite %3 %6 %7 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Matrix in which the sizes of column vectors are not equal. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeVector %1 3 - %4 = OpTypeMatrix %2 4 - %5 = OpSpecConstant %1 1.0 - %6 = OpConstant %1 0.0 - %7 = OpSpecConstantComposite %2 %5 %6 %6 %6 - %8 = OpSpecConstantComposite %2 %6 %5 %6 %6 - %9 = OpSpecConstantComposite %2 %6 %6 %5 %6 - %10 = OpSpecConstantComposite %3 %6 %6 %6 -%11 = OpSpecConstantComposite %4 %7 %8 %9 %10)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '10[%10]' " - "vector component count does not match Result Type " - " '4[%mat4v4float]'s vector component count.")); -} - -// Invalid: Matrix type expects 4 columns but only 3 specified. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixNumColsBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeMatrix %2 4 - %4 = OpSpecConstant %1 1.0 - %5 = OpConstant %1 0.0 - %6 = OpSpecConstantComposite %2 %4 %5 %5 %5 - %7 = OpSpecConstantComposite %2 %5 %4 %5 %5 - %8 = OpSpecConstantComposite %2 %5 %5 %4 %5 -%10 = OpSpecConstantComposite %3 %6 %7 %8)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent count does " - "not match Result Type '3[%mat4v4float]'s matrix column " - "count.")); -} - -// Invalid: Composite contains a non-const/undef component -TEST_F(ValidateIdWithMessage, - OpSpecConstantCompositeMatrixConstituentNotConstBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpConstant %1 0.0 - %3 = OpTypeVector %1 4 - %4 = OpTypeMatrix %3 4 - %5 = OpSpecConstantComposite %3 %2 %2 %2 %2 - %6 = OpTypePointer Uniform %1 - %7 = OpVariable %6 Uniform - %8 = OpSpecConstantComposite %4 %5 %5 %5 %7)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '7[%7]' is " - "not a constant or undef.")); -} - -// Invalid: Composite contains a column that is *not* a vector (it's an array) -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeInt 32 0 - %3 = OpSpecConstant %2 4 - %4 = OpConstant %1 0.0 - %5 = OpTypeVector %1 4 - %6 = OpTypeArray %2 %3 - %7 = OpTypeMatrix %5 4 - %8 = OpSpecConstantComposite %6 %3 %3 %3 %3 - %9 = OpSpecConstantComposite %5 %4 %4 %4 %4 - %10 = OpSpecConstantComposite %7 %9 %9 %9 %8)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '8[%8]' type " - "does not match Result Type '7[%mat4v4float]'s " - "matrix column type.")); -} - -// Invalid: Matrix with an Undef column of the wrong size. -TEST_F(ValidateIdWithMessage, - OpSpecConstantCompositeMatrixConstituentUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeFloat 32 - %2 = OpTypeVector %1 4 - %3 = OpTypeVector %1 3 - %4 = OpTypeMatrix %2 4 - %5 = OpSpecConstant %1 1.0 - %6 = OpSpecConstant %1 0.0 - %7 = OpSpecConstantComposite %2 %5 %6 %6 %6 - %8 = OpSpecConstantComposite %2 %6 %5 %6 %6 - %9 = OpSpecConstantComposite %2 %6 %6 %5 %6 - %10 = OpUndef %3 - %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '10[%10]' " - "vector component count does not match Result Type " - " '4[%mat4v4float]'s vector component count.")); -} - -// Invalid: Matrix in which some columns are Int and some are Float. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColumnTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeInt 32 0 - %2 = OpTypeFloat 32 - %3 = OpTypeVector %1 2 - %4 = OpTypeVector %2 2 - %5 = OpTypeMatrix %4 2 - %6 = OpSpecConstant %1 42 - %7 = OpConstant %2 3.14 - %8 = OpSpecConstantComposite %3 %6 %6 - %9 = OpSpecConstantComposite %4 %7 %7 -%10 = OpSpecConstantComposite %5 %8 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '8[%8]' " - "component type does not match Result Type " - "'5[%mat2v2float]'s matrix column component type.")); -} - -// Valid: Array of integers -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpSpecConstant %1 4 -%5 = OpConstant %1 5 -%3 = OpTypeArray %1 %2 -%6 = OpTypeArray %1 %5 -%4 = OpSpecConstantComposite %3 %2 %2 %2 %2 -%7 = OpSpecConstantComposite %3 %5 %5 %5 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Expecting an array of 4 components, but 3 specified. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayNumComponentsBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%4 = OpSpecConstantComposite %3 %2 %2 %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent count does not " - "match Result Type '3[%_arr_uint_uint_4]'s array " - "length.")); -} - -// Valid: Array of Integers and Undef-int -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayWithUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpSpecConstant %1 4 -%9 = OpUndef %1 -%3 = OpTypeArray %1 %2 -%4 = OpSpecConstantComposite %3 %2 %2 %2 %9)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Array uses a type as operand. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstConstituentBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%4 = OpTypePointer Uniform %1 -%5 = OpVariable %4 Uniform -%6 = OpSpecConstantComposite %3 %2 %2 %2 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '5[%5]' is " - "not a constant or undef.")); -} - -// Invalid: Array has a mix of Int and Float components. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstituentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpConstant %1 4 -%3 = OpTypeArray %1 %2 -%4 = OpTypeFloat 32 -%5 = OpSpecConstant %4 3.14 ; bad type for const value -%6 = OpSpecConstantComposite %3 %2 %2 %2 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '5[%5]'s " - "type does not match Result Type " - "'3[%_arr_uint_uint_4]'s array element type.")); -} - -// Invalid: Array has a mix of Int and Undef-float. -TEST_F(ValidateIdWithMessage, - OpSpecConstantCompositeArrayConstituentUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpSpecConstant %1 4 -%3 = OpTypeArray %1 %2 -%5 = OpTypeFloat 32 -%6 = OpUndef %5 ; bad type for undef -%4 = OpSpecConstantComposite %3 %2 %2 %2 %6)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '5[%5]'s " - "type does not match Result Type " - "'3[%_arr_uint_2]'s array element type.")); -} - -// Valid: Struct of {Int32,Int32,Int64}. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpConstant %1 42 -%5 = OpSpecConstant %2 4300000000 -%6 = OpSpecConstantComposite %3 %4 %4 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: missing one int32 struct member. -TEST_F(ValidateIdWithMessage, - OpSpecConstantCompositeStructMissingComponentBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%3 = OpTypeStruct %1 %1 %1 -%4 = OpConstant %1 42 -%5 = OpSpecConstant %1 430 -%6 = OpSpecConstantComposite %3 %4 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent " - "'2[%_struct_2]' count does not match Result Type " - " '2[%_struct_2]'s struct member count.")); -} - -// Valid: Struct uses Undef-int64. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructUndefGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpSpecConstant %1 42 -%5 = OpUndef %2 -%6 = OpSpecConstantComposite %3 %4 %4 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Composite contains non-const/undef component. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructNonConstBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpSpecConstant %1 42 -%5 = OpUndef %2 -%6 = OpTypePointer Uniform %1 -%7 = OpVariable %6 Uniform -%8 = OpSpecConstantComposite %3 %4 %7 %5)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '7[%7]' is " - "not a constant or undef.")); -} - -// Invalid: Struct component type does not match expected specialization type. -// Second component was expected to be Int32, but got Int64. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpConstant %1 42 -%5 = OpSpecConstant %2 4300000000 -%6 = OpSpecConstantComposite %3 %4 %5 %4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '5[%5]' type " - "does not match the Result Type '3[%_struct_3]'s " - "member type.")); -} - -// Invalid: Undef-int64 used when Int32 was expected. -TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberUndefTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeInt 64 0 -%3 = OpTypeStruct %1 %1 %2 -%4 = OpSpecConstant %1 42 -%5 = OpUndef %2 -%6 = OpSpecConstantComposite %3 %4 %5 %4)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSpecConstantComposite Constituent '5[%5]' type " - "does not match the Result Type '3[%_struct_3]'s " - "member type.")); -} - -// TODO: OpSpecConstantOp - -TEST_F(ValidateIdWithMessage, OpVariableGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypePointer Input %1 -%3 = OpVariable %2 Input)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpVariableInitializerConstantGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypePointer Input %1 -%3 = OpConstant %1 42 -%4 = OpVariable %2 Input %3)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpVariableInitializerGlobalVariableGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypePointer Uniform %1 -%3 = OpVariable %2 Uniform -%4 = OpTypePointer Private %2 ; pointer to pointer -%5 = OpVariable %4 Private %3 -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -// TODO: Positive test OpVariable with OpConstantNull of OpTypePointer -TEST_F(ValidateIdWithMessage, OpVariableResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpVariable %1 Input)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVariable Result Type '1[%uint]' is not a pointer " - "type.")); -} -TEST_F(ValidateIdWithMessage, OpVariableInitializerIsTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypePointer Input %1 -%3 = OpVariable %2 Input %2)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 2[%_ptr_Input_uint] " - "cannot be a type")); -} - -TEST_F(ValidateIdWithMessage, OpVariableInitializerIsFunctionVarBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ptrint = OpTypePointer Function %int -%ptrptrint = OpTypePointer Function %ptrint -%void = OpTypeVoid -%fnty = OpTypeFunction %void -%main = OpFunction %void None %fnty -%entry = OpLabel -%var = OpVariable %ptrint Function -%varinit = OpVariable %ptrptrint Function %var ; Can't initialize function variable. -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpVariable Initializer '8[%8]' is not a constant " - "or module-scope variable")); -} - -TEST_F(ValidateIdWithMessage, OpVariableInitializerIsModuleVarGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ptrint = OpTypePointer Uniform %int -%mvar = OpVariable %ptrint Uniform -%ptrptrint = OpTypePointer Function %ptrint -%void = OpTypeVoid -%fnty = OpTypeFunction %void -%main = OpFunction %void None %fnty -%entry = OpLabel -%goodvar = OpVariable %ptrptrint Function %mvar ; This is ok -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVariableContainsBoolBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%block = OpTypeStruct %bool %int -%_ptr_Uniform_block = OpTypePointer Uniform %block -%var = OpVariable %_ptr_Uniform_block Uniform -%void = OpTypeVoid -%fnty = OpTypeFunction %void -%main = OpFunction %void None %fnty -%entry = OpLabel -%load = OpLoad %block %var -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("If OpTypeBool is stored in conjunction with OpVariable" - ", it can only be used with non-externally visible " - "shader Storage Classes: Workgroup, CrossWorkgroup, " - "Private, and Function")); -} - -TEST_F(ValidateIdWithMessage, OpVariableContainsBoolPointerGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%bool = OpTypeBool -%boolptr = OpTypePointer Uniform %bool -%int = OpTypeInt 32 0 -%block = OpTypeStruct %boolptr %int -%_ptr_Uniform_block = OpTypePointer Uniform %block -%var = OpVariable %_ptr_Uniform_block Uniform -%void = OpTypeVoid -%fnty = OpTypeFunction %void -%main = OpFunction %void None %fnty -%entry = OpLabel -%load = OpLoad %block %var -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVariableContainsBuiltinBoolGood) { - std::string spirv = kGLSL450MemoryModel + R"( -OpMemberDecorate %input 0 BuiltIn FrontFacing -%bool = OpTypeBool -%input = OpTypeStruct %bool -%_ptr_input = OpTypePointer Input %input -%var = OpVariable %_ptr_input Input -%void = OpTypeVoid -%fnty = OpTypeFunction %void -%main = OpFunction %void None %fnty -%entry = OpLabel -%load = OpLoad %input %var -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVariableContainsRayPayloadBoolGood) { - std::string spirv = R"( -OpCapability RayTracingNV -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_NV_ray_tracing" -OpMemoryModel Logical GLSL450 -%bool = OpTypeBool -%PerRayData = OpTypeStruct %bool -%_ptr_PerRayData = OpTypePointer RayPayloadNV %PerRayData -%var = OpVariable %_ptr_PerRayData RayPayloadNV -%void = OpTypeVoid -%fnty = OpTypeFunction %void -%main = OpFunction %void None %fnty -%entry = OpLabel -%load = OpLoad %PerRayData %var -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVariablePointerNoVariablePointersBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%_ptr_workgroup_int = OpTypePointer Workgroup %int -%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%var = OpVariable %_ptr_function_ptr Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "In Logical addressing, variables may not allocate a pointer type")); -} - -TEST_F(ValidateIdWithMessage, - OpVariablePointerNoVariablePointersRelaxedLogicalGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%_ptr_workgroup_int = OpTypePointer Workgroup %int -%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%var = OpVariable %_ptr_function_ptr Function -OpReturn -OpFunctionEnd -)"; - - auto options = getValidatorOptions(); - options->relax_logical_pointer = true; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpFunctionWithNonMemoryObject) { - // DXC generates code that looks like when given something like: - // T t; - // t.s.fn_1(); - // This needs to be accepted before legalization takes place, so we - // will include it with the relaxed logical pointer. - - const std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %1 "main" - OpSource HLSL 600 - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %void = OpTypeVoid - %9 = OpTypeFunction %void - %_struct_5 = OpTypeStruct - %_struct_6 = OpTypeStruct %_struct_5 -%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6 -%_ptr_Function__struct_5 = OpTypePointer Function %_struct_5 - %23 = OpTypeFunction %void %_ptr_Function__struct_5 - %1 = OpFunction %void None %9 - %10 = OpLabel - %11 = OpVariable %_ptr_Function__struct_6 Function - %20 = OpAccessChain %_ptr_Function__struct_5 %11 %int_0 - %21 = OpFunctionCall %void %12 %20 - OpReturn - OpFunctionEnd - %12 = OpFunction %void None %23 - %13 = OpFunctionParameter %_ptr_Function__struct_5 - %14 = OpLabel - OpReturn - OpFunctionEnd -)"; - - auto options = getValidatorOptions(); - options->relax_logical_pointer = true; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, - OpVariablePointerVariablePointersStorageBufferGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%_ptr_workgroup_int = OpTypePointer Workgroup %int -%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%var = OpVariable %_ptr_function_ptr Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVariablePointerVariablePointersGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%_ptr_workgroup_int = OpTypePointer Workgroup %int -%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%var = OpVariable %_ptr_function_ptr Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVariablePointerVariablePointersBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%_ptr_workgroup_int = OpTypePointer Workgroup %int -%_ptr_uniform_ptr = OpTypePointer Uniform %_ptr_workgroup_int -%var = OpVariable %_ptr_uniform_ptr Uniform -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In Logical addressing with variable pointers, " - "variables that allocate pointers must be in Function " - "or Private storage classes")); -} - -TEST_F(ValidateIdWithMessage, OpLoadGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeInt 32 0 - %3 = OpTypePointer UniformConstant %2 - %4 = OpTypeFunction %1 - %5 = OpVariable %3 UniformConstant - %6 = OpFunction %1 None %4 - %7 = OpLabel - %8 = OpLoad %2 %5 - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// TODO: Add tests that exercise VariablePointersStorageBuffer instead of -// VariablePointers. -void createVariablePointerSpirvProgram(std::ostringstream* spirv, - std::string result_strategy, - bool use_varptr_cap, - bool add_helper_function) { - *spirv << "OpCapability Shader "; - if (use_varptr_cap) { - *spirv << "OpCapability VariablePointers "; - *spirv << "OpExtension \"SPV_KHR_variable_pointers\" "; - } - *spirv << "OpExtension \"SPV_KHR_storage_buffer_storage_class\" "; - *spirv << R"( - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - %void = OpTypeVoid - %voidf = OpTypeFunction %void - %bool = OpTypeBool - %i32 = OpTypeInt 32 1 - %f32 = OpTypeFloat 32 - %f32ptr = OpTypePointer StorageBuffer %f32 - %i = OpConstant %i32 1 - %zero = OpConstant %i32 0 - %float_1 = OpConstant %f32 1.0 - %ptr1 = OpVariable %f32ptr StorageBuffer - %ptr2 = OpVariable %f32ptr StorageBuffer - )"; - if (add_helper_function) { - *spirv << R"( - ; //////////////////////////////////////////////////////////// - ;;;; Function that returns a pointer - ; //////////////////////////////////////////////////////////// - %selector_func_type = OpTypeFunction %f32ptr %bool %f32ptr %f32ptr - %choose_input_func = OpFunction %f32ptr None %selector_func_type - %is_neg_param = OpFunctionParameter %bool - %first_ptr_param = OpFunctionParameter %f32ptr - %second_ptr_param = OpFunctionParameter %f32ptr - %selector_func_begin = OpLabel - %result_ptr = OpSelect %f32ptr %is_neg_param %first_ptr_param %second_ptr_param - OpReturnValue %result_ptr - OpFunctionEnd - )"; - } - *spirv << R"( - %main = OpFunction %void None %voidf - %label = OpLabel - )"; - *spirv << result_strategy; - *spirv << R"( - OpReturn - OpFunctionEnd - )"; -} - -// With the VariablePointer Capability, OpLoad should allow loading a -// VaiablePointer. In this test the variable pointer is obtained by an OpSelect -TEST_F(ValidateIdWithMessage, OpLoadVarPtrOpSelectGood) { - std::string result_strategy = R"( - %isneg = OpSLessThan %bool %i %zero - %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2 - %result = OpLoad %f32 %varptr - )"; - - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, result_strategy, - true /* Add VariablePointers Capability? */, - false /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Without the VariablePointers Capability, OpLoad will not allow loading -// through a variable pointer. -// Disabled since using OpSelect with pointers without VariablePointers will -// fail LogicalsPass. -TEST_F(ValidateIdWithMessage, DISABLED_OpLoadVarPtrOpSelectBad) { - std::string result_strategy = R"( - %isneg = OpSLessThan %bool %i %zero - %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2 - %result = OpLoad %f32 %varptr - )"; - - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, result_strategy, - false /* Add VariablePointers Capability?*/, - false /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a logical pointer.")); -} - -// With the VariablePointer Capability, OpLoad should allow loading a -// VaiablePointer. In this test the variable pointer is obtained by an OpPhi -TEST_F(ValidateIdWithMessage, OpLoadVarPtrOpPhiGood) { - std::string result_strategy = R"( - %is_neg = OpSLessThan %bool %i %zero - OpSelectionMerge %end_label None - OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2 - %take_ptr_1 = OpLabel - OpBranch %end_label - %take_ptr_2 = OpLabel - OpBranch %end_label - %end_label = OpLabel - %varptr = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2 - %result = OpLoad %f32 %varptr - )"; - - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, result_strategy, - true /* Add VariablePointers Capability?*/, - false /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Without the VariablePointers Capability, OpPhi can have a pointer result -// type. -TEST_F(ValidateIdWithMessage, OpPhiBad) { - std::string result_strategy = R"( - %is_neg = OpSLessThan %bool %i %zero - OpSelectionMerge %end_label None - OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2 - %take_ptr_1 = OpLabel - OpBranch %end_label - %take_ptr_2 = OpLabel - OpBranch %end_label - %end_label = OpLabel - %varptr = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2 - %result = OpLoad %f32 %varptr - )"; - - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, result_strategy, - false /* Add VariablePointers Capability?*/, - false /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Using pointers with OpPhi requires capability " - "VariablePointers or VariablePointersStorageBuffer")); -} - -// With the VariablePointer Capability, OpLoad should allow loading through a -// VaiablePointer. In this test the variable pointer is obtained from an -// OpFunctionCall (return value from a function) -TEST_F(ValidateIdWithMessage, OpLoadVarPtrOpFunctionCallGood) { - std::ostringstream spirv; - std::string result_strategy = R"( - %isneg = OpSLessThan %bool %i %zero - %varptr = OpFunctionCall %f32ptr %choose_input_func %isneg %ptr1 %ptr2 - %result = OpLoad %f32 %varptr - )"; - - createVariablePointerSpirvProgram(&spirv, result_strategy, - true /* Add VariablePointers Capability?*/, - true /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpLoadResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer UniformConstant %2 -%4 = OpTypeFunction %1 -%5 = OpVariable %3 UniformConstant -%6 = OpFunction %1 None %4 -%7 = OpLabel -%8 = OpLoad %3 %5 - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpLoad Result Type " - "'3[%_ptr_UniformConstant_uint]' does not match " - "Pointer '5[%5]'s type.")); -} - -TEST_F(ValidateIdWithMessage, OpLoadPointerBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer UniformConstant %2 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -%7 = OpLoad %2 %8 - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - // Prove that SSA checks trigger for a bad Id value. - // The next test case show the not-a-logical-pointer case. - EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 8[%8] has not been " - "defined")); -} - -// Disabled as bitcasting type to object is now not valid. -TEST_F(ValidateIdWithMessage, DISABLED_OpLoadLogicalPointerBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFloat 32 -%4 = OpTypePointer UniformConstant %2 -%5 = OpTypePointer UniformConstant %3 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -%9 = OpBitcast %5 %4 ; Not valid in logical addressing -%10 = OpLoad %3 %9 ; Should trigger message - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - // Once we start checking bitcasts, we might catch that - // as the error first, instead of catching it here. - // I don't know if it's possible to generate a bad case - // if/when the validator is complete. - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpLoad Pointer '9' is not a logical pointer.")); -} - -TEST_F(ValidateIdWithMessage, OpStoreGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 -%6 = OpVariable %3 Uniform -%7 = OpFunction %1 None %4 -%8 = OpLabel - OpStore %6 %5 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpStorePointerBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer UniformConstant %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 -%6 = OpVariable %3 UniformConstant -%7 = OpConstant %2 0 -%8 = OpFunction %1 None %4 -%9 = OpLabel - OpStore %7 %5 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpStore Pointer '7[%uint_0]' is not a logical " - "pointer.")); -} - -// Disabled as bitcasting type to object is now not valid. -TEST_F(ValidateIdWithMessage, DISABLED_OpStoreLogicalPointerBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFloat 32 -%4 = OpTypePointer UniformConstant %2 -%5 = OpTypePointer UniformConstant %3 -%6 = OpTypeFunction %1 -%7 = OpConstantNull %5 -%8 = OpFunction %1 None %6 -%9 = OpLabel -%10 = OpBitcast %5 %4 ; Not valid in logical addressing -%11 = OpStore %10 %7 ; Should trigger message - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpStore Pointer '10' is not a logical pointer.")); -} - -// Without the VariablePointer Capability, OpStore should may not store -// through a variable pointer. -// Disabled since using OpSelect with pointers without VariablePointers will -// fail LogicalsPass. -TEST_F(ValidateIdWithMessage, DISABLED_OpStoreVarPtrBad) { - std::string result_strategy = R"( - %isneg = OpSLessThan %bool %i %zero - %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2 - OpStore %varptr %float_1 - )"; - - std::ostringstream spirv; - createVariablePointerSpirvProgram( - &spirv, result_strategy, false /* Add VariablePointers Capability? */, - false /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a logical pointer.")); -} - -// With the VariablePointer Capability, OpStore should allow storing through a -// variable pointer. -TEST_F(ValidateIdWithMessage, OpStoreVarPtrGood) { - std::string result_strategy = R"( - %isneg = OpSLessThan %bool %i %zero - %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2 - OpStore %varptr %float_1 - )"; - - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, result_strategy, - true /* Add VariablePointers Capability? */, - false /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpStoreObjectGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 -%6 = OpVariable %3 Uniform -%7 = OpFunction %1 None %4 -%8 = OpLabel -%9 = OpUndef %1 - OpStore %6 %9 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpStore Object '9[%9]'s type is void.")); -} -TEST_F(ValidateIdWithMessage, OpStoreTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%9 = OpTypeFloat 32 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %9 3.14 -%6 = OpVariable %3 Uniform -%7 = OpFunction %1 None %4 -%8 = OpLabel - OpStore %6 %5 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpStore Pointer '7[%7]'s type does not match " - "Object '6[%float_3_1400001]'s type.")); -} - -// The next series of test check test a relaxation of the rules for stores to -// structs. The first test checks that we get a failure when the option is not -// set to relax the rule. -// TODO: Add tests for layout compatible arrays and matricies when the validator -// relaxes the rules for them as well. Also need test to check for layout -// decorations specific to those types. -TEST_F(ValidateIdWithMessage, OpStoreTypeBadStruct) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 Offset 0 - OpMemberDecorate %1 1 Offset 4 - OpMemberDecorate %2 0 Offset 0 - OpMemberDecorate %2 1 Offset 4 -%3 = OpTypeVoid -%4 = OpTypeFloat 32 -%1 = OpTypeStruct %4 %4 -%5 = OpTypePointer Uniform %1 -%2 = OpTypeStruct %4 %4 -%6 = OpTypeFunction %3 -%7 = OpConstant %4 3.14 -%8 = OpVariable %5 Uniform -%9 = OpFunction %3 None %6 -%10 = OpLabel -%11 = OpCompositeConstruct %2 %7 %7 - OpStore %8 %11 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpStore Pointer '8[%8]'s type does not match " - "Object '11[%11]'s type.")); -} - -// Same code as the last test. The difference is that we relax the rule. -// Because the structs %3 and %5 are defined the same way. -TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedStruct) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 Offset 0 - OpMemberDecorate %1 1 Offset 4 - OpMemberDecorate %2 0 Offset 0 - OpMemberDecorate %2 1 Offset 4 -%3 = OpTypeVoid -%4 = OpTypeFloat 32 -%1 = OpTypeStruct %4 %4 -%5 = OpTypePointer Uniform %1 -%2 = OpTypeStruct %4 %4 -%6 = OpTypeFunction %3 -%7 = OpConstant %4 3.14 -%8 = OpVariable %5 Uniform -%9 = OpFunction %3 None %6 -%10 = OpLabel -%11 = OpCompositeConstruct %2 %7 %7 - OpStore %8 %11 - OpReturn - OpFunctionEnd)"; - spvValidatorOptionsSetRelaxStoreStruct(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Same code as the last test excect for an extra decoration on one of the -// members. With the relaxed rules, the code is still valid. -TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedStructWithExtraDecoration) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 Offset 0 - OpMemberDecorate %1 1 Offset 4 - OpMemberDecorate %1 0 RelaxedPrecision - OpMemberDecorate %2 0 Offset 0 - OpMemberDecorate %2 1 Offset 4 -%3 = OpTypeVoid -%4 = OpTypeFloat 32 -%1 = OpTypeStruct %4 %4 -%5 = OpTypePointer Uniform %1 -%2 = OpTypeStruct %4 %4 -%6 = OpTypeFunction %3 -%7 = OpConstant %4 3.14 -%8 = OpVariable %5 Uniform -%9 = OpFunction %3 None %6 -%10 = OpLabel -%11 = OpCompositeConstruct %2 %7 %7 - OpStore %8 %11 - OpReturn - OpFunctionEnd)"; - spvValidatorOptionsSetRelaxStoreStruct(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// This test check that we recursively traverse the struct to check if they are -// interchangable. -TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedNestedStruct) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 Offset 0 - OpMemberDecorate %1 1 Offset 4 - OpMemberDecorate %2 0 Offset 0 - OpMemberDecorate %2 1 Offset 8 - OpMemberDecorate %3 0 Offset 0 - OpMemberDecorate %3 1 Offset 4 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 8 -%5 = OpTypeVoid -%6 = OpTypeInt 32 0 -%7 = OpTypeFloat 32 -%1 = OpTypeStruct %7 %6 -%2 = OpTypeStruct %1 %1 -%8 = OpTypePointer Uniform %2 -%3 = OpTypeStruct %7 %6 -%4 = OpTypeStruct %3 %3 -%9 = OpTypeFunction %5 -%10 = OpConstant %6 7 -%11 = OpConstant %7 3.14 -%12 = OpConstantComposite %3 %11 %10 -%13 = OpVariable %8 Uniform -%14 = OpFunction %5 None %9 -%15 = OpLabel -%16 = OpCompositeConstruct %4 %12 %12 - OpStore %13 %16 - OpReturn - OpFunctionEnd)"; - spvValidatorOptionsSetRelaxStoreStruct(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// This test check that the even with the relaxed rules an error is identified -// if the members of the struct are in a different order. -TEST_F(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct1) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 Offset 0 - OpMemberDecorate %1 1 Offset 4 - OpMemberDecorate %2 0 Offset 0 - OpMemberDecorate %2 1 Offset 8 - OpMemberDecorate %3 0 Offset 0 - OpMemberDecorate %3 1 Offset 4 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 8 -%5 = OpTypeVoid -%6 = OpTypeInt 32 0 -%7 = OpTypeFloat 32 -%1 = OpTypeStruct %6 %7 -%2 = OpTypeStruct %1 %1 -%8 = OpTypePointer Uniform %2 -%3 = OpTypeStruct %7 %6 -%4 = OpTypeStruct %3 %3 -%9 = OpTypeFunction %5 -%10 = OpConstant %6 7 -%11 = OpConstant %7 3.14 -%12 = OpConstantComposite %3 %11 %10 -%13 = OpVariable %8 Uniform -%14 = OpFunction %5 None %9 -%15 = OpLabel -%16 = OpCompositeConstruct %4 %12 %12 - OpStore %13 %16 - OpReturn - OpFunctionEnd)"; - spvValidatorOptionsSetRelaxStoreStruct(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpStore Pointer '13[%13]'s layout does not match Object " - " '16[%16]'s layout.")); -} - -// This test check that the even with the relaxed rules an error is identified -// if the members of the struct are at different offsets. -TEST_F(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct2) { - std::string spirv = kGLSL450MemoryModel + R"( - OpMemberDecorate %1 0 Offset 4 - OpMemberDecorate %1 1 Offset 0 - OpMemberDecorate %2 0 Offset 0 - OpMemberDecorate %2 1 Offset 8 - OpMemberDecorate %3 0 Offset 0 - OpMemberDecorate %3 1 Offset 4 - OpMemberDecorate %4 0 Offset 0 - OpMemberDecorate %4 1 Offset 8 -%5 = OpTypeVoid -%6 = OpTypeInt 32 0 -%7 = OpTypeFloat 32 -%1 = OpTypeStruct %7 %6 -%2 = OpTypeStruct %1 %1 -%8 = OpTypePointer Uniform %2 -%3 = OpTypeStruct %7 %6 -%4 = OpTypeStruct %3 %3 -%9 = OpTypeFunction %5 -%10 = OpConstant %6 7 -%11 = OpConstant %7 3.14 -%12 = OpConstantComposite %3 %11 %10 -%13 = OpVariable %8 Uniform -%14 = OpFunction %5 None %9 -%15 = OpLabel -%16 = OpCompositeConstruct %4 %12 %12 - OpStore %13 %16 - OpReturn - OpFunctionEnd)"; - spvValidatorOptionsSetRelaxStoreStruct(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpStore Pointer '13[%13]'s layout does not match Object " - " '16[%16]'s layout.")); -} - -TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerReturnPointer) { - const std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%1 = OpTypeInt 32 1 -%2 = OpTypePointer Function %1 -%3 = OpTypeFunction %2 %2 -%4 = OpFunction %2 None %3 -%5 = OpFunctionParameter %2 -%6 = OpLabel - OpReturnValue %5 - OpFunctionEnd)"; - - spvValidatorOptionsSetRelaxLogicalPointer(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerAllocPointer) { - const std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - %1 = OpTypeVoid - %2 = OpTypeInt 32 1 - %3 = OpTypeFunction %1 ; void(void) - %4 = OpTypePointer Uniform %2 ; int* - %5 = OpTypePointer Private %4 ; int** (Private) - %6 = OpTypePointer Function %4 ; int** (Function) - %7 = OpVariable %5 Private - %8 = OpFunction %1 None %3 - %9 = OpLabel -%10 = OpVariable %6 Function - OpReturn - OpFunctionEnd)"; - - spvValidatorOptionsSetRelaxLogicalPointer(options_, true); - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpStoreVoid) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 -%6 = OpVariable %3 Uniform -%7 = OpFunction %1 None %4 -%8 = OpLabel -%9 = OpFunctionCall %1 %7 - OpStore %6 %9 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpStore Object '8[%8]'s type is void.")); -} - -TEST_F(ValidateIdWithMessage, OpStoreLabel) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 -%6 = OpVariable %3 Uniform -%7 = OpFunction %1 None %4 -%8 = OpLabel - OpStore %6 %8 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 7[%7] requires a type")); -} - -// TODO: enable when this bug is fixed: -// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404 -TEST_F(ValidateIdWithMessage, DISABLED_OpStoreFunction) { - std::string spirv = kGLSL450MemoryModel + R"( -%2 = OpTypeInt 32 0 -%3 = OpTypePointer UniformConstant %2 -%4 = OpTypeFunction %2 -%5 = OpConstant %2 123 -%6 = OpVariable %3 UniformConstant -%7 = OpFunction %2 None %4 -%8 = OpLabel - OpStore %6 %7 - OpReturnValue %5 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpStoreBuiltin) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 450 - OpName %main "main" - - OpName %gl_GlobalInvocationID "gl_GlobalInvocationID" - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - - %int = OpTypeInt 32 1 - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input - - %zero = OpConstant %uint 0 - %v3uint_000 = OpConstantComposite %v3uint %zero %zero %zero - - %void = OpTypeVoid - %voidfunc = OpTypeFunction %void - %main = OpFunction %void None %voidfunc - %lmain = OpLabel - - OpStore %gl_GlobalInvocationID %v3uint_000 - - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("storage class is read-only")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemoryGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeInt 32 0 - %3 = OpTypePointer UniformConstant %2 - %4 = OpConstant %2 42 - %5 = OpVariable %3 UniformConstant %4 - %6 = OpTypePointer Function %2 - %7 = OpTypeFunction %1 - %8 = OpFunction %1 None %7 - %9 = OpLabel -%10 = OpVariable %6 Function - OpCopyMemory %10 %5 None - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemoryNonPointerTarget) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 %2 %3 -%5 = OpFunction %1 None %4 -%6 = OpFunctionParameter %2 -%7 = OpFunctionParameter %3 -%8 = OpLabel -OpCopyMemory %6 %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target operand '6[%6]' is not a pointer.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemoryNonPointerSource) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpTypeFunction %1 %2 %3 -%5 = OpFunction %1 None %4 -%6 = OpFunctionParameter %2 -%7 = OpFunctionParameter %3 -%8 = OpLabel -OpCopyMemory %7 %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Source operand '6[%6]' is not a pointer.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemoryBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeInt 32 0 - %3 = OpTypePointer UniformConstant %2 - %4 = OpConstant %2 42 - %5 = OpVariable %3 UniformConstant %4 -%11 = OpTypeFloat 32 - %6 = OpTypePointer Function %11 - %7 = OpTypeFunction %1 - %8 = OpFunction %1 None %7 - %9 = OpLabel -%10 = OpVariable %6 Function - OpCopyMemory %10 %5 None - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target '5[%5]'s type does not match " - "Source '2[%uint]'s type.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemoryVoidTarget) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %1 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFunction %1 %3 %4 -%6 = OpFunction %1 None %5 -%7 = OpFunctionParameter %3 -%8 = OpFunctionParameter %4 -%9 = OpLabel -OpCopyMemory %7 %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target operand '7[%7]' cannot be a void " - "pointer.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemoryVoidSource) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %1 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFunction %1 %3 %4 -%6 = OpFunction %1 None %5 -%7 = OpFunctionParameter %3 -%8 = OpFunctionParameter %4 -%9 = OpLabel -OpCopyMemory %8 %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Source operand '7[%7]' cannot be a void " - "pointer.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedGood) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeInt 32 0 - %3 = OpTypePointer UniformConstant %2 - %4 = OpTypePointer Function %2 - %5 = OpConstant %2 4 - %6 = OpVariable %3 UniformConstant %5 - %7 = OpTypeFunction %1 - %8 = OpFunction %1 None %7 - %9 = OpLabel -%10 = OpVariable %4 Function - OpCopyMemorySized %10 %6 %5 None - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer UniformConstant %2 -%4 = OpTypePointer Function %2 -%5 = OpConstant %2 4 -%6 = OpVariable %3 UniformConstant %5 -%7 = OpTypeFunction %1 -%8 = OpFunction %1 None %7 -%9 = OpLabel - OpCopyMemorySized %5 %5 %5 None - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Target operand '5[%uint_4]' is not a pointer.")); -} -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer UniformConstant %2 -%4 = OpTypePointer Function %2 -%5 = OpConstant %2 4 -%6 = OpTypeFunction %1 -%7 = OpFunction %1 None %6 -%8 = OpLabel -%9 = OpVariable %4 Function - OpCopyMemorySized %9 %5 %5 None - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Source operand '5[%uint_4]' is not a pointer.")); -} -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeInt 32 0 - %3 = OpTypePointer UniformConstant %2 - %4 = OpTypePointer Function %2 - %5 = OpConstant %2 4 - %6 = OpVariable %3 UniformConstant %5 - %7 = OpTypeFunction %1 - %8 = OpFunction %1 None %7 - %9 = OpLabel -%10 = OpVariable %4 Function - OpCopyMemorySized %10 %6 %6 None - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Size operand '6[%6]' must be a scalar integer type.")); -} -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeInt 32 0 - %3 = OpTypePointer UniformConstant %2 - %4 = OpTypePointer Function %2 - %5 = OpConstant %2 4 - %6 = OpVariable %3 UniformConstant %5 - %7 = OpTypeFunction %1 -%11 = OpTypeFloat 32 -%12 = OpConstant %11 1.0 - %8 = OpFunction %1 None %7 - %9 = OpLabel -%10 = OpVariable %4 Function - OpCopyMemorySized %10 %6 %12 None - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Size operand '9[%float_1]' must be a scalar integer " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNull) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstantNull %2 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Size operand '3[%3]' cannot be a constant " - "zero.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 0 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Size operand '3[%uint_0]' cannot be a constant " - "zero.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero64) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 64 0 -%3 = OpConstant %2 0 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Size operand '3[%ulong_0]' cannot be a constant " - "zero.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 1 -%3 = OpConstant %2 -1 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Size operand '3[%int_n1]' cannot have the sign bit set " - "to 1.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative64) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 64 1 -%3 = OpConstant %2 -1 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Size operand '3[%long_n1]' cannot have the sign bit set " - "to 1.")); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 2147483648 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative64) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 64 0 -%3 = OpConstant %2 9223372036854775808 -%4 = OpTypePointer Uniform %2 -%5 = OpTypeFloat 32 -%6 = OpTypePointer UniformConstant %5 -%7 = OpTypeFunction %1 %4 %6 -%8 = OpFunction %1 None %7 -%9 = OpFunctionParameter %4 -%10 = OpFunctionParameter %6 -%11 = OpLabel -OpCopyMemorySized %9 %10 %3 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -const char kDeeplyNestedStructureSetup[] = R"( -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%int = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%v3float = OpTypeVector %float 3 -%mat4x3 = OpTypeMatrix %v3float 4 -%_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3 -%_ptr_Private_float = OpTypePointer Private %float -%my_matrix = OpVariable %_ptr_Private_mat4x3 Private -%my_float_var = OpVariable %_ptr_Private_float Private -%_ptr_Function_float = OpTypePointer Function %float -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_3 = OpConstant %int 3 -%int_5 = OpConstant %int 5 - -; Making the following nested structures. -; -; struct S { -; bool b; -; vec4 v[5]; -; int i; -; mat4x3 m[5]; -; } -; uniform blockName { -; S s; -; bool cond; -; RunTimeArray arr; -; } - -%f32arr = OpTypeRuntimeArray %float -%v4float = OpTypeVector %float 4 -%array5_mat4x3 = OpTypeArray %mat4x3 %int_5 -%array5_vec4 = OpTypeArray %v4float %int_5 -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_ptr_Function_vec4 = OpTypePointer Function %v4float -%_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float -%struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3 -%struct_blockName = OpTypeStruct %struct_s %int %f32arr -%_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName -%_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s -%_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3 -%_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3 -%_ptr_Uniform_v3float = OpTypePointer Uniform %v3float -%blockName_var = OpVariable %_ptr_Uniform_blockName Uniform -%spec_int = OpSpecConstant %int 2 -%float_0 = OpConstant %float 0 -%func = OpFunction %void None %void_f -%my_label = OpLabel -)"; - -// In what follows, Access Chain Instruction refers to one of the following: -// OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain, and -// OpInBoundsPtrAccessChain -using AccessChainInstructionTest = spvtest::ValidateBase; - -// Determines whether the access chain instruction requires the 'element id' -// argument. -bool AccessChainRequiresElemId(const std::string& instr) { - return (instr == "OpPtrAccessChain" || instr == "OpInBoundsPtrAccessChain"); -} - -// Valid: Access a float in a matrix using an access chain instruction. -TEST_P(AccessChainInstructionTest, AccessChainGood) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + - "%float_entry = " + instr + - R"( %_ptr_Private_float %my_matrix )" + elem + - R"(%int_0 %int_1 - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid. The result type of an access chain instruction must be a pointer. -TEST_P(AccessChainInstructionTest, AccessChainResultTypeBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%float_entry = )" + - instr + - R"( %float %my_matrix )" + elem + - R"(%int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - - const std::string expected_err = "The Result Type of " + instr + - " '36[%36]' must be " - "OpTypePointer. Found OpTypeFloat."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid. The base type of an access chain instruction must be a pointer. -TEST_P(AccessChainInstructionTest, AccessChainBaseTypeVoidBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%float_entry = )" + - instr + " %_ptr_Private_float %void " + elem + - R"(%int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%void] cannot be a " - "type")); -} - -// Invalid. The base type of an access chain instruction must be a pointer. -TEST_P(AccessChainInstructionTest, AccessChainBaseTypeNonPtrVariableBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_float %_ptr_Private_float )" + - elem + - R"(%int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 8[%_ptr_Private_float] cannot be a type")); -} - -// Invalid: The storage class of Base and Result do not match. -TEST_P(AccessChainInstructionTest, - AccessChainResultAndBaseStorageClassDoesntMatchBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Function_float %my_matrix )" + elem + - R"(%int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = - "The result pointer storage class and base pointer storage class in " + - instr + " do not match."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid. The base type of an access chain instruction must point to a -// composite object. -TEST_P(AccessChainInstructionTest, - AccessChainBasePtrNotPointingToCompositeBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_float %my_float_var )" + elem + - R"(%int_0 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = instr + - " reached non-composite type while " - "indexes still remain to be traversed."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Valid. No Indexes were passed to the access chain instruction. The Result -// Type is the same as the Base type. -TEST_P(AccessChainInstructionTest, AccessChainNoIndexesGood) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_float %my_float_var )" + elem + - R"( -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid. No Indexes were passed to the access chain instruction, but the -// Result Type is different from the Base type. -TEST_P(AccessChainInstructionTest, AccessChainNoIndexesBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_mat4x3 %my_float_var )" + elem + - R"( -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("result type (OpTypeMatrix) does not match the type that " - "results from indexing into the base (OpTypeFloat).")); -} - -// Valid: 255 indexes passed to the access chain instruction. Limit is 255. -TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesGood) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : ""; - int depth = 255; - std::string header = kGLSL450MemoryModel + kDeeplyNestedStructureSetup; - header.erase(header.find("%func")); - std::ostringstream spirv; - spirv << header << "\n"; - - // Build nested structures. Struct 'i' contains struct 'i-1' - spirv << "%s_depth_1 = OpTypeStruct %float\n"; - for (int i = 2; i <= depth; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n"; - } - - // Define Pointer and Variable to use for the AccessChain instruction. - spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_" - << depth << "\n"; - spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n"; - - // Function Start - spirv << R"( - %func = OpFunction %void None %void_f - %my_label = OpLabel - )"; - - // AccessChain with 'n' indexes (n = depth) - spirv << "%entry = " << instr << " %_ptr_Uniform_float %deep_var" << elem; - for (int i = 0; i < depth; ++i) { - spirv << " %int_0"; - } - - // Function end - spirv << R"( - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: 256 indexes passed to the access chain instruction. Limit is 255. -TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : ""; - std::ostringstream spirv; - spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup; - spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix" << elem; - for (int i = 0; i < 256; ++i) { - spirv << " %int_0"; - } - spirv << R"( - OpReturn - OpFunctionEnd - )"; - const std::string expected_err = "The number of indexes in " + instr + - " may not exceed 255. Found 256 indexes."; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Valid: 10 indexes passed to the access chain instruction. (Custom limit: 10) -TEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesGood) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : ""; - int depth = 10; - std::string header = kGLSL450MemoryModel + kDeeplyNestedStructureSetup; - header.erase(header.find("%func")); - std::ostringstream spirv; - spirv << header << "\n"; - - // Build nested structures. Struct 'i' contains struct 'i-1' - spirv << "%s_depth_1 = OpTypeStruct %float\n"; - for (int i = 2; i <= depth; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n"; - } - - // Define Pointer and Variable to use for the AccessChain instruction. - spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_" - << depth << "\n"; - spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n"; - - // Function Start - spirv << R"( - %func = OpFunction %void None %void_f - %my_label = OpLabel - )"; - - // AccessChain with 'n' indexes (n = depth) - spirv << "%entry = " << instr << " %_ptr_Uniform_float %deep_var" << elem; - for (int i = 0; i < depth; ++i) { - spirv << " %int_0"; - } - - // Function end - spirv << R"( - OpReturn - OpFunctionEnd - )"; - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_access_chain_indexes, 10u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: 11 indexes passed to the access chain instruction. Custom Limit:10 -TEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : ""; - std::ostringstream spirv; - spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup; - spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix" << elem; - for (int i = 0; i < 11; ++i) { - spirv << " %int_0"; - } - spirv << R"( - OpReturn - OpFunctionEnd - )"; - const std::string expected_err = "The number of indexes in " + instr + - " may not exceed 10. Found 11 indexes."; - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_access_chain_indexes, 10u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: Index passed to the access chain instruction is float (must be -// integer). -TEST_P(AccessChainInstructionTest, AccessChainUndefinedIndexBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_float %my_matrix )" + elem + - R"(%float_0 %int_1 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = - "Indexes passed to " + instr + " must be of type integer."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: The index argument that indexes into a struct must be of type -// OpConstant. -TEST_P(AccessChainInstructionTest, AccessChainStructIndexNotConstantBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%f = )" + - instr + R"( %_ptr_Uniform_float %blockName_var )" + elem + - R"(%int_0 %spec_int %int_2 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = - "The passed to " + instr + - " to index into a structure must be an OpConstant."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: Indexing up to a vec4 granularity, but result type expected float. -TEST_P(AccessChainInstructionTest, - AccessChainStructResultTypeDoesntMatchIndexedTypeBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Uniform_float %blockName_var )" + elem + - R"(%int_0 %int_1 %int_2 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = instr + - " result type (OpTypeFloat) does not match " - "the type that results from indexing into " - "the base (OpTypeVector)."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: Reach non-composite type (bool) when unused indexes remain. -TEST_P(AccessChainInstructionTest, AccessChainStructTooManyIndexesBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Uniform_float %blockName_var )" + elem + - R"(%int_0 %int_2 %int_2 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = instr + - " reached non-composite type while " - "indexes still remain to be traversed."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: Trying to find index 3 of the struct that has only 3 members. -TEST_P(AccessChainInstructionTest, AccessChainStructIndexOutOfBoundBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Uniform_float %blockName_var )" + elem + - R"(%int_3 %int_2 %int_2 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = "Index is out of bounds: " + instr + - " can not find index 3 into the structure " - " '25[%_struct_25]'. This structure " - "has 3 members. Largest valid index is 2."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Valid: Tests that we can index into Struct, Array, Matrix, and Vector! -TEST_P(AccessChainInstructionTest, AccessChainIndexIntoAllTypesGood) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::ostringstream spirv; - spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup << std::endl; - spirv << "%ss = " << instr << " %_ptr_Uniform_struct_s %blockName_var " - << elem << "%int_0" << std::endl; - spirv << "%sa = " << instr << " %_ptr_Uniform_array5_mat4x3 %blockName_var " - << elem << "%int_0 %int_3" << std::endl; - spirv << "%sm = " << instr << " %_ptr_Uniform_mat4x3 %blockName_var " << elem - << "%int_0 %int_3 %int_1" << std::endl; - spirv << "%sc = " << instr << " %_ptr_Uniform_v3float %blockName_var " << elem - << "%int_0 %int_3 %int_1 %int_2" << std::endl; - spirv << "%entry = " << instr << " %_ptr_Uniform_float %blockName_var " - << elem << "%int_0 %int_3 %int_1 %int_2 %int_0" << std::endl; - spirv << R"( -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Valid: Access an element of OpTypeRuntimeArray. -TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayGood) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%runtime_arr_entry = )" + - instr + R"( %_ptr_Uniform_float %blockName_var )" + elem + - R"(%int_2 %int_0 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Unused index when accessing OpTypeRuntimeArray. -TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%runtime_arr_entry = )" + - instr + R"( %_ptr_Uniform_float %blockName_var )" + elem + - R"(%int_2 %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = - instr + - " reached non-composite type while indexes still remain to be traversed."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: Reached scalar type before arguments to the access chain instruction -// finished. -TEST_P(AccessChainInstructionTest, AccessChainMatrixMoreArgsThanNeededBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_float %my_matrix )" + elem + - R"(%int_0 %int_1 %int_0 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = instr + - " reached non-composite type while " - "indexes still remain to be traversed."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Invalid: The result type and the type indexed into do not match. -TEST_P(AccessChainInstructionTest, - AccessChainResultTypeDoesntMatchIndexedTypeBad) { - const std::string instr = GetParam(); - const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : ""; - std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"( -%entry = )" + - instr + R"( %_ptr_Private_mat4x3 %my_matrix )" + elem + - R"(%int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - const std::string expected_err = instr + - " result type (OpTypeMatrix) does not match " - "the type that results from indexing into " - "the base (OpTypeFloat)."; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); -} - -// Run tests for Access Chain Instructions. -INSTANTIATE_TEST_SUITE_P( - CheckAccessChainInstructions, AccessChainInstructionTest, - ::testing::Values("OpAccessChain", "OpInBoundsAccessChain", - "OpPtrAccessChain", "OpInBoundsPtrAccessChain")); - -// TODO: OpArrayLength -// TODO: OpImagePointer -// TODO: OpGenericPtrMemSemantics - -TEST_F(ValidateIdWithMessage, OpFunctionGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %1 %2 %2 -%4 = OpFunction %1 None %3 -%5 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpFunctionResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpConstant %2 42 -%4 = OpTypeFunction %1 %2 %2 -%5 = OpFunction %2 None %4 -%6 = OpLabel - OpReturnValue %3 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpFunction Result Type '2[%uint]' does not " - "match the Function Type's return type " - "'1[%void]'.")); -} -TEST_F(ValidateIdWithMessage, OpReturnValueTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFloat 32 -%3 = OpConstant %2 0 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel - OpReturnValue %3 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpReturnValue Value '3[%float_0]'s type does " - "not match OpFunction's return type.")); -} -TEST_F(ValidateIdWithMessage, OpFunctionFunctionTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%4 = OpFunction %1 None %2 -%5 = OpLabel - OpReturn -OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpFunction Function Type '2[%uint]' is not a function " - "type.")); -} - -TEST_F(ValidateIdWithMessage, OpFunctionUseBad) { - const std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeFloat 32 -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -OpReturnValue %3 -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid use of function result id 3[%3].")); -} - -TEST_F(ValidateIdWithMessage, OpFunctionParameterGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %1 %2 -%4 = OpFunction %1 None %3 -%5 = OpFunctionParameter %2 -%6 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpFunctionParameterMultipleGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %1 %2 %2 -%4 = OpFunction %1 None %3 -%5 = OpFunctionParameter %2 -%6 = OpFunctionParameter %2 -%7 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %1 %2 -%4 = OpFunction %1 None %3 -%5 = OpFunctionParameter %1 -%6 = OpLabel - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpFunctionParameter Result Type '1[%void]' does not " - "match the OpTypeFunction parameter type of the same index.")); -} - -TEST_F(ValidateIdWithMessage, OpFunctionCallGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 ;21 - -%6 = OpFunction %2 None %3 -%7 = OpFunctionParameter %2 -%8 = OpLabel - OpReturnValue %7 - OpFunctionEnd - -%10 = OpFunction %1 None %4 -%11 = OpLabel -%12 = OpFunctionCall %2 %6 %5 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpFunctionCallResultTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 ;21 - -%6 = OpFunction %2 None %3 -%7 = OpFunctionParameter %2 -%8 = OpLabel -%9 = OpIAdd %2 %7 %7 - OpReturnValue %9 - OpFunctionEnd - -%10 = OpFunction %1 None %4 -%11 = OpLabel -%12 = OpFunctionCall %1 %6 %5 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpFunctionCall Result Type '1[%void]'s type " - "does not match Function '2[%uint]'s return " - "type.")); -} -TEST_F(ValidateIdWithMessage, OpFunctionCallFunctionBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 ;21 - -%10 = OpFunction %1 None %4 -%11 = OpLabel -%12 = OpFunctionCall %2 %5 %5 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpFunctionCall Function '5[%uint_42]' is not a " - "function.")); -} -TEST_F(ValidateIdWithMessage, OpFunctionCallArgumentTypeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 - -%13 = OpTypeFloat 32 -%14 = OpConstant %13 3.14 - -%6 = OpFunction %2 None %3 -%7 = OpFunctionParameter %2 -%8 = OpLabel -%9 = OpIAdd %2 %7 %7 - OpReturnValue %9 - OpFunctionEnd - -%10 = OpFunction %1 None %4 -%11 = OpLabel -%12 = OpFunctionCall %2 %6 %14 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpFunctionCall Argument '7[%float_3_1400001]'s " - "type does not match Function '2[%uint]'s " - "parameter type.")); -} - -// Valid: OpSampledImage result is used in the same block by -// OpImageSampleImplictLod -TEST_F(ValidateIdWithMessage, OpSampledImageGood) { - std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"( -%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst -%si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: OpSampledImage result is defined in one block and used in a -// different block. -TEST_F(ValidateIdWithMessage, OpSampledImageUsedInDifferentBlockBad) { - std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"( -%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst -OpBranch %label_2 -%label_2 = OpLabel -%si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1 -OpReturn -OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("All OpSampledImage instructions must be in the same block in " - "which their Result are consumed. OpSampledImage Result " - "Type '23[%23]' has a consumer in a different basic " - "block. The consumer instruction is '25[%25]'.")); -} - -// Invalid: OpSampledImage result is used by OpSelect -// Note: According to the Spec, OpSelect parameters must be either a scalar or a -// vector. Therefore, OpTypeSampledImage is an illegal parameter for OpSelect. -// However, the OpSelect validation does not catch this today. Therefore, it is -// caught by the OpSampledImage validation. If the OpSelect validation code is -// updated, the error message for this test may change. -// -// Disabled since OpSelect catches this now. -TEST_F(ValidateIdWithMessage, DISABLED_OpSampledImageUsedInOpSelectBad) { - std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"( -%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst -%select_img = OpSelect %sampled_image_type %spec_true %smpld_img %smpld_img -OpReturn -OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result from OpSampledImage instruction must not " - "appear as operands of OpSelect. Found result " - "'23' as an operand of '24'.")); -} - -// Valid: Get a float in a matrix using CompositeExtract. -// Valid: Insert float into a matrix using CompositeInsert. -TEST_F(ValidateIdWithMessage, CompositeExtractInsertGood) { - std::ostringstream spirv; - spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup << std::endl; - spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; - spirv << "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl; - - // To test CompositeInsert, insert the object back in after extraction. - spirv << "%new_composite = OpCompositeInsert %mat4x3 %float_entry %matrix 0 1" - << std::endl; - spirv << R"(OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -#if 0 -TEST_F(ValidateIdWithMessage, OpFunctionCallArgumentCountBar) { - const char *spirv = R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 %2 -%4 = OpTypeFunction %1 -%5 = OpConstant %2 42 ;21 - -%6 = OpFunction %2 None %3 -%7 = OpFunctionParameter %2 -%8 = OpLabel -%9 = OpLoad %2 %7 - OpReturnValue %9 - OpFunctionEnd - -%10 = OpFunction %1 None %4 -%11 = OpLabel - OpReturn -%12 = OpFunctionCall %2 %6 %5 - OpFunctionEnd)"; - CHECK(spirv, SPV_ERROR_INVALID_ID); -} -#endif - -// TODO: The many things that changed with how images are used. -// TODO: OpTextureSample -// TODO: OpTextureSampleDref -// TODO: OpTextureSampleLod -// TODO: OpTextureSampleProj -// TODO: OpTextureSampleGrad -// TODO: OpTextureSampleOffset -// TODO: OpTextureSampleProjLod -// TODO: OpTextureSampleProjGrad -// TODO: OpTextureSampleLodOffset -// TODO: OpTextureSampleProjOffset -// TODO: OpTextureSampleGradOffset -// TODO: OpTextureSampleProjLodOffset -// TODO: OpTextureSampleProjGradOffset -// TODO: OpTextureFetchTexelLod -// TODO: OpTextureFetchTexelOffset -// TODO: OpTextureFetchSample -// TODO: OpTextureFetchTexel -// TODO: OpTextureGather -// TODO: OpTextureGatherOffset -// TODO: OpTextureGatherOffsets -// TODO: OpTextureQuerySizeLod -// TODO: OpTextureQuerySize -// TODO: OpTextureQueryLevels -// TODO: OpTextureQuerySamples -// TODO: OpConvertUToF -// TODO: OpConvertFToS -// TODO: OpConvertSToF -// TODO: OpConvertUToF -// TODO: OpUConvert -// TODO: OpSConvert -// TODO: OpFConvert -// TODO: OpConvertPtrToU -// TODO: OpConvertUToPtr -// TODO: OpPtrCastToGeneric -// TODO: OpGenericCastToPtr -// TODO: OpBitcast -// TODO: OpGenericCastToPtrExplicit -// TODO: OpSatConvertSToU -// TODO: OpSatConvertUToS -// TODO: OpVectorExtractDynamic -// TODO: OpVectorInsertDynamic - -TEST_F(ValidateIdWithMessage, OpVectorShuffleIntGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ivec3 = OpTypeVector %int 3 -%ivec4 = OpTypeVector %int 4 -%ptr_ivec3 = OpTypePointer Function %ivec3 -%undef = OpUndef %ivec4 -%int_42 = OpConstant %int 42 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2 -%2 = OpTypeFunction %ivec3 -%3 = OpFunction %ivec3 None %2 -%4 = OpLabel -%var = OpVariable %ptr_ivec3 Function %1 -%5 = OpLoad %ivec3 %var -%6 = OpVectorShuffle %ivec3 %5 %undef 2 1 0 - OpReturnValue %6 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleFloatGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%float = OpTypeFloat 32 -%vec2 = OpTypeVector %float 2 -%vec3 = OpTypeVector %float 3 -%vec4 = OpTypeVector %float 4 -%ptr_vec2 = OpTypePointer Function %vec2 -%ptr_vec3 = OpTypePointer Function %vec3 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%1 = OpConstantComposite %vec2 %float_2 %float_1 -%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2 -%3 = OpTypeFunction %vec4 -%4 = OpFunction %vec4 None %3 -%5 = OpLabel -%var = OpVariable %ptr_vec2 Function %1 -%var2 = OpVariable %ptr_vec3 Function %2 -%6 = OpLoad %vec2 %var -%7 = OpLoad %vec3 %var2 -%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0xffffffff - OpReturnValue %8 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleScalarResultType) { - std::string spirv = kGLSL450MemoryModel + R"( -%float = OpTypeFloat 32 -%vec2 = OpTypeVector %float 2 -%ptr_vec2 = OpTypePointer Function %vec2 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%1 = OpConstantComposite %vec2 %float_2 %float_1 -%2 = OpTypeFunction %float -%3 = OpFunction %float None %2 -%4 = OpLabel -%var = OpVariable %ptr_vec2 Function %1 -%5 = OpLoad %vec2 %var -%6 = OpVectorShuffle %float %5 %5 0 - OpReturnValue %6 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result Type of OpVectorShuffle must be OpTypeVector.")); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleComponentCount) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ivec3 = OpTypeVector %int 3 -%ptr_ivec3 = OpTypePointer Function %ivec3 -%int_42 = OpConstant %int 42 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2 -%2 = OpTypeFunction %ivec3 -%3 = OpFunction %ivec3 None %2 -%4 = OpLabel -%var = OpVariable %ptr_ivec3 Function %1 -%5 = OpLoad %ivec3 %var -%6 = OpVectorShuffle %ivec3 %5 %5 0 1 - OpReturnValue %6 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVectorShuffle component literals count does not match " - "Result Type '2[%v3uint]'s vector component count.")); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleVector1Type) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ivec2 = OpTypeVector %int 2 -%ptr_int = OpTypePointer Function %int -%undef = OpUndef %ivec2 -%int_42 = OpConstant %int 42 -%2 = OpTypeFunction %ivec2 -%3 = OpFunction %ivec2 None %2 -%4 = OpLabel -%var = OpVariable %ptr_int Function %int_42 -%5 = OpLoad %int %var -%6 = OpVectorShuffle %ivec2 %5 %undef 0 0 - OpReturnValue %6 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The type of Vector 1 must be OpTypeVector.")); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleVector2Type) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ivec2 = OpTypeVector %int 2 -%ptr_ivec2 = OpTypePointer Function %ivec2 -%undef = OpUndef %int -%int_42 = OpConstant %int 42 -%1 = OpConstantComposite %ivec2 %int_42 %int_42 -%2 = OpTypeFunction %ivec2 -%3 = OpFunction %ivec2 None %2 -%4 = OpLabel -%var = OpVariable %ptr_ivec2 Function %1 -%5 = OpLoad %ivec2 %var -%6 = OpVectorShuffle %ivec2 %5 %undef 0 1 - OpReturnValue %6 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The type of Vector 2 must be OpTypeVector.")); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleVector1ComponentType) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ivec3 = OpTypeVector %int 3 -%ptr_ivec3 = OpTypePointer Function %ivec3 -%int_42 = OpConstant %int 42 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%float = OpTypeFloat 32 -%vec3 = OpTypeVector %float 3 -%vec4 = OpTypeVector %float 4 -%ptr_vec3 = OpTypePointer Function %vec3 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2 -%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2 -%3 = OpTypeFunction %vec4 -%4 = OpFunction %vec4 None %3 -%5 = OpLabel -%var = OpVariable %ptr_ivec3 Function %1 -%var2 = OpVariable %ptr_vec3 Function %2 -%6 = OpLoad %ivec3 %var -%7 = OpLoad %vec3 %var2 -%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0 - OpReturnValue %8 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Component Type of Vector 1 must be the same as " - "ResultType.")); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleVector2ComponentType) { - std::string spirv = kGLSL450MemoryModel + R"( -%int = OpTypeInt 32 0 -%ivec3 = OpTypeVector %int 3 -%ptr_ivec3 = OpTypePointer Function %ivec3 -%int_42 = OpConstant %int 42 -%int_0 = OpConstant %int 0 -%int_2 = OpConstant %int 2 -%float = OpTypeFloat 32 -%vec3 = OpTypeVector %float 3 -%vec4 = OpTypeVector %float 4 -%ptr_vec3 = OpTypePointer Function %vec3 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2 -%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2 -%3 = OpTypeFunction %vec4 -%4 = OpFunction %vec4 None %3 -%5 = OpLabel -%var = OpVariable %ptr_ivec3 Function %1 -%var2 = OpVariable %ptr_vec3 Function %2 -%6 = OpLoad %vec3 %var2 -%7 = OpLoad %ivec3 %var -%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0 - OpReturnValue %8 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Component Type of Vector 2 must be the same as " - "ResultType.")); -} - -TEST_F(ValidateIdWithMessage, OpVectorShuffleLiterals) { - std::string spirv = kGLSL450MemoryModel + R"( -%float = OpTypeFloat 32 -%vec2 = OpTypeVector %float 2 -%vec3 = OpTypeVector %float 3 -%vec4 = OpTypeVector %float 4 -%ptr_vec2 = OpTypePointer Function %vec2 -%ptr_vec3 = OpTypePointer Function %vec3 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%1 = OpConstantComposite %vec2 %float_2 %float_1 -%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2 -%3 = OpTypeFunction %vec4 -%4 = OpFunction %vec4 None %3 -%5 = OpLabel -%var = OpVariable %ptr_vec2 Function %1 -%var2 = OpVariable %ptr_vec3 Function %2 -%6 = OpLoad %vec2 %var -%7 = OpLoad %vec3 %var2 -%8 = OpVectorShuffle %vec4 %6 %7 0 8 2 6 - OpReturnValue %8 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Component index 8 is out of bounds for combined (Vector1 + Vector2) " - "size of 5.")); -} - -TEST_F(ValidateIdWithMessage, WebGPUOpVectorShuffle0xFFFFFFFFLiteralBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR -%float = OpTypeFloat 32 -%vec2 = OpTypeVector %float 2 -%vec3 = OpTypeVector %float 3 -%vec4 = OpTypeVector %float 4 -%ptr_vec2 = OpTypePointer Function %vec2 -%ptr_vec3 = OpTypePointer Function %vec3 -%float_1 = OpConstant %float 1 -%float_2 = OpConstant %float 2 -%1 = OpConstantComposite %vec2 %float_2 %float_1 -%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2 -%3 = OpTypeFunction %vec4 -%4 = OpFunction %vec4 None %3 -%5 = OpLabel -%var = OpVariable %ptr_vec2 Function %1 -%var2 = OpVariable %ptr_vec3 Function %2 -%6 = OpLoad %vec2 %var -%7 = OpLoad %vec3 %var2 -%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0xffffffff - OpReturnValue %8 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Component literal at operand 3 cannot be 0xFFFFFFFF in" - " WebGPU execution environment.")); -} - -// TODO: OpCompositeConstruct -// TODO: OpCompositeExtract -// TODO: OpCompositeInsert -// TODO: OpCopyObject -// TODO: OpTranspose -// TODO: OpSNegate -// TODO: OpFNegate -// TODO: OpNot -// TODO: OpIAdd -// TODO: OpFAdd -// TODO: OpISub -// TODO: OpFSub -// TODO: OpIMul -// TODO: OpFMul -// TODO: OpUDiv -// TODO: OpSDiv -// TODO: OpFDiv -// TODO: OpUMod -// TODO: OpSRem -// TODO: OpSMod -// TODO: OpFRem -// TODO: OpFMod -// TODO: OpVectorTimesScalar -// TODO: OpMatrixTimesScalar -// TODO: OpVectorTimesMatrix -// TODO: OpMatrixTimesVector -// TODO: OpMatrixTimesMatrix -// TODO: OpOuterProduct -// TODO: OpDot -// TODO: OpShiftRightLogical -// TODO: OpShiftRightArithmetic -// TODO: OpShiftLeftLogical -// TODO: OpBitwiseOr -// TODO: OpBitwiseXor -// TODO: OpBitwiseAnd -// TODO: OpAny -// TODO: OpAll -// TODO: OpIsNan -// TODO: OpIsInf -// TODO: OpIsFinite -// TODO: OpIsNormal -// TODO: OpSignBitSet -// TODO: OpLessOrGreater -// TODO: OpOrdered -// TODO: OpUnordered -// TODO: OpLogicalOr -// TODO: OpLogicalXor -// TODO: OpLogicalAnd -// TODO: OpSelect -// TODO: OpIEqual -// TODO: OpFOrdEqual -// TODO: OpFUnordEqual -// TODO: OpINotEqual -// TODO: OpFOrdNotEqual -// TODO: OpFUnordNotEqual -// TODO: OpULessThan -// TODO: OpSLessThan -// TODO: OpFOrdLessThan -// TODO: OpFUnordLessThan -// TODO: OpUGreaterThan -// TODO: OpSGreaterThan -// TODO: OpFOrdGreaterThan -// TODO: OpFUnordGreaterThan -// TODO: OpULessThanEqual -// TODO: OpSLessThanEqual -// TODO: OpFOrdLessThanEqual -// TODO: OpFUnordLessThanEqual -// TODO: OpUGreaterThanEqual -// TODO: OpSGreaterThanEqual -// TODO: OpFOrdGreaterThanEqual -// TODO: OpFUnordGreaterThanEqual -// TODO: OpDPdx -// TODO: OpDPdy -// TODO: OpFWidth -// TODO: OpDPdxFine -// TODO: OpDPdyFine -// TODO: OpFwidthFine -// TODO: OpDPdxCoarse -// TODO: OpDPdyCoarse -// TODO: OpFwidthCoarse -// TODO: OpLoopMerge -// TODO: OpSelectionMerge -// TODO: OpBranch - -TEST_F(ValidateIdWithMessage, OpPhiNotAType) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %3 %3 %7 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 3[%true] is not a type " - "id")); -} - -TEST_F(ValidateIdWithMessage, OpPhiSamePredecessor) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranchConditional %3 %8 %8 -%8 = OpLabel -%9 = OpPhi %2 %3 %7 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpPhiOddArgumentNumber) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %2 %3 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi does not have an equal number of incoming " - "values and basic blocks.")); -} - -TEST_F(ValidateIdWithMessage, OpPhiTooFewPredecessors) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranch %8 -%8 = OpLabel -%9 = OpPhi %2 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi's number of incoming blocks (0) does not match " - "block's predecessor count (1).")); -} - -TEST_F(ValidateIdWithMessage, OpPhiTooManyPredecessors) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranch %8 -%9 = OpLabel -OpReturn -%8 = OpLabel -%10 = OpPhi %2 %3 %7 %3 %9 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi's number of incoming blocks (2) does not match " - "block's predecessor count (1).")); -} - -TEST_F(ValidateIdWithMessage, OpPhiMismatchedTypes) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeInt 32 0 -%6 = OpConstant %5 0 -%7 = OpTypeFunction %4 -%8 = OpFunction %4 None %7 -%9 = OpLabel -OpBranchConditional %3 %10 %11 -%11 = OpLabel -OpBranch %10 -%10 = OpLabel -%12 = OpPhi %2 %3 %9 %6 %11 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi's result type 2[%bool] does not match " - "incoming value 6[%uint_0] type " - "5[%uint].")); -} - -TEST_F(ValidateIdWithMessage, OpPhiPredecessorNotABlock) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranchConditional %3 %8 %9 -%9 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %8 -%8 = OpLabel -%10 = OpPhi %2 %3 %7 %3 %3 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi's incoming basic block 3[%true] is not an " - "OpLabel.")); -} - -TEST_F(ValidateIdWithMessage, OpPhiNotAPredecessor) { - std::string spirv = kOpenCLMemoryModel32 + R"( -%2 = OpTypeBool -%3 = OpConstantTrue %2 -%4 = OpTypeVoid -%5 = OpTypeFunction %4 -%6 = OpFunction %4 None %5 -%7 = OpLabel -OpBranchConditional %3 %8 %9 -%9 = OpLabel -OpBranch %11 -%11 = OpLabel -OpBranch %8 -%8 = OpLabel -%10 = OpPhi %2 %3 %7 %3 %9 -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpPhi's incoming basic block 9[%9] is not a " - "predecessor of 8[%8].")); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditionalGood) { - std::string spirv = BranchConditionalSetup + R"( - %branch_cond = OpINotEqual %bool %i0 %i1 - OpSelectionMerge %end None - OpBranchConditional %branch_cond %target_t %target_f - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditionalWithWeightsGood) { - std::string spirv = BranchConditionalSetup + R"( - %branch_cond = OpINotEqual %bool %i0 %i1 - OpSelectionMerge %end None - OpBranchConditional %branch_cond %target_t %target_f 1 1 - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditional_CondIsScalarInt) { - std::string spirv = BranchConditionalSetup + R"( - OpSelectionMerge %end None - OpBranchConditional %i0 %target_t %target_f - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Condition operand for OpBranchConditional must be of boolean type")); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditional_TrueTargetIsNotLabel) { - std::string spirv = BranchConditionalSetup + R"( - OpSelectionMerge %end None - OpBranchConditional %true %i0 %target_f - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The 'True Label' operand for OpBranchConditional must " - "be the ID of an OpLabel instruction")); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditional_FalseTargetIsNotLabel) { - std::string spirv = BranchConditionalSetup + R"( - OpSelectionMerge %end None - OpBranchConditional %true %target_t %i0 - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The 'False Label' operand for OpBranchConditional " - "must be the ID of an OpLabel instruction")); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditional_NotEnoughWeights) { - std::string spirv = BranchConditionalSetup + R"( - %branch_cond = OpINotEqual %bool %i0 %i1 - OpSelectionMerge %end None - OpBranchConditional %branch_cond %target_t %target_f 1 - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpBranchConditional requires either 3 or 5 parameters")); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditional_TooManyWeights) { - std::string spirv = BranchConditionalSetup + R"( - %branch_cond = OpINotEqual %bool %i0 %i1 - OpSelectionMerge %end None - OpBranchConditional %branch_cond %target_t %target_f 1 2 3 - )" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpBranchConditional requires either 3 or 5 parameters")); -} - -TEST_F(ValidateIdWithMessage, OpBranchConditional_ConditionIsAType) { - std::string spirv = BranchConditionalSetup + R"( -OpBranchConditional %bool %target_t %target_f -)" + BranchConditionalTail; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 3[%bool] cannot be a " - "type")); -} - -// TODO: OpSwitch - -TEST_F(ValidateIdWithMessage, OpReturnValueConstantGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 -%4 = OpConstant %2 42 -%5 = OpFunction %2 None %3 -%6 = OpLabel - OpReturnValue %4 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueVariableGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 ;10 -%3 = OpTypeFunction %2 -%8 = OpTypePointer Function %2 ;18 -%4 = OpConstant %2 42 ;22 -%5 = OpFunction %2 None %3 ;27 -%6 = OpLabel ;29 -%7 = OpVariable %8 Function %4 ;34 -%9 = OpLoad %2 %7 - OpReturnValue %9 ;36 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueExpressionGood) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 -%4 = OpConstant %2 42 -%5 = OpFunction %2 None %3 -%6 = OpLabel -%7 = OpIAdd %2 %4 %4 - OpReturnValue %7 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueIsType) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 -%5 = OpFunction %2 None %3 -%6 = OpLabel - OpReturnValue %1 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%void] cannot be a " - "type")); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueIsLabel) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 -%5 = OpFunction %2 None %3 -%6 = OpLabel - OpReturnValue %6 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 5[%5] requires a type")); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueIsVoid) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %1 -%5 = OpFunction %1 None %3 -%6 = OpLabel -%7 = OpFunctionCall %1 %5 - OpReturnValue %7 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpReturnValue value's type '1[%void]' is missing or " - "void.")); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) { - // It's valid to return a pointer in a physical addressing model. - std::string spirv = kOpCapabilitySetup + R"( - OpMemoryModel Physical32 OpenCL -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Function %2 -%4 = OpTypeFunction %3 -%5 = OpFunction %3 None %4 -%6 = OpLabel -%7 = OpVariable %3 Function - OpReturnValue %7 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) { - // It's invalid to return a pointer in a physical addressing model. - std::string spirv = kOpCapabilitySetup + R"( - OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Function %2 -%4 = OpTypeFunction %3 -%5 = OpFunction %3 None %4 -%6 = OpLabel -%7 = OpVariable %3 Function - OpReturnValue %7 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpReturnValue value's type " - "'3[%_ptr_Function_uint]' is a pointer, which is " - "invalid in the Logical addressing model.")); -} - -// With the VariablePointer Capability, the return value of a function is -// allowed to be a pointer. -TEST_F(ValidateIdWithMessage, OpReturnValueVarPtrGood) { - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, - "" /* Instructions to add to "main" */, - true /* Add VariablePointers Capability?*/, - true /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Without the VariablePointer Capability, the return value of a function is -// *not* allowed to be a pointer. -// Disabled since using OpSelect with pointers without VariablePointers will -// fail LogicalsPass. -TEST_F(ValidateIdWithMessage, DISABLED_OpReturnValueVarPtrBad) { - std::ostringstream spirv; - createVariablePointerSpirvProgram(&spirv, - "" /* Instructions to add to "main" */, - false /* Add VariablePointers Capability?*/, - true /* Use Helper Function? */); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpReturnValue value's type '7' is a pointer, " - "which is invalid in the Logical addressing model.")); -} - -// TODO: enable when this bug is fixed: -// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404 -TEST_F(ValidateIdWithMessage, DISABLED_OpReturnValueIsFunction) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypeFunction %2 -%5 = OpFunction %2 None %3 -%6 = OpLabel - OpReturnValue %5 - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, UndefinedTypeId) { - std::string spirv = kGLSL450MemoryModel + R"( -%s = OpTypeStruct %i32 -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 2[%2] requires a previous definition")); -} - -TEST_F(ValidateIdWithMessage, UndefinedIdScope) { - std::string spirv = kGLSL450MemoryModel + R"( -%u32 = OpTypeInt 32 0 -%memsem = OpConstant %u32 0 -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%f = OpFunction %void None %void_f -%l = OpLabel - OpMemoryBarrier %undef %memsem - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 7[%7] has not been " - "defined")); -} - -TEST_F(ValidateIdWithMessage, UndefinedIdMemSem) { - std::string spirv = kGLSL450MemoryModel + R"( -%u32 = OpTypeInt 32 0 -%scope = OpConstant %u32 0 -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%f = OpFunction %void None %void_f -%l = OpLabel - OpMemoryBarrier %scope %undef - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 7[%7] has not been " - "defined")); -} - -TEST_F(ValidateIdWithMessage, - KernelOpEntryPointAndOpInBoundsPtrAccessChainGood) { - std::string spirv = kOpenCLMemoryModel32 + R"( - OpEntryPoint Kernel %2 "simple_kernel" - OpSource OpenCL_C 200000 - OpDecorate %3 BuiltIn GlobalInvocationId - OpDecorate %3 Constant - OpDecorate %4 FuncParamAttr NoCapture - OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import - %5 = OpTypeInt 32 0 - %6 = OpTypeVector %5 3 - %7 = OpTypePointer UniformConstant %6 - %3 = OpVariable %7 UniformConstant - %8 = OpTypeVoid - %9 = OpTypeStruct %5 -%10 = OpTypePointer CrossWorkgroup %9 -%11 = OpTypeFunction %8 %10 -%12 = OpConstant %5 0 -%13 = OpTypePointer CrossWorkgroup %5 -%14 = OpConstant %5 42 - %2 = OpFunction %8 None %11 - %4 = OpFunctionParameter %10 -%15 = OpLabel -%16 = OpLoad %6 %3 Aligned 0 -%17 = OpCompositeExtract %5 %16 0 -%18 = OpInBoundsPtrAccessChain %13 %4 %17 %12 - OpStore %18 %14 Aligned 4 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpPtrAccessChainGood) { - std::string spirv = kOpenCLMemoryModel64 + R"( - OpEntryPoint Kernel %2 "another_kernel" - OpSource OpenCL_C 200000 - OpDecorate %3 BuiltIn GlobalInvocationId - OpDecorate %3 Constant - OpDecorate %4 FuncParamAttr NoCapture - OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import - %5 = OpTypeInt 64 0 - %6 = OpTypeVector %5 3 - %7 = OpTypePointer UniformConstant %6 - %3 = OpVariable %7 UniformConstant - %8 = OpTypeVoid - %9 = OpTypeInt 32 0 -%10 = OpTypeStruct %9 -%11 = OpTypePointer CrossWorkgroup %10 -%12 = OpTypeFunction %8 %11 -%13 = OpConstant %5 4294967295 -%14 = OpConstant %9 0 -%15 = OpTypePointer CrossWorkgroup %9 -%16 = OpConstant %9 42 - %2 = OpFunction %8 None %12 - %4 = OpFunctionParameter %11 -%17 = OpLabel -%18 = OpLoad %6 %3 Aligned 0 -%19 = OpCompositeExtract %5 %18 0 -%20 = OpBitwiseAnd %5 %19 %13 -%21 = OpPtrAccessChain %15 %4 %20 %14 - OpStore %21 %16 Aligned 4 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, StgBufOpPtrAccessChainGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpCapability VariablePointersStorageBuffer - OpExtension "SPV_KHR_variable_pointers" - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %3 "" -%int = OpTypeInt 32 0 -%int_2 = OpConstant %int 2 -%int_4 = OpConstant %int 4 -%struct = OpTypeStruct %int -%array = OpTypeArray %struct %int_4 -%ptr = OpTypePointer StorageBuffer %array -%var = OpVariable %ptr StorageBuffer -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel -%5 = OpPtrAccessChain %ptr %var %int_2 - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateIdWithMessage, OpLoadBitcastPointerGood) { - std::string spirv = kOpenCLMemoryModel64 + R"( -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypeFloat 32 -%5 = OpTypePointer UniformConstant %3 -%6 = OpTypePointer UniformConstant %4 -%7 = OpVariable %5 UniformConstant -%8 = OpTypeFunction %2 -%9 = OpFunction %2 None %8 -%10 = OpLabel -%11 = OpBitcast %6 %7 -%12 = OpLoad %4 %11 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) { - std::string spirv = kOpenCLMemoryModel64 + R"( -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypeFloat 32 -%5 = OpTypePointer UniformConstant %3 -%6 = OpTypeFunction %2 -%7 = OpVariable %5 UniformConstant -%8 = OpFunction %2 None %6 -%9 = OpLabel -%10 = OpLoad %3 %7 -%11 = OpBitcast %4 %10 -%12 = OpLoad %3 %11 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpLoad type for pointer '11[%11]' is not a pointer " - "type.")); -} -TEST_F(ValidateIdWithMessage, OpStoreBitcastPointerGood) { - std::string spirv = kOpenCLMemoryModel64 + R"( -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypeFloat 32 -%5 = OpTypePointer Function %3 -%6 = OpTypePointer Function %4 -%7 = OpTypeFunction %2 -%8 = OpConstant %3 42 -%9 = OpFunction %2 None %7 -%10 = OpLabel -%11 = OpVariable %6 Function -%12 = OpBitcast %5 %11 - OpStore %12 %8 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -TEST_F(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) { - std::string spirv = kOpenCLMemoryModel64 + R"( -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypeFloat 32 -%5 = OpTypePointer Function %4 -%6 = OpTypeFunction %2 -%7 = OpConstant %4 42 -%8 = OpFunction %2 None %6 -%9 = OpLabel -%10 = OpVariable %5 Function -%11 = OpBitcast %3 %7 - OpStore %11 %7 - OpReturn - OpFunctionEnd)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpStore type for pointer '11[%11]' is not a pointer " - "type.")); -} - -// Result resulting from an instruction within a function may not be used -// outside that function. -TEST_F(ValidateIdWithMessage, ResultIdUsedOutsideOfFunctionBad) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Function %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -%7 = OpVariable %4 Function -OpReturn -OpFunctionEnd -%8 = OpFunction %1 None %2 -%9 = OpLabel -%10 = OpLoad %3 %7 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ID 7[%7] defined in block 6[%6] does not dominate its use in block " - "9[%9]")); -} - -TEST_F(ValidateIdWithMessage, SpecIdTargetNotSpecializationConstant) { - std::string spirv = kGLSL450MemoryModel + R"( -OpDecorate %1 SpecId 200 -%void = OpTypeVoid -%2 = OpTypeFunction %void -%int = OpTypeInt 32 0 -%1 = OpConstant %int 3 -%main = OpFunction %void None %2 -%4 = OpLabel -OpReturnValue %1 -OpFunctionEnd - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpDecorate SpecId decoration target " - "'1[%uint_3]' is not a scalar specialization " - "constant.")); -} - -TEST_F(ValidateIdWithMessage, SpecIdTargetOpSpecConstantOpBad) { - std::string spirv = kGLSL450MemoryModel + R"( -OpDecorate %1 SpecId 200 -%void = OpTypeVoid -%2 = OpTypeFunction %void -%int = OpTypeInt 32 0 -%3 = OpConstant %int 1 -%4 = OpConstant %int 2 -%1 = OpSpecConstantOp %int IAdd %3 %4 -%main = OpFunction %void None %2 -%6 = OpLabel -OpReturnValue %3 -OpFunctionEnd - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpDecorate SpecId decoration target '1[%1]' is " - "not a scalar specialization constant.")); -} - -TEST_F(ValidateIdWithMessage, SpecIdTargetOpSpecConstantCompositeBad) { - std::string spirv = kGLSL450MemoryModel + R"( -OpDecorate %1 SpecId 200 -%void = OpTypeVoid -%2 = OpTypeFunction %void -%int = OpTypeInt 32 0 -%3 = OpConstant %int 1 -%1 = OpSpecConstantComposite %int -%main = OpFunction %void None %2 -%4 = OpLabel -OpReturnValue %3 -OpFunctionEnd - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpDecorate SpecId decoration target '1[%1]' is " - "not a scalar specialization constant.")); -} - -TEST_F(ValidateIdWithMessage, SpecIdTargetGood) { - std::string spirv = kGLSL450MemoryModel + R"( -OpDecorate %3 SpecId 200 -OpDecorate %4 SpecId 201 -OpDecorate %5 SpecId 202 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%int = OpTypeInt 32 0 -%bool = OpTypeBool -%3 = OpSpecConstant %int 3 -%4 = OpSpecConstantTrue %bool -%5 = OpSpecConstantFalse %bool -%main = OpFunction %1 None %2 -%6 = OpLabel -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidateIdWithMessage, CorrectErrorForShuffle) { - std::string spirv = kGLSL450MemoryModel + R"( - %uint = OpTypeInt 32 0 - %float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%v2float = OpTypeVector %float 2 - %void = OpTypeVoid - %548 = OpTypeFunction %void - %CS = OpFunction %void None %548 - %550 = OpLabel - %6275 = OpUndef %v2float - %6280 = OpUndef %v2float - %6282 = OpVectorShuffle %v4float %6275 %6280 0 1 4 5 - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Component index 4 is out of bounds for combined (Vector1 + Vector2) " - "size of 4.")); - EXPECT_EQ(25, getErrorPosition().index); -} - -TEST_F(ValidateIdWithMessage, VoidStructMember) { - const std::string spirv = kGLSL450MemoryModel + R"( -%void = OpTypeVoid -%struct = OpTypeStruct %void -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Structures cannot contain a void type.")); -} - -TEST_F(ValidateIdWithMessage, TypeFunctionBadUse) { - std::string spirv = kGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypePointer Function %2 -%4 = OpFunction %1 None %2 -%5 = OpLabel - OpReturn - OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid use of function type result id 2[%2].")); -} - -TEST_F(ValidateIdWithMessage, BadTypeId) { - std::string spirv = kGLSL450MemoryModel + R"( - %1 = OpTypeVoid - %2 = OpTypeFunction %1 - %3 = OpTypeFloat 32 - %4 = OpConstant %3 0 - %5 = OpFunction %1 None %2 - %6 = OpLabel - %7 = OpUndef %4 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 4[%float_0] is not a type " - "id")); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelLoadMakePointerVisibleGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypeFunction %1 -%6 = OpConstant %2 2 -%7 = OpFunction %1 None %5 -%8 = OpLabel -%9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerVisibleKHR %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelLoadMakePointerVisibleMissingNonPrivatePointer) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypeFunction %1 -%6 = OpConstant %2 2 -%7 = OpFunction %1 None %5 -%8 = OpLabel -%9 = OpLoad %2 %4 MakePointerVisibleKHR %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR must be specified if " - "MakePointerVisibleKHR is specified.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelLoadNonPrivatePointerBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Private %2 -%4 = OpVariable %3 Private -%5 = OpTypeFunction %1 -%6 = OpConstant %2 2 -%7 = OpFunction %1 None %5 -%8 = OpLabel -%9 = OpLoad %2 %4 NonPrivatePointerKHR -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, " - "Workgroup, CrossWorkgroup, Generic, Image or " - "StorageBuffer storage classes.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelLoadMakePointerAvailableCannotBeUsed) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypeFunction %1 -%6 = OpConstant %2 2 -%7 = OpFunction %1 None %5 -%8 = OpLabel -%9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerAvailableKHR %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad")); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelStoreMakePointerAvailableGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpVariable %3 Uniform -%5 = OpTypeFunction %1 -%6 = OpConstant %2 5 -%7 = OpFunction %1 None %5 -%8 = OpLabel -OpStore %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelStoreMakePointerAvailableMissingNonPrivatePointer) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpVariable %3 Uniform -%5 = OpTypeFunction %1 -%6 = OpConstant %2 5 -%7 = OpFunction %1 None %5 -%8 = OpLabel -OpStore %4 %6 MakePointerAvailableKHR %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR must be specified if " - "MakePointerAvailableKHR is specified.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelStoreNonPrivatePointerBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Output %2 -%4 = OpVariable %3 Output -%5 = OpTypeFunction %1 -%6 = OpConstant %2 5 -%7 = OpFunction %1 None %5 -%8 = OpLabel -OpStore %4 %6 NonPrivatePointerKHR -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, " - "Workgroup, CrossWorkgroup, Generic, Image or " - "StorageBuffer storage classes.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelStoreMakePointerVisibleCannotBeUsed) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Uniform %2 -%4 = OpVariable %3 Uniform -%5 = OpTypeFunction %1 -%6 = OpConstant %2 5 -%7 = OpFunction %1 None %5 -%8 = OpLabel -OpStore %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MakePointerVisibleKHR cannot be used with OpStore.")); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailable) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryVisible) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailableAndVisible) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemoryAvailableMissingNonPrivatePointer) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 MakePointerAvailableKHR %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR must be specified if " - "MakePointerAvailableKHR is specified.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemoryVisibleMissingNonPrivatePointer) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 MakePointerVisibleKHR %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR must be specified if " - "MakePointerVisibleKHR is specified.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemoryAvailableBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Output %2 -%4 = OpVariable %3 Output -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 NonPrivatePointerKHR -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, " - "Workgroup, CrossWorkgroup, Generic, Image or " - "StorageBuffer storage classes.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemoryVisibleBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Input %2 -%6 = OpVariable %5 Input -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemory %4 %6 NonPrivatePointerKHR -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, " - "Workgroup, CrossWorkgroup, Generic, Image or " - "StorageBuffer storage classes.")); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedAvailable) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR|MakePointerAvailableKHR %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedVisible) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR|MakePointerVisibleKHR %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemorySizedAvailableAndVisible) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemorySizedAvailableMissingNonPrivatePointer) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 MakePointerAvailableKHR %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR must be specified if " - "MakePointerAvailableKHR is specified.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemorySizedVisibleMissingNonPrivatePointer) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 MakePointerVisibleKHR %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR must be specified if " - "MakePointerVisibleKHR is specified.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemorySizedAvailableBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Output %2 -%4 = OpVariable %3 Output -%5 = OpTypePointer Uniform %2 -%6 = OpVariable %5 Uniform -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, " - "Workgroup, CrossWorkgroup, Generic, Image or " - "StorageBuffer storage classes.")); -} - -TEST_F(ValidateIdWithMessage, - VulkanMemoryModelCopyMemorySizedVisibleBadStorageClass) { - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%1 = OpTypeVoid -%2 = OpTypeInt 32 0 -%3 = OpTypePointer Workgroup %2 -%4 = OpVariable %3 Workgroup -%5 = OpTypePointer Input %2 -%6 = OpVariable %5 Input -%7 = OpConstant %2 2 -%8 = OpConstant %2 5 -%9 = OpTypeFunction %1 -%10 = OpFunction %1 None %9 -%11 = OpLabel -OpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, " - "Workgroup, CrossWorkgroup, Generic, Image or " - "StorageBuffer storage classes.")); -} - -TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock1) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -OpReturn -%7 = OpLabel -%8 = OpFunctionCall %3 %9 -OpUnreachable -OpFunctionEnd -%9 = OpFunction %3 None %4 -%10 = OpLabel -OpReturnValue %8 -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 8[%8] defined in block 7[%7] does not dominate its " - "use in block 10[%10]\n %10 = OpLabel")); -} - -TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock2) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -OpReturn -%7 = OpLabel -%8 = OpFunctionCall %3 %9 -OpUnreachable -OpFunctionEnd -%9 = OpFunction %3 None %4 -%10 = OpLabel -OpReturnValue %8 -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 8[%8] defined in block 7[%7] does not dominate its " - "use in block 10[%10]\n %10 = OpLabel")); -} - -TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock3) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -OpReturn -%7 = OpLabel -%8 = OpFunctionCall %3 %9 -OpReturn -OpFunctionEnd -%9 = OpFunction %3 None %4 -%10 = OpLabel -OpReturnValue %8 -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 8[%8] defined in block 7[%7] does not dominate its " - "use in block 10[%10]\n %10 = OpLabel")); -} - -TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock4) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -OpReturn -%7 = OpLabel -%8 = OpUndef %3 -%9 = OpCopyObject %3 %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock5) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -OpReturn -%7 = OpLabel -%8 = OpUndef %3 -OpBranch %9 -%9 = OpLabel -%10 = OpCopyObject %3 %8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock6) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -OpBranch %7 -%8 = OpLabel -%9 = OpUndef %3 -OpBranch %7 -%7 = OpLabel -%10 = OpCopyObject %3 %9 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ID 9[%9] defined in block 8[%8] does not dominate its " - "use in block 7[%7]\n %7 = OpLabel")); -} - -TEST_F(ValidateIdWithMessage, ReachableDefUnreachableUse) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeFloat 32 -%4 = OpTypeFunction %3 -%5 = OpFunction %1 None %2 -%6 = OpLabel -%7 = OpUndef %3 -OpReturn -%8 = OpLabel -%9 = OpCopyObject %3 %7 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateIdWithMessage, UnreachableDefUsedInPhi) { - const std::string spirv = kNoKernelGLSL450MemoryModel + R"( - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %bool = OpTypeBool - %6 = OpTypeFunction %float - %1 = OpFunction %void None %3 - %7 = OpLabel - %8 = OpUndef %bool - OpSelectionMerge %9 None - OpBranchConditional %8 %10 %9 - %10 = OpLabel - %11 = OpUndef %float - OpBranch %9 - %12 = OpLabel - %13 = OpUndef %float - OpUnreachable - %9 = OpLabel - %14 = OpPhi %float %11 %10 %13 %7 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In OpPhi instruction 14[%14], ID 13[%13] definition does not " - "dominate its parent 7[%7]\n %14 = OpPhi %float %11 %10 %13 " - "%7")); -} - -TEST_F(ValidateIdWithMessage, OpTypeForwardPointerNotAPointerType) { - std::string spirv = R"( - OpCapability GenericPointer - OpCapability VariablePointersStorageBuffer - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginLowerLeft - OpTypeForwardPointer %2 CrossWorkgroup -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%1 = OpFunction %2 DontInline %3 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer " - "type.\n OpTypeForwardPointer %void CrossWorkgroup")); -} - -TEST_F(ValidateIdWithMessage, OpTypeForwardPointerWrongStorageClass) { - std::string spirv = R"( - OpCapability GenericPointer - OpCapability VariablePointersStorageBuffer - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginLowerLeft - OpTypeForwardPointer %2 CrossWorkgroup -%int = OpTypeInt 32 1 -%2 = OpTypePointer Function %int -%void = OpTypeVoid -%3 = OpTypeFunction %void -%1 = OpFunction %void None %3 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Storage class in OpTypeForwardPointer does not match the " - "pointer definition.\n OpTypeForwardPointer " - "%_ptr_Function_int CrossWorkgroup")); -} - -TEST_F(ValidateIdWithMessage, MissingForwardPointer) { - const std::string spirv = R"( - OpCapability Linkage - OpCapability Shader - OpMemoryModel Logical Simple - %float = OpTypeFloat 32 - %_struct_9 = OpTypeStruct %float %_ptr_Uniform__struct_9 -%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 - %1278 = OpVariable %_ptr_Uniform__struct_9 Uniform -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Operand 3[%_ptr_Uniform__struct_2] requires a previous definition")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_image_test.cpp b/3rdparty/spirv-tools/test/val/val_image_test.cpp deleted file mode 100644 index 433c9faed..000000000 --- a/3rdparty/spirv-tools/test/val/val_image_test.cpp +++ /dev/null @@ -1,4849 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateImage = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "Fragment", - const std::string& execution_mode = "", - const spv_target_env env = SPV_ENV_UNIVERSAL_1_0, - const std::string& memory_model = "GLSL450") { - std::ostringstream ss; - ss << R"( -OpCapability Shader -OpCapability InputAttachment -OpCapability ImageGatherExtended -OpCapability MinLod -OpCapability Sampled1D -OpCapability ImageQuery -OpCapability Int64 -OpCapability Float64 -OpCapability SparseResidency -OpCapability ImageBuffer -)"; - - if (env == SPV_ENV_UNIVERSAL_1_0) { - ss << "OpCapability SampledRect\n"; - } - - // In 1.4, the entry point must list all module-scope variables used. Just - // list all of them. - std::string interface_vars = (env != SPV_ENV_UNIVERSAL_1_4) ? "" : - R"( -%uniform_image_f32_1d_0001 -%uniform_image_f32_1d_0002_rgba32f -%uniform_image_f32_2d_0001 -%uniform_image_f32_2d_0010 -%uniform_image_u32_2d_0001 -%uniform_image_u32_2d_0000 -%uniform_image_s32_3d_0001 -%uniform_image_f32_2d_0002 -%uniform_image_s32_2d_0002 -%uniform_image_f32_spd_0002 -%uniform_image_f32_3d_0111 -%uniform_image_f32_cube_0101 -%uniform_image_f32_cube_0102_rgba32f -%uniform_sampler -%private_image_u32_buffer_0002_r32ui -%private_image_u32_spd_0002 -%private_image_f32_buffer_0002_r32ui -)"; - - ss << capabilities_and_extensions; - ss << "OpMemoryModel Logical " << memory_model << "\n"; - ss << "OpEntryPoint " << execution_model - << " %main \"main\" " + interface_vars + "\n"; - if (execution_model == "Fragment") { - ss << "OpExecutionMode %main OriginUpperLeft\n"; - } - ss << execution_mode; - - if (env == SPV_ENV_VULKAN_1_0) { - ss << R"( -OpDecorate %uniform_image_f32_1d_0001 DescriptorSet 0 -OpDecorate %uniform_image_f32_1d_0001 Binding 0 -OpDecorate %uniform_image_f32_1d_0002_rgba32f DescriptorSet 0 -OpDecorate %uniform_image_f32_1d_0002_rgba32f Binding 1 -OpDecorate %uniform_image_f32_2d_0001 DescriptorSet 0 -OpDecorate %uniform_image_f32_2d_0001 Binding 2 -OpDecorate %uniform_image_f32_2d_0010 DescriptorSet 0 -OpDecorate %uniform_image_f32_2d_0010 Binding 3 -OpDecorate %uniform_image_u32_2d_0001 DescriptorSet 1 -OpDecorate %uniform_image_u32_2d_0001 Binding 0 -OpDecorate %uniform_image_u32_2d_0000 DescriptorSet 1 -OpDecorate %uniform_image_u32_2d_0000 Binding 1 -OpDecorate %uniform_image_s32_3d_0001 DescriptorSet 1 -OpDecorate %uniform_image_s32_3d_0001 Binding 2 -OpDecorate %uniform_image_f32_2d_0002 DescriptorSet 1 -OpDecorate %uniform_image_f32_2d_0002 Binding 3 -OpDecorate %uniform_image_s32_2d_0002 DescriptorSet 1 -OpDecorate %uniform_image_s32_2d_0002 Binding 4 -OpDecorate %uniform_image_f32_spd_0002 DescriptorSet 2 -OpDecorate %uniform_image_f32_spd_0002 Binding 0 -OpDecorate %uniform_image_f32_3d_0111 DescriptorSet 2 -OpDecorate %uniform_image_f32_3d_0111 Binding 1 -OpDecorate %uniform_image_f32_cube_0101 DescriptorSet 2 -OpDecorate %uniform_image_f32_cube_0101 Binding 2 -OpDecorate %uniform_image_f32_cube_0102_rgba32f DescriptorSet 2 -OpDecorate %uniform_image_f32_cube_0102_rgba32f Binding 3 -OpDecorate %uniform_sampler DescriptorSet 3 -OpDecorate %uniform_sampler Binding 0 -)"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%f64 = OpTypeFloat 64 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%u64 = OpTypeInt 64 0 -%s32vec2 = OpTypeVector %s32 2 -%u32vec2 = OpTypeVector %u32 2 -%f32vec2 = OpTypeVector %f32 2 -%u32vec3 = OpTypeVector %u32 3 -%s32vec3 = OpTypeVector %s32 3 -%f32vec3 = OpTypeVector %f32 3 -%u32vec4 = OpTypeVector %u32 4 -%s32vec4 = OpTypeVector %s32 4 -%f32vec4 = OpTypeVector %f32 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_0_5 = OpConstant %f32 0.5 -%f32_0_25 = OpConstant %f32 0.25 -%f32_0_75 = OpConstant %f32 0.75 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 - -%s32_0 = OpConstant %s32 0 -%s32_1 = OpConstant %s32 1 -%s32_2 = OpConstant %s32 2 -%s32_3 = OpConstant %s32 3 -%s32_4 = OpConstant %s32 4 -%s32_m1 = OpConstant %s32 -1 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%u64_0 = OpConstant %u64 0 - -%u32vec2arr4 = OpTypeArray %u32vec2 %u32_4 -%u32vec2arr3 = OpTypeArray %u32vec2 %u32_3 -%u32arr4 = OpTypeArray %u32 %u32_4 -%u32vec3arr4 = OpTypeArray %u32vec3 %u32_4 - -%struct_u32_f32vec4 = OpTypeStruct %u32 %f32vec4 -%struct_u64_f32vec4 = OpTypeStruct %u64 %f32vec4 -%struct_u32_u32vec4 = OpTypeStruct %u32 %u32vec4 -%struct_u32_f32vec3 = OpTypeStruct %u32 %f32vec3 -%struct_f32_f32vec4 = OpTypeStruct %f32 %f32vec4 -%struct_u32_u32 = OpTypeStruct %u32 %u32 -%struct_f32_f32 = OpTypeStruct %f32 %f32 -%struct_u32 = OpTypeStruct %u32 -%struct_u32_f32_u32 = OpTypeStruct %u32 %f32 %u32 -%struct_u32_f32vec4_u32 = OpTypeStruct %u32 %f32vec4 %u32 -%struct_u32_u32arr4 = OpTypeStruct %u32 %u32arr4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1 -%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2 -%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2 -%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3 -%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3 -%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4 - -%f32vec2_00 = OpConstantComposite %f32vec2 %f32_0 %f32_0 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_10 = OpConstantComposite %f32vec2 %f32_1 %f32_0 -%f32vec2_11 = OpConstantComposite %f32vec2 %f32_1 %f32_1 -%f32vec2_hh = OpConstantComposite %f32vec2 %f32_0_5 %f32_0_5 - -%f32vec3_000 = OpConstantComposite %f32vec3 %f32_0 %f32_0 %f32_0 -%f32vec3_hhh = OpConstantComposite %f32vec3 %f32_0_5 %f32_0_5 %f32_0_5 - -%f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0 - -%const_offsets = OpConstantComposite %u32vec2arr4 %u32vec2_01 %u32vec2_12 %u32vec2_01 %u32vec2_12 -%const_offsets3x2 = OpConstantComposite %u32vec2arr3 %u32vec2_01 %u32vec2_12 %u32vec2_01 -%const_offsets4xu = OpConstantComposite %u32arr4 %u32_0 %u32_0 %u32_0 %u32_0 -%const_offsets4x3 = OpConstantComposite %u32vec3arr4 %u32vec3_012 %u32vec3_012 %u32vec3_012 %u32vec3_012 - -%type_image_f32_1d_0001 = OpTypeImage %f32 1D 0 0 0 1 Unknown -%ptr_image_f32_1d_0001 = OpTypePointer UniformConstant %type_image_f32_1d_0001 -%uniform_image_f32_1d_0001 = OpVariable %ptr_image_f32_1d_0001 UniformConstant -%type_sampled_image_f32_1d_0001 = OpTypeSampledImage %type_image_f32_1d_0001 - -%type_image_f32_1d_0002_rgba32f = OpTypeImage %f32 1D 0 0 0 2 Rgba32f -%ptr_image_f32_1d_0002_rgba32f = OpTypePointer UniformConstant %type_image_f32_1d_0002_rgba32f -%uniform_image_f32_1d_0002_rgba32f = OpVariable %ptr_image_f32_1d_0002_rgba32f UniformConstant -%type_sampled_image_f32_1d_0002_rgba32f = OpTypeSampledImage %type_image_f32_1d_0002_rgba32f - -%type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown -%ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001 -%uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant -%type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001 - -%type_image_f32_2d_0010 = OpTypeImage %f32 2D 0 0 1 0 Unknown -%ptr_image_f32_2d_0010 = OpTypePointer UniformConstant %type_image_f32_2d_0010 -%uniform_image_f32_2d_0010 = OpVariable %ptr_image_f32_2d_0010 UniformConstant -%type_sampled_image_f32_2d_0010 = OpTypeSampledImage %type_image_f32_2d_0010 - -%type_image_u32_2d_0001 = OpTypeImage %u32 2D 0 0 0 1 Unknown -%ptr_image_u32_2d_0001 = OpTypePointer UniformConstant %type_image_u32_2d_0001 -%uniform_image_u32_2d_0001 = OpVariable %ptr_image_u32_2d_0001 UniformConstant -%type_sampled_image_u32_2d_0001 = OpTypeSampledImage %type_image_u32_2d_0001 - -%type_image_u32_2d_0000 = OpTypeImage %u32 2D 0 0 0 0 Unknown -%ptr_image_u32_2d_0000 = OpTypePointer UniformConstant %type_image_u32_2d_0000 -%uniform_image_u32_2d_0000 = OpVariable %ptr_image_u32_2d_0000 UniformConstant -%type_sampled_image_u32_2d_0000 = OpTypeSampledImage %type_image_u32_2d_0000 - -%type_image_s32_3d_0001 = OpTypeImage %s32 3D 0 0 0 1 Unknown -%ptr_image_s32_3d_0001 = OpTypePointer UniformConstant %type_image_s32_3d_0001 -%uniform_image_s32_3d_0001 = OpVariable %ptr_image_s32_3d_0001 UniformConstant -%type_sampled_image_s32_3d_0001 = OpTypeSampledImage %type_image_s32_3d_0001 - -%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Unknown -%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002 -%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant -%type_sampled_image_f32_2d_0002 = OpTypeSampledImage %type_image_f32_2d_0002 - -%type_image_s32_2d_0002 = OpTypeImage %s32 2D 0 0 0 2 Unknown -%ptr_image_s32_2d_0002 = OpTypePointer UniformConstant %type_image_s32_2d_0002 -%uniform_image_s32_2d_0002 = OpVariable %ptr_image_s32_2d_0002 UniformConstant -%type_sampled_image_s32_2d_0002 = OpTypeSampledImage %type_image_s32_2d_0002 - -%type_image_f32_spd_0002 = OpTypeImage %f32 SubpassData 0 0 0 2 Unknown -%ptr_image_f32_spd_0002 = OpTypePointer UniformConstant %type_image_f32_spd_0002 -%uniform_image_f32_spd_0002 = OpVariable %ptr_image_f32_spd_0002 UniformConstant -%type_sampled_image_f32_spd_0002 = OpTypeSampledImage %type_image_f32_spd_0002 - -%type_image_f32_3d_0111 = OpTypeImage %f32 3D 0 1 1 1 Unknown -%ptr_image_f32_3d_0111 = OpTypePointer UniformConstant %type_image_f32_3d_0111 -%uniform_image_f32_3d_0111 = OpVariable %ptr_image_f32_3d_0111 UniformConstant -%type_sampled_image_f32_3d_0111 = OpTypeSampledImage %type_image_f32_3d_0111 - -%type_image_f32_cube_0101 = OpTypeImage %f32 Cube 0 1 0 1 Unknown -%ptr_image_f32_cube_0101 = OpTypePointer UniformConstant %type_image_f32_cube_0101 -%uniform_image_f32_cube_0101 = OpVariable %ptr_image_f32_cube_0101 UniformConstant -%type_sampled_image_f32_cube_0101 = OpTypeSampledImage %type_image_f32_cube_0101 - -%type_image_f32_cube_0102_rgba32f = OpTypeImage %f32 Cube 0 1 0 2 Rgba32f -%ptr_image_f32_cube_0102_rgba32f = OpTypePointer UniformConstant %type_image_f32_cube_0102_rgba32f -%uniform_image_f32_cube_0102_rgba32f = OpVariable %ptr_image_f32_cube_0102_rgba32f UniformConstant -%type_sampled_image_f32_cube_0102_rgba32f = OpTypeSampledImage %type_image_f32_cube_0102_rgba32f - -%type_sampler = OpTypeSampler -%ptr_sampler = OpTypePointer UniformConstant %type_sampler -%uniform_sampler = OpVariable %ptr_sampler UniformConstant - -%type_image_u32_buffer_0002_r32ui = OpTypeImage %u32 Buffer 0 0 0 2 R32ui -%ptr_Image_u32 = OpTypePointer Image %u32 -%ptr_image_u32_buffer_0002_r32ui = OpTypePointer Private %type_image_u32_buffer_0002_r32ui -%private_image_u32_buffer_0002_r32ui = OpVariable %ptr_image_u32_buffer_0002_r32ui Private - -%ptr_Image_u32arr4 = OpTypePointer Image %u32arr4 - -%type_image_u32_spd_0002 = OpTypeImage %u32 SubpassData 0 0 0 2 Unknown -%ptr_image_u32_spd_0002 = OpTypePointer Private %type_image_u32_spd_0002 -%private_image_u32_spd_0002 = OpVariable %ptr_image_u32_spd_0002 Private - -%type_image_f32_buffer_0002_r32ui = OpTypeImage %f32 Buffer 0 0 0 2 R32ui -%ptr_Image_f32 = OpTypePointer Image %f32 -%ptr_image_f32_buffer_0002_r32ui = OpTypePointer Private %type_image_f32_buffer_0002_r32ui -%private_image_f32_buffer_0002_r32ui = OpVariable %ptr_image_f32_buffer_0002_r32ui Private -)"; - - if (env == SPV_ENV_UNIVERSAL_1_0) { - ss << R"( -%type_image_void_2d_0001 = OpTypeImage %void 2D 0 0 0 1 Unknown -%ptr_image_void_2d_0001 = OpTypePointer UniformConstant %type_image_void_2d_0001 -%uniform_image_void_2d_0001 = OpVariable %ptr_image_void_2d_0001 UniformConstant -%type_sampled_image_void_2d_0001 = OpTypeSampledImage %type_image_void_2d_0001 - -%type_image_void_2d_0002 = OpTypeImage %void 2D 0 0 0 2 Unknown -%ptr_image_void_2d_0002 = OpTypePointer UniformConstant %type_image_void_2d_0002 -%uniform_image_void_2d_0002 = OpVariable %ptr_image_void_2d_0002 UniformConstant -%type_sampled_image_void_2d_0002 = OpTypeSampledImage %type_image_void_2d_0002 - -%type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown -%ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001 -%uniform_image_f32_rect_0001 = OpVariable %ptr_image_f32_rect_0001 UniformConstant -%type_sampled_image_f32_rect_0001 = OpTypeSampledImage %type_image_f32_rect_0001 -)"; - } - - ss << R"( -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -std::string GenerateKernelCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - std::ostringstream ss; - ss << R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability ImageQuery -OpCapability ImageGatherExtended -OpCapability InputAttachment -OpCapability SampledRect -)"; - - ss << capabilities_and_extensions; - ss << R"( -OpMemoryModel Physical32 OpenCL -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%u32vec2 = OpTypeVector %u32 2 -%f32vec2 = OpTypeVector %f32 2 -%u32vec3 = OpTypeVector %u32 3 -%f32vec3 = OpTypeVector %f32 3 -%u32vec4 = OpTypeVector %u32 4 -%f32vec4 = OpTypeVector %f32 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_0_5 = OpConstant %f32 0.5 -%f32_0_25 = OpConstant %f32 0.25 -%f32_0_75 = OpConstant %f32 0.75 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%f32vec2_00 = OpConstantComposite %f32vec2 %f32_0 %f32_0 -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_10 = OpConstantComposite %f32vec2 %f32_1 %f32_0 -%f32vec2_11 = OpConstantComposite %f32vec2 %f32_1 %f32_1 -%f32vec2_hh = OpConstantComposite %f32vec2 %f32_0_5 %f32_0_5 - -%f32vec3_000 = OpConstantComposite %f32vec3 %f32_0 %f32_0 %f32_0 -%f32vec3_hhh = OpConstantComposite %f32vec3 %f32_0_5 %f32_0_5 %f32_0_5 - -%f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0 - -%type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown -%ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001 -%uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant -%type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001 - -%type_image_f32_2d_0010 = OpTypeImage %f32 2D 0 0 1 0 Unknown -%ptr_image_f32_2d_0010 = OpTypePointer UniformConstant %type_image_f32_2d_0010 -%uniform_image_f32_2d_0010 = OpVariable %ptr_image_f32_2d_0010 UniformConstant -%type_sampled_image_f32_2d_0010 = OpTypeSampledImage %type_image_f32_2d_0010 - -%type_image_f32_3d_0010 = OpTypeImage %f32 3D 0 0 1 0 Unknown -%ptr_image_f32_3d_0010 = OpTypePointer UniformConstant %type_image_f32_3d_0010 -%uniform_image_f32_3d_0010 = OpVariable %ptr_image_f32_3d_0010 UniformConstant -%type_sampled_image_f32_3d_0010 = OpTypeSampledImage %type_image_f32_3d_0010 - -%type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown -%ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001 -%uniform_image_f32_rect_0001 = OpVariable %ptr_image_f32_rect_0001 UniformConstant -%type_sampled_image_f32_rect_0001 = OpTypeSampledImage %type_image_f32_rect_0001 - -%type_sampler = OpTypeSampler -%ptr_sampler = OpTypePointer UniformConstant %type_sampler -%uniform_sampler = OpVariable %ptr_sampler UniformConstant - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -std::string GetShaderHeader(const std::string& capabilities_and_extensions = "", - bool include_entry_point = true) { - std::ostringstream ss; - ss << R"( -OpCapability Shader -OpCapability Int64 -)"; - - ss << capabilities_and_extensions; - if (!include_entry_point) { - ss << "OpCapability Linkage"; - } - - ss << R"( -OpMemoryModel Logical GLSL450 -)"; - - if (include_entry_point) { - ss << "OpEntryPoint Fragment %main \"main\"\n"; - ss << "OpExecutionMode %main OriginUpperLeft"; - } - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%u64 = OpTypeInt 64 0 -%s32 = OpTypeInt 32 1 -)"; - - return ss.str(); -} - -TEST_F(ValidateImage, TypeImageWrongSampledType) { - const std::string code = GetShaderHeader("", false) + R"( -%img_type = OpTypeImage %bool 2D 0 0 0 1 Unknown -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sampled Type to be either void or " - "numerical scalar " - "type")); -} - -TEST_F(ValidateImage, TypeImageVoidSampledTypeVulkan) { - const std::string code = GetShaderHeader() + R"( -%img_type = OpTypeImage %void 2D 0 0 0 1 Unknown -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -OpReturn -OpFunctionEnd -)"; - - const spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(code, env); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sampled Type to be a 32-bit int " - "or float scalar type for Vulkan environment")); -} - -TEST_F(ValidateImage, TypeImageU64SampledTypeVulkan) { - const std::string code = GetShaderHeader() + R"( -%img_type = OpTypeImage %u64 2D 0 0 0 1 Unknown -%void_func = OpTypeFunction %void -%main = OpFunction %void None %void_func -%main_lab = OpLabel -OpReturn -OpFunctionEnd -)"; - - const spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(code, env); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sampled Type to be a 32-bit int " - "or float scalar type for Vulkan environment")); -} - -TEST_F(ValidateImage, TypeImageWrongDepth) { - const std::string code = GetShaderHeader("", false) + R"( -%img_type = OpTypeImage %f32 2D 3 0 0 1 Unknown -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid Depth 3 (must be 0, 1 or 2)")); -} - -TEST_F(ValidateImage, TypeImageWrongArrayed) { - const std::string code = GetShaderHeader("", false) + R"( -%img_type = OpTypeImage %f32 2D 0 2 0 1 Unknown -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid Arrayed 2 (must be 0 or 1)")); -} - -TEST_F(ValidateImage, TypeImageWrongMS) { - const std::string code = GetShaderHeader("", false) + R"( -%img_type = OpTypeImage %f32 2D 0 0 2 1 Unknown -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid MS 2 (must be 0 or 1)")); -} - -TEST_F(ValidateImage, TypeImageWrongSampled) { - const std::string code = GetShaderHeader("", false) + R"( -%img_type = OpTypeImage %f32 2D 0 0 0 3 Unknown -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid Sampled 3 (must be 0, 1 or 2)")); -} - -TEST_F(ValidateImage, TypeImageWrongSampledForSubpassData) { - const std::string code = - GetShaderHeader("OpCapability InputAttachment\n", false) + - R"( -%img_type = OpTypeImage %f32 SubpassData 0 0 0 1 Unknown -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Dim SubpassData requires Sampled to be 2")); -} - -TEST_F(ValidateImage, TypeImageWrongFormatForSubpassData) { - const std::string code = - GetShaderHeader("OpCapability InputAttachment\n", false) + - R"( -%img_type = OpTypeImage %f32 SubpassData 0 0 0 2 Rgba32f -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Dim SubpassData requires format Unknown")); -} - -TEST_F(ValidateImage, TypeSampledImageNotImage) { - const std::string code = GetShaderHeader("", false) + R"( -%simg_type = OpTypeSampledImage %f32 -)"; - - CompileSuccessfully(code.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, SampledImageSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampledImageVulkanSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -)"; - - const spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateImage, SampledImageWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_image_f32_2d_0001 %img %sampler -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampledImageNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg1 = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%simg2 = OpSampledImage %type_sampled_image_f32_2d_0001 %simg1 %sampler -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, SampledImageImageNotForSampling) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0002 %img %sampler -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled' parameter to be 0 or 1")); -} - -TEST_F(ValidateImage, SampledImageVulkanUnknownSampled) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0000 %img %sampler -)"; - - const spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled' parameter to " - "be 1 for Vulkan environment.")); -} - -TEST_F(ValidateImage, SampledImageNotSampler) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %img -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sampler to be of type OpTypeSampler")); -} - -TEST_F(ValidateImage, ImageTexelPointerSuccess) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ImageTexelPointerResultTypeNotPointer) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %type_image_u32_buffer_0002_r32ui %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypePointer")); -} - -TEST_F(ValidateImage, ImageTexelPointerResultTypeNotImageClass) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypePointer whose " - "Storage Class operand is Image")); -} - -TEST_F(ValidateImage, ImageTexelPointerResultTypeNotNumericNorVoid) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32arr4 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypePointer whose Type operand " - "must be a scalar numerical type or OpTypeVoid")); -} - -TEST_F(ValidateImage, ImageTexelPointerImageNotResultTypePointer) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %type_image_f32_buffer_0002_r32ui %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 140[%140] cannot be a " - "type")); -} - -TEST_F(ValidateImage, ImageTexelPointerImageNotImage) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_sampler %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image to be OpTypePointer with Type OpTypeImage")); -} - -TEST_F(ValidateImage, ImageTexelPointerImageSampledNotResultType) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_f32_cube_0101 %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as the " - "Type pointed to by Result Type")); -} - -TEST_F(ValidateImage, ImageTexelPointerImageDimSubpassDataBad) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_spd_0002 %u32_0 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Dim SubpassData cannot be used with OpImageTexelPointer")); -} - -TEST_F(ValidateImage, ImageTexelPointerImageCoordTypeBad) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32ui %f32_0 %f32_0 -%sum = OpAtomicIAdd %f32 %texel_ptr %f32_1 %f32_0 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be integer scalar or vector")); -} - -TEST_F(ValidateImage, ImageTexelPointerImageCoordSizeBad) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_u32_2d_0000 %u32vec3_012 %u32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Coordinate to have 2 components, but given 3")); -} - -TEST_F(ValidateImage, ImageTexelPointerSampleNotIntScalar) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %f32_0 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sample to be integer scalar")); -} - -TEST_F(ValidateImage, ImageTexelPointerSampleNotZeroForImageWithMSZero) { - const std::string body = R"( -%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_1 -%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sample for Image with MS 0 to be a valid " - " for the value 0")); -} - -TEST_F(ValidateImage, SampleImplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0_25 -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01 -%res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Offset %s32vec2_01 -%res6 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_5 -%res7 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 -%res8 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleImplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -TEST_F(ValidateImage, SampleImplicitLodWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec3 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, SampleImplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageSampleImplicitLod %f32vec4 %img %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleImplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, SampleImplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleImplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %img -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleImplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, SampleExplicitLodSuccessShader) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod %f32_1 -%res2 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_10 %f32vec2_01 -%res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01 -%res4 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01 -%res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset|MinLod %f32vec2_10 %f32vec2_01 %s32vec2_01 %f32_0_5 -%res6 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod|NonPrivateTexelKHR %f32_1 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleExplicitLodSuccessKernel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec4_0123 Lod %f32_1 -%res2 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Grad %f32vec2_10 %f32vec2_01 -%res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %u32vec2_01 -%res4 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Offset %u32vec2_01 -%res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset %f32vec2_10 %f32vec2_01 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleExplicitLodSuccessCubeArrayed) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleExplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32 %simg %f32vec2_hh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -TEST_F(ValidateImage, SampleExplicitLodWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec3 %simg %f32vec2_hh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, SampleExplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageSampleExplicitLod %f32vec4 %img %f32vec2_hh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleExplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, SampleExplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleExplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %img Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleExplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, SampleExplicitLodBias) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Bias|Lod %f32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand Bias can only be used with ImplicitLod opcodes")); -} - -TEST_F(ValidateImage, LodAndGrad) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|Grad %f32_1 %f32vec2_hh %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand bits Lod and Grad cannot be set at the same time")); -} - -TEST_F(ValidateImage, ImplicitLodWithLod) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image Operand Lod can only be used with ExplicitLod opcodes " - "and OpImageFetch")); -} - -TEST_F(ValidateImage, LodWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32vec2_hh)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand Lod to be float scalar when " - "used with ExplicitLod")); -} - -TEST_F(ValidateImage, LodWrongDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand Lod requires 'Dim' parameter to be 1D, " - "2D, 3D or Cube")); -} - -TEST_F(ValidateImage, LodMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0010 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand Lod requires 'MS' parameter to be 0")); -} - -TEST_F(ValidateImage, MinLodIncompatible) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|MinLod %f32_0 %f32_0)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand MinLod can only be used with ImplicitLod opcodes or " - "together with Image Operand Grad")); -} - -TEST_F(ValidateImage, ImplicitLodWithGrad) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_hh %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand Grad can only be used with ExplicitLod opcodes")); -} - -TEST_F(ValidateImage, SampleImplicitLod3DArrayedMultisampledSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012 -%res3 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleImplicitLodCubeArrayedSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25 -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_5 -%res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias|MinLod %f32_0_25 %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleImplicitLodBiasWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand Bias to be float scalar")); -} - -TEST_F(ValidateImage, SampleImplicitLodBiasWrongDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand Bias requires 'Dim' parameter to be 1D, " - "2D, 3D or Cube")); -} - -TEST_F(ValidateImage, SampleImplicitLodBiasMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand Bias requires 'MS' parameter to be 0")); -} - -TEST_F(ValidateImage, SampleExplicitLodGradDxWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %s32vec3_012 %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both Image Operand Grad ids to be float " - "scalars or vectors")); -} - -TEST_F(ValidateImage, SampleExplicitLodGradDyWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %s32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both Image Operand Grad ids to be float " - "scalars or vectors")); -} - -TEST_F(ValidateImage, SampleExplicitLodGradDxWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec2_00 %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image Operand Grad dx to have 3 components, but given 2")); -} - -TEST_F(ValidateImage, SampleExplicitLodGradDyWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec2_00 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image Operand Grad dy to have 3 components, but given 2")); -} - -TEST_F(ValidateImage, SampleExplicitLodGradMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_000 %f32vec3_000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand Grad requires 'MS' parameter to be 0")); -} - -TEST_F(ValidateImage, SampleImplicitLodConstOffsetCubeDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand ConstOffset cannot be used with Cube Image 'Dim'")); -} - -TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %f32vec3_000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image Operand ConstOffset to be int scalar or vector")); -} - -TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand ConstOffset to have 3 " - "components, but given 2")); -} - -TEST_F(ValidateImage, SampleImplicitLodConstOffsetNotConst) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%offset = OpSNegate %s32vec3 %s32vec3_012 -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %offset -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image Operand ConstOffset to be a const object")); -} - -TEST_F(ValidateImage, SampleImplicitLodOffsetCubeDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image Operand Offset cannot be used with Cube Image 'Dim'")); -} - -TEST_F(ValidateImage, SampleImplicitLodOffsetWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %f32vec3_000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image Operand Offset to be int scalar or vector")); -} - -TEST_F(ValidateImage, SampleImplicitLodOffsetWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image Operand Offset to have 3 components, but given 2")); -} - -TEST_F(ValidateImage, SampleImplicitLodMoreThanOneOffset) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec3_012 %s32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets " - "cannot be used together")); -} - -TEST_F(ValidateImage, SampleImplicitLodMinLodWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %s32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand MinLod to be float scalar")); -} - -TEST_F(ValidateImage, SampleImplicitLodMinLodWrongDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_25 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand MinLod requires 'Dim' parameter to be " - "1D, 2D, 3D or Cube")); -} - -TEST_F(ValidateImage, SampleImplicitLodMinLodMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_25 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image Operand MinLod requires 'MS' parameter to be 0")); -} - -TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod %f32_1 -%res3 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01 -%res4 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01 -%res5 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01 -%res7 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01 -%res8 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod|NonPrivateTexelKHR %f32_1 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleProjExplicitLodSuccessRect) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01 -%res2 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleProjExplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %f32 %simg %f32vec3_hhh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -TEST_F(ValidateImage, SampleProjExplicitLodWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %f32vec3 %simg %f32vec3_hhh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, SampleProjExplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageSampleProjExplicitLod %f32vec4 %img %f32vec3_hhh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleProjExplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, SampleProjExplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleProjExplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %img Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleProjExplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 3 components, " - "but given only 2")); -} - -TEST_F(ValidateImage, SampleProjImplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh -%res2 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias %f32_0_25 -%res4 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01 -%res5 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01 -%res6 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh MinLod %f32_0_5 -%res7 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 -%res8 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleProjImplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %f32 %simg %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -TEST_F(ValidateImage, SampleProjImplicitLodWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %f32vec3 %simg %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, SampleProjImplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageSampleProjImplicitLod %f32vec4 %img %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleProjImplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, SampleProjImplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleProjImplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %img -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleProjImplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 3 components, " - "but given only 2")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 -%res2 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25 -%res4 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01 -%res5 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01 -%res6 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5 -%res7 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 -%res8 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %void %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%res1 = OpImageSampleDrefImplicitLod %u32 %img %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_00 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %u32 %simg %img %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32_0_5 %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, SampleDrefImplicitLodWrongDrefType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler -%res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Dref to be of 32-bit float type")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod %f32_1 -%res3 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad %f32vec3_hhh %f32vec3_hhh -%res4 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 ConstOffset %s32vec3_012 -%res5 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Offset %s32vec3_012 -%res7 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad|Offset %f32vec3_hhh %f32vec3_hhh %s32vec3_012 -%res8 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod|NonPrivateTexelKHR %f32_1 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %bool %simg %f32vec3_hhh %s32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%res1 = OpImageSampleDrefExplicitLod %s32 %img %f32vec3_hhh %s32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec3_hhh %s32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %u32 %simg %f32vec2_00 %s32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %s32 %simg %img %s32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec2_hh %s32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 3 components, " - "but given only 2")); -} - -TEST_F(ValidateImage, SampleDrefExplicitLodWrongDrefType) { - const std::string body = R"( -%img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler -%res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %u32_1 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Dref to be of 32-bit float type")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 -%res2 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias %f32_0_25 -%res4 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 ConstOffset %s32vec2_01 -%res5 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Offset %s32vec2_01 -%res6 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 MinLod %f32_0_5 -%res7 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 -%res8 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %void %simg %f32vec3_hhh %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageSampleProjDrefImplicitLod %f32 %img %f32vec3_hhh %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %img %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec2_hh %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 3 components, " - "but given only 2")); -} - -TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongDrefType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Dref to be of 32-bit float type")); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler -%res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1 -%res2 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Grad %f32_0_5 %f32_0_5 -%res3 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 ConstOffset %s32_1 -%res4 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Offset %s32_1 -%res5 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Grad|Offset %f32_0_5 %f32_0_5 %s32_1 -%res6 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod|NonPrivateTexelKHR %f32_1 -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler -%res1 = OpImageSampleProjDrefExplicitLod %bool %simg %f32vec2_hh %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float scalar type")); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%res1 = OpImageSampleProjDrefExplicitLod %f32 %img %f32vec2_hh %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler -%res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec3_hhh %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type")); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler -%res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %img %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler -%res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32_0_5 %f32_0_5 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, FetchSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%res1 = OpImageFetch %f32vec4 %img %u32vec2_01 -%res2 = OpImageFetch %f32vec4 %img %u32vec2_01 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, FetchWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageFetch %f32 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -TEST_F(ValidateImage, FetchWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageFetch %f32vec3 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, FetchNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, FetchSampledImageDirectly) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageFetch %f32vec4 %simg %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSampledImage instruction must not appear as operand " - "for OpImageFetch")); -} - -TEST_F(ValidateImage, FetchNotSampled) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageFetch %u32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled' parameter to be 1")); -} - -TEST_F(ValidateImage, FetchCube) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%res1 = OpImageFetch %f32vec4 %img %u32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' cannot be Cube")); -} - -TEST_F(ValidateImage, FetchWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageFetch %u32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, FetchVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%res1 = OpImageFetch %f32vec4 %img %u32vec2_01 -%res2 = OpImageFetch %u32vec4 %img %u32vec2_01 -%res3 = OpImageFetch %s32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, FetchWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageFetch %f32vec4 %img %f32vec2_00 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be int scalar or vector")); -} - -TEST_F(ValidateImage, FetchCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageFetch %f32vec4 %img %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, FetchLodNotInt) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Lod %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand Lod to be int scalar when used " - "with OpImageFetch")); -} - -TEST_F(ValidateImage, GatherSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 -%res2 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets -%res3 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, GatherWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32 %simg %f32vec4_0000 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -TEST_F(ValidateImage, GatherWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32vec3 %simg %f32vec4_0000 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, GatherNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%res1 = OpImageGather %f32vec4 %img %f32vec4_0000 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, GatherWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %u32vec4 %simg %f32vec4_0000 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, GatherVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageGather %u32vec4 %simg %f32vec2_00 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, GatherWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %u32vec4_0123 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, GatherCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32_0_5 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 4 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, GatherWrongComponentType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Component to be 32-bit int scalar")); -} - -TEST_F(ValidateImage, GatherComponentNot32Bit) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u64_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Component to be 32-bit int scalar")); -} - -TEST_F(ValidateImage, GatherDimCube) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand ConstOffsets cannot be used with Cube Image 'Dim'")); -} - -TEST_F(ValidateImage, GatherConstOffsetsNotArray) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image Operand ConstOffsets to be an array of size 4")); -} - -TEST_F(ValidateImage, GatherConstOffsetsArrayWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets3x2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image Operand ConstOffsets to be an array of size 4")); -} - -TEST_F(ValidateImage, GatherConstOffsetsArrayNotVector) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4xu -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand ConstOffsets array componenets " - "to be int vectors of size 2")); -} - -TEST_F(ValidateImage, GatherConstOffsetsArrayVectorWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4x3 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand ConstOffsets array componenets " - "to be int vectors of size 2")); -} - -TEST_F(ValidateImage, GatherConstOffsetsArrayNotConst) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%offsets = OpUndef %u32vec2arr4 -%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %offsets -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image Operand ConstOffsets to be a const object")); -} - -TEST_F(ValidateImage, NotGatherWithConstOffsets) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffsets %const_offsets -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Image Operand ConstOffsets can only be used with OpImageGather " - "and OpImageDrefGather")); -} - -TEST_F(ValidateImage, DrefGatherSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 -%res2 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 ConstOffsets %const_offsets -%res3 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, DrefGatherVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler -%res1 = OpImageDrefGather %u32vec4 %simg %f32vec2_00 %f32_0_5 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, DrefGatherWrongDrefType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler -%res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Dref to be of 32-bit float type")); -} - -TEST_F(ValidateImage, ReadSuccess1) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ReadSuccess2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability Image1D\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ReadSuccess3) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f -%res1 = OpImageRead %f32vec4 %img %u32vec3_012 -)"; - - const std::string extra = "\nOpCapability ImageCubeArray\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ReadSuccess4) { - const std::string body = R"( -%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002 -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormat) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 -)"; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(), - env); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability StorageImageReadWithoutFormat is required " - "to read storage image")); -} - -TEST_F(ValidateImage, ReadNeedCapabilityImage1D) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Capability Image1D is required to access storage image")); -} - -TEST_F(ValidateImage, ReadNeedCapabilityImageCubeArray) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f -%res1 = OpImageRead %f32vec4 %img %u32vec3_012 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability ImageCubeArray is required to access storage image")); -} - -// TODO(atgoo@github.com) Disabled until the spec is clarified. -TEST_F(ValidateImage, DISABLED_ReadWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %f32 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int or float vector type")); -} - -// TODO(atgoo@github.com) Disabled until the spec is clarified. -TEST_F(ValidateImage, DISABLED_ReadWrongNumComponentsResultType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %f32vec3 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 4 components")); -} - -TEST_F(ValidateImage, ReadNotImage) { - const std::string body = R"( -%sampler = OpLoad %type_sampler %uniform_sampler -%res1 = OpImageRead %f32vec4 %sampler %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, ReadImageSampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2")); -} - -TEST_F(ValidateImage, ReadWrongSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type components")); -} - -TEST_F(ValidateImage, ReadVoidSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_void_2d_0002 %uniform_image_void_2d_0002 -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -%res2 = OpImageRead %u32vec4 %img %u32vec2_01 -%res3 = OpImageRead %s32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ReadWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %f32vec2_00 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be int scalar or vector")); -} - -TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32_1 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, WriteSuccess1) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, WriteSuccess2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f -OpImageWrite %img %u32_1 %f32vec4_0000 -)"; - - const std::string extra = "\nOpCapability Image1D\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, WriteSuccess3) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f -OpImageWrite %img %u32vec3_012 %f32vec4_0000 -)"; - - const std::string extra = "\nOpCapability ImageCubeArray\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, WriteSuccess4) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -;TODO(atgoo@github.com) Is it legal to write to MS image without sample index? -OpImageWrite %img %u32vec2_01 %f32vec4_0000 -OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, WriteSubpassData) { - const std::string body = R"( -%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002 -OpImageWrite %img %u32vec2_01 %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image 'Dim' cannot be SubpassData")); -} - -TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormat) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 -)"; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(), - env); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability StorageImageWriteWithoutFormat is required to write to " - "storage image")); -} - -TEST_F(ValidateImage, WriteNeedCapabilityImage1D) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f -OpImageWrite %img %u32vec2_01 %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Capability Image1D is required to access storage " - "image")); -} - -TEST_F(ValidateImage, WriteNeedCapabilityImageCubeArray) { - const std::string body = R"( -%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f -OpImageWrite %img %u32vec3_012 %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Capability ImageCubeArray is required to access storage image")); -} - -TEST_F(ValidateImage, WriteNotImage) { - const std::string body = R"( -%sampler = OpLoad %type_sampler %uniform_sampler -OpImageWrite %sampler %u32vec2_01 %f32vec4_0000 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, WriteImageSampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -OpImageWrite %img %u32vec2_01 %f32vec4_0000 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2")); -} - -TEST_F(ValidateImage, WriteWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %f32vec2_00 %u32vec4_0123 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be int scalar or vector")); -} - -TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32_1 %u32vec4_0123 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, WriteTexelWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %img -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Texel to be int or float vector or scalar")); -} - -TEST_F(ValidateImage, DISABLED_WriteTexelNotVector4) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec3_012 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Texel to have 4 components")); -} - -TEST_F(ValidateImage, WriteTexelWrongComponentType) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %f32vec4_0000 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected Image 'Sampled Type' to be the same as Texel components")); -} - -TEST_F(ValidateImage, WriteSampleNotInteger) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image Operand Sample to be int scalar")); -} - -TEST_F(ValidateImage, SampleNotMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1 -)"; - - const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image Operand Sample requires non-zero 'MS' parameter")); -} - -TEST_F(ValidateImage, SampleWrongOpcode) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0010 %img %sampler -%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Sample %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand Sample can only be used with " - "OpImageFetch, OpImageRead, OpImageWrite, " - "OpImageSparseFetch and OpImageSparseRead")); -} - -TEST_F(ValidateImage, SampleImageToImageSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%img2 = OpImage %type_image_f32_2d_0001 %simg -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SampleImageToImageWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%img2 = OpImage %type_sampled_image_f32_2d_0001 %simg -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeImage")); -} - -TEST_F(ValidateImage, SampleImageToImageNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%img2 = OpImage %type_image_f32_2d_0001 %img -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Sample Image to be of type OpTypeSampleImage")); -} - -TEST_F(ValidateImage, SampleImageToImageNotTheSameImageType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%img2 = OpImage %type_image_f32_2d_0002 %simg -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Sample Image image type to be equal to " - "Result Type")); -} - -TEST_F(ValidateImage, QueryFormatSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryFormat %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QueryFormatWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryFormat %bool %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int scalar type")); -} - -TEST_F(ValidateImage, QueryFormatNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryFormat %u32 %sampler -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected operand to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, QueryOrderSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryOrder %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QueryOrderWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryOrder %bool %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int scalar type")); -} - -TEST_F(ValidateImage, QueryOrderNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryOrder %u32 %sampler -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected operand to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, QuerySizeLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QuerySizeLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQuerySizeLod %f32vec2 %img %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be int scalar or vector type")); -} - -TEST_F(ValidateImage, QuerySizeLodResultTypeWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQuerySizeLod %u32 %img %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result Type has 1 components, but 2 expected")); -} - -TEST_F(ValidateImage, QuerySizeLodNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSampledImage instruction must not appear as operand " - "for OpImageQuerySizeLod")); -} - -TEST_F(ValidateImage, QuerySizeLodWrongImageDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube")); -} - -TEST_F(ValidateImage, QuerySizeLodMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0")); -} - -TEST_F(ValidateImage, QuerySizeLodWrongLodType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQuerySizeLod %u32vec2 %img %f32_0 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Level of Detail to be int scalar")); -} - -TEST_F(ValidateImage, QuerySizeSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%res1 = OpImageQuerySize %u32vec2 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QuerySizeWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%res1 = OpImageQuerySize %f32vec2 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be int scalar or vector type")); -} - -TEST_F(ValidateImage, QuerySizeNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQuerySize %u32vec2 %sampler -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, QuerySizeSampledImageDirectly) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQuerySize %u32vec2 %simg -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSampledImage instruction must not appear as operand " - "for OpImageQuerySize")); -} - -TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) { - const std::string body = R"( -%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002 -%res1 = OpImageQuerySize %u32vec2 %img -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect")); -} - -TEST_F(ValidateImage, QuerySizeWrongSampling) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQuerySize %u32vec2 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2")); -} - -TEST_F(ValidateImage, QuerySizeWrongNumberOfComponents) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111 -%res1 = OpImageQuerySize %u32vec2 %img -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result Type has 2 components, but 4 expected")); -} - -TEST_F(ValidateImage, QueryLodSuccessKernel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -%res2 = OpImageQueryLod %f32vec2 %simg %u32vec2_01 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QueryLodSuccessShader) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QueryLodWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %u32vec2 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be float vector type")); -} - -TEST_F(ValidateImage, QueryLodResultTypeWrongSize) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec3 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to have 2 components")); -} - -TEST_F(ValidateImage, QueryLodNotSampledImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryLod %f32vec2 %img %f32vec2_hh -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Image operand to be of type OpTypeSampledImage")); -} - -TEST_F(ValidateImage, QueryLodWrongDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube")); -} - -TEST_F(ValidateImage, QueryLodWrongCoordinateType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to be float scalar or vector")); -} - -TEST_F(ValidateImage, QueryLodCoordinateSizeTooSmall) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Coordinate to have at least 2 components, " - "but given only 1")); -} - -TEST_F(ValidateImage, QueryLevelsSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryLevels %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QueryLevelsWrongResultType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQueryLevels %f32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be int scalar type")); -} - -TEST_F(ValidateImage, QueryLevelsNotImage) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLevels %u32 %sampler -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image to be of type OpTypeImage")); -} - -TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLevels %u32 %simg -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSampledImage instruction must not appear as operand " - "for OpImageQueryLevels")); -} - -TEST_F(ValidateImage, QueryLevelsWrongDim) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageQueryLevels %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube")); -} - -TEST_F(ValidateImage, QuerySamplesSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010 -%res1 = OpImageQuerySamples %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QuerySamplesNot2D) { - const std::string body = R"( -%img = OpLoad %type_image_f32_3d_0010 %uniform_image_f32_3d_0010 -%res1 = OpImageQuerySamples %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' must be 2D")); -} - -TEST_F(ValidateImage, QuerySamplesNotMultisampled) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%res1 = OpImageQuerySamples %u32 %img -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 1")); -} - -TEST_F(ValidateImage, QueryLodWrongExecutionModel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpImageQueryLod requires Fragment or GLCompute execution model")); -} - -TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) { - const std::string body = R"( -%call_ret = OpFunctionCall %void %my_func -OpReturn -OpFunctionEnd -%my_func = OpFunction %void None %func -%my_func_entry = OpLabel -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpImageQueryLod requires Fragment or GLCompute execution model")); -} - -TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -)"; - - const std::string extra = R"( -OpCapability ComputeDerivativeGroupLinearNV -OpExtension "SPV_NV_compute_shader_derivatives" -)"; - const std::string mode = R"( -OpExecutionMode %main LocalSize 8 8 1 -OpExecutionMode %main DerivativeGroupLinearNV -)"; - CompileSuccessfully( - GenerateShaderCode(body, extra, "GLCompute", mode).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh -)"; - - const std::string extra = R"( -OpCapability ComputeDerivativeGroupLinearNV -OpExtension "SPV_NV_compute_shader_derivatives" -)"; - const std::string mode = R"( -OpExecutionMode %main LocalSize 8 8 1 -)"; - CompileSuccessfully( - GenerateShaderCode(body, extra, "GLCompute", mode).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or " - "DerivativeGroupLinearNV execution mode for GLCompute " - "execution model")); -} - -TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("ImplicitLod instructions require Fragment or " - "GLCompute execution model")); -} - -TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh -)"; - - const std::string extra = R"( -OpCapability ComputeDerivativeGroupLinearNV -OpExtension "SPV_NV_compute_shader_derivatives" -)"; - const std::string mode = R"( -OpExecutionMode %main LocalSize 8 8 1 -OpExecutionMode %main DerivativeGroupLinearNV -)"; - CompileSuccessfully( - GenerateShaderCode(body, extra, "GLCompute", mode).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh -)"; - - const std::string extra = R"( -OpCapability ComputeDerivativeGroupLinearNV -OpExtension "SPV_NV_compute_shader_derivatives" -)"; - const std::string mode = R"( -OpExecutionMode %main LocalSize 8 8 1 -)"; - CompileSuccessfully( - GenerateShaderCode(body, extra, "GLCompute", mode).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or " - "DerivativeGroupLinearNV execution mode for GLCompute " - "execution model")); -} - -TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002 -%res1 = OpImageRead %f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Vertex").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Dim SubpassData requires Fragment execution model")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh -%res2 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Bias %f32_0_25 -%res4 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01 -%res5 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Offset %s32vec2_01 -%res6 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh MinLod %f32_0_5 -%res7 = OpImageSparseSampleImplicitLod %struct_u64_f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 -%res8 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotStruct) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %f32 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeStruct")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers1) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_u32 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an int " - "scalar and a texel")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4_u32 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeFirstMemberNotInt) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_f32_f32vec4 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeTexelNotVector) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_u32_u32 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to be int or " - "float vector type")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodWrongNumComponentsTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec3 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to have 4 " - "components")); -} - -TEST_F(ValidateImage, SparseSampleImplicitLodWrongComponentTypeTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleImplicitLod %struct_u32_u32vec4 %simg %f32vec2_hh -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type's second member components")); -} - -TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 -%res2 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25 -%res4 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01 -%res5 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01 -%res6 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5 -%res7 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 -%res8 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotStruct) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeStruct")); -} - -TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers1) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleDrefImplicitLod %struct_u32 %simg %f32vec2_hh %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an int scalar " - "and a texel")); -} - -TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_f32_u32 %simg %f32vec2_hh %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an int scalar " - "and a texel")); -} - -TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleDrefImplicitLod %struct_f32_f32 %simg %f32vec2_hh %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an int scalar " - "and a texel")); -} - -TEST_F(ValidateImage, SparseSampleDrefImplicitLodDifferentSampledType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type's second member")); -} - -TEST_F(ValidateImage, SparseFetchSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 -%res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 -%res2 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SparseFetchResultTypeNotStruct) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %f32 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeStruct")); -} - -TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers1) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %struct_u32 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %struct_u32_f32vec4_u32 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseFetchResultTypeFirstMemberNotInt) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %struct_f32_f32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseFetchResultTypeTexelNotVector) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %struct_u32_u32 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to be int or " - "float vector type")); -} - -TEST_F(ValidateImage, SparseFetchWrongNumComponentsTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %struct_u32_f32vec3 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to have 4 " - "components")); -} - -TEST_F(ValidateImage, SparseFetchWrongComponentTypeTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 -%res1 = OpImageSparseFetch %struct_u32_u32vec4 %img %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type's second member components")); -} - -TEST_F(ValidateImage, SparseReadSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SparseReadResultTypeNotStruct) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %f32 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeStruct")); -} - -TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers1) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_u32 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_u32_f32vec4_u32 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseReadResultTypeFirstMemberNotInt) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_f32_f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseReadResultTypeTexelWrongType) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_u32_u32arr4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to be int or " - "float scalar or vector type")); -} - -TEST_F(ValidateImage, SparseReadWrongComponentTypeTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_u32_u32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type's second member components")); -} - -TEST_F(ValidateImage, SparseReadSubpassDataNotAllowed) { - const std::string body = R"( -%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002 -%res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 -)"; - - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment").c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image Dim SubpassData cannot be used with ImageSparseRead")); -} - -TEST_F(ValidateImage, SparseGatherSuccess) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 -%res2 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR -)"; - - const std::string extra = R"( -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, SparseGatherResultTypeNotStruct) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %f32 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be OpTypeStruct")); -} - -TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers1) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_u32 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an int " - "scalar and a texel")); -} - -TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers2) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_u32_f32vec4_u32 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an int " - "scalar and a texel")); -} - -TEST_F(ValidateImage, SparseGatherResultTypeFirstMemberNotInt) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_f32_f32vec4 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be a struct containing an " - "int scalar and a texel")); -} - -TEST_F(ValidateImage, SparseGatherResultTypeTexelNotVector) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_u32_u32 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to be int or " - "float vector type")); -} - -TEST_F(ValidateImage, SparseGatherWrongNumComponentsTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_u32_f32vec3 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type's second member to have 4 " - "components")); -} - -TEST_F(ValidateImage, SparseGatherWrongComponentTypeTexel) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSparseGather %struct_u32_u32vec4 %simg %f32vec2_hh %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Image 'Sampled Type' to be the same as " - "Result Type's second member components")); -} - -TEST_F(ValidateImage, SparseTexelsResidentSuccess) { - const std::string body = R"( -%res1 = OpImageSparseTexelsResident %bool %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateImage, SparseTexelsResidentResultTypeNotBool) { - const std::string body = R"( -%res1 = OpImageSparseTexelsResident %u32 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected Result Type to be bool scalar type")); -} - -TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageSparseRead) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002 -%res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, MakeTexelVisibleKHRFailureOpcode) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Image Operand MakeTexelVisibleKHR can only be used with " - "OpImageRead or OpImageSparseRead: OpImageSampleImplicitLod")); -} - -TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand MakeTexelVisibleKHR requires " - "NonPrivateTexelKHR is also specified: OpImageRead")); -} - -TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_2 -)"; - - const std::string extra = R"( -OpCapability StorageImageWriteWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, MakeTexelAvailableKHRFailureOpcode) { - const std::string body = R"( -%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001 -%sampler = OpLoad %type_sampler %uniform_sampler -%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler -%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand MakeTexelAvailableKHR can only be used " - "with OpImageWrite: OpImageSampleImplicitLod")); -} - -TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageWriteWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Image Operand MakeTexelAvailableKHR requires " - "NonPrivateTexelKHR is also specified: OpImageWrite")); -} - -TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteBad) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageWriteWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteGood) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageWriteWithoutFormat -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadBad) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadGood) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1 -)"; - - const std::string extra = R"( -OpCapability StorageImageReadWithoutFormat -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpExtension "SPV_KHR_vulkan_memory_model" -)"; - CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", - SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") - .c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -// This example used to cause a seg fault on OpReturnValue, verifying it doesn't -// anymore. -TEST_F(ValidateImage, Issue2463NoSegFault) { - const std::string spirv = R"( - OpCapability Linkage - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - %void = OpTypeVoid - %6 = OpTypeFunction %void - %float = OpTypeFloat 32 - %8 = OpTypeImage %float 3D 0 0 0 1 Unknown -%_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8 - %10 = OpTypeSampler -%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 - %12 = OpTypeSampledImage %8 - %13 = OpTypeFunction %12 %_ptr_UniformConstant_8 %_ptr_UniformConstant_10 - %23 = OpFunction %12 None %13 - %24 = OpFunctionParameter %_ptr_UniformConstant_8 - %25 = OpFunctionParameter %_ptr_UniformConstant_10 - %26 = OpLabel - %27 = OpLoad %8 %24 - %28 = OpLoad %10 %25 - %29 = OpSampledImage %12 %27 %28 - OpReturnValue %29 - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpSampledImage instruction must not appear as operand " - "for OpReturnValue")); -} - -TEST_F(ValidateImage, SignExtendV13Bad) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend -)"; - - EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "", - SPV_ENV_UNIVERSAL_1_3)), - HasSubstr("Invalid image operand 'SignExtend'")); -} - -TEST_F(ValidateImage, ZeroExtendV13Bad) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend -)"; - - EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "", - SPV_ENV_UNIVERSAL_1_3)), - HasSubstr("Invalid image operand 'ZeroExtend'")); -} - -TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) { - // Unsigned int sampled type - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32 %img %u32vec2_01 SignExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) { - // Signed int sampled type - const std::string body = R"( -%img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002 -%res1 = OpImageRead %s32 %img %u32vec2_01 SignExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) { - const std::string body = R"( -%img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002 -%res1 = OpImageRead %s32vec4 %img %u32vec2_01 SignExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -// No negative tests for SignExtend since we don't truly know the -// texel format. - -TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) { - // Unsigned int sampled type - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32 %img %u32vec2_01 ZeroExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) { - // Zeroed int sampled type - const std::string body = R"( -%img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002 -%res1 = OpImageRead %s32 %img %u32vec2_01 ZeroExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) { - const std::string body = R"( -%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 -%res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) { - const std::string body = R"( -%img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002 -%res1 = OpImageRead %s32vec4 %img %u32vec2_01 ZeroExtend -)"; - const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n"; - - CompileSuccessfully( - GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4), - SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -// No negative tests for ZeroExtend since we don't truly know the -// texel format. - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_interfaces_test.cpp b/3rdparty/spirv-tools/test/val/val_interfaces_test.cpp deleted file mode 100644 index 3410616dd..000000000 --- a/3rdparty/spirv-tools/test/val/val_interfaces_test.cpp +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; - -using ValidateInterfacesTest = spvtest::ValidateBase; - -TEST_F(ValidateInterfacesTest, EntryPointMissingInput) { - std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Input %3 -%5 = OpVariable %4 Input -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -%8 = OpLoad %3 %5 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Interface variable id <5> is used by entry point 'func' id <1>, " - "but is not listed as an interface")); -} - -TEST_F(ValidateInterfacesTest, EntryPointMissingOutput) { - std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Output %3 -%5 = OpVariable %4 Output -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -%8 = OpLoad %3 %5 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Interface variable id <5> is used by entry point 'func' id <1>, " - "but is not listed as an interface")); -} - -TEST_F(ValidateInterfacesTest, InterfaceMissingUseInSubfunction) { - std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Input %3 -%5 = OpVariable %4 Input -%6 = OpTypeFunction %2 -%1 = OpFunction %2 None %6 -%7 = OpLabel -%8 = OpFunctionCall %2 %9 -OpReturn -OpFunctionEnd -%9 = OpFunction %2 None %6 -%10 = OpLabel -%11 = OpLoad %3 %5 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Interface variable id <5> is used by entry point 'func' id <1>, " - "but is not listed as an interface")); -} - -TEST_F(ValidateInterfacesTest, TwoEntryPointsOneFunction) { - std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" %2 -OpEntryPoint Fragment %1 "func2" -OpExecutionMode %1 OriginUpperLeft -%3 = OpTypeVoid -%4 = OpTypeInt 32 0 -%5 = OpTypePointer Input %4 -%2 = OpVariable %5 Input -%6 = OpTypeFunction %3 -%1 = OpFunction %3 None %6 -%7 = OpLabel -%8 = OpLoad %4 %2 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Interface variable id <2> is used by entry point 'func2' id <1>, " - "but is not listed as an interface")); -} - -TEST_F(ValidateInterfacesTest, MissingInterfaceThroughInitializer) { - const std::string text = R"( -OpCapability Shader -OpCapability VariablePointers -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %1 "func" -OpExecutionMode %1 OriginUpperLeft -%2 = OpTypeVoid -%3 = OpTypeInt 32 0 -%4 = OpTypePointer Input %3 -%5 = OpTypePointer Function %4 -%6 = OpVariable %4 Input -%7 = OpTypeFunction %2 -%1 = OpFunction %2 None %7 -%8 = OpLabel -%9 = OpVariable %5 Function %6 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Interface variable id <6> is used by entry point 'func' id <1>, " - "but is not listed as an interface")); -} - -TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p3) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %var %var -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer Input %struct -%var = OpVariable %ptr_struct Input -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p4) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %var %var -OpExecutionMode %main LocalSize 1 1 1 -OpName %main "main" -OpName %var "var" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer Input %struct -%var = OpVariable %ptr_struct Input -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Non-unique OpEntryPoint interface 2[%var] is disallowed")); -} - -TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p3) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_struct StorageBuffer -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %struct %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p4) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpName %var "var" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_struct StorageBuffer -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %struct %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Interface variable id <2> is used by entry point " - "'main' id <1>, but is not listed as an interface")); -} - -TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p3) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %var -OpExecutionMode %main LocalSize 1 1 1 -OpName %var "var" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer Function %struct -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -%var = OpVariable %ptr_struct Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpEntryPoint interfaces must be OpVariables with " - "Storage Class of Input(1) or Output(3). Found Storage " - "Class 7 for Entry Point id 1.")); -} - -TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p4) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %var -OpExecutionMode %main LocalSize 1 1 1 -OpName %var "var" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer Function %struct -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -%var = OpVariable %ptr_struct Function -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpEntryPoint interfaces should only list global variables")); -} - -TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_NotAllUsedGlobals) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpName %var "var" -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint3 = OpTypeVector %uint 3 -%struct = OpTypeStruct %uint3 -%ptr_struct = OpTypePointer StorageBuffer %struct -%var = OpVariable %ptr_struct StorageBuffer -%func_ty = OpTypeFunction %void -%main = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %struct %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_DuplicateInterface) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %gid %gid -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %gid BuiltIn GlobalInvocationId -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int3 = OpTypeVector %int 3 -%ptr_input_int3 = OpTypePointer Input %int3 -%gid = OpVariable %ptr_input_int3 Input -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateInterfacesTest, SPV14MultipleEntryPointsSameFunction) { - const std::string text = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main1" %gid -OpEntryPoint GLCompute %main "main2" %gid -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %gid BuiltIn GlobalInvocationId -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int3 = OpTypeVector %int 3 -%ptr_input_int3 = OpTypePointer Input %int3 -%gid = OpVariable %ptr_input_int3 Input -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_layout_test.cpp b/3rdparty/spirv-tools/test/val/val_layout_test.cpp deleted file mode 100644 index 9d4491c37..000000000 --- a/3rdparty/spirv-tools/test/val/val_layout_test.cpp +++ /dev/null @@ -1,706 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Validation tests for Logical Layout - -#include -#include -#include -#include -#include -#include -#include - -#include "gmock/gmock.h" -#include "source/diagnostic.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::StrEq; - -using pred_type = std::function; -using ValidateLayout = spvtest::ValidateBase< - std::tuple>>; - -// returns true if order is equal to VAL -template -spv_result_t Equals(int order) { - return order == VAL ? SPV_SUCCESS : RET; -} - -// returns true if order is between MIN and MAX(inclusive) -template -struct Range { - explicit Range(bool inverse = false) : inverse_(inverse) {} - spv_result_t operator()(int order) { - return (inverse_ ^ (order >= MIN && order <= MAX)) ? SPV_SUCCESS : RET; - } - - private: - bool inverse_; -}; - -template -spv_result_t InvalidSet(int order) { - for (spv_result_t val : {T(true)(order)...}) - if (val != SPV_SUCCESS) return val; - return SPV_SUCCESS; -} - -// SPIRV source used to test the logical layout -const std::vector& getInstructions() { - // clang-format off - static const std::vector instructions = { - "OpCapability Shader", - "OpExtension \"TestExtension\"", - "%inst = OpExtInstImport \"GLSL.std.450\"", - "OpMemoryModel Logical GLSL450", - "OpEntryPoint GLCompute %func \"\"", - "OpExecutionMode %func LocalSize 1 1 1", - "OpExecutionModeId %func LocalSizeId %one %one %one", - "%str = OpString \"Test String\"", - "%str2 = OpString \"blabla\"", - "OpSource GLSL 450 %str \"uniform vec3 var = vec3(4.0);\"", - "OpSourceContinued \"void main(){return;}\"", - "OpSourceExtension \"Test extension\"", - "OpName %func \"MyFunction\"", - "OpMemberName %struct 1 \"my_member\"", - "OpDecorate %dgrp RowMajor", - "OpMemberDecorate %struct 1 RowMajor", - "%dgrp = OpDecorationGroup", - "OpGroupDecorate %dgrp %mat33 %mat44", - "%intt = OpTypeInt 32 1", - "%floatt = OpTypeFloat 32", - "%voidt = OpTypeVoid", - "%boolt = OpTypeBool", - "%vec4 = OpTypeVector %floatt 4", - "%vec3 = OpTypeVector %floatt 3", - "%mat33 = OpTypeMatrix %vec3 3", - "%mat44 = OpTypeMatrix %vec4 4", - "%struct = OpTypeStruct %intt %mat33", - "%vfunct = OpTypeFunction %voidt", - "%viifunct = OpTypeFunction %voidt %intt %intt", - "%one = OpConstant %intt 1", - // TODO(umar): OpConstant fails because the type is not defined - // TODO(umar): OpGroupMemberDecorate - "OpLine %str 3 4", - "OpNoLine", - "%func = OpFunction %voidt None %vfunct", - "%l = OpLabel", - "OpReturn ; %func return", - "OpFunctionEnd ; %func end", - "%func2 = OpFunction %voidt None %viifunct", - "%funcp1 = OpFunctionParameter %intt", - "%funcp2 = OpFunctionParameter %intt", - "%fLabel = OpLabel", - "OpNop", - "OpReturn ; %func2 return", - "OpFunctionEnd" - }; - return instructions; -} - -static const int kRangeEnd = 1000; -pred_type All = Range<0, kRangeEnd>(); - -INSTANTIATE_TEST_SUITE_P(InstructionsOrder, - ValidateLayout, - ::testing::Combine(::testing::Range((int)0, (int)getInstructions().size()), - // Note: Because of ID dependencies between instructions, some instructions - // are not free to be placed anywhere without triggering an non-layout - // validation error. Therefore, "Lines to compile" for some instructions - // are not "All" in the below. - // - // | Instruction | Line(s) valid | Lines to compile - ::testing::Values(std::make_tuple(std::string("OpCapability") , Equals<0> , Range<0, 2>()) - , std::make_tuple(std::string("OpExtension") , Equals<1> , All) - , std::make_tuple(std::string("OpExtInstImport") , Equals<2> , All) - , std::make_tuple(std::string("OpMemoryModel") , Equals<3> , Range<1, kRangeEnd>()) - , std::make_tuple(std::string("OpEntryPoint") , Equals<4> , All) - , std::make_tuple(std::string("OpExecutionMode ") , Range<5, 6>() , All) - , std::make_tuple(std::string("OpExecutionModeId") , Range<5, 6>() , All) - , std::make_tuple(std::string("OpSource ") , Range<7, 11>() , Range<8, kRangeEnd>()) - , std::make_tuple(std::string("OpSourceContinued ") , Range<7, 11>() , All) - , std::make_tuple(std::string("OpSourceExtension ") , Range<7, 11>() , All) - , std::make_tuple(std::string("%str2 = OpString ") , Range<7, 11>() , All) - , std::make_tuple(std::string("OpName ") , Range<12, 13>() , All) - , std::make_tuple(std::string("OpMemberName ") , Range<12, 13>() , All) - , std::make_tuple(std::string("OpDecorate ") , Range<14, 17>() , All) - , std::make_tuple(std::string("OpMemberDecorate ") , Range<14, 17>() , All) - , std::make_tuple(std::string("OpGroupDecorate ") , Range<14, 17>() , Range<17, kRangeEnd>()) - , std::make_tuple(std::string("OpDecorationGroup") , Range<14, 17>() , Range<0, 16>()) - , std::make_tuple(std::string("OpTypeBool") , Range<18, 31>() , All) - , std::make_tuple(std::string("OpTypeVoid") , Range<18, 31>() , Range<0, 26>()) - , std::make_tuple(std::string("OpTypeFloat") , Range<18, 31>() , Range<0,21>()) - , std::make_tuple(std::string("OpTypeInt") , Range<18, 31>() , Range<0, 21>()) - , std::make_tuple(std::string("OpTypeVector %floatt 4") , Range<18, 31>() , Range<20, 24>()) - , std::make_tuple(std::string("OpTypeMatrix %vec4 4") , Range<18, 31>() , Range<23, kRangeEnd>()) - , std::make_tuple(std::string("OpTypeStruct") , Range<18, 31>() , Range<25, kRangeEnd>()) - , std::make_tuple(std::string("%vfunct = OpTypeFunction"), Range<18, 31>() , Range<21, 31>()) - , std::make_tuple(std::string("OpConstant") , Range<18, 31>() , Range<21, kRangeEnd>()) - , std::make_tuple(std::string("OpLine ") , Range<18, kRangeEnd>() , Range<8, kRangeEnd>()) - , std::make_tuple(std::string("OpNoLine") , Range<18, kRangeEnd>() , All) - , std::make_tuple(std::string("%fLabel = OpLabel") , Equals<39> , All) - , std::make_tuple(std::string("OpNop") , Equals<40> , Range<40,kRangeEnd>()) - , std::make_tuple(std::string("OpReturn ; %func2 return") , Equals<41> , All) - ))); -// clang-format on - -// Creates a new vector which removes the string if the substr is found in the -// instructions vector and reinserts it in the location specified by order. -// NOTE: This will not work correctly if there are two instances of substr in -// instructions -std::vector GenerateCode(std::string substr, int order) { - std::vector code(getInstructions().size()); - std::vector inst(1); - partition_copy(std::begin(getInstructions()), std::end(getInstructions()), - std::begin(code), std::begin(inst), - [=](const std::string& str) { - return std::string::npos == str.find(substr); - }); - - code.insert(std::begin(code) + order, inst.front()); - return code; -} - -// This test will check the logical layout of a binary by removing each -// instruction in the pair of the INSTANTIATE_TEST_SUITE_P call and moving it in -// the SPIRV source formed by combining the vector "instructions". -TEST_P(ValidateLayout, Layout) { - int order; - std::string instruction; - pred_type pred; - pred_type test_pred; // Predicate to determine if the test should be build - std::tuple testCase; - - std::tie(order, testCase) = GetParam(); - std::tie(instruction, pred, test_pred) = testCase; - - // Skip test which break the code generation - if (test_pred(order)) return; - - std::vector code = GenerateCode(instruction, order); - - std::stringstream ss; - std::copy(std::begin(code), std::end(code), - std::ostream_iterator(ss, "\n")); - - const auto env = SPV_ENV_UNIVERSAL_1_3; - // printf("code: \n%s\n", ss.str().c_str()); - CompileSuccessfully(ss.str(), env); - spv_result_t result; - // clang-format off - ASSERT_EQ(pred(order), result = ValidateInstructions(env)) - << "Actual: " << spvResultToString(result) - << "\nExpected: " << spvResultToString(pred(order)) - << "\nOrder: " << order - << "\nInstruction: " << instruction - << "\nCode: \n" << ss.str(); - // clang-format on -} - -TEST_F(ValidateLayout, MemoryModelMissingBeforeEntryPoint) { - std::string str = R"( - OpCapability Matrix - OpExtension "TestExtension" - %inst = OpExtInstImport "GLSL.std.450" - OpEntryPoint GLCompute %func "" - OpExecutionMode %func LocalSize 1 1 1 - )"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "EntryPoint cannot appear before the memory model instruction")); -} - -TEST_F(ValidateLayout, MemoryModelMissing) { - char str[] = R"(OpCapability Linkage)"; - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Missing required OpMemoryModel instruction")); -} - -TEST_F(ValidateLayout, MemoryModelSpecifiedTwice) { - char str[] = R"( - OpCapability Linkage - OpCapability Shader - OpMemoryModel Logical Simple - OpMemoryModel Logical Simple - )"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpMemoryModel should only be provided once")); -} - -TEST_F(ValidateLayout, FunctionDefinitionBeforeDeclarationBad) { - char str[] = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpDecorate %var Restrict -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%vifunct = OpTypeFunction %voidt %intt -%ptrt = OpTypePointer Function %intt -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel - OpNop - OpReturn - OpFunctionEnd -%func2 = OpFunction %voidt None %vifunct ; must appear before definition -%func2p = OpFunctionParameter %intt - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Function declarations must appear before function definitions.")); -} - -// TODO(umar): Passes but gives incorrect error message. Should be fixed after -// type checking -TEST_F(ValidateLayout, LabelBeforeFunctionParameterBad) { - char str[] = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpDecorate %var Restrict -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%vifunct = OpTypeFunction %voidt %intt -%ptrt = OpTypePointer Function %intt -%func = OpFunction %voidt None %vifunct -%funcl = OpLabel ; Label appears before function parameter -%func2p = OpFunctionParameter %intt - OpNop - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Function parameters must only appear immediately " - "after the function definition")); -} - -TEST_F(ValidateLayout, FuncParameterNotImmediatlyAfterFuncBad) { - char str[] = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpDecorate %var Restrict -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%vifunct = OpTypeFunction %voidt %intt -%ptrt = OpTypePointer Function %intt -%func = OpFunction %voidt None %vifunct -%funcl = OpLabel - OpNop - OpBranch %next -%func2p = OpFunctionParameter %intt ;FunctionParameter appears in a function but not immediately afterwards -%next = OpLabel - OpNop - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Function parameters must only appear immediately " - "after the function definition")); -} - -TEST_F(ValidateLayout, OpUndefCanAppearInTypeDeclarationSection) { - std::string str = R"( - OpCapability Kernel - OpCapability Linkage - OpMemoryModel Logical OpenCL -%voidt = OpTypeVoid -%uintt = OpTypeInt 32 0 -%funct = OpTypeFunction %voidt -%udef = OpUndef %uintt -%func = OpFunction %voidt None %funct -%entry = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLayout, OpUndefCanAppearInBlock) { - std::string str = R"( - OpCapability Kernel - OpCapability Linkage - OpMemoryModel Logical OpenCL -%voidt = OpTypeVoid -%uintt = OpTypeInt 32 0 -%funct = OpTypeFunction %voidt -%func = OpFunction %voidt None %funct -%entry = OpLabel -%udef = OpUndef %uintt - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLayout, MissingFunctionEndForFunctionWithBody) { - const auto s = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%tf = OpTypeFunction %void -%f = OpFunction %void None %tf -%l = OpLabel -OpReturn -)"; - - CompileSuccessfully(s); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - StrEq("Missing OpFunctionEnd at end of module.")); -} - -TEST_F(ValidateLayout, MissingFunctionEndForFunctionPrototype) { - const auto s = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%tf = OpTypeFunction %void -%f = OpFunction %void None %tf -)"; - - CompileSuccessfully(s); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - StrEq("Missing OpFunctionEnd at end of module.")); -} - -using ValidateOpFunctionParameter = spvtest::ValidateBase; - -TEST_F(ValidateOpFunctionParameter, OpLineBetweenParameters) { - const auto s = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%foo_frag = OpString "foo.frag" -%i32 = OpTypeInt 32 1 -%tf = OpTypeFunction %i32 %i32 %i32 -%c = OpConstant %i32 123 -%f = OpFunction %i32 None %tf -OpLine %foo_frag 1 1 -%p1 = OpFunctionParameter %i32 -OpNoLine -%p2 = OpFunctionParameter %i32 -%l = OpLabel -OpReturnValue %c -OpFunctionEnd -)"; - CompileSuccessfully(s); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateOpFunctionParameter, TooManyParameters) { - const auto s = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%i32 = OpTypeInt 32 1 -%tf = OpTypeFunction %i32 %i32 %i32 -%c = OpConstant %i32 123 -%f = OpFunction %i32 None %tf -%p1 = OpFunctionParameter %i32 -%p2 = OpFunctionParameter %i32 -%xp3 = OpFunctionParameter %i32 -%xp4 = OpFunctionParameter %i32 -%xp5 = OpFunctionParameter %i32 -%xp6 = OpFunctionParameter %i32 -%xp7 = OpFunctionParameter %i32 -%l = OpLabel -OpReturnValue %c -OpFunctionEnd -)"; - CompileSuccessfully(s); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); -} - -using ValidateEntryPoint = spvtest::ValidateBase; - -// Tests that not having OpEntryPoint causes an error. -TEST_F(ValidateEntryPoint, NoEntryPointBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("No OpEntryPoint instruction was found. This is only " - "allowed if the Linkage capability is being used.")); -} - -// Invalid. A function may not be a target of both OpEntryPoint and -// OpFunctionCall. -TEST_F(ValidateEntryPoint, FunctionIsTargetOfEntryPointAndFunctionCallBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %foo "foo" - OpExecutionMode %foo OriginUpperLeft -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%foo = OpFunction %voidt None %funct -%entry = OpLabel -%recurse = OpFunctionCall %voidt %foo - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("A function (1) may not be targeted by both an OpEntryPoint " - "instruction and an OpFunctionCall instruction.")); -} - -// Invalid. Must be within a function to make a function call. -TEST_F(ValidateEntryPoint, FunctionCallOutsideFunctionBody) { - std::string spirv = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpName %variableName "variableName" - %34 = OpFunctionCall %variableName %1 - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("FunctionCall must happen within a function body.")); -} - -// Valid. Module with a function but no entry point is valid when Linkage -// Capability is used. -TEST_F(ValidateEntryPoint, NoEntryPointWithLinkageCapGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%foo = OpFunction %voidt None %funct -%entry = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLayout, ModuleProcessedInvalidIn10) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %void "void" - OpModuleProcessed "this is ok in 1.1 and later" - OpDecorate %void Volatile ; bogus, but makes the example short -%void = OpTypeVoid -)"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_WRONG_VERSION, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_0)); - // In a 1.0 environment the version check fails. - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid SPIR-V binary version 1.1 for target " - "environment SPIR-V 1.0.")); -} - -TEST_F(ValidateLayout, ModuleProcessedValidIn11) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %void "void" - OpModuleProcessed "this is ok in 1.1 and later" - OpDecorate %void Volatile ; bogus, but makes the example short -%void = OpTypeVoid -)"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateLayout, ModuleProcessedBeforeLastNameIsTooEarly) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpModuleProcessed "this is too early" - OpName %void "void" -%void = OpTypeVoid -)"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - // By the mechanics of the validator, we assume ModuleProcessed is in the - // right spot, but then that OpName is in the wrong spot. - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Name cannot appear in a function declaration")); -} - -TEST_F(ValidateLayout, ModuleProcessedInvalidAfterFirstAnnotation) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %void Volatile ; this is bogus, but keeps the example short - OpModuleProcessed "this is too late" -%void = OpTypeVoid -)"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ModuleProcessed cannot appear in a function declaration")); -} - -TEST_F(ValidateLayout, ModuleProcessedInvalidInFunctionBeforeLabel) { - char str[] = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn - OpModuleProcessed "this is too late, in function before label" -%entry = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ModuleProcessed cannot appear in a function declaration")); -} - -TEST_F(ValidateLayout, ModuleProcessedInvalidInBasicBlock) { - char str[] = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel - OpModuleProcessed "this is too late, in basic block" - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("ModuleProcessed cannot appear in a function declaration")); -} - -TEST_F(ValidateLayout, WebGPUCallerBeforeCalleeBad) { - char str[] = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%1 = OpLabel -%2 = OpFunctionCall %void %callee - OpReturn - OpFunctionEnd -%callee = OpFunction %void None %voidfn -%3 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str, SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, functions need to be defined before being " - "called.\n %5 = OpFunctionCall %void %6\n")); -} - -TEST_F(ValidateLayout, WebGPUCalleeBeforeCallerGood) { - char str[] = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%callee = OpFunction %void None %voidfn -%3 = OpLabel - OpReturn - OpFunctionEnd -%main = OpFunction %void None %voidfn -%1 = OpLabel -%2 = OpFunctionCall %void %callee - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str, SPV_ENV_WEBGPU_0); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -// TODO(umar): Test optional instructions - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_limits_test.cpp b/3rdparty/spirv-tools/test/val/val_limits_test.cpp deleted file mode 100644 index 0ef61e21b..000000000 --- a/3rdparty/spirv-tools/test/val/val_limits_test.cpp +++ /dev/null @@ -1,778 +0,0 @@ -// 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. - -// Validation tests for Universal Limits. (Section 2.17 of the SPIR-V Spec) - -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; - -using ValidateLimits = spvtest::ValidateBase; - -std::string header = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -)"; - -TEST_F(ValidateLimits, IdLargerThanBoundBad) { - std::string str = header + R"( -; %i32 has ID 1 -%i32 = OpTypeInt 32 1 -%c = OpConstant %i32 100 - -; Fake an instruction with 64 as the result id. -; !64 = OpConstantNull %i32 -!0x3002e !1 !64 -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result '64' must be less than the ID bound '3'.")); -} - -TEST_F(ValidateLimits, IdEqualToBoundBad) { - std::string str = header + R"( -; %i32 has ID 1 -%i32 = OpTypeInt 32 1 -%c = OpConstant %i32 100 - -; Fake an instruction with 64 as the result id. -; !64 = OpConstantNull %i32 -!0x3002e !1 !64 -)"; - - CompileSuccessfully(str); - - // The largest ID used in this program is 64. Let's overwrite the ID bound in - // the header to be 64. This should result in an error because all IDs must - // satisfy: 0 < id < bound. - OverwriteAssembledBinary(3, 64); - - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Result '64' must be less than the ID bound '64'.")); -} - -TEST_F(ValidateLimits, IdBoundTooBigDeaultLimit) { - std::string str = header; - - CompileSuccessfully(str); - - // The largest ID used in this program is 64. Let's overwrite the ID bound in - // the header to be 64. This should result in an error because all IDs must - // satisfy: 0 < id < bound. - OverwriteAssembledBinary(3, 0x4FFFFF); - - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid SPIR-V. The id bound is larger than the max " - "id bound 4194303.")); -} - -TEST_F(ValidateLimits, IdBoundAtSetLimit) { - std::string str = header; - - CompileSuccessfully(str); - - // The largest ID used in this program is 64. Let's overwrite the ID bound in - // the header to be 64. This should result in an error because all IDs must - // satisfy: 0 < id < bound. - uint32_t id_bound = 0x4FFFFF; - - OverwriteAssembledBinary(3, id_bound); - getValidatorOptions()->universal_limits_.max_id_bound = id_bound; - - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLimits, IdBoundJustAboveSetLimit) { - std::string str = header; - - CompileSuccessfully(str); - - // The largest ID used in this program is 64. Let's overwrite the ID bound in - // the header to be 64. This should result in an error because all IDs must - // satisfy: 0 < id < bound. - uint32_t id_bound = 5242878; - - OverwriteAssembledBinary(3, id_bound); - getValidatorOptions()->universal_limits_.max_id_bound = id_bound - 1; - - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid SPIR-V. The id bound is larger than the max " - "id bound 5242877.")); -} - -TEST_F(ValidateLimits, IdBoundAtInMaxLimit) { - std::string str = header; - - CompileSuccessfully(str); - - uint32_t id_bound = std::numeric_limits::max(); - - OverwriteAssembledBinary(3, id_bound); - getValidatorOptions()->universal_limits_.max_id_bound = id_bound; - - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLimits, StructNumMembersGood) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct)"; - for (int i = 0; i < 16383; ++i) { - spirv << " %1"; - } - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLimits, StructNumMembersExceededBad) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct)"; - for (int i = 0; i < 16384; ++i) { - spirv << " %1"; - } - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of OpTypeStruct members (16384) has exceeded " - "the limit (16383).")); -} - -TEST_F(ValidateLimits, CustomizedStructNumMembersGood) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct)"; - for (int i = 0; i < 32000; ++i) { - spirv << " %1"; - } - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_struct_members, 32000u); - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLimits, CustomizedStructNumMembersBad) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeStruct)"; - for (int i = 0; i < 32001; ++i) { - spirv << " %1"; - } - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_struct_members, 32000u); - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of OpTypeStruct members (32001) has exceeded " - "the limit (32000).")); -} - -// Valid: Switch statement has 16,383 branches. -TEST_F(ValidateLimits, SwitchNumBranchesGood) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeInt 32 0 -%4 = OpConstant %3 1234 -%5 = OpFunction %1 None %2 -%7 = OpLabel -%8 = OpIAdd %3 %4 %4 - OpSwitch %4 %10)"; - - // Now add the (literal, label) pairs - for (int i = 0; i < 16383; ++i) { - spirv << " 1 %10"; - } - - spirv << R"( -%10 = OpLabel -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Switch statement has 16,384 branches. -TEST_F(ValidateLimits, SwitchNumBranchesBad) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeInt 32 0 -%4 = OpConstant %3 1234 -%5 = OpFunction %1 None %2 -%7 = OpLabel -%8 = OpIAdd %3 %4 %4 - OpSwitch %4 %10)"; - - // Now add the (literal, label) pairs - for (int i = 0; i < 16384; ++i) { - spirv << " 1 %10"; - } - - spirv << R"( -%10 = OpLabel -OpReturn -OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of (literal, label) pairs in OpSwitch (16384) " - "exceeds the limit (16383).")); -} - -// Valid: Switch statement has 10 branches (limit is 10) -TEST_F(ValidateLimits, CustomizedSwitchNumBranchesGood) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeInt 32 0 -%4 = OpConstant %3 1234 -%5 = OpFunction %1 None %2 -%7 = OpLabel -%8 = OpIAdd %3 %4 %4 - OpSwitch %4 %10)"; - - // Now add the (literal, label) pairs - for (int i = 0; i < 10; ++i) { - spirv << " 1 %10"; - } - - spirv << R"( -%10 = OpLabel -OpReturn -OpFunctionEnd - )"; - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_switch_branches, 10u); - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Switch statement has 11 branches (limit is 10) -TEST_F(ValidateLimits, CustomizedSwitchNumBranchesBad) { - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpTypeInt 32 0 -%4 = OpConstant %3 1234 -%5 = OpFunction %1 None %2 -%7 = OpLabel -%8 = OpIAdd %3 %4 %4 - OpSwitch %4 %10)"; - - // Now add the (literal, label) pairs - for (int i = 0; i < 11; ++i) { - spirv << " 1 %10"; - } - - spirv << R"( -%10 = OpLabel -OpReturn -OpFunctionEnd - )"; - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_switch_branches, 10u); - CompileSuccessfully(spirv.str()); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of (literal, label) pairs in OpSwitch (11) " - "exceeds the limit (10).")); -} - -// Valid: OpTypeFunction with 255 arguments. -TEST_F(ValidateLimits, OpTypeFunctionGood) { - int num_args = 255; - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFunction %1)"; - // add parameters - for (int i = 0; i < num_args; ++i) { - spirv << " %1"; - } - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: OpTypeFunction with 256 arguments. (limit is 255 according to the -// spec Universal Limits (2.17). -TEST_F(ValidateLimits, OpTypeFunctionBad) { - int num_args = 256; - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFunction %1)"; - for (int i = 0; i < num_args; ++i) { - spirv << " %1"; - } - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeFunction may not take more than 255 arguments. " - "OpTypeFunction '2[%2]' has 256 arguments.")); -} - -// Valid: OpTypeFunction with 100 arguments (Custom limit: 100) -TEST_F(ValidateLimits, CustomizedOpTypeFunctionGood) { - int num_args = 100; - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFunction %1)"; - // add parameters - for (int i = 0; i < num_args; ++i) { - spirv << " %1"; - } - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_function_args, 100u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: OpTypeFunction with 101 arguments. (Custom limit: 100) -TEST_F(ValidateLimits, CustomizedOpTypeFunctionBad) { - int num_args = 101; - std::ostringstream spirv; - spirv << header << R"( -%1 = OpTypeInt 32 0 -%2 = OpTypeFunction %1)"; - for (int i = 0; i < num_args; ++i) { - spirv << " %1"; - } - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_function_args, 100u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeFunction may not take more than 100 arguments. " - "OpTypeFunction '2[%2]' has 101 arguments.")); -} - -// Valid: module has 65,535 global variables. -TEST_F(ValidateLimits, NumGlobalVarsGood) { - int num_globals = 65535; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 -%_ptr_int = OpTypePointer Input %int - )"; - - for (int i = 0; i < num_globals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Input\n"; - } - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: module has 65,536 global variables (limit is 65,535). -TEST_F(ValidateLimits, NumGlobalVarsBad) { - int num_globals = 65536; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 -%_ptr_int = OpTypePointer Input %int - )"; - - for (int i = 0; i < num_globals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Input\n"; - } - - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of Global Variables (Storage Class other than " - "'Function') exceeded the valid limit (65535).")); -} - -// Valid: module has 50 global variables (limit is 50) -TEST_F(ValidateLimits, CustomizedNumGlobalVarsGood) { - int num_globals = 50; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 -%_ptr_int = OpTypePointer Input %int - )"; - - for (int i = 0; i < num_globals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Input\n"; - } - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_global_variables, 50u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: module has 51 global variables (limit is 50). -TEST_F(ValidateLimits, CustomizedNumGlobalVarsBad) { - int num_globals = 51; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 -%_ptr_int = OpTypePointer Input %int - )"; - - for (int i = 0; i < num_globals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Input\n"; - } - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_global_variables, 50u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of Global Variables (Storage Class other than " - "'Function') exceeded the valid limit (50).")); -} - -// Valid: module has 524,287 local variables. -// Note: AppVeyor limits process time to 300s. For a VisualStudio Debug -// build, going up to 524287 local variables gets too close to that -// limit. So test with an artificially lowered limit. -TEST_F(ValidateLimits, NumLocalVarsGoodArtificiallyLowLimit5K) { - int num_locals = 5000; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %_ptr_int = OpTypePointer Function %int - %voidt = OpTypeVoid - %funct = OpTypeFunction %voidt - %main = OpFunction %voidt None %funct - %entry = OpLabel - )"; - - for (int i = 0; i < num_locals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Function\n"; - } - - spirv << R"( - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - // Artificially limit it. - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_local_variables, num_locals); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: module has 524,288 local variables (limit is 524,287). -// Artificially limit the check to 5001. -TEST_F(ValidateLimits, NumLocalVarsBadArtificiallyLowLimit5K) { - int num_locals = 5001; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %_ptr_int = OpTypePointer Function %int - %voidt = OpTypeVoid - %funct = OpTypeFunction %voidt - %main = OpFunction %voidt None %funct - %entry = OpLabel - )"; - - for (int i = 0; i < num_locals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Function\n"; - } - - spirv << R"( - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(spirv.str()); - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_local_variables, 5000u); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of local variables ('Function' Storage Class) " - "exceeded the valid limit (5000).")); -} - -// Valid: module has 100 local variables (limit is 100). -TEST_F(ValidateLimits, CustomizedNumLocalVarsGood) { - int num_locals = 100; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %_ptr_int = OpTypePointer Function %int - %voidt = OpTypeVoid - %funct = OpTypeFunction %voidt - %main = OpFunction %voidt None %funct - %entry = OpLabel - )"; - - for (int i = 0; i < num_locals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Function\n"; - } - - spirv << R"( - OpReturn - OpFunctionEnd - )"; - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_local_variables, 100u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: module has 101 local variables (limit is 100). -TEST_F(ValidateLimits, CustomizedNumLocalVarsBad) { - int num_locals = 101; - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %_ptr_int = OpTypePointer Function %int - %voidt = OpTypeVoid - %funct = OpTypeFunction %voidt - %main = OpFunction %voidt None %funct - %entry = OpLabel - )"; - - for (int i = 0; i < num_locals; ++i) { - spirv << "%var_" << i << " = OpVariable %_ptr_int Function\n"; - } - - spirv << R"( - OpReturn - OpFunctionEnd - )"; - - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_local_variables, 100u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Number of local variables ('Function' Storage Class) " - "exceeded the valid limit (100).")); -} - -// Valid: Structure nesting depth of 255. -TEST_F(ValidateLimits, StructNestingDepthGood) { - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %s_depth_1 = OpTypeStruct %int - )"; - for (auto i = 2; i <= 255; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %int %s_depth_" << i - 1; - spirv << "\n"; - } - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Structure nesting depth of 256. -TEST_F(ValidateLimits, StructNestingDepthBad) { - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %s_depth_1 = OpTypeStruct %int - )"; - for (auto i = 2; i <= 256; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %int %s_depth_" << i - 1; - spirv << "\n"; - } - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure Nesting Depth may not be larger than 255. Found 256.")); -} - -// Valid: Structure nesting depth of 100 (limit is 100). -TEST_F(ValidateLimits, CustomizedStructNestingDepthGood) { - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %s_depth_1 = OpTypeStruct %int - )"; - for (auto i = 2; i <= 100; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %int %s_depth_" << i - 1; - spirv << "\n"; - } - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_struct_depth, 100u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Structure nesting depth of 101 (limit is 100). -TEST_F(ValidateLimits, CustomizedStructNestingDepthBad) { - std::ostringstream spirv; - spirv << header << R"( - %int = OpTypeInt 32 0 - %s_depth_1 = OpTypeStruct %int - )"; - for (auto i = 2; i <= 101; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %int %s_depth_" << i - 1; - spirv << "\n"; - } - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_struct_depth, 100u); - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Structure Nesting Depth may not be larger than 100. Found 101.")); -} - -// clang-format off -// Generates an SPIRV program with the given control flow nesting depth -void GenerateSpirvProgramWithCfgNestingDepth(std::string& str, int depth) { - std::ostringstream spirv; - spirv << header << R"( - %void = OpTypeVoid - %3 = OpTypeFunction %void - %bool = OpTypeBool - %12 = OpConstantTrue %bool - %main = OpFunction %void None %3 - %5 = OpLabel - OpBranch %6 - %6 = OpLabel - OpLoopMerge %8 %9 None - OpBranch %10 - %10 = OpLabel - OpBranchConditional %12 %7 %8 - %7 = OpLabel - )"; - int first_id = 13; - int last_id = 14; - // We already have 1 level of nesting due to the Loop. - int num_if_conditions = depth-1; - int largest_index = first_id + 2*num_if_conditions - 2; - for (int i = first_id; i <= largest_index; i = i + 2) { - spirv << "OpSelectionMerge %" << i+1 << " None" << "\n"; - spirv << "OpBranchConditional %12 " << "%" << i << " %" << i+1 << "\n"; - spirv << "%" << i << " = OpLabel" << "\n"; - } - spirv << "OpBranch %9" << "\n"; - - for (int i = largest_index+1; i > last_id; i = i - 2) { - spirv << "%" << i << " = OpLabel" << "\n"; - spirv << "OpBranch %" << i-2 << "\n"; - } - spirv << "%" << last_id << " = OpLabel" << "\n"; - spirv << "OpBranch %9" << "\n"; - spirv << R"( - %9 = OpLabel - OpBranch %6 - %8 = OpLabel - OpReturn - OpFunctionEnd - )"; - str = spirv.str(); -} -// clang-format on - -// Invalid: Control Flow Nesting depth is 1024. (limit is 1023). -TEST_F(ValidateLimits, ControlFlowDepthBad) { - std::string spirv; - GenerateSpirvProgramWithCfgNestingDepth(spirv, 1024); - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Maximum Control Flow nesting depth exceeded.")); -} - -// Valid: Control Flow Nesting depth is 10 (custom limit: 10). -TEST_F(ValidateLimits, CustomizedControlFlowDepthGood) { - std::string spirv; - GenerateSpirvProgramWithCfgNestingDepth(spirv, 10); - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_control_flow_nesting_depth, 10u); - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: Control Flow Nesting depth is 11. (custom limit: 10). -TEST_F(ValidateLimits, CustomizedControlFlowDepthBad) { - std::string spirv; - GenerateSpirvProgramWithCfgNestingDepth(spirv, 11); - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_control_flow_nesting_depth, 10u); - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Maximum Control Flow nesting depth exceeded.")); -} - -// Valid. The purpose here is to test the CFG depth calculation code when a loop -// continue target is the loop iteself. It also exercises the case where a loop -// is unreachable. -TEST_F(ValidateLimits, ControlFlowNoEntryToLoopGood) { - std::string str = header + R"( - OpName %entry "entry" - OpName %loop "loop" - OpName %exit "exit" -%voidt = OpTypeVoid -%boolt = OpTypeBool -%undef = OpUndef %boolt -%funct = OpTypeFunction %voidt -%main = OpFunction %voidt None %funct -%entry = OpLabel - OpBranch %exit -%loop = OpLabel - OpLoopMerge %dead %loop None - OpBranchConditional %undef %loop %loop -%dead = OpLabel - OpUnreachable -%exit = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_literals_test.cpp b/3rdparty/spirv-tools/test/val/val_literals_test.cpp deleted file mode 100644 index 6eadf321c..000000000 --- a/3rdparty/spirv-tools/test/val/val_literals_test.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2017 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. - -// Validation tests for ilegal literals - -#include -#include - -#include "gmock/gmock.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; - -using ValidateLiterals = spvtest::ValidateBase; -using ValidateLiteralsShader = spvtest::ValidateBase; -using ValidateLiteralsKernel = spvtest::ValidateBase; - -std::string GenerateShaderCode() { - std::string str = R"( - OpCapability Shader - OpCapability Linkage - OpCapability Int16 - OpCapability Int64 - OpCapability Float16 - OpCapability Float64 - OpMemoryModel Logical GLSL450 -%int16 = OpTypeInt 16 1 -%uint16 = OpTypeInt 16 0 -%int32 = OpTypeInt 32 1 -%uint32 = OpTypeInt 32 0 -%int64 = OpTypeInt 64 1 -%uint64 = OpTypeInt 64 0 -%half = OpTypeFloat 16 -%float = OpTypeFloat 32 -%double = OpTypeFloat 64 -%10 = OpTypeVoid - )"; - return str; -} - -std::string GenerateKernelCode() { - std::string str = R"( - OpCapability Kernel - OpCapability Addresses - OpCapability Linkage - OpCapability Int8 - OpMemoryModel Physical64 OpenCL -%uint8 = OpTypeInt 8 0 - )"; - return str; -} - -TEST_F(ValidateLiterals, LiteralsShaderGood) { - std::string str = GenerateShaderCode() + R"( -%11 = OpConstant %int16 !0x00007FFF -%12 = OpConstant %int16 !0xFFFF8000 -%13 = OpConstant %int16 !0xFFFFABCD -%14 = OpConstant %uint16 !0x0000ABCD -%15 = OpConstant %int16 -32768 -%16 = OpConstant %uint16 65535 -%17 = OpConstant %int32 -2147483648 -%18 = OpConstant %uint32 4294967295 -%19 = OpConstant %int64 -9223372036854775808 -%20 = OpConstant %uint64 18446744073709551615 -%21 = OpConstant %half !0x0000FFFF -%22 = OpConstant %float !0xFFFFFFFF -%23 = OpConstant %double !0xFFFFFFFF !0xFFFFFFFF - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLiterals, InvalidInt) { - std::string str = GenerateShaderCode() + R"( -%11 = OpTypeInt 32 90 - )"; - CompileSuccessfully(str); - EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpTypeInt has invalid signedness:")); -} - -TEST_P(ValidateLiteralsShader, LiteralsShaderBad) { - std::string str = GenerateShaderCode() + GetParam(); - std::string inst_id = "11"; - CompileSuccessfully(str); - EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The high-order bits of a literal number in instruction " + - inst_id + - " must be 0 for a floating-point type, " - "or 0 for an integer type with Signedness of 0, " - "or sign extended when Signedness is 1")); -} - -INSTANTIATE_TEST_SUITE_P( - LiteralsShaderCases, ValidateLiteralsShader, - ::testing::Values("%11 = OpConstant %int16 !0xFFFF0000", // Sign bit is 0 - "%11 = OpConstant %int16 !0x00008000", // Sign bit is 1 - "%11 = OpConstant %int16 !0xABCD8000", // Sign bit is 1 - "%11 = OpConstant %int16 !0xABCD0000", - "%11 = OpConstant %uint16 !0xABCD0000", - "%11 = OpConstant %half !0xABCD0000", - "%11 = OpConstant %half !0x00010000")); - -TEST_F(ValidateLiterals, LiteralsKernelGood) { - std::string str = GenerateKernelCode() + R"( -%4 = OpConstant %uint8 !0x000000AB -%6 = OpConstant %uint8 255 - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateLiteralsKernel, LiteralsKernelBad) { - std::string str = GenerateKernelCode() + GetParam(); - std::string inst_id = "2"; - CompileSuccessfully(str); - EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The high-order bits of a literal number in instruction " + - inst_id + - " must be 0 for a floating-point type, " - "or 0 for an integer type with Signedness of 0, " - "or sign extended when Signedness is 1")); -} - -INSTANTIATE_TEST_SUITE_P( - LiteralsKernelCases, ValidateLiteralsKernel, - ::testing::Values("%2 = OpConstant %uint8 !0xABCDEF00", - "%2 = OpConstant %uint8 !0xABCDEFFF")); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_logicals_test.cpp b/3rdparty/spirv-tools/test/val/val_logicals_test.cpp deleted file mode 100644 index b57c74337..000000000 --- a/3rdparty/spirv-tools/test/val/val_logicals_test.cpp +++ /dev/null @@ -1,1164 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateLogicals = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - const std::string capabilities = - R"( -OpCapability Shader -OpCapability Int64 -OpCapability Float64)"; - - const std::string after_extension_before_body = - R"( -%ext_inst = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%s32 = OpTypeInt 32 1 -%f64 = OpTypeFloat 64 -%u64 = OpTypeInt 64 0 -%s64 = OpTypeInt 64 1 -%boolvec2 = OpTypeVector %bool 2 -%s32vec2 = OpTypeVector %s32 2 -%u32vec2 = OpTypeVector %u32 2 -%u64vec2 = OpTypeVector %u64 2 -%f32vec2 = OpTypeVector %f32 2 -%f64vec2 = OpTypeVector %f64 2 -%boolvec3 = OpTypeVector %bool 3 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%s32vec3 = OpTypeVector %s32 3 -%f32vec3 = OpTypeVector %f32 3 -%f64vec3 = OpTypeVector %f64 3 -%boolvec4 = OpTypeVector %bool 4 -%u32vec4 = OpTypeVector %u32 4 -%u64vec4 = OpTypeVector %u64 4 -%s32vec4 = OpTypeVector %s32 4 -%f32vec4 = OpTypeVector %f32 4 -%f64vec4 = OpTypeVector %f64 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 - -%s32_0 = OpConstant %s32 0 -%s32_1 = OpConstant %s32 1 -%s32_2 = OpConstant %s32 2 -%s32_3 = OpConstant %s32 3 -%s32_4 = OpConstant %s32 4 -%s32_m1 = OpConstant %s32 -1 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64_4 = OpConstant %f64 4 - -%s64_0 = OpConstant %s64 0 -%s64_1 = OpConstant %s64 1 -%s64_2 = OpConstant %s64 2 -%s64_3 = OpConstant %s64 3 -%s64_4 = OpConstant %s64 4 -%s64_m1 = OpConstant %s64 -1 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_4 = OpConstant %u64 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1 -%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2 -%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2 -%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3 -%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3 -%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4 - -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 -%f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4 - -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%boolvec2_tf = OpConstantComposite %boolvec2 %true %false -%boolvec3_tft = OpConstantComposite %boolvec3 %true %false %true -%boolvec4_tftf = OpConstantComposite %boolvec4 %true %false %true %false - -%arr_u32_2 = OpTypeArray %u32 %u32_2 -%st_u32_u32 = OpTypeStruct %u32 %u32 -%mat_f32_2_2 = OpTypeMatrix %f32vec2 2 - -%nul_arr_u32_2 = OpConstantNull %arr_u32_2 -%nul_st_u32_u32 = OpConstantNull %st_u32_u32 -%nul_mat_f32_2_2 = OpConstantNull %mat_f32_2_2 - -%arr_u32_2_1_2 = OpConstantComposite %arr_u32_2 %u32_1 %u32_2 -%st_u32_u32_1_2 = OpConstantComposite %st_u32_u32 %u32_1 %u32_2 -%mat_f32_2_2_01_12 = OpConstantComposite %mat_f32_2_2 %f32vec2_01 %f32vec2_12 - -%f32vec4ptr = OpTypePointer Function %f32vec4 - -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string after_body = - R"( -OpReturn -OpFunctionEnd)"; - - return capabilities + capabilities_and_extensions + - after_extension_before_body + body + after_body; -} - -std::string GenerateKernelCode( - const std::string& body, - const std::string& capabilities_and_extensions = "") { - const std::string capabilities = - R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability Int64 -OpCapability Float64)"; - - const std::string after_extension_before_body = - R"( -OpMemoryModel Physical32 OpenCL -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%f64 = OpTypeFloat 64 -%u64 = OpTypeInt 64 0 -%boolvec2 = OpTypeVector %bool 2 -%u32vec2 = OpTypeVector %u32 2 -%u64vec2 = OpTypeVector %u64 2 -%f32vec2 = OpTypeVector %f32 2 -%f64vec2 = OpTypeVector %f64 2 -%boolvec3 = OpTypeVector %bool 3 -%u32vec3 = OpTypeVector %u32 3 -%u64vec3 = OpTypeVector %u64 3 -%f32vec3 = OpTypeVector %f32 3 -%f64vec3 = OpTypeVector %f64 3 -%boolvec4 = OpTypeVector %bool 4 -%u32vec4 = OpTypeVector %u32 4 -%u64vec4 = OpTypeVector %u64 4 -%f32vec4 = OpTypeVector %f32 4 -%f64vec4 = OpTypeVector %f64 4 - -%f32_0 = OpConstant %f32 0 -%f32_1 = OpConstant %f32 1 -%f32_2 = OpConstant %f32 2 -%f32_3 = OpConstant %f32 3 -%f32_4 = OpConstant %f32 4 - -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32_4 = OpConstant %u32 4 - -%f64_0 = OpConstant %f64 0 -%f64_1 = OpConstant %f64 1 -%f64_2 = OpConstant %f64 2 -%f64_3 = OpConstant %f64 3 -%f64_4 = OpConstant %f64 4 - -%u64_0 = OpConstant %u64 0 -%u64_1 = OpConstant %u64 1 -%u64_2 = OpConstant %u64 2 -%u64_3 = OpConstant %u64 3 -%u64_4 = OpConstant %u64 4 - -%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 -%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2 -%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2 -%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 -%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4 - -%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 -%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 -%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2 -%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3 -%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 -%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4 - -%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1 -%f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2 -%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2 -%f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3 -%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3 -%f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4 - -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%boolvec2_tf = OpConstantComposite %boolvec2 %true %false -%boolvec3_tft = OpConstantComposite %boolvec3 %true %false %true -%boolvec4_tftf = OpConstantComposite %boolvec4 %true %false %true %false - -%f32vec4ptr = OpTypePointer Function %f32vec4 - -%main = OpFunction %void None %func -%main_entry = OpLabel)"; - - const std::string after_body = - R"( -OpReturn -OpFunctionEnd)"; - - return capabilities + capabilities_and_extensions + - after_extension_before_body + body + after_body; -} - -TEST_F(ValidateLogicals, OpAnySuccess) { - const std::string body = R"( -%val1 = OpAny %bool %boolvec2_tf -%val2 = OpAny %bool %boolvec3_tft -%val3 = OpAny %bool %boolvec4_tftf -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpAnyWrongTypeId) { - const std::string body = R"( -%val = OpAny %u32 %boolvec2_tf -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected bool scalar type as Result Type: Any")); -} - -TEST_F(ValidateLogicals, OpAnyWrongOperand) { - const std::string body = R"( -%val = OpAny %bool %u32vec3_123 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected operand to be vector bool: Any")); -} - -TEST_F(ValidateLogicals, OpIsNanSuccess) { - const std::string body = R"( -%val1 = OpIsNan %bool %f32_1 -%val2 = OpIsNan %bool %f64_0 -%val3 = OpIsNan %boolvec2 %f32vec2_12 -%val4 = OpIsNan %boolvec3 %f32vec3_123 -%val5 = OpIsNan %boolvec4 %f32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpIsNanWrongTypeId) { - const std::string body = R"( -%val1 = OpIsNan %u32 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected bool scalar or vector type as Result Type: IsNan")); -} - -TEST_F(ValidateLogicals, OpIsNanOperandNotFloat) { - const std::string body = R"( -%val1 = OpIsNan %bool %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operand to be scalar or vector float: IsNan")); -} - -TEST_F(ValidateLogicals, OpIsNanOperandWrongSize) { - const std::string body = R"( -%val1 = OpIsNan %bool %f32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the operand to be equal: " - "IsNan")); -} - -TEST_F(ValidateLogicals, OpLessOrGreaterSuccess) { - const std::string body = R"( -%val1 = OpLessOrGreater %bool %f32_0 %f32_1 -%val2 = OpLessOrGreater %bool %f64_0 %f64_0 -%val3 = OpLessOrGreater %boolvec2 %f32vec2_12 %f32vec2_12 -%val4 = OpLessOrGreater %boolvec3 %f32vec3_123 %f32vec3_123 -%val5 = OpLessOrGreater %boolvec4 %f32vec4_1234 %f32vec4_1234 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpLessOrGreaterWrongTypeId) { - const std::string body = R"( -%val1 = OpLessOrGreater %u32 %f32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected bool scalar or vector type as Result Type: LessOrGreater")); -} - -TEST_F(ValidateLogicals, OpLessOrGreaterLeftOperandNotFloat) { - const std::string body = R"( -%val1 = OpLessOrGreater %bool %u32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected operands to be scalar or vector float: LessOrGreater")); -} - -TEST_F(ValidateLogicals, OpLessOrGreaterLeftOperandWrongSize) { - const std::string body = R"( -%val1 = OpLessOrGreater %bool %f32vec2_12 %f32_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the operands to be equal: " - "LessOrGreater")); -} - -TEST_F(ValidateLogicals, OpLessOrGreaterOperandsDifferentType) { - const std::string body = R"( -%val1 = OpLessOrGreater %bool %f32_1 %f64_1 -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected left and right operands to have the same type: " - "LessOrGreater")); -} - -TEST_F(ValidateLogicals, OpFOrdEqualSuccess) { - const std::string body = R"( -%val1 = OpFOrdEqual %bool %f32_0 %f32_1 -%val2 = OpFOrdEqual %bool %f64_0 %f64_0 -%val3 = OpFOrdEqual %boolvec2 %f32vec2_12 %f32vec2_12 -%val4 = OpFOrdEqual %boolvec3 %f32vec3_123 %f32vec3_123 -%val5 = OpFOrdEqual %boolvec4 %f32vec4_1234 %f32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpFOrdEqualWrongTypeId) { - const std::string body = R"( -%val1 = OpFOrdEqual %u32 %f32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected bool scalar or vector type as Result Type: FOrdEqual")); -} - -TEST_F(ValidateLogicals, OpFOrdEqualLeftOperandNotFloat) { - const std::string body = R"( -%val1 = OpFOrdEqual %bool %u32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector float: FOrdEqual")); -} - -TEST_F(ValidateLogicals, OpFOrdEqualLeftOperandWrongSize) { - const std::string body = R"( -%val1 = OpFOrdEqual %bool %f32vec2_12 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the operands to be equal: " - "FOrdEqual")); -} - -TEST_F(ValidateLogicals, OpFOrdEqualOperandsDifferentType) { - const std::string body = R"( -%val1 = OpFOrdEqual %bool %f32_1 %f64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected left and right operands to have the same type: " - "FOrdEqual")); -} - -TEST_F(ValidateLogicals, OpLogicalEqualSuccess) { - const std::string body = R"( -%val1 = OpLogicalEqual %bool %true %false -%val2 = OpLogicalEqual %boolvec2 %boolvec2_tf %boolvec2_tf -%val3 = OpLogicalEqual %boolvec3 %boolvec3_tft %boolvec3_tft -%val4 = OpLogicalEqual %boolvec4 %boolvec4_tftf %boolvec4_tftf -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpLogicalEqualWrongTypeId) { - const std::string body = R"( -%val1 = OpLogicalEqual %u32 %true %false -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected bool scalar or vector type as Result Type: LogicalEqual")); -} - -TEST_F(ValidateLogicals, OpLogicalEqualWrongLeftOperand) { - const std::string body = R"( -%val1 = OpLogicalEqual %bool %boolvec2_tf %false -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected both operands to be of Result Type: LogicalEqual")); -} - -TEST_F(ValidateLogicals, OpLogicalEqualWrongRightOperand) { - const std::string body = R"( -%val1 = OpLogicalEqual %boolvec2 %boolvec2_tf %false -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected both operands to be of Result Type: LogicalEqual")); -} - -TEST_F(ValidateLogicals, OpLogicalNotSuccess) { - const std::string body = R"( -%val1 = OpLogicalNot %bool %true -%val2 = OpLogicalNot %boolvec2 %boolvec2_tf -%val3 = OpLogicalNot %boolvec3 %boolvec3_tft -%val4 = OpLogicalNot %boolvec4 %boolvec4_tftf -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpLogicalNotWrongTypeId) { - const std::string body = R"( -%val1 = OpLogicalNot %u32 %true -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected bool scalar or vector type as Result Type: LogicalNot")); -} - -TEST_F(ValidateLogicals, OpLogicalNotWrongOperand) { - const std::string body = R"( -%val1 = OpLogicalNot %bool %boolvec2_tf -)"; - - CompileSuccessfully(GenerateKernelCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected operand to be of Result Type: LogicalNot")); -} - -TEST_F(ValidateLogicals, OpSelectSuccess) { - const std::string body = R"( -%val1 = OpSelect %u32 %true %u32_0 %u32_1 -%val2 = OpSelect %f32 %true %f32_0 %f32_1 -%val3 = OpSelect %f64 %true %f64_0 %f64_1 -%val4 = OpSelect %f32vec2 %boolvec2_tf %f32vec2_01 %f32vec2_12 -%val5 = OpSelect %f32vec4 %boolvec4_tftf %f32vec4_0123 %f32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpSelectWrongTypeId) { - const std::string body = R"( -%val1 = OpSelect %void %true %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectWrongTypeIdV14) { - // In 1.4, the message changes to allow composites. - const std::string body = R"( -%val1 = OpSelect %void %true %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar or composite type as Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectPointerNoCapability) { - const std::string body = R"( -%x = OpVariable %f32vec4ptr Function -%y = OpVariable %f32vec4ptr Function -OpStore %x %f32vec4_0123 -OpStore %y %f32vec4_1234 -%val1 = OpSelect %f32vec4ptr %true %x %y -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Using pointers with OpSelect requires capability VariablePointers " - "or VariablePointersStorageBuffer")); -} - -TEST_F(ValidateLogicals, OpSelectPointerWithCapability1) { - const std::string body = R"( -%x = OpVariable %f32vec4ptr Function -%y = OpVariable %f32vec4ptr Function -OpStore %x %f32vec4_0123 -OpStore %y %f32vec4_1234 -%val1 = OpSelect %f32vec4ptr %true %x %y -)"; - - const std::string extra_cap_ext = R"( -OpCapability VariablePointers -OpExtension "SPV_KHR_variable_pointers" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra_cap_ext).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpSelectPointerWithCapability2) { - const std::string body = R"( -%x = OpVariable %f32vec4ptr Function -%y = OpVariable %f32vec4ptr Function -OpStore %x %f32vec4_0123 -OpStore %y %f32vec4_1234 -%val1 = OpSelect %f32vec4ptr %true %x %y -)"; - - const std::string extra_cap_ext = R"( -OpCapability VariablePointersStorageBuffer -OpExtension "SPV_KHR_variable_pointers" -)"; - - CompileSuccessfully(GenerateShaderCode(body, extra_cap_ext).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpSelectWrongCondition) { - const std::string body = R"( -%val1 = OpSelect %u32 %u32_1 %u32_0 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected bool scalar or vector type as condition: Select")); -} - -TEST_F(ValidateLogicals, OpSelectWrongConditionDimension) { - const std::string body = R"( -%val1 = OpSelect %u32vec2 %true %u32vec2_01 %u32vec2_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the condition to be equal: " - "Select")); -} - -TEST_F(ValidateLogicals, OpSelectWrongLeftObject) { - const std::string body = R"( -%val1 = OpSelect %bool %true %u32vec2_01 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both objects to be of Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectWrongRightObject) { - const std::string body = R"( -%val1 = OpSelect %bool %true %u32_1 %u32vec2_01 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both objects to be of Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectArrayV13Bad) { - const std::string body = R"( -%val1 = OpSelect %arr_u32_2 %true %nul_arr_u32_2 %arr_u32_2_1_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectArrayV13TargetV14Bad) { - const std::string body = R"( -%val1 = OpSelect %arr_u32_2 %true %nul_arr_u32_2 %arr_u32_2_1_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type")); -} - -TEST_F(ValidateLogicals, OpSelectArrayV14Good) { - const std::string body = R"( -%val1 = OpSelect %arr_u32_2 %true %nul_arr_u32_2 %arr_u32_2_1_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateLogicals, OpSelectStructV13Bad) { - const std::string body = R"( -%val1 = OpSelect %st_u32_u32 %true %nul_st_u32_u32 %st_u32_u32_1_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectStructV13TargetV14Bad) { - const std::string body = R"( -%val1 = OpSelect %st_u32_u32 %true %nul_st_u32_u32 %st_u32_u32_1_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type")); -} - -TEST_F(ValidateLogicals, OpSelectStructV14Good) { - const std::string body = R"( -%val1 = OpSelect %st_u32_u32 %true %nul_st_u32_u32 %st_u32_u32_1_2 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateLogicals, OpSelectMatrixV13Bad) { - const std::string body = R"( -%val1 = OpSelect %mat_f32_2_2 %true %nul_mat_f32_2_2 %mat_f32_2_2_01_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type: Select")); -} - -TEST_F(ValidateLogicals, OpSelectMatrixV13TargetV14Bad) { - const std::string body = R"( -%val1 = OpSelect %mat_f32_2_2 %true %nul_mat_f32_2_2 %mat_f32_2_2_01_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected scalar or vector type as Result Type")); -} - -TEST_F(ValidateLogicals, OpSelectMatrixV14Good) { - const std::string body = R"( -%val1 = OpSelect %mat_f32_2_2 %true %nul_mat_f32_2_2 %mat_f32_2_2_01_12 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateLogicals, OpIEqualSuccess) { - const std::string body = R"( -%val1 = OpIEqual %bool %u32_0 %s32_1 -%val2 = OpIEqual %bool %s64_0 %u64_0 -%val3 = OpIEqual %boolvec2 %s32vec2_12 %u32vec2_12 -%val4 = OpIEqual %boolvec3 %s32vec3_123 %u32vec3_123 -%val5 = OpIEqual %boolvec4 %s32vec4_1234 %u32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpIEqualWrongTypeId) { - const std::string body = R"( -%val1 = OpIEqual %u32 %s32_1 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected bool scalar or vector type as Result Type: IEqual")); -} - -TEST_F(ValidateLogicals, OpIEqualLeftOperandNotInt) { - const std::string body = R"( -%val1 = OpIEqual %bool %f32_1 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector int: IEqual")); -} - -TEST_F(ValidateLogicals, OpIEqualLeftOperandWrongSize) { - const std::string body = R"( -%val1 = OpIEqual %bool %s32vec2_12 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the operands to be equal: " - "IEqual")); -} - -TEST_F(ValidateLogicals, OpIEqualRightOperandNotInt) { - const std::string body = R"( -%val1 = OpIEqual %bool %u32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector int: IEqual")); -} - -TEST_F(ValidateLogicals, OpIEqualDifferentBitWidth) { - const std::string body = R"( -%val1 = OpIEqual %bool %u32_1 %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both operands to have the same component bit " - "width: IEqual")); -} - -TEST_F(ValidateLogicals, OpUGreaterThanSuccess) { - const std::string body = R"( -%val1 = OpUGreaterThan %bool %u32_0 %u32_1 -%val2 = OpUGreaterThan %bool %s32_0 %u32_1 -%val3 = OpUGreaterThan %bool %u64_0 %u64_0 -%val4 = OpUGreaterThan %bool %u64_0 %s64_0 -%val5 = OpUGreaterThan %boolvec2 %u32vec2_12 %u32vec2_12 -%val6 = OpUGreaterThan %boolvec3 %s32vec3_123 %u32vec3_123 -%val7 = OpUGreaterThan %boolvec4 %u32vec4_1234 %u32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpUGreaterThanWrongTypeId) { - const std::string body = R"( -%val1 = OpUGreaterThan %u32 %u32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected bool scalar or vector type as Result Type: UGreaterThan")); -} - -TEST_F(ValidateLogicals, OpUGreaterThanLeftOperandNotInt) { - const std::string body = R"( -%val1 = OpUGreaterThan %bool %f32_1 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector int: UGreaterThan")); -} - -TEST_F(ValidateLogicals, OpUGreaterThanLeftOperandWrongSize) { - const std::string body = R"( -%val1 = OpUGreaterThan %bool %u32vec2_12 %u32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the operands to be equal: " - "UGreaterThan")); -} - -TEST_F(ValidateLogicals, OpUGreaterThanRightOperandNotInt) { - const std::string body = R"( -%val1 = OpUGreaterThan %bool %u32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector int: UGreaterThan")); -} - -TEST_F(ValidateLogicals, OpUGreaterThanDifferentBitWidth) { - const std::string body = R"( -%val1 = OpUGreaterThan %bool %u32_1 %u64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected both operands to have the same component bit width: " - "UGreaterThan")); -} - -TEST_F(ValidateLogicals, OpSGreaterThanSuccess) { - const std::string body = R"( -%val1 = OpSGreaterThan %bool %s32_0 %s32_1 -%val2 = OpSGreaterThan %bool %u32_0 %s32_1 -%val3 = OpSGreaterThan %bool %s64_0 %s64_0 -%val4 = OpSGreaterThan %bool %s64_0 %u64_0 -%val5 = OpSGreaterThan %boolvec2 %s32vec2_12 %s32vec2_12 -%val6 = OpSGreaterThan %boolvec3 %s32vec3_123 %u32vec3_123 -%val7 = OpSGreaterThan %boolvec4 %s32vec4_1234 %s32vec4_1234 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, OpSGreaterThanWrongTypeId) { - const std::string body = R"( -%val1 = OpSGreaterThan %s32 %s32_1 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected bool scalar or vector type as Result Type: SGreaterThan")); -} - -TEST_F(ValidateLogicals, OpSGreaterThanLeftOperandNotInt) { - const std::string body = R"( -%val1 = OpSGreaterThan %bool %f32_1 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector int: SGreaterThan")); -} - -TEST_F(ValidateLogicals, OpSGreaterThanLeftOperandWrongSize) { - const std::string body = R"( -%val1 = OpSGreaterThan %bool %s32vec2_12 %s32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Expected vector sizes of Result Type and the operands to be equal: " - "SGreaterThan")); -} - -TEST_F(ValidateLogicals, OpSGreaterThanRightOperandNotInt) { - const std::string body = R"( -%val1 = OpSGreaterThan %bool %s32_1 %f32_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Expected operands to be scalar or vector int: SGreaterThan")); -} - -TEST_F(ValidateLogicals, OpSGreaterThanDifferentBitWidth) { - const std::string body = R"( -%val1 = OpSGreaterThan %bool %s32_1 %s64_1 -)"; - - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected both operands to have the same component bit " - "width: SGreaterThan")); -} - -TEST_F(ValidateLogicals, PSBSelectSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%bool = OpTypeBool -%true = OpConstantTrue %bool -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -%val2 = OpLoad %ptr %val1 -%val3 = OpSelect %ptr %true %val2 %val2 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateLogicals, SelectVectorsScalarCondition) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%int4 = OpTypeVector %int 4 -%int4_0 = OpConstantNull %int4 -%true = OpConstantTrue %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%select = OpSelect %int4 %true %int4_0 %int4_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected vector sizes of Result Type and the " - "condition to be equal: Select")); -} - -TEST_F(ValidateLogicals, SelectVectorsScalarCondition1p4) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%int4 = OpTypeVector %int 4 -%int4_0 = OpConstantNull %int4 -%true = OpConstantTrue %bool -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%select = OpSelect %int4 %true %int4_0 %int4_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_F(ValidateLogicals, SelectVectorsVectorConditionMismatchedDimensions1p4) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%bool3 = OpTypeVector %bool 3 -%int = OpTypeInt 32 0 -%int4 = OpTypeVector %int 4 -%int4_0 = OpConstantNull %int4 -%bool3_null = OpConstantNull %bool3 -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%1 = OpLabel -%select = OpSelect %int4 %bool3_null %int4_0 %int4_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected vector sizes of Result Type and the " - "condition to be equal: Select")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_memory_test.cpp b/3rdparty/spirv-tools/test/val/val_memory_test.cpp deleted file mode 100644 index 22761cc1e..000000000 --- a/3rdparty/spirv-tools/test/val/val_memory_test.cpp +++ /dev/null @@ -1,4483 +0,0 @@ -// Copyright (c) 2018 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. - -// Validation tests for memory/storage - -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Combine; -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Values; - -using ValidateMemory = spvtest::ValidateBase; - -TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer UniformConstant %float -%2 = OpVariable %float_ptr UniformConstant -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\n" - "Variables identified with the UniformConstant storage class " - "are used only as handles to refer to opaque resources. Such " - "variables must be typed as OpTypeImage, OpTypeSampler, " - "OpTypeSampledImage, OpTypeAccelerationStructureNV, or an " - "array of one of these types.")); -} - -TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %2 DescriptorSet 0 -OpDecorate %2 Binding 0 -%sampler = OpTypeSampler -%sampler_ptr = OpTypePointer UniformConstant %sampler -%2 = OpVariable %sampler_ptr UniformConstant -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceArrayBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%uint = OpTypeInt 32 0 -%array_size = OpConstant %uint 5 -%array = OpTypeArray %float %array_size -%array_ptr = OpTypePointer UniformConstant %array -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\n" - "Variables identified with the UniformConstant storage class " - "are used only as handles to refer to opaque resources. Such " - "variables must be typed as OpTypeImage, OpTypeSampler, " - "OpTypeSampledImage, OpTypeAccelerationStructureNV, or an " - "array of one of these types.")); -} - -TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceArrayGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %2 DescriptorSet 0 -OpDecorate %2 Binding 0 -%sampler = OpTypeSampler -%uint = OpTypeInt 32 0 -%array_size = OpConstant %uint 5 -%array = OpTypeArray %sampler %array_size -%array_ptr = OpTypePointer UniformConstant %array -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceRuntimeArrayGood) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %2 DescriptorSet 0 -OpDecorate %2 Binding 0 -%sampler = OpTypeSampler -%uint = OpTypeInt 32 0 -%array = OpTypeRuntimeArray %sampler -%array_ptr = OpTypePointer UniformConstant %array -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanUniformOnIntBad) { - char src[] = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %kernel "main" - OpExecutionMode %kernel LocalSize 1 1 1 - - OpDecorate %var DescriptorSet 0 - OpDecorate %var Binding 0 - - %voidty = OpTypeVoid -%kernelty = OpTypeFunction %voidty - %intty = OpTypeInt 32 0 - %varty = OpTypePointer Uniform %intty - %value = OpConstant %intty 42 - - %var = OpVariable %varty Uniform - - %kernel = OpFunction %voidty None %kernelty - %label = OpLabel - OpStore %var %value - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(src, SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\n" - "Variables identified with the Uniform storage class are used " - "to access transparent buffer backed resources. Such variables " - "must be typed as OpTypeStruct, or an array of this type")); -} - -// #version 440 -// #extension GL_EXT_nonuniform_qualifier : enable -// layout(binding = 1) uniform sampler2D s2d[][2]; -// layout(location = 0) in nonuniformEXT int i; -// void main() -// { -// vec4 v = texture(s2d[i][i], vec2(0.3)); -// } -TEST_F(ValidateMemory, VulkanUniformOnRuntimeArrayOfArrayBad) { - char src[] = R"( - OpCapability Shader - OpCapability ShaderNonUniformEXT - OpCapability RuntimeDescriptorArrayEXT - OpCapability SampledImageArrayNonUniformIndexingEXT - OpExtension "SPV_EXT_descriptor_indexing" - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %i - OpSource GLSL 440 - OpSourceExtension "GL_EXT_nonuniform_qualifier" - OpName %main "main" - OpName %v "v" - OpName %s2d "s2d" - OpName %i "i" - OpDecorate %s2d DescriptorSet 0 - OpDecorate %s2d Binding 1 - OpDecorate %i Location 0 - OpDecorate %i NonUniformEXT - OpDecorate %21 NonUniformEXT - OpDecorate %22 NonUniformEXT - OpDecorate %25 NonUniformEXT - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Function_v4float = OpTypePointer Function %v4float - %10 = OpTypeImage %float 2D 0 0 0 1 Unknown - %11 = OpTypeSampledImage %10 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_11_uint_2 = OpTypeArray %11 %uint_2 -%_runtimearr__arr_11_uint_2 = OpTypeRuntimeArray %_arr_11_uint_2 -%_ptr_Uniform__runtimearr__arr_11_uint_2 = OpTypePointer Uniform %_runtimearr__arr_11_uint_2 - %s2d = OpVariable %_ptr_Uniform__runtimearr__arr_11_uint_2 Uniform - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int - %i = OpVariable %_ptr_Input_int Input -%_ptr_Uniform_11 = OpTypePointer Uniform %11 - %v2float = OpTypeVector %float 2 -%float_0_300000012 = OpConstant %float 0.300000012 - %28 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012 - %float_0 = OpConstant %float 0 - %main = OpFunction %void None %3 - %5 = OpLabel - %v = OpVariable %_ptr_Function_v4float Function - %21 = OpLoad %int %i - %22 = OpLoad %int %i - %24 = OpAccessChain %_ptr_Uniform_11 %s2d %21 %22 - %25 = OpLoad %11 %24 - %30 = OpImageSampleExplicitLod %v4float %25 %28 Lod %float_0 - OpStore %v %30 - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(src, SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\n" - "Variables identified with the Uniform storage class are used " - "to access transparent buffer backed resources. Such variables " - "must be typed as OpTypeStruct, or an array of this type")); -} - -// #version 440 -// layout (set=1, binding=1) uniform sampler2D variableName[2][2]; -// void main() { -// } -TEST_F(ValidateMemory, VulkanUniformOnArrayOfArrayBad) { - char src[] = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 440 - OpName %main "main" - OpName %variableName "variableName" - OpDecorate %variableName DescriptorSet 1 - OpDecorate %variableName Binding 1 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %7 = OpTypeImage %float 2D 0 0 0 1 Unknown - %8 = OpTypeSampledImage %7 - %uint = OpTypeInt 32 0 - %uint_2 = OpConstant %uint 2 -%_arr_8_uint_2 = OpTypeArray %8 %uint_2 -%_arr__arr_8_uint_2_uint_2 = OpTypeArray %_arr_8_uint_2 %uint_2 -%_ptr_Uniform__arr__arr_8_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_8_uint_2_uint_2 -%variableName = OpVariable %_ptr_Uniform__arr__arr_8_uint_2_uint_2 Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(src, SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\n" - "Variables identified with the Uniform storage class are used " - "to access transparent buffer backed resources. Such variables " - "must be typed as OpTypeStruct, or an array of this type")); -} - -TEST_F(ValidateMemory, MismatchingStorageClassesBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Uniform %float -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -%2 = OpVariable %float_ptr Function -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "From SPIR-V spec, section 3.32.8 on OpVariable:\n" - "Its Storage Class operand must be the same as the Storage Class " - "operand of the result type.")); -} - -TEST_F(ValidateMemory, MatchingStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Function %float -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -%2 = OpVariable %float_ptr Function -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, WebGPUInitializerWithOutputStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Output %float -%init_val = OpConstant %float 1.0 -%1 = OpVariable %float_ptr Output %init_val -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateMemory, WebGPUInitializerWithFunctionStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Function %float -%init_val = OpConstant %float 1.0 -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -%2 = OpVariable %float_ptr Function %init_val -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateMemory, WebGPUInitializerWithPrivateStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Private %float -%init_val = OpConstant %float 1.0 -%1 = OpVariable %float_ptr Private %init_val -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateMemory, WebGPUInitializerWithDisallowedStorageClassesBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Uniform %float -%init_val = OpConstant %float 1.0 -%1 = OpVariable %float_ptr Uniform %init_val -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVariable, '5[%5]', has a disallowed initializer & " - "storage class combination.\nFrom WebGPU spec:\nVariable " - "declarations that include initializers must have one of the " - "following storage classes: Output, Private, or Function\n %5 " - "= OpVariable %_ptr_Uniform_float Uniform %float_1\n")); -} - -TEST_F(ValidateMemory, WebGPUOutputStorageClassWithoutInitializerBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Output %float -%1 = OpVariable %float_ptr Output -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVariable, '4[%4]', must have an initializer.\n" - "From WebGPU execution environment spec:\n" - "All variables in the following storage classes must have an " - "initializer: Output, Private, or Function\n" - " %4 = OpVariable %_ptr_Output_float Output\n")); -} - -TEST_F(ValidateMemory, WebGPUFunctionStorageClassWithoutInitializerBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Function %float -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -%2 = OpVariable %float_ptr Function -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVariable, '7[%7]', must have an initializer.\n" - "From WebGPU execution environment spec:\n" - "All variables in the following storage classes must have an " - "initializer: Output, Private, or Function\n" - " %7 = OpVariable %_ptr_Function_float Function\n")); -} - -TEST_F(ValidateMemory, WebGPUPrivateStorageClassWithoutInitializerBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Private %float -%1 = OpVariable %float_ptr Private -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVariable, '4[%4]', must have an initializer.\n" - "From WebGPU execution environment spec:\n" - "All variables in the following storage classes must have an " - "initializer: Output, Private, or Function\n" - " %4 = OpVariable %_ptr_Private_float Private\n")); -} - -TEST_F(ValidateMemory, VulkanInitializerWithOutputStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Output %float -%init_val = OpConstant %float 1.0 -%1 = OpVariable %float_ptr Output %init_val -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanInitializerWithFunctionStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Function %float -%init_val = OpConstant %float 1.0 -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -%2 = OpVariable %float_ptr Function %init_val -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanInitializerWithPrivateStorageClassesGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Private %float -%init_val = OpConstant %float 1.0 -%1 = OpVariable %float_ptr Private %init_val -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanInitializerWithDisallowedStorageClassesBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%float = OpTypeFloat 32 -%float_ptr = OpTypePointer Input %float -%init_val = OpConstant %float 1.0 -%1 = OpVariable %float_ptr Input %init_val -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%2 = OpLabel -OpReturn -OpFunctionEnd -)"; - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpVariable, '5[%5]', has a disallowed initializer & " - "storage class combination.\nFrom Vulkan spec:\nVariable " - "declarations that include initializers must have one of the " - "following storage classes: Output, Private, or Function\n %5 " - "= OpVariable %_ptr_Input_float Input %float_1\n")); -} - -TEST_F(ValidateMemory, ArrayLenCorrectResultType) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %uint %10 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, ArrayLenIndexCorrectWith2Members) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %float %_runtimearr_float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %uint %10 1 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, ArrayLenResultNotIntType) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_6 = OpTypeStruct %_runtimearr_float -%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6 - %1 = OpFunction %void None %3 - %8 = OpLabel - %9 = OpVariable %_ptr_Function__struct_6 Function - %10 = OpArrayLength %float %9 0 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "The Result Type of OpArrayLength '10[%10]' must be OpTypeInt " - "with width 32 and signedness 0.\n %10 = OpArrayLength %float %9 " - "0\n")); -} - -TEST_F(ValidateMemory, ArrayLenResultNot32bits) { - std::string spirv = R"( - OpCapability Shader - OpCapability Int16 - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %ushort = OpTypeInt 16 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %ushort %10 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "The Result Type of OpArrayLength '11[%11]' must be OpTypeInt " - "with width 32 and signedness 0.\n %11 = OpArrayLength %ushort %10 " - "0\n")); -} - -TEST_F(ValidateMemory, ArrayLenResultSigned) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %int = OpTypeInt 32 1 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %int %10 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "The Result Type of OpArrayLength '11[%11]' must be OpTypeInt " - "with width 32 and signedness 0.\n %11 = OpArrayLength %int %10 " - "0\n")); -} - -TEST_F(ValidateMemory, ArrayLenInputNotStruct) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Function_float = OpTypePointer Function %float - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function_float Function - %11 = OpArrayLength %uint %10 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Struture's type in OpArrayLength '11[%11]' " - "must be a pointer to an OpTypeStruct.")); -} - -TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %uint %10 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The Struture's last member in OpArrayLength '11[%11]' " - "must be an OpTypeRuntimeArray.\n %11 = OpArrayLength %uint " - "%10 0\n")); -} - -TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA2) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %_runtimearr_float %float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %uint %10 1 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The Struture's last member in OpArrayLength '11[%11]' " - "must be an OpTypeRuntimeArray.\n %11 = OpArrayLength %uint " - "%10 1\n")); -} - -TEST_F(ValidateMemory, ArrayLenIndexNotLastMember) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %float %_runtimearr_float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpArrayLength %uint %10 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "The array member in OpArrayLength '11[%11]' must be an the " - "last member of the struct.\n %11 = OpArrayLength %uint %10 0\n")); -} - -TEST_F(ValidateMemory, ArrayLenIndexNotPointerToStruct) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 -%_runtimearr_float = OpTypeRuntimeArray %float - %_struct_7 = OpTypeStruct %float %_runtimearr_float -%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 - %1 = OpFunction %void None %3 - %9 = OpLabel - %10 = OpVariable %_ptr_Function__struct_7 Function - %11 = OpLoad %_struct_7 %10 - %12 = OpArrayLength %uint %11 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "The Struture's type in OpArrayLength '12[%12]' must be a " - "pointer to an OpTypeStruct.\n %12 = OpArrayLength %uint %11 0\n")); -} - -TEST_F(ValidateMemory, ArrayLenPointerIsAType) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %uint = OpTypeInt 32 0 - %1 = OpFunction %void None %3 - %9 = OpLabel - %12 = OpArrayLength %uint %float 0 - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv.c_str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a " - "type")); -} - -TEST_F(ValidateMemory, PushConstantNotStructGood) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %ptr = OpTypePointer PushConstant %float - %pc = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, VulkanPushConstantNotStructBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %ptr = OpTypePointer PushConstant %float - %pc = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("PushConstant OpVariable '6[%6]' has illegal " - "type.\nFrom Vulkan spec, section 14.5.1:\n" - "Such variables must be typed as OpTypeStruct, " - "or an array of this type")); -} - -TEST_F(ValidateMemory, VulkanPushConstant) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %1 "main" - OpExecutionMode %1 OriginUpperLeft - - OpDecorate %struct Block - OpMemberDecorate %struct 0 Offset 0 - - %void = OpTypeVoid - %voidfn = OpTypeFunction %void - %float = OpTypeFloat 32 - %struct = OpTypeStruct %float - %ptr = OpTypePointer PushConstant %struct - %pc = OpVariable %ptr PushConstant - - %1 = OpFunction %void None %voidfn - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -%load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 MakePointerAvailableKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad3) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood3) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessAvVisBadBinaryV13) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 - MakePointerAvailableKHR|NonPrivatePointerKHR %device - MakePointerVisibleKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "with two memory access operands requires SPIR-V 1.4 or later")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessAvVisGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 - MakePointerAvailableKHR|NonPrivatePointerKHR %device - MakePointerVisibleKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessFirstWithAvBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 - MakePointerAvailableKHR|NonPrivatePointerKHR %device - MakePointerAvailableKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Source memory access must not include MakePointerAvailableKHR\n" - " OpCopyMemory %5 %6 MakePointerAvailable|NonPrivatePointer" - " %uint_1 MakePointerAvailable|NonPrivatePointer %uint_1")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessSecondWithVisBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 - MakePointerVisibleKHR|NonPrivatePointerKHR %device - MakePointerVisibleKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Target memory access must not include MakePointerVisibleKHR\n" - " OpCopyMemory %5 %6 MakePointerVisible|NonPrivatePointer" - " %uint_1 MakePointerVisible|NonPrivatePointer %uint_1")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %device MakePointerAvailableKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad3) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Use of device scope with VulkanKHR memory model requires the " - "VulkanMemoryModelDeviceScopeKHR capability")); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood1) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %device MakePointerAvailableKHR|NonPrivatePointerKHR %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood2) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood3) { - const std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpCapability VulkanMemoryModelDeviceScopeKHR -OpCapability Linkage -OpCapability Addresses -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%device = OpConstant %int 1 -%workgroup = OpConstant %int 2 -%int_ptr_ssbo = OpTypePointer StorageBuffer %int -%var1 = OpVariable %int_ptr_ssbo StorageBuffer -%var2 = OpVariable %int_ptr_ssbo StorageBuffer -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, ArrayLengthStructIsLabel) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpName %20 "incorrect" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%float = OpTypeFloat 32 -%v4float = OpTypeVector %float 4 -%uint = OpTypeInt 32 0 -%4 = OpFunction %void None %3 -%20 = OpLabel -%24 = OpArrayLength %uint %20 0 -%25 = OpLoad %v4float %24 -OpReturnValue %25 -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand 1[%incorrect] requires a type")); -} - -TEST_F(ValidateMemory, PSBLoadAlignedSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -%val2 = OpLoad %ptr %val1 -%val3 = OpLoad %uint64 %val2 Aligned 8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, PSBLoadAlignedMissing) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -%val2 = OpLoad %ptr %val1 -%val3 = OpLoad %uint64 %val2 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Memory accesses with PhysicalStorageBufferEXT must use Aligned")); -} - -TEST_F(ValidateMemory, PSBStoreAlignedSuccess) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%u64_1 = OpConstant %uint64 1 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -%val2 = OpLoad %ptr %val1 -OpStore %val2 %u64_1 Aligned 8 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, PSBStoreAlignedMissing) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%u64_1 = OpConstant %uint64 1 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%pptr_f = OpTypePointer Function %ptr -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -%val1 = OpVariable %pptr_f Function -%val2 = OpLoad %ptr %val1 -OpStore %val2 %u64_1 None -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Memory accesses with PhysicalStorageBufferEXT must use Aligned")); -} - -TEST_F(ValidateMemory, PSBVariable) { - const std::string body = R"( -OpCapability PhysicalStorageBufferAddressesEXT -OpCapability Int64 -OpCapability Shader -OpExtension "SPV_EXT_physical_storage_buffer" -OpMemoryModel PhysicalStorageBuffer64EXT GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpDecorate %val1 AliasedPointerEXT -%uint64 = OpTypeInt 64 0 -%ptr = OpTypePointer PhysicalStorageBufferEXT %uint64 -%val1 = OpVariable %ptr PhysicalStorageBufferEXT -%void = OpTypeVoid -%voidfn = OpTypeFunction %void -%main = OpFunction %void None %voidfn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(body); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("PhysicalStorageBufferEXT must not be used with OpVariable")); -} - -std::string GenCoopMatLoadStoreShader(const std::string& storeMemoryAccess, - const std::string& loadMemoryAccess) { - std::string s = R"( -OpCapability Shader -OpCapability GroupNonUniform -OpCapability VulkanMemoryModelKHR -OpCapability CooperativeMatrixNV -OpExtension "SPV_KHR_vulkan_memory_model" -OpExtension "SPV_NV_cooperative_matrix" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical VulkanKHR -OpEntryPoint GLCompute %4 "main" %11 %21 -OpExecutionMode %4 LocalSize 1 1 1 -OpDecorate %11 BuiltIn SubgroupId -OpDecorate %21 BuiltIn WorkgroupId -OpDecorate %74 ArrayStride 4 -OpMemberDecorate %75 0 Offset 0 -OpDecorate %75 Block -OpDecorate %77 DescriptorSet 0 -OpDecorate %77 Binding 0 -OpDecorate %92 ArrayStride 4 -OpMemberDecorate %93 0 Offset 0 -OpDecorate %93 Block -OpDecorate %95 DescriptorSet 0 -OpDecorate %95 Binding 1 -OpDecorate %102 ArrayStride 4 -OpMemberDecorate %103 0 Offset 0 -OpDecorate %103 Block -OpDecorate %105 DescriptorSet 0 -OpDecorate %105 Binding 2 -OpDecorate %117 ArrayStride 4 -OpMemberDecorate %118 0 Offset 0 -OpDecorate %118 Block -OpDecorate %120 DescriptorSet 0 -OpDecorate %120 Binding 3 -OpDecorate %123 SpecId 2 -OpDecorate %124 SpecId 3 -OpDecorate %125 SpecId 4 -OpDecorate %126 SpecId 5 -OpDecorate %127 SpecId 0 -OpDecorate %128 SpecId 1 -OpDecorate %129 BuiltIn WorkgroupSize -%2 = OpTypeVoid -%3 = OpTypeFunction %2 -%6 = OpTypeInt 32 0 -%7 = OpTypeVector %6 2 -%8 = OpTypePointer Function %7 -%10 = OpTypePointer Input %6 -%11 = OpVariable %10 Input -%13 = OpConstant %6 2 -%19 = OpTypeVector %6 3 -%20 = OpTypePointer Input %19 -%21 = OpVariable %20 Input -%27 = OpConstantComposite %7 %13 %13 -%31 = OpTypePointer Function %6 -%33 = OpConstant %6 1024 -%34 = OpConstant %6 1 -%38 = OpConstant %6 8 -%39 = OpConstant %6 0 -%68 = OpTypeFloat 32 -%69 = OpConstant %6 16 -%70 = OpConstant %6 3 -%71 = OpTypeCooperativeMatrixNV %68 %70 %69 %38 -%72 = OpTypePointer Function %71 -%74 = OpTypeRuntimeArray %68 -%75 = OpTypeStruct %74 -%76 = OpTypePointer StorageBuffer %75 -%77 = OpVariable %76 StorageBuffer -%78 = OpTypeInt 32 1 -%79 = OpConstant %78 0 -%81 = OpConstant %6 5 -%82 = OpTypePointer StorageBuffer %68 -%84 = OpConstant %6 64 -%85 = OpTypeBool -%86 = OpConstantFalse %85 -%88 = OpTypePointer Private %71 -%89 = OpVariable %88 Private -%92 = OpTypeRuntimeArray %68 -%93 = OpTypeStruct %92 -%94 = OpTypePointer StorageBuffer %93 -%95 = OpVariable %94 StorageBuffer -%99 = OpVariable %88 Private -%102 = OpTypeRuntimeArray %68 -%103 = OpTypeStruct %102 -%104 = OpTypePointer StorageBuffer %103 -%105 = OpVariable %104 StorageBuffer -%109 = OpVariable %88 Private -%111 = OpVariable %88 Private -%112 = OpSpecConstantOp %6 CooperativeMatrixLengthNV %71 -%113 = OpSpecConstantOp %78 IAdd %112 %79 -%117 = OpTypeRuntimeArray %68 -%118 = OpTypeStruct %117 -%119 = OpTypePointer StorageBuffer %118 -%120 = OpVariable %119 StorageBuffer -%123 = OpSpecConstant %78 1 -%124 = OpSpecConstant %78 1 -%125 = OpSpecConstant %78 1 -%126 = OpSpecConstant %78 1 -%127 = OpSpecConstant %6 1 -%128 = OpSpecConstant %6 1 -%129 = OpSpecConstantComposite %19 %127 %128 %34 -%4 = OpFunction %2 None %3 -%5 = OpLabel -%9 = OpVariable %8 Function -%18 = OpVariable %8 Function -%32 = OpVariable %31 Function -%44 = OpVariable %31 Function -%52 = OpVariable %31 Function -%60 = OpVariable %31 Function -%73 = OpVariable %72 Function -%91 = OpVariable %72 Function -%101 = OpVariable %72 Function -%12 = OpLoad %6 %11 -%14 = OpUMod %6 %12 %13 -%15 = OpLoad %6 %11 -%16 = OpUDiv %6 %15 %13 -%17 = OpCompositeConstruct %7 %14 %16 -OpStore %9 %17 -%22 = OpLoad %19 %21 -%23 = OpVectorShuffle %7 %22 %22 0 1 -%24 = OpCompositeExtract %6 %23 0 -%25 = OpCompositeExtract %6 %23 1 -%26 = OpCompositeConstruct %7 %24 %25 -%28 = OpIMul %7 %26 %27 -%29 = OpLoad %7 %9 -%30 = OpIAdd %7 %28 %29 -OpStore %18 %30 -%35 = OpAccessChain %31 %18 %34 -%36 = OpLoad %6 %35 -%37 = OpIMul %6 %33 %36 -%40 = OpAccessChain %31 %18 %39 -%41 = OpLoad %6 %40 -%42 = OpIMul %6 %38 %41 -%43 = OpIAdd %6 %37 %42 -OpStore %32 %43 -%45 = OpAccessChain %31 %18 %34 -%46 = OpLoad %6 %45 -%47 = OpIMul %6 %33 %46 -%48 = OpAccessChain %31 %18 %39 -%49 = OpLoad %6 %48 -%50 = OpIMul %6 %38 %49 -%51 = OpIAdd %6 %47 %50 -OpStore %44 %51 -%53 = OpAccessChain %31 %18 %34 -%54 = OpLoad %6 %53 -%55 = OpIMul %6 %33 %54 -%56 = OpAccessChain %31 %18 %39 -%57 = OpLoad %6 %56 -%58 = OpIMul %6 %38 %57 -%59 = OpIAdd %6 %55 %58 -OpStore %52 %59 -%61 = OpAccessChain %31 %18 %34 -%62 = OpLoad %6 %61 -%63 = OpIMul %6 %33 %62 -%64 = OpAccessChain %31 %18 %39 -%65 = OpLoad %6 %64 -%66 = OpIMul %6 %38 %65 -%67 = OpIAdd %6 %63 %66 -OpStore %60 %67 -%80 = OpLoad %6 %32 -%83 = OpAccessChain %82 %77 %79 %80 -%87 = OpCooperativeMatrixLoadNV %71 %83 %84 %86 )" + - loadMemoryAccess + R"( %81 -OpStore %73 %87 -%90 = OpLoad %71 %73 -OpStore %89 %90 -%96 = OpLoad %6 %44 -%97 = OpAccessChain %82 %95 %79 %96 -%98 = OpCooperativeMatrixLoadNV %71 %97 %84 %86 MakePointerVisibleKHR|NonPrivatePointerKHR %81 -OpStore %91 %98 -%100 = OpLoad %71 %91 -OpStore %99 %100 -%106 = OpLoad %6 %52 -%107 = OpAccessChain %82 %105 %79 %106 -%108 = OpCooperativeMatrixLoadNV %71 %107 %84 %86 MakePointerVisibleKHR|NonPrivatePointerKHR %81 -OpStore %101 %108 -%110 = OpLoad %71 %101 -OpStore %109 %110 -%114 = OpConvertSToF %68 %113 -%115 = OpCompositeConstruct %71 %114 -OpStore %111 %115 -%116 = OpLoad %71 %111 -%121 = OpLoad %6 %60 -%122 = OpAccessChain %82 %120 %79 %121 -OpCooperativeMatrixStoreNV %122 %116 %84 %86 )" + storeMemoryAccess + R"( %81 -OpReturn -OpFunctionEnd -)"; - - return s; -} - -TEST_F(ValidateMemory, CoopMatLoadStoreSuccess) { - std::string spirv = - GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR", - "MakePointerVisibleKHR|NonPrivatePointerKHR"); - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, CoopMatStoreMemoryAccessFail) { - std::string spirv = - GenCoopMatLoadStoreShader("MakePointerVisibleKHR|NonPrivatePointerKHR", - "MakePointerVisibleKHR|NonPrivatePointerKHR"); - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MakePointerVisibleKHR cannot be used with OpStore")); -} - -TEST_F(ValidateMemory, CoopMatLoadMemoryAccessFail) { - std::string spirv = - GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR", - "MakePointerAvailableKHR|NonPrivatePointerKHR"); - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad")); -} - -TEST_F(ValidateMemory, CoopMatInvalidStorageClassFail) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%f16 = OpTypeFloat 16 -%u32 = OpTypeInt 32 0 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 - -%str = OpTypeStruct %f16mat -%str_ptr = OpTypePointer Workgroup %str -%sh = OpVariable %str_ptr Workgroup - -%main = OpFunction %void None %func -%main_entry = OpLabel - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Cooperative matrix types (or types containing them) can only be " - "allocated in Function or Private storage classes or as function " - "parameters")); -} - -TEST_F(ValidateMemory, CoopMatMatrixLengthResultTypeBad) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%f16 = OpTypeFloat 16 -%u32 = OpTypeInt 32 0 -%i32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%1 = OpCooperativeMatrixLengthNV %i32 %f16mat - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The Result Type of OpCooperativeMatrixLengthNV " - "'11[%11]' must be OpTypeInt with width 32 and signedness 0")); -} - -TEST_F(ValidateMemory, CoopMatMatrixLengthOperandTypeBad) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%f16 = OpTypeFloat 16 -%u32 = OpTypeInt 32 0 -%i32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%1 = OpCooperativeMatrixLengthNV %u32 %u32 - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The type in OpCooperativeMatrixLengthNV '5[%uint]' " - "must be OpTypeCooperativeMatrixNV")); -} - -TEST_F(ValidateMemory, CoopMatMatrixLengthGood) { - const std::string body = - R"( -OpCapability Shader -OpCapability Float16 -OpCapability CooperativeMatrixNV -OpExtension "SPV_NV_cooperative_matrix" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -%void = OpTypeVoid -%func = OpTypeFunction %void -%f16 = OpTypeFloat 16 -%u32 = OpTypeInt 32 0 -%i32 = OpTypeInt 32 1 - -%u32_8 = OpConstant %u32 8 -%subgroup = OpConstant %u32 3 - -%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8 - -%main = OpFunction %void None %func -%main_entry = OpLabel - -%1 = OpCooperativeMatrixLengthNV %u32 %f16mat - -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(body.c_str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, VulkanRTAOutsideOfStructBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%sampler_t = OpTypeSampler -%array_t = OpTypeRuntimeArray %sampler_t -%array_ptr = OpTypePointer UniformConstant %array_t -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpVariable, '5[%5]', is attempting to create memory for an " - "illegal type, OpTypeRuntimeArray.\nFor Vulkan OpTypeRuntimeArray " - "can only appear as the final member of an OpTypeStruct, thus cannot " - "be instantiated via OpVariable\n %5 = OpVariable " - "%_ptr_UniformConstant__runtimearr_2 UniformConstant\n")); -} - -TEST_F(ValidateMemory, WebGPURTAOutsideOfStructBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%sampler_t = OpTypeSampler -%array_t = OpTypeRuntimeArray %sampler_t -%array_ptr = OpTypePointer UniformConstant %array_t -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpVariable, '5[%5]', is attempting to create memory for an " - "illegal type, OpTypeRuntimeArray.\nFor WebGPU OpTypeRuntimeArray " - "can only appear as the final member of an OpTypeStruct, thus cannot " - "be instantiated via OpVariable\n %5 = OpVariable " - "%_ptr_UniformConstant__runtimearr_2 UniformConstant\n")); -} - -TEST_F(ValidateMemory, VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -%sampler_t = OpTypeSampler -%uint = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %sampler_t -%struct = OpTypeStruct %uint -%sb_array_t = OpTypeRuntimeArray %struct -%array_sb_ptr = OpTypePointer StorageBuffer %sb_array_t -%2 = OpVariable %array_sb_ptr StorageBuffer -%array_uc_ptr = OpTypePointer UniformConstant %array_t -%3 = OpVariable %array_uc_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F( - ValidateMemory, - VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayAndWrongStorageClassBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%array_ptr = OpTypePointer Workgroup %array_t -%2 = OpVariable %array_ptr Workgroup -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("For Vulkan with RuntimeDescriptorArrayEXT, a variable " - "containing OpTypeRuntimeArray must have storage class of " - "StorageBuffer, Uniform, or UniformConstant.\n %5 = " - "OpVariable %_ptr_Workgroup__runtimearr_uint Workgroup\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, WebGPURTAInsideStorageBufferStructGood) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateMemory, VulkanRTAInsideWrongStorageClassStructBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer Workgroup %struct_t -%2 = OpVariable %struct_ptr Workgroup -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "For Vulkan, OpTypeStruct variables containing OpTypeRuntimeArray " - "must have storage class of StorageBuffer or Uniform.\n %6 = " - "OpVariable %_ptr_Workgroup__struct_4 Workgroup\n")); -} - -TEST_F(ValidateMemory, WebGPURTAInsideWrongStorageClassStructBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer Workgroup %struct_t -%2 = OpVariable %struct_ptr Workgroup -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("For WebGPU, OpTypeStruct variables containing " - "OpTypeRuntimeArray must have storage class of StorageBuffer\n " - " %6 = OpVariable %_ptr_Workgroup__struct_4 Workgroup\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructWithoutBlockBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For Vulkan, an OpTypeStruct variable containing an " - "OpTypeRuntimeArray must be decorated with Block if it " - "has storage class StorageBuffer.\n %6 = OpVariable " - "%_ptr_StorageBuffer__struct_4 StorageBuffer\n")); -} - -TEST_F(ValidateMemory, WebGPURTAInsideStorageBufferStructWithoutBlockBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, an OpTypeStruct variable containing an " - "OpTypeRuntimeArray must be decorated with Block if it " - "has storage class StorageBuffer.\n %6 = OpVariable " - "%_ptr_StorageBuffer__struct_4 StorageBuffer\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideUniformStructGood) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t BufferBlock -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer Uniform %struct_t -%2 = OpVariable %struct_ptr Uniform -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, WebGPURTAInsideUniformStructBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer Uniform %struct_t -%2 = OpVariable %struct_ptr Uniform -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("For WebGPU, OpTypeStruct variables containing " - "OpTypeRuntimeArray must have storage class of StorageBuffer\n " - " %6 = OpVariable %_ptr_Uniform__struct_3 Uniform\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideUniformStructWithoutBufferBlockBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer Uniform %struct_t -%2 = OpVariable %struct_ptr Uniform -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For Vulkan, an OpTypeStruct variable containing an " - "OpTypeRuntimeArray must be decorated with BufferBlock " - "if it has storage class Uniform.\n %6 = OpVariable " - "%_ptr_Uniform__struct_4 Uniform\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideRTABad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%sampler_t = OpTypeSampler -%inner_array_t = OpTypeRuntimeArray %sampler_t -%array_t = OpTypeRuntimeArray %inner_array_t -%array_ptr = OpTypePointer UniformConstant %array_t -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '3[%_runtimearr_2]' is not " - "valid in Vulkan environments.\n %_runtimearr__runtimearr_2 = " - "OpTypeRuntimeArray %_runtimearr_2\n")); -} - -TEST_F(ValidateMemory, WebGPURTAInsideRTABad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%sampler_t = OpTypeSampler -%inner_array_t = OpTypeRuntimeArray %sampler_t -%array_t = OpTypeRuntimeArray %inner_array_t -%array_ptr = OpTypePointer UniformConstant %array_t -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '3[%_runtimearr_2]' is not " - "valid in WebGPU environments.\n %_runtimearr__runtimearr_2 = " - "OpTypeRuntimeArray %_runtimearr_2\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t Block -%uint_t = OpTypeInt 32 0 -%inner_array_t = OpTypeRuntimeArray %uint_t -%array_t = OpTypeRuntimeArray %inner_array_t -%array_ptr = OpTypePointer StorageBuffer %array_t -%2 = OpVariable %array_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '4[%_runtimearr_uint]' is not " - "valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = " - "OpTypeRuntimeArray %_runtimearr_uint\n")); -} - -TEST_F(ValidateMemory, - VulkanUniformStructInsideRTAWithRuntimeDescriptorArrayGood) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%struct_t = OpTypeStruct %uint_t -%array_t = OpTypeRuntimeArray %struct_t -%array_ptr = OpTypePointer Uniform %array_t -%2 = OpVariable %array_ptr Uniform -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanRTAInsideRTAInsideStructBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%inner_array_t = OpTypeRuntimeArray %uint_t -%array_t = OpTypeRuntimeArray %inner_array_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '5[%_runtimearr_uint]' is not " - "valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = " - "OpTypeRuntimeArray %_runtimearr_uint\n")); -} - -TEST_F(ValidateMemory, - VulkanRTAInsideRTAInsideStructWithRuntimeDescriptorArrayBad) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%inner_array_t = OpTypeRuntimeArray %uint_t -%array_t = OpTypeRuntimeArray %inner_array_t -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '5[%_runtimearr_uint]' is not " - "valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = " - "OpTypeRuntimeArray %_runtimearr_uint\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideArrayBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%dim = OpConstant %uint_t 1 -%sampler_t = OpTypeSampler -%inner_array_t = OpTypeRuntimeArray %sampler_t -%array_t = OpTypeArray %inner_array_t %dim -%array_ptr = OpTypePointer UniformConstant %array_t -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpTypeArray Element Type '5[%_runtimearr_4]' is not " - "valid in Vulkan environments.\n %_arr__runtimearr_4_uint_1 = " - "OpTypeArray %_runtimearr_4 %uint_1\n")); -} - -TEST_F(ValidateMemory, WebGPURTAInsideArrayBad) { - std::string spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%uint_t = OpTypeInt 32 0 -%dim = OpConstant %uint_t 1 -%sampler_t = OpTypeSampler -%inner_array_t = OpTypeRuntimeArray %sampler_t -%array_t = OpTypeArray %inner_array_t %dim -%array_ptr = OpTypePointer UniformConstant %array_t -%2 = OpVariable %array_ptr UniformConstant -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpTypeArray Element Type '5[%_runtimearr_4]' is not " - "valid in WebGPU environments.\n %_arr__runtimearr_4_uint_1 = " - "OpTypeArray %_runtimearr_4 %uint_1\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t Block -%uint_t = OpTypeInt 32 0 -%dim = OpConstant %uint_t 1 -%sampler_t = OpTypeSampler -%inner_array_t = OpTypeRuntimeArray %uint_t -%array_t = OpTypeRuntimeArray %inner_array_t -%array_ptr = OpTypePointer StorageBuffer %array_t -%2 = OpVariable %array_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeRuntimeArray Element Type '6[%_runtimearr_uint]' is not " - "valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = " - "OpTypeRuntimeArray %_runtimearr_uint\n")); -} - -TEST_F(ValidateMemory, VulkanRTAInsideArrayInsideStructBad) { - std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%dim = OpConstant %uint_t 1 -%inner_array_t = OpTypeRuntimeArray %uint_t -%array_t = OpTypeArray %inner_array_t %dim -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeArray Element Type '6[%_runtimearr_uint]' is not " - "valid in Vulkan environments.\n %_arr__runtimearr_uint_uint_1 " - "= OpTypeArray %_runtimearr_uint %uint_1\n")); -} - -TEST_F(ValidateMemory, - VulkanRTAInsideArrayInsideStructWithRuntimeDescriptorArrayBad) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%dim = OpConstant %uint_t 1 -%inner_array_t = OpTypeRuntimeArray %uint_t -%array_t = OpTypeArray %inner_array_t %dim -%struct_t = OpTypeStruct %array_t -%struct_ptr = OpTypePointer StorageBuffer %struct_t -%2 = OpVariable %struct_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpTypeArray Element Type '6[%_runtimearr_uint]' is not " - "valid in Vulkan environments.\n %_arr__runtimearr_uint_uint_1 " - "= OpTypeArray %_runtimearr_uint %uint_1\n")); -} - -TEST_F(ValidateMemory, VulkanRTAStructInsideRTAWithRuntimeDescriptorArrayGood) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %inner_array_t ArrayStride 4 -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%inner_array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %inner_array_t -%array_t = OpTypeRuntimeArray %struct_t -%array_ptr = OpTypePointer StorageBuffer %array_t -%2 = OpVariable %array_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, VulkanRTAStructInsideArrayGood) { - std::string spirv = R"( -OpCapability RuntimeDescriptorArrayEXT -OpCapability Shader -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -OpDecorate %inner_array_t ArrayStride 4 -OpDecorate %array_t ArrayStride 4 -OpMemberDecorate %struct_t 0 Offset 0 -OpDecorate %struct_t Block -%uint_t = OpTypeInt 32 0 -%inner_array_t = OpTypeRuntimeArray %uint_t -%struct_t = OpTypeStruct %inner_array_t -%array_size = OpConstant %uint_t 5 -%array_t = OpTypeArray %struct_t %array_size -%array_ptr = OpTypePointer StorageBuffer %array_t -%2 = OpVariable %array_ptr StorageBuffer -%void = OpTypeVoid -%func_t = OpTypeFunction %void -%func = OpFunction %void None %func_t -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, CopyMemoryNoAccessGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateMemory, CopyMemorySimpleMixedAccessGood) { - // Test one memory access operand using features that don't require the - // Vulkan memory model. - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Volatile|Aligned|Nontemporal 4 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV13Bad) { - // Two memory access operands is invalid up to SPIR-V 1.3 - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Volatile Volatile -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("CopyMemory with two memory access operands requires " - "SPIR-V 1.4 or later")); -} - -TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV14Good) { - // Two memory access operands is valid in SPIR-V 1.4 - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemory %var1 %var2 Volatile Volatile -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateMemory, CopyMemorySizedNoAccessGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_16 = OpConstant %int 16 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %int_16 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -TEST_F(ValidateMemory, CopyMemorySizedSimpleMixedAccessGood) { - // Test one memory access operand using features that don't require the - // Vulkan memory model. - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_16 = OpConstant %int 16 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %int_16 Volatile|Aligned|Nontemporal 4 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV13Bad) { - // Two memory access operands is invalid up to SPIR-V 1.3 - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_16 = OpConstant %int 16 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("CopyMemorySized with two memory access operands requires " - "SPIR-V 1.4 or later")); -} - -TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV14Good) { - // Two memory access operands is valid in SPIR-V 1.4 - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability Addresses -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_16 = OpConstant %int 16 -%int_ptr_priv = OpTypePointer Private %int -%var1 = OpVariable %int_ptr_priv Private -%var2 = OpVariable %int_ptr_priv Private -%voidfn = OpTypeFunction %void -%func = OpFunction %void None %voidfn -%entry = OpLabel -OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), Eq("")); -} - -using ValidatePointerComparisons = spvtest::ValidateBase; - -TEST_P(ValidatePointerComparisons, Good) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer StorageBuffer %int -%var = OpVariable %ptr_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%var %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_P(ValidatePointerComparisons, GoodWorkgroup) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointers -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int Workgroup -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%var %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); -} - -TEST_P(ValidatePointerComparisons, BadResultType) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer StorageBuffer %int -%var = OpVariable %ptr_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %bool "; - } else { - spirv += " %int "; - } - - spirv += R"(%var %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - if (operation == "OpPtrDiff") { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result Type must be an integer scalar")); - } else { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Result Type must be OpTypeBool")); - } -} - -TEST_P(ValidatePointerComparisons, BadCapabilities) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer StorageBuffer %int -%var = OpVariable %ptr_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%var %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - if (operation == "OpPtrDiff") { - // Gets caught by the grammar. - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Instruction cannot be used without a variable " - "pointers capability")); - } -} - -TEST_P(ValidatePointerComparisons, BadOperandType) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer StorageBuffer %int -%var = OpVariable %ptr_int StorageBuffer -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%ld %ld -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Operand type must be a pointer")); -} - -TEST_P(ValidatePointerComparisons, BadStorageClassWorkgroup) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer Workgroup %int -%var = OpVariable %ptr_int Workgroup -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%var %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Workgroup storage class pointer requires " - "VariablePointers capability to be specified")); -} - -TEST_P(ValidatePointerComparisons, BadStorageClass) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer Private %int -%var = OpVariable %ptr_int Private -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%var %var -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid pointer storage class")); -} - -TEST_P(ValidatePointerComparisons, BadDiffOperandTypes) { - const std::string operation = GetParam(); - - std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%bool = OpTypeBool -%int = OpTypeInt 32 0 -%ptr_int = OpTypePointer Private %int -%var = OpVariable %ptr_int Private -%func_ty = OpTypeFunction %void -%func = OpFunction %void None %func_ty -%1 = OpLabel -%ld = OpLoad %int %var -%equal = )" + operation; - - if (operation == "OpPtrDiff") { - spirv += " %int "; - } else { - spirv += " %bool "; - } - - spirv += R"(%var %ld -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The types of Operand 1 and Operand 2 must match")); -} - -INSTANTIATE_TEST_SUITE_P(PointerComparisons, ValidatePointerComparisons, - Values("OpPtrEqual", "OpPtrNotEqual", "OpPtrDiff")); - -TEST_F(ValidateMemory, VariableInitializerWrongType) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability VariablePointersStorageBuffer -OpMemoryModel Logical GLSL450 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%float = OpTypeFloat 32 -%ptr_wg_int = OpTypePointer Workgroup %int -%ptr_wg_float = OpTypePointer Workgroup %int -%wg_var = OpVariable %ptr_wg_int Workgroup -%ptr_private_wg_float = OpTypePointer Private %ptr_wg_float -%priv_var = OpVariable %ptr_private_wg_float Private %wg_var -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Initializer type must match the type pointed to by " - "the Result Type")); -} - -TEST_F(ValidateMemory, StoreToUniformBlock) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int4 = OpTypeVector %int 4 -%struct = OpTypeStruct %int4 -%ptr_uniform_struct = OpTypePointer Uniform %struct -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_struct Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 -%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMemory, StoreToUniformBlockVulkan) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int4 = OpTypeVector %int 4 -%struct = OpTypeStruct %int4 -%ptr_uniform_struct = OpTypePointer Uniform %struct -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_struct Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 -%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks")); -} - -// This test requires that the struct is not id 2. -TEST_F(ValidateMemory, StoreToUniformBlockVulkan2) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %gid_var -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %3 Block -OpMemberDecorate %3 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -OpDecorate %gid_var BuiltIn GlobalInvocationId -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int3 = OpTypeVector %int 3 -%int4 = OpTypeVector %int 4 -%3 = OpTypeStruct %int4 -%ptr_uniform_struct = OpTypePointer Uniform %3 -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_struct Uniform -%ptr_input_int3 = OpTypePointer Input %int3 -%gid_var = OpVariable %ptr_input_int3 Input -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 -%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks")); -} - -TEST_F(ValidateMemory, StoreToUniformBufferBlockVulkan) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct BufferBlock -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int4 = OpTypeVector %int 4 -%struct = OpTypeStruct %int4 -%ptr_uniform_struct = OpTypePointer Uniform %struct -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_struct Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 -%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int4 = OpTypeVector %int 4 -%struct = OpTypeStruct %int4 -%array_struct = OpTypeArray %struct %int_1 -%ptr_uniform_array = OpTypePointer Uniform %array_struct -%ptr_uniform_struct = OpTypePointer Uniform %struct -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_array Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0 -%gep2 = OpCopyObject %ptr_uniform_int %gep1 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks")); -} - -// This test requires that the struct is not id 2. -TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray2) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" %gid_var -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -OpDecorate %gid_var BuiltIn GlobalInvocationId -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int3 = OpTypeVector %int 3 -%int4 = OpTypeVector %int 4 -%struct = OpTypeStruct %int4 -%array_struct = OpTypeArray %struct %int_1 -%ptr_uniform_array = OpTypePointer Uniform %array_struct -%ptr_uniform_struct = OpTypePointer Uniform %struct -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_array Uniform -%ptr_input_int3 = OpTypePointer Input %int3 -%gid_var = OpVariable %ptr_input_int3 Input -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0 -%gep2 = OpCopyObject %ptr_uniform_int %gep1 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks")); -} - -TEST_F(ValidateMemory, StoreToUniformBlockVulkanRuntimeArray) { - const std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -OpDecorate %struct Block -OpMemberDecorate %struct 0 Offset 0 -OpDecorate %var DescriptorSet 0 -OpDecorate %var Binding 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int4 = OpTypeVector %int 4 -%struct = OpTypeStruct %int4 -%array_struct = OpTypeRuntimeArray %struct -%ptr_uniform_array = OpTypePointer Uniform %array_struct -%ptr_uniform_struct = OpTypePointer Uniform %struct -%ptr_uniform_int4 = OpTypePointer Uniform %int4 -%ptr_uniform_int = OpTypePointer Uniform %int -%var = OpVariable %ptr_uniform_array Uniform -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 %int_0 -%gep2 = OpInBoundsAccessChain %ptr_uniform_int %gep1 %int_0 -OpStore %gep2 %int_0 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks")); -} - -using ValidateSizedVariable = - spvtest::ValidateBase>; - -CodeGenerator GetSizedVariableCodeGenerator(bool is_8bit) { - CodeGenerator generator; - generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n"; - generator.extensions_ = - "OpExtension \"SPV_KHR_16bit_storage\"\nOpExtension " - "\"SPV_KHR_8bit_storage\"\n"; - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - if (is_8bit) { - generator.before_types_ = R"(OpDecorate %char_buffer_block BufferBlock -OpMemberDecorate %char_buffer_block 0 Offset 0 -)"; - generator.types_ = R"(%void = OpTypeVoid -%char = OpTypeInt 8 0 -%char4 = OpTypeVector %char 4 -%char_buffer_block = OpTypeStruct %char -)"; - } else { - generator.before_types_ = R"(OpDecorate %half_buffer_block BufferBlock -OpDecorate %short_buffer_block BufferBlock -OpMemberDecorate %half_buffer_block 0 Offset 0 -OpMemberDecorate %short_buffer_block 0 Offset 0 -)"; - generator.types_ = R"(%void = OpTypeVoid -%short = OpTypeInt 16 0 -%half = OpTypeFloat 16 -%short4 = OpTypeVector %short 4 -%half4 = OpTypeVector %half 4 -%mat4x4 = OpTypeMatrix %half4 4 -%short_buffer_block = OpTypeStruct %short -%half_buffer_block = OpTypeStruct %half -)"; - } - generator.after_types_ = R"(%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -)"; - generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n"; - return generator; -} - -TEST_P(ValidateSizedVariable, Capability) { - const std::string storage_class = std::get<0>(GetParam()); - const std::string capability = std::get<1>(GetParam()); - const std::string var_type = std::get<2>(GetParam()); - - bool type_8bit = false; - if (var_type == "%char" || var_type == "%char4" || - var_type == "%char_buffer_block") { - type_8bit = true; - } - - auto generator = GetSizedVariableCodeGenerator(type_8bit); - generator.types_ += "%ptr_type = OpTypePointer " + storage_class + " " + - var_type + "\n%var = OpVariable %ptr_type " + - storage_class + "\n"; - generator.capabilities_ += "OpCapability " + capability + "\n"; - - bool capability_ok = false; - bool storage_class_ok = false; - if (storage_class == "Input" || storage_class == "Output") { - if (!type_8bit) { - capability_ok = capability == "StorageInputOutput16"; - storage_class_ok = true; - } - } else if (storage_class == "StorageBuffer") { - if (type_8bit) { - capability_ok = capability == "StorageBuffer8BitAccess" || - capability == "UniformAndStorageBuffer8BitAccess"; - } else { - capability_ok = capability == "StorageBuffer16BitAccess" || - capability == "UniformAndStorageBuffer16BitAccess"; - } - storage_class_ok = true; - } else if (storage_class == "PushConstant") { - if (type_8bit) { - capability_ok = capability == "StoragePushConstant8"; - } else { - capability_ok = capability == "StoragePushConstant16"; - } - storage_class_ok = true; - } else if (storage_class == "Uniform") { - bool buffer_block = var_type.find("buffer_block") != std::string::npos; - if (type_8bit) { - capability_ok = capability == "UniformAndStorageBuffer8BitAccess" || - (capability == "StorageBuffer8BitAccess" && buffer_block); - } else { - capability_ok = - capability == "UniformAndStorageBuffer16BitAccess" || - (capability == "StorageBuffer16BitAccess" && buffer_block); - } - storage_class_ok = true; - } - - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - spv_result_t result = ValidateInstructions(SPV_ENV_UNIVERSAL_1_3); - if (capability_ok) { - EXPECT_EQ(SPV_SUCCESS, result); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_ID, result); - if (storage_class_ok) { - std::string message = std::string("Allocating a variable containing a ") + - (type_8bit ? "8" : "16") + "-bit element in " + - storage_class + - " storage class requires an additional capability"; - EXPECT_THAT(getDiagnosticString(), HasSubstr(message)); - } else { - std::string message = - std::string("Cannot allocate a variable containing a ") + - (type_8bit ? "8" : "16") + "-bit type in " + storage_class + - " storage class"; - EXPECT_THAT(getDiagnosticString(), HasSubstr(message)); - } - } -} - -INSTANTIATE_TEST_SUITE_P( - Storage8, ValidateSizedVariable, - Combine(Values("UniformConstant", "Input", "Output", "Workgroup", - "CrossWorkgroup", "Private", "StorageBuffer", "Uniform"), - Values("StorageBuffer8BitAccess", - "UniformAndStorageBuffer8BitAccess", "StoragePushConstant8"), - Values("%char", "%char4", "%char_buffer_block"))); - -INSTANTIATE_TEST_SUITE_P( - Storage16, ValidateSizedVariable, - Combine(Values("UniformConstant", "Input", "Output", "Workgroup", - "CrossWorkgroup", "Private", "StorageBuffer", "Uniform"), - Values("StorageBuffer16BitAccess", - "UniformAndStorageBuffer16BitAccess", - "StoragePushConstant16", "StorageInputOutput16"), - Values("%short", "%half", "%short4", "%half4", "%mat4x4", - "%short_buffer_block", "%half_buffer_block"))); - -using ValidateSizedLoadStore = - spvtest::ValidateBase>; - -CodeGenerator GetSizedLoadStoreCodeGenerator(const std::string& base_type, - uint32_t width) { - CodeGenerator generator; - generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n"; - if (width == 8) { - generator.capabilities_ += - "OpCapability UniformAndStorageBuffer8BitAccess\n"; - generator.extensions_ = "OpExtension \"SPV_KHR_8bit_storage\"\n"; - } else { - generator.capabilities_ += - "OpCapability UniformAndStorageBuffer16BitAccess\n"; - generator.extensions_ = "OpExtension \"SPV_KHR_16bit_storage\"\n"; - } - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - generator.before_types_ = R"(OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -OpMemberDecorate %struct 0 Offset 0 -)"; - generator.types_ = R"(%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_3 = OpConstant %int 3 -)"; - - if (width == 8) { - generator.types_ += R"(%scalar = OpTypeInt 8 0 -%vector = OpTypeVector %scalar 4 -%struct = OpTypeStruct %vector -)"; - } else if (base_type == "int") { - generator.types_ += R"(%scalar = OpTypeInt 16 0 -%vector = OpTypeVector %scalar 4 -%struct = OpTypeStruct %vector -)"; - } else { - generator.types_ += R"(%scalar = OpTypeFloat 16 -%vector = OpTypeVector %scalar 4 -%matrix = OpTypeMatrix %vector 4 -%struct = OpTypeStruct %matrix -%ptr_ssbo_matrix = OpTypePointer StorageBuffer %matrix -)"; - generator.before_types_ += R"(OpMemberDecorate %struct 0 RowMajor -OpMemberDecorate %struct 0 MatrixStride 16 -)"; - } - generator.types_ += R"(%block = OpTypeStruct %struct -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct -%ptr_ssbo_vector = OpTypePointer StorageBuffer %vector -%ptr_ssbo_scalar = OpTypePointer StorageBuffer %scalar -%ld_var = OpVariable %ptr_ssbo_block StorageBuffer -%st_var = OpVariable %ptr_ssbo_block StorageBuffer -)"; - - generator.after_types_ = R"(%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -)"; - generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n"; - return generator; -} - -TEST_P(ValidateSizedLoadStore, Load) { - std::string base_type = std::get<0>(GetParam()); - uint32_t width = std::get<1>(GetParam()); - std::string mem_type = std::get<2>(GetParam()); - - CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width); - generator.after_types_ += - "%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0"; - if (mem_type != "struct") { - generator.after_types_ += " %int_0"; - if (mem_type != "matrix" && base_type == "float") { - generator.after_types_ += " %int_0"; - } - if (mem_type == "scalar") { - generator.after_types_ += " %int_0"; - } - } - generator.after_types_ += "\n"; - generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n"; - - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - if (mem_type == "struct") { - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "8- or 16-bit loads must be a scalar, vector or matrix type")); - } else { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - } -} - -TEST_P(ValidateSizedLoadStore, Store) { - std::string base_type = std::get<0>(GetParam()); - uint32_t width = std::get<1>(GetParam()); - std::string mem_type = std::get<2>(GetParam()); - - CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width); - generator.after_types_ += - "%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0"; - if (mem_type != "struct") { - generator.after_types_ += " %int_0"; - if (mem_type != "matrix" && base_type == "float") { - generator.after_types_ += " %int_0"; - } - if (mem_type == "scalar") { - generator.after_types_ += " %int_0"; - } - } - generator.after_types_ += "\n"; - generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n"; - generator.after_types_ += - "%st_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %st_var %int_0"; - if (mem_type != "struct") { - generator.after_types_ += " %int_0"; - if (mem_type != "matrix" && base_type == "float") { - generator.after_types_ += " %int_0"; - } - if (mem_type == "scalar") { - generator.after_types_ += " %int_0"; - } - } - generator.after_types_ += "\n"; - generator.after_types_ += "OpStore %st_gep %ld\n"; - - CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3); - if (mem_type == "struct") { - EXPECT_EQ(SPV_ERROR_INVALID_ID, - ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - // Can only catch the load. - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "8- or 16-bit loads must be a scalar, vector or matrix type")); - } else { - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - } -} - -INSTANTIATE_TEST_SUITE_P(LoadStoreInt8, ValidateSizedLoadStore, - Combine(Values("int"), Values(8u), - Values("scalar", "vector", "struct"))); -INSTANTIATE_TEST_SUITE_P(LoadStoreInt16, ValidateSizedLoadStore, - Combine(Values("int"), Values(16u), - Values("scalar", "vector", "struct"))); -INSTANTIATE_TEST_SUITE_P(LoadStoreFloat16, ValidateSizedLoadStore, - Combine(Values("float"), Values(16u), - Values("scalar", "vector", "matrix", - "struct"))); - -TEST_F(ValidateMemory, SmallStorageCopyMemoryChar) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer8BitAccess -OpExtension "SPV_KHR_8bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%char = OpTypeInt 8 0 -%block = OpTypeStruct %char -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%in = OpVariable %ptr_ssbo_block StorageBuffer -%out = OpVariable %ptr_ssbo_block StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %out %in -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types")); -} - -TEST_F(ValidateMemory, SmallStorageCopyMemoryShort) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%short = OpTypeInt 16 0 -%block = OpTypeStruct %short -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%in = OpVariable %ptr_ssbo_block StorageBuffer -%out = OpVariable %ptr_ssbo_block StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %out %in -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types")); -} - -TEST_F(ValidateMemory, SmallStorageCopyMemoryHalf) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability UniformAndStorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int_0 = OpConstant %int 0 -%half = OpTypeFloat 16 -%block = OpTypeStruct %half -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%in = OpVariable %ptr_ssbo_block StorageBuffer -%out = OpVariable %ptr_ssbo_block StorageBuffer -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entry = OpLabel -OpCopyMemory %out %in -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types")); -} - -TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockShort) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block BufferBlock -OpMemberDecorate %block 0 Offset 0 -%void = OpTypeVoid -%short = OpTypeInt 16 0 -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%block = OpTypeStruct %short -%block_array = OpTypeArray %block %int_4 -%ptr_block_array = OpTypePointer Uniform %block_array -%var = OpVariable %ptr_block_array Uniform -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockChar) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer8BitAccess -OpExtension "SPV_KHR_8bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block BufferBlock -OpMemberDecorate %block 0 Offset 0 -%void = OpTypeVoid -%char = OpTypeInt 8 0 -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%block = OpTypeStruct %char -%block_array = OpTypeArray %block %int_4 -%ptr_block_array = OpTypePointer Uniform %block_array -%var = OpVariable %ptr_block_array Uniform -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockHalf) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -OpDecorate %block BufferBlock -OpMemberDecorate %block 0 Offset 0 -%void = OpTypeVoid -%half = OpTypeFloat 16 -%int = OpTypeInt 32 0 -%int_4 = OpConstant %int 4 -%block = OpTypeStruct %half -%block_array = OpTypeArray %block %int_4 -%ptr_block_array = OpTypePointer Uniform %block_array -%var = OpVariable %ptr_block_array Uniform -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); -} - -TEST_F(ValidateMemory, VulkanStorageBufferNotAStruct) { - const std::string spirv = R"( -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%ptr_ssbo = OpTypePointer StorageBuffer %uint -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nVariables identified with " - "the StorageBuffer storage class are used to access " - "transparent buffer backed resources. Such variables must be " - "typed as OpTypeStruct, or an array of this type")); -} - -TEST_F(ValidateMemory, VulkanStorageBufferRuntimeArrayNotAStruct) { - const std::string spirv = R"( -OpCapability Shader -OpCapability RuntimeDescriptorArrayEXT -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpExtension "SPV_EXT_descriptor_indexing" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%array = OpTypeRuntimeArray %uint -%ptr_ssbo = OpTypePointer StorageBuffer %array -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nVariables identified with " - "the StorageBuffer storage class are used to access " - "transparent buffer backed resources. Such variables must be " - "typed as OpTypeStruct, or an array of this type")); -} - -TEST_F(ValidateMemory, VulkanStorageBufferArrayNotAStruct) { - const std::string spirv = R"( -OpCapability Shader -OpExtension "SPV_KHR_storage_buffer_storage_class" -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%uint = OpTypeInt 32 0 -%uint_4 = OpConstant %uint 4 -%array = OpTypeArray %uint %uint_4 -%ptr_ssbo = OpTypePointer StorageBuffer %array -%var = OpVariable %ptr_ssbo StorageBuffer -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("From Vulkan spec, section 14.5.2:\nVariables identified with " - "the StorageBuffer storage class are used to access " - "transparent buffer backed resources. Such variables must be " - "typed as OpTypeStruct, or an array of this type")); -} - -TEST_F(ValidateMemory, PhysicalStorageBufferPtrEqual) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Int64 -OpCapability PhysicalStorageBufferAddresses -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%bool = OpTypeBool -%long = OpTypeInt 64 0 -%long_0 = OpConstant %long 0 -%ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%conv = OpConvertUToPtr %ptr_pssbo_long %long_0 -%eq = OpPtrEqual %bool %conv %conv -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Cannot use a pointer in the PhysicalStorageBuffer storage class")); -} - -TEST_F(ValidateMemory, PhysicalStorageBufferPtrNotEqual) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Int64 -OpCapability PhysicalStorageBufferAddresses -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%bool = OpTypeBool -%long = OpTypeInt 64 0 -%long_0 = OpConstant %long 0 -%ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%conv = OpConvertUToPtr %ptr_pssbo_long %long_0 -%neq = OpPtrNotEqual %bool %conv %conv -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Cannot use a pointer in the PhysicalStorageBuffer storage class")); -} - -TEST_F(ValidateMemory, PhysicalStorageBufferPtrDiff) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Int64 -OpCapability PhysicalStorageBufferAddresses -OpCapability VariablePointers -OpMemoryModel PhysicalStorageBuffer64 GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -%void = OpTypeVoid -%long = OpTypeInt 64 0 -%long_0 = OpConstant %long 0 -%ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -%conv = OpConvertUToPtr %ptr_pssbo_long %long_0 -%diff = OpPtrDiff %long %conv %conv -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Cannot use a pointer in the PhysicalStorageBuffer storage class")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_misc_test.cpp b/3rdparty/spirv-tools/test/val/val_misc_test.cpp deleted file mode 100644 index 93954844e..000000000 --- a/3rdparty/spirv-tools/test/val/val_misc_test.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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. - -// Validation tests for misc instructions - -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; - -using ValidateMisc = spvtest::ValidateBase; - -TEST_F(ValidateMisc, UndefRestrictedShort) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -%short = OpTypeInt 16 0 -%undef = OpUndef %short -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot create undefined values with 8- or 16-bit types")); -} - -TEST_F(ValidateMisc, UndefRestrictedChar) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer8BitAccess -OpExtension "SPV_KHR_8bit_storage" -OpMemoryModel Logical GLSL450 -%char = OpTypeInt 8 0 -%undef = OpUndef %char -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot create undefined values with 8- or 16-bit types")); -} - -TEST_F(ValidateMisc, UndefRestrictedHalf) { - const std::string spirv = R"( -OpCapability Shader -OpCapability Linkage -OpCapability StorageBuffer16BitAccess -OpExtension "SPV_KHR_16bit_storage" -OpMemoryModel Logical GLSL450 -%half = OpTypeFloat 16 -%undef = OpUndef %half -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Cannot create undefined values with 8- or 16-bit types")); -} - -const std::string ShaderClockSpriv = R"( -OpCapability Shader -OpCapability Int64 -OpCapability ShaderClockKHR -OpExtension "SPV_KHR_shader_clock" -%1 = OpExtInstImport "GLSL.std.450" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpSource GLSL 450 -OpSourceExtension "GL_ARB_gpu_shader_int64" -OpSourceExtension "GL_ARB_shader_clock" -OpSourceExtension "GL_EXT_shader_realtime_clock" -OpName %main "main" -OpName %time1 "time1" -%void = OpTypeVoid -)"; - -TEST_F(ValidateMisc, ShaderClockInt64) { - const std::string spirv = ShaderClockSpriv + R"( -%3 = OpTypeFunction %void -%uint = OpTypeInt 32 0 -%_ptr_Function_uint = OpTypePointer Function %uint -%uint_3 = OpConstant %uint 3 -%uint_1 = OpConstant %uint 1 -%main = OpFunction %void None %3 -%5 = OpLabel -%time1 = OpVariable %_ptr_Function_uint Function -%11 = OpReadClockKHR %uint %uint_3 -OpStore %time1 %11 -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("or 64bit unsigned integer")); -} - -TEST_F(ValidateMisc, ShaderClockVec2) { - const std::string spirv = ShaderClockSpriv + R"( -%3 = OpTypeFunction %void -%ulong = OpTypeInt 64 0 -%_ptr_Function_ulong = OpTypePointer Function %ulong -%uint = OpTypeInt 32 0 -%uint_3 = OpConstant %uint 3 -%v2uint = OpTypeVector %ulong 2 -%_ptr_Function_v2uint = OpTypePointer Function %v2uint -%main = OpFunction %void None %3 -%5 = OpLabel -%time1 = OpVariable %_ptr_Function_v2uint Function -%15 = OpReadClockKHR %v2uint %uint_3 -OpStore %time1 %15 -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("vector of two components")); -} - -TEST_F(ValidateMisc, ShaderClockInvalidScopeValue) { - const std::string spirv = ShaderClockSpriv + R"( -%3 = OpTypeFunction %void -%ulong = OpTypeInt 64 0 -%uint = OpTypeInt 32 0 -%_ptr_Function_ulong = OpTypePointer Function %ulong -%uint_10 = OpConstant %uint 10 -%uint_1 = OpConstant %uint 1 -%main = OpFunction %void None %3 -%5 = OpLabel -%time1 = OpVariable %_ptr_Function_ulong Function -%11 = OpReadClockKHR %ulong %uint_10 -OpStore %time1 %11 -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("Invalid scope value")); -} - -TEST_F(ValidateMisc, ShaderClockSubgroupScope) { - const std::string spirv = ShaderClockSpriv + R"( -%3 = OpTypeFunction %void -%ulong = OpTypeInt 64 0 -%uint = OpTypeInt 32 0 -%_ptr_Function_ulong = OpTypePointer Function %ulong -%subgroup = OpConstant %uint 3 -%uint_1 = OpConstant %uint 1 -%main = OpFunction %void None %3 -%5 = OpLabel -%time1 = OpVariable %_ptr_Function_ulong Function -%11 = OpReadClockKHR %ulong %subgroup -OpStore %time1 %11 -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMisc, ShaderClockDeviceScope) { - const std::string spirv = ShaderClockSpriv + R"( -%3 = OpTypeFunction %void -%ulong = OpTypeInt 64 0 -%uint = OpTypeInt 32 0 -%_ptr_Function_ulong = OpTypePointer Function %ulong -%device = OpConstant %uint 1 -%uint_1 = OpConstant %uint 1 -%main = OpFunction %void None %3 -%5 = OpLabel -%time1 = OpVariable %_ptr_Function_ulong Function -%11 = OpReadClockKHR %ulong %device -OpStore %time1 %11 -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMisc, ShaderClockWorkgroupScope) { - const std::string spirv = ShaderClockSpriv + R"( -%3 = OpTypeFunction %void -%ulong = OpTypeInt 64 0 -%uint = OpTypeInt 32 0 -%_ptr_Function_ulong = OpTypePointer Function %ulong -%workgroup = OpConstant %uint 2 -%uint_1 = OpConstant %uint 1 -%main = OpFunction %void None %3 -%5 = OpLabel -%time1 = OpVariable %_ptr_Function_ulong Function -%11 = OpReadClockKHR %ulong %workgroup -OpStore %time1 %11 -OpReturn -OpFunctionEnd)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Scope must be Subgroup or Device")); -} -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_modes_test.cpp b/3rdparty/spirv-tools/test/val/val_modes_test.cpp deleted file mode 100644 index 688f43399..000000000 --- a/3rdparty/spirv-tools/test/val/val_modes_test.cpp +++ /dev/null @@ -1,1183 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "source/spirv_target_env.h" -#include "test/test_fixture.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Combine; -using ::testing::HasSubstr; -using ::testing::Values; -using ::testing::ValuesIn; - -using ValidateMode = spvtest::ValidateBase; - -const std::string kVoidFunction = R"(%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpReturn -OpFunctionEnd -)"; - -TEST_F(ValidateMode, GLComputeNoMode) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMode, GLComputeNoModeVulkan) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the Vulkan environment, GLCompute execution model entry " - "points require either the LocalSize execution mode or an " - "object decorated with WorkgroupSize must be specified.")); -} - -TEST_F(ValidateMode, GLComputeNoModeVulkanWorkgroupSize) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpDecorate %int3_1 BuiltIn WorkgroupSize -%int = OpTypeInt 32 0 -%int3 = OpTypeVector %int 3 -%int_1 = OpConstant %int 1 -%int3_1 = OpConstantComposite %int3 %int_1 %int_1 %int_1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateMode, GLComputeVulkanLocalSize) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %main "main" -OpExecutionMode %main LocalSize 1 1 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateMode, FragmentOriginLowerLeftVulkan) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginLowerLeft -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In the Vulkan environment, the OriginLowerLeft " - "execution mode must not be used.")); -} - -TEST_F(ValidateMode, FragmentPixelCenterIntegerVulkan) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main PixelCenterInteger -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_VULKAN_1_0; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In the Vulkan environment, the PixelCenterInteger " - "execution mode must not be used.")); -} - -TEST_F(ValidateMode, GeometryNoOutputMode) { - const std::string spirv = R"( -OpCapability Geometry -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" -OpExecutionMode %main InputPoints -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Geometry execution model entry points must specify " - "exactly one of OutputPoints, OutputLineStrip or " - "OutputTriangleStrip execution modes.")); -} - -TEST_F(ValidateMode, GeometryNoInputMode) { - const std::string spirv = R"( -OpCapability Geometry -OpMemoryModel Logical GLSL450 -OpEntryPoint Geometry %main "main" -OpExecutionMode %main OutputPoints -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Geometry execution model entry points must specify exactly " - "one of InputPoints, InputLines, InputLinesAdjacency, " - "Triangles or InputTrianglesAdjacency execution modes.")); -} - -TEST_F(ValidateMode, FragmentNoOrigin) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Fragment execution model entry points require either an " - "OriginUpperLeft or OriginLowerLeft execution mode.")); -} - -TEST_F(ValidateMode, FragmentBothOrigins) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main OriginLowerLeft -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Fragment execution model entry points can only specify one of " - "OriginUpperLeft or OriginLowerLeft execution modes.")); -} - -TEST_F(ValidateMode, FragmentDepthGreaterAndLess) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main DepthGreater -OpExecutionMode %main DepthLess -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Fragment execution model entry points can specify at " - "most one of DepthGreater, DepthLess or DepthUnchanged " - "execution modes.")); -} - -TEST_F(ValidateMode, FragmentDepthGreaterAndUnchanged) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main DepthGreater -OpExecutionMode %main DepthUnchanged -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Fragment execution model entry points can specify at " - "most one of DepthGreater, DepthLess or DepthUnchanged " - "execution modes.")); -} - -TEST_F(ValidateMode, FragmentDepthLessAndUnchanged) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main DepthLess -OpExecutionMode %main DepthUnchanged -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Fragment execution model entry points can specify at " - "most one of DepthGreater, DepthLess or DepthUnchanged " - "execution modes.")); -} - -TEST_F(ValidateMode, FragmentAllDepths) { - const std::string spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main DepthGreater -OpExecutionMode %main DepthLess -OpExecutionMode %main DepthUnchanged -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Fragment execution model entry points can specify at " - "most one of DepthGreater, DepthLess or DepthUnchanged " - "execution modes.")); -} - -TEST_F(ValidateMode, TessellationControlSpacingEqualAndFractionalOdd) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %main "main" -OpExecutionMode %main SpacingEqual -OpExecutionMode %main SpacingFractionalOdd -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, TessellationControlSpacingEqualAndSpacingFractionalEven) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %main "main" -OpExecutionMode %main SpacingEqual -OpExecutionMode %main SpacingFractionalEven -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, - TessellationControlSpacingFractionalOddAndSpacingFractionalEven) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %main "main" -OpExecutionMode %main SpacingFractionalOdd -OpExecutionMode %main SpacingFractionalEven -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, TessellationControlAllSpacing) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %main "main" -OpExecutionMode %main SpacingEqual -OpExecutionMode %main SpacingFractionalOdd -OpExecutionMode %main SpacingFractionalEven -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, - TessellationEvaluationSpacingEqualAndSpacingFractionalOdd) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" -OpExecutionMode %main SpacingEqual -OpExecutionMode %main SpacingFractionalOdd -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, - TessellationEvaluationSpacingEqualAndSpacingFractionalEven) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" -OpExecutionMode %main SpacingEqual -OpExecutionMode %main SpacingFractionalEven -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, - TessellationEvaluationSpacingFractionalOddAndSpacingFractionalEven) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" -OpExecutionMode %main SpacingFractionalOdd -OpExecutionMode %main SpacingFractionalEven -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, TessellationEvaluationAllSpacing) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" -OpExecutionMode %main SpacingEqual -OpExecutionMode %main SpacingFractionalOdd -OpExecutionMode %main SpacingFractionalEven -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify " - "at most one of SpacingEqual, SpacingFractionalOdd or " - "SpacingFractionalEven execution modes.")); -} - -TEST_F(ValidateMode, TessellationControlBothVertex) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationControl %main "main" -OpExecutionMode %main VertexOrderCw -OpExecutionMode %main VertexOrderCcw -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify at most " - "one of VertexOrderCw or VertexOrderCcw execution modes.")); -} - -TEST_F(ValidateMode, TessellationEvaluationBothVertex) { - const std::string spirv = R"( -OpCapability Tessellation -OpMemoryModel Logical GLSL450 -OpEntryPoint TessellationEvaluation %main "main" -OpExecutionMode %main VertexOrderCw -OpExecutionMode %main VertexOrderCcw -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Tessellation execution model entry points can specify at most " - "one of VertexOrderCw or VertexOrderCcw execution modes.")); -} - -using ValidateModeGeometry = spvtest::ValidateBase, - std::tuple>>; - -TEST_P(ValidateModeGeometry, ExecutionMode) { - std::vector input_modes; - std::vector output_modes; - input_modes.push_back(std::get<0>(std::get<0>(GetParam()))); - input_modes.push_back(std::get<1>(std::get<0>(GetParam()))); - input_modes.push_back(std::get<2>(std::get<0>(GetParam()))); - input_modes.push_back(std::get<3>(std::get<0>(GetParam()))); - input_modes.push_back(std::get<4>(std::get<0>(GetParam()))); - output_modes.push_back(std::get<0>(std::get<1>(GetParam()))); - output_modes.push_back(std::get<1>(std::get<1>(GetParam()))); - output_modes.push_back(std::get<2>(std::get<1>(GetParam()))); - - std::ostringstream sstr; - sstr << "OpCapability Geometry\n"; - sstr << "OpMemoryModel Logical GLSL450\n"; - sstr << "OpEntryPoint Geometry %main \"main\"\n"; - size_t num_input_modes = 0; - for (auto input : input_modes) { - if (!input.empty()) { - num_input_modes++; - sstr << "OpExecutionMode %main " << input << "\n"; - } - } - size_t num_output_modes = 0; - for (auto output : output_modes) { - if (!output.empty()) { - num_output_modes++; - sstr << "OpExecutionMode %main " << output << "\n"; - } - } - sstr << "%void = OpTypeVoid\n"; - sstr << "%void_fn = OpTypeFunction %void\n"; - sstr << "%int = OpTypeInt 32 0\n"; - sstr << "%int1 = OpConstant %int 1\n"; - sstr << "%main = OpFunction %void None %void_fn\n"; - sstr << "%entry = OpLabel\n"; - sstr << "OpReturn\n"; - sstr << "OpFunctionEnd\n"; - - CompileSuccessfully(sstr.str()); - if (num_input_modes == 1 && num_output_modes == 1) { - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); - } else { - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - if (num_input_modes != 1) { - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Geometry execution model entry points must " - "specify exactly one of InputPoints, InputLines, " - "InputLinesAdjacency, Triangles or " - "InputTrianglesAdjacency execution modes.")); - } else { - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Geometry execution model entry points must specify " - "exactly one of OutputPoints, OutputLineStrip or " - "OutputTriangleStrip execution modes.")); - } - } -} - -INSTANTIATE_TEST_SUITE_P( - GeometryRequiredModes, ValidateModeGeometry, - Combine(Combine(Values("InputPoints", ""), Values("InputLines", ""), - Values("InputLinesAdjacency", ""), Values("Triangles", ""), - Values("InputTrianglesAdjacency", "")), - Combine(Values("OutputPoints", ""), Values("OutputLineStrip", ""), - Values("OutputTriangleStrip", "")))); - -using ValidateModeExecution = - spvtest::ValidateBase>; - -TEST_P(ValidateModeExecution, ExecutionMode) { - const spv_result_t expectation = std::get<0>(GetParam()); - const std::string error = std::get<1>(GetParam()); - const std::string model = std::get<2>(GetParam()); - const std::string mode = std::get<3>(GetParam()); - const spv_target_env env = std::get<4>(GetParam()); - - std::ostringstream sstr; - sstr << "OpCapability Shader\n"; - if (!spvIsWebGPUEnv(env)) { - sstr << "OpCapability Geometry\n"; - sstr << "OpCapability Tessellation\n"; - sstr << "OpCapability TransformFeedback\n"; - } - if (!spvIsVulkanOrWebGPUEnv(env)) { - sstr << "OpCapability Kernel\n"; - if (env == SPV_ENV_UNIVERSAL_1_3) { - sstr << "OpCapability SubgroupDispatch\n"; - } - } - if (spvIsWebGPUEnv(env)) { - sstr << "OpCapability VulkanMemoryModelKHR\n"; - sstr << "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"; - sstr << "OpMemoryModel Logical VulkanKHR\n"; - } else { - sstr << "OpMemoryModel Logical GLSL450\n"; - } - sstr << "OpEntryPoint " << model << " %main \"main\"\n"; - if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 || - mode.find("SubgroupsPerWorkgroupId") == 0) { - sstr << "OpExecutionModeId %main " << mode << "\n"; - } else { - sstr << "OpExecutionMode %main " << mode << "\n"; - } - if (model == "Geometry") { - if (!(mode.find("InputPoints") == 0 || mode.find("InputLines") == 0 || - mode.find("InputLinesAdjacency") == 0 || - mode.find("Triangles") == 0 || - mode.find("InputTrianglesAdjacency") == 0)) { - // Exactly one of the above modes is required for Geometry shaders. - sstr << "OpExecutionMode %main InputPoints\n"; - } - if (!(mode.find("OutputPoints") == 0 || mode.find("OutputLineStrip") == 0 || - mode.find("OutputTriangleStrip") == 0)) { - // Exactly one of the above modes is required for Geometry shaders. - sstr << "OpExecutionMode %main OutputPoints\n"; - } - } else if (model == "Fragment") { - if (!(mode.find("OriginUpperLeft") == 0 || - mode.find("OriginLowerLeft") == 0)) { - // Exactly one of the above modes is required for Fragment shaders. - sstr << "OpExecutionMode %main OriginUpperLeft\n"; - } - } - sstr << "%void = OpTypeVoid\n"; - sstr << "%void_fn = OpTypeFunction %void\n"; - sstr << "%int = OpTypeInt 32 0\n"; - sstr << "%int1 = OpConstant %int 1\n"; - sstr << "%main = OpFunction %void None %void_fn\n"; - sstr << "%entry = OpLabel\n"; - sstr << "OpReturn\n"; - sstr << "OpFunctionEnd\n"; - - CompileSuccessfully(sstr.str(), env); - EXPECT_THAT(expectation, ValidateInstructions(env)); - if (expectation != SPV_SUCCESS) { - EXPECT_THAT(getDiagnosticString(), HasSubstr(error)); - } -} - -INSTANTIATE_TEST_SUITE_P( - ValidateModeGeometryOnlyGoodSpv10, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), Values("Geometry"), - Values("Invocations 3", "InputPoints", "InputLines", - "InputLinesAdjacency", "InputTrianglesAdjacency", - "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeGeometryOnlyBadSpv10, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode can only be used with the Geometry " - "execution model."), - Values("Fragment", "TessellationEvaluation", "TessellationControl", - "GLCompute", "Vertex", "Kernel"), - Values("Invocations 3", "InputPoints", "InputLines", - "InputLinesAdjacency", "InputTrianglesAdjacency", - "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeTessellationOnlyGoodSpv10, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), - Values("TessellationControl", "TessellationEvaluation"), - Values("SpacingEqual", "SpacingFractionalEven", - "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw", - "PointMode", "Quads", "Isolines"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeTessellationOnlyBadSpv10, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode can only be used with a tessellation " - "execution model."), - Values("Fragment", "Geometry", "GLCompute", "Vertex", "Kernel"), - Values("SpacingEqual", "SpacingFractionalEven", - "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw", - "PointMode", "Quads", "Isolines"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P(ValidateModeGeometryAndTessellationGoodSpv10, - ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), - Values("TessellationControl", - "TessellationEvaluation", "Geometry"), - Values("Triangles", "OutputVertices 3"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeGeometryAndTessellationBadSpv10, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode can only be used with a Geometry or " - "tessellation execution model."), - Values("Fragment", "GLCompute", "Vertex", "Kernel"), - Values("Triangles", "OutputVertices 3"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeFragmentOnlyGoodSpv10, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"), - Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft", - "EarlyFragmentTests", "DepthReplacing", "DepthLess", - "DepthUnchanged"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeFragmentOnlyBadSpv10, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode can only be used with the Fragment " - "execution model."), - Values("Geometry", "TessellationControl", "TessellationEvaluation", - "GLCompute", "Vertex", "Kernel"), - Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft", - "EarlyFragmentTests", "DepthReplacing", "DepthGreater", - "DepthLess", "DepthUnchanged"), - Values(SPV_ENV_UNIVERSAL_1_0))); - -INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), - Values("Kernel"), - Values("LocalSizeHint 1 1 1", "VecTypeHint 4", - "ContractionOff", - "LocalSizeHintId %int1"), - Values(SPV_ENV_UNIVERSAL_1_3))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeKernelOnlyBadSpv13, ValidateModeExecution, - Combine( - Values(SPV_ERROR_INVALID_DATA), - Values( - "Execution mode can only be used with the Kernel execution model."), - Values("Geometry", "TessellationControl", "TessellationEvaluation", - "GLCompute", "Vertex", "Fragment"), - Values("LocalSizeHint 1 1 1", "VecTypeHint 4", "ContractionOff", - "LocalSizeHintId %int1"), - Values(SPV_ENV_UNIVERSAL_1_3))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeGLComputeAndKernelGoodSpv13, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), Values("Kernel", "GLCompute"), - Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"), - Values(SPV_ENV_UNIVERSAL_1_3))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeGLComputeAndKernelBadSpv13, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode can only be used with a Kernel or GLCompute " - "execution model."), - Values("Geometry", "TessellationControl", "TessellationEvaluation", - "Fragment", "Vertex"), - Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"), - Values(SPV_ENV_UNIVERSAL_1_3))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeAllGoodSpv13, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), - Values("Kernel", "GLCompute", "Geometry", "TessellationControl", - "TessellationEvaluation", "Fragment", "Vertex"), - Values("Xfb", "Initializer", "Finalizer", "SubgroupSize 1", - "SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"), - Values(SPV_ENV_UNIVERSAL_1_3))); - -INSTANTIATE_TEST_SUITE_P(ValidateModeGLComputeWebGPUWhitelistGood, - ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), - Values("GLCompute"), Values("LocalSize 1 1 1"), - Values(SPV_ENV_WEBGPU_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeGLComputeWebGPUWhitelistBad, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode must be one of OriginUpperLeft, " - "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, " - "LocalSize, or LocalSizeHint for WebGPU environment"), - Values("GLCompute"), Values("LocalSizeId %int1 %int1 %int1"), - Values(SPV_ENV_WEBGPU_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeFragmentWebGPUWhitelistGood, ValidateModeExecution, - Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"), - Values("OriginUpperLeft", "DepthReplacing", "DepthGreater", - "DepthLess", "DepthUnchanged"), - Values(SPV_ENV_WEBGPU_0))); - -INSTANTIATE_TEST_SUITE_P( - ValidateModeFragmentWebGPUWhitelistBad, ValidateModeExecution, - Combine(Values(SPV_ERROR_INVALID_DATA), - Values("Execution mode must be one of OriginUpperLeft, " - "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, " - "LocalSize, or LocalSizeHint for WebGPU environment"), - Values("Fragment"), - Values("PixelCenterInteger", "OriginLowerLeft", - "EarlyFragmentTests"), - Values(SPV_ENV_WEBGPU_0))); - -TEST_F(ValidateModeExecution, MeshNVLocalSize) { - const std::string spirv = R"( -OpCapability Shader -OpCapability MeshShadingNV -OpExtension "SPV_NV_mesh_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint MeshNV %main "main" -OpExecutionMode %main LocalSize 1 1 1 -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateModeExecution, TaskNVLocalSize) { - const std::string spirv = R"( -OpCapability Shader -OpCapability MeshShadingNV -OpExtension "SPV_NV_mesh_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint TaskNV %main "main" -OpExecutionMode %main LocalSize 1 1 1 -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateModeExecution, MeshNVOutputPoints) { - const std::string spirv = R"( -OpCapability Shader -OpCapability MeshShadingNV -OpExtension "SPV_NV_mesh_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint MeshNV %main "main" -OpExecutionMode %main OutputPoints -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateModeExecution, MeshNVOutputVertices) { - const std::string spirv = R"( -OpCapability Shader -OpCapability MeshShadingNV -OpExtension "SPV_NV_mesh_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint MeshNV %main "main" -OpExecutionMode %main OutputVertices 42 -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateModeExecution, MeshNVLocalSizeId) { - const std::string spirv = R"( -OpCapability Shader -OpCapability MeshShadingNV -OpExtension "SPV_NV_mesh_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint MeshNV %main "main" -OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateModeExecution, TaskNVLocalSizeId) { - const std::string spirv = R"( -OpCapability Shader -OpCapability MeshShadingNV -OpExtension "SPV_NV_mesh_shader" -OpMemoryModel Logical GLSL450 -OpEntryPoint TaskNV %main "main" -OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateModeExecution, ExecModeSubgroupsPerWorkgroupIdBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability SubgroupDispatch -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpExecutionMode %main SubgroupsPerWorkgroupId %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpExecutionMode is only valid when the Mode operand " - "is an execution mode that takes no Extra Operands")); -} - -TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability SubgroupDispatch -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdNonConstantBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability SubgroupDispatch -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1 -%int = OpTypeInt 32 0 -%int_ptr = OpTypePointer Private %int -%int_1 = OpVariable %int_ptr Private -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For OpExecutionModeId all Extra Operand ids must be " - "constant instructions.")); -} - -TEST_F(ValidateModeExecution, ExecModeLocalSizeHintIdBad) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Kernel %main "main" -OpExecutionMode %main LocalSizeHintId %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpExecutionMode is only valid when the Mode operand " - "is an execution mode that takes no Extra Operands")); -} - -TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdGood) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Kernel %main "main" -OpExecutionModeId %main LocalSizeHintId %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdNonConstantBad) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpExecutionModeId %main LocalSizeHintId %int_1 -%int = OpTypeInt 32 0 -%int_ptr = OpTypePointer Private %int -%int_1 = OpVariable %int_ptr Private -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For OpExecutionModeId all Extra Operand ids must be " - "constant instructions.")); -} - -TEST_F(ValidateModeExecution, ExecModeLocalSizeIdBad) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Kernel %main "main" -OpExecutionMode %main LocalSizeId %int_1 %int_1 %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpExecutionMode is only valid when the Mode operand " - "is an execution mode that takes no Extra Operands")); -} - -TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdGood) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Kernel %main "main" -OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1 -%int = OpTypeInt 32 0 -%int_1 = OpConstant %int 1 -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env)); -} - -TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdNonConstantBad) { - const std::string spirv = R"( -OpCapability Kernel -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1 -%int = OpTypeInt 32 0 -%int_ptr = OpTypePointer Private %int -%int_1 = OpVariable %int_ptr Private -)" + kVoidFunction; - - spv_target_env env = SPV_ENV_UNIVERSAL_1_3; - CompileSuccessfully(spirv, env); - EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For OpExecutionModeId all Extra Operand ids must be " - "constant instructions.")); -} - -TEST_F(ValidateMode, FragmentShaderInterlockVertexBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability FragmentShaderPixelInterlockEXT -OpExtension "SPV_EXT_fragment_shader_interlock" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -OpExecutionMode %main PixelInterlockOrderedEXT -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Execution mode can only be used with the Fragment execution model")); -} - -TEST_F(ValidateMode, FragmentShaderInterlockTooManyModesBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability FragmentShaderPixelInterlockEXT -OpCapability FragmentShaderSampleInterlockEXT -OpExtension "SPV_EXT_fragment_shader_interlock" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main PixelInterlockOrderedEXT -OpExecutionMode %main SampleInterlockOrderedEXT -)" + kVoidFunction; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Fragment execution model entry points can specify at most " - "one fragment shader interlock execution mode")); -} - -TEST_F(ValidateMode, FragmentShaderInterlockNoModeBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability FragmentShaderPixelInterlockEXT -OpExtension "SPV_EXT_fragment_shader_interlock" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entryf = OpLabel -OpBeginInvocationInterlockEXT -OpEndInvocationInterlockEXT -OpReturn -OpFunctionEnd -%main = OpFunction %void None %void_fn -%entry = OpLabel -%1 = OpFunctionCall %void %func -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT require a " - "fragment shader interlock execution mode")); -} - -TEST_F(ValidateMode, FragmentShaderInterlockGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability FragmentShaderPixelInterlockEXT -OpExtension "SPV_EXT_fragment_shader_interlock" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -OpExecutionMode %main PixelInterlockOrderedEXT -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%func = OpFunction %void None %void_fn -%entryf = OpLabel -OpBeginInvocationInterlockEXT -OpEndInvocationInterlockEXT -OpReturn -OpFunctionEnd -%main = OpFunction %void None %void_fn -%entry = OpLabel -%1 = OpFunctionCall %void %func -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMode, FragmentShaderDemoteVertexBad) { - const std::string spirv = R"( -OpCapability Shader -OpCapability DemoteToHelperInvocationEXT -OpExtension "SPV_EXT_demote_to_helper_invocation" -OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %main "main" -%bool = OpTypeBool -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpDemoteToHelperInvocationEXT -%1 = OpIsHelperInvocationEXT %bool -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpDemoteToHelperInvocationEXT requires Fragment execution model")); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpIsHelperInvocationEXT requires Fragment execution model")); -} - -TEST_F(ValidateMode, FragmentShaderDemoteGood) { - const std::string spirv = R"( -OpCapability Shader -OpCapability DemoteToHelperInvocationEXT -OpExtension "SPV_EXT_demote_to_helper_invocation" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%bool = OpTypeBool -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpDemoteToHelperInvocationEXT -%1 = OpIsHelperInvocationEXT %bool -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateMode, FragmentShaderDemoteBadType) { - const std::string spirv = R"( -OpCapability Shader -OpCapability DemoteToHelperInvocationEXT -OpExtension "SPV_EXT_demote_to_helper_invocation" -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" -OpExecutionMode %main OriginUpperLeft -%u32 = OpTypeInt 32 0 -%void = OpTypeVoid -%void_fn = OpTypeFunction %void -%main = OpFunction %void None %void_fn -%entry = OpLabel -OpDemoteToHelperInvocationEXT -%1 = OpIsHelperInvocationEXT %u32 -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Expected bool scalar type as Result Type")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_non_uniform_test.cpp b/3rdparty/spirv-tools/test/val/val_non_uniform_test.cpp deleted file mode 100644 index fbd11a9ef..000000000 --- a/3rdparty/spirv-tools/test/val/val_non_uniform_test.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Combine; -using ::testing::HasSubstr; -using ::testing::Values; -using ::testing::ValuesIn; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = "", - const std::string& execution_model = "GLCompute") { - std::ostringstream ss; - ss << R"( -OpCapability Shader -OpCapability GroupNonUniform -OpCapability GroupNonUniformVote -OpCapability GroupNonUniformBallot -OpCapability GroupNonUniformShuffle -OpCapability GroupNonUniformShuffleRelative -OpCapability GroupNonUniformArithmetic -OpCapability GroupNonUniformClustered -OpCapability GroupNonUniformQuad -)"; - - ss << capabilities_and_extensions; - ss << "OpMemoryModel Logical GLSL450\n"; - ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; - if (execution_model == "GLCompute") { - ss << "OpExecutionMode %main LocalSize 1 1 1\n"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%bool = OpTypeBool -%u32 = OpTypeInt 32 0 -%int = OpTypeInt 32 1 -%float = OpTypeFloat 32 -%u32vec4 = OpTypeVector %u32 4 -%u32vec3 = OpTypeVector %u32 3 - -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool - -%u32_0 = OpConstant %u32 0 - -%float_0 = OpConstant %float 0 - -%u32vec4_null = OpConstantComposite %u32vec4 %u32_0 %u32_0 %u32_0 %u32_0 -%u32vec3_null = OpConstantComposite %u32vec3 %u32_0 %u32_0 %u32_0 - -%cross_device = OpConstant %u32 0 -%device = OpConstant %u32 1 -%workgroup = OpConstant %u32 2 -%subgroup = OpConstant %u32 3 -%invocation = OpConstant %u32 4 - -%reduce = OpConstant %u32 0 -%inclusive_scan = OpConstant %u32 1 -%exclusive_scan = OpConstant %u32 2 -%clustered_reduce = OpConstant %u32 3 - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -SpvScope scopes[] = {SpvScopeCrossDevice, SpvScopeDevice, SpvScopeWorkgroup, - SpvScopeSubgroup, SpvScopeInvocation}; - -using GroupNonUniform = spvtest::ValidateBase< - std::tuple>; - -std::string ConvertScope(SpvScope scope) { - switch (scope) { - case SpvScopeCrossDevice: - return "%cross_device"; - case SpvScopeDevice: - return "%device"; - case SpvScopeWorkgroup: - return "%workgroup"; - case SpvScopeSubgroup: - return "%subgroup"; - case SpvScopeInvocation: - return "%invocation"; - default: - return ""; - } -} - -TEST_P(GroupNonUniform, Vulkan1p1) { - std::string opcode = std::get<0>(GetParam()); - std::string type = std::get<1>(GetParam()); - SpvScope execution_scope = std::get<2>(GetParam()); - std::string args = std::get<3>(GetParam()); - std::string error = std::get<4>(GetParam()); - - std::ostringstream sstr; - sstr << "%result = " << opcode << " "; - sstr << type << " "; - sstr << ConvertScope(execution_scope) << " "; - sstr << args << "\n"; - - CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_VULKAN_1_1); - spv_result_t result = ValidateInstructions(SPV_ENV_VULKAN_1_1); - if (error == "") { - if (execution_scope == SpvScopeSubgroup) { - EXPECT_EQ(SPV_SUCCESS, result); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "in Vulkan environment Execution scope is limited to Subgroup")); - } - } else { - EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); - EXPECT_THAT(getDiagnosticString(), HasSubstr(error)); - } -} - -TEST_P(GroupNonUniform, Spirv1p3) { - std::string opcode = std::get<0>(GetParam()); - std::string type = std::get<1>(GetParam()); - SpvScope execution_scope = std::get<2>(GetParam()); - std::string args = std::get<3>(GetParam()); - std::string error = std::get<4>(GetParam()); - - std::ostringstream sstr; - sstr << "%result = " << opcode << " "; - sstr << type << " "; - sstr << ConvertScope(execution_scope) << " "; - sstr << args << "\n"; - - CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_UNIVERSAL_1_3); - spv_result_t result = ValidateInstructions(SPV_ENV_UNIVERSAL_1_3); - if (error == "") { - if (execution_scope == SpvScopeSubgroup || - execution_scope == SpvScopeWorkgroup) { - EXPECT_EQ(SPV_SUCCESS, result); - } else { - EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Execution scope is limited to Subgroup or Workgroup")); - } - } else { - EXPECT_EQ(SPV_ERROR_INVALID_DATA, result); - EXPECT_THAT(getDiagnosticString(), HasSubstr(error)); - } -} - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformElect, GroupNonUniform, - Combine(Values("OpGroupNonUniformElect"), - Values("%bool"), ValuesIn(scopes), Values(""), - Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformVote, GroupNonUniform, - Combine(Values("OpGroupNonUniformAll", - "OpGroupNonUniformAny", - "OpGroupNonUniformAllEqual"), - Values("%bool"), ValuesIn(scopes), - Values("%true"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcast, GroupNonUniform, - Combine(Values("OpGroupNonUniformBroadcast"), - Values("%bool"), ValuesIn(scopes), - Values("%true %u32_0"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastFirst, GroupNonUniform, - Combine(Values("OpGroupNonUniformBroadcastFirst"), - Values("%bool"), ValuesIn(scopes), - Values("%true"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallot, GroupNonUniform, - Combine(Values("OpGroupNonUniformBallot"), - Values("%u32vec4"), ValuesIn(scopes), - Values("%true"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformInverseBallot, GroupNonUniform, - Combine(Values("OpGroupNonUniformInverseBallot"), - Values("%bool"), ValuesIn(scopes), - Values("%u32vec4_null"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitExtract, GroupNonUniform, - Combine(Values("OpGroupNonUniformBallotBitExtract"), - Values("%bool"), ValuesIn(scopes), - Values("%u32vec4_null %u32_0"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCount, GroupNonUniform, - Combine(Values("OpGroupNonUniformBallotBitCount"), - Values("%u32"), ValuesIn(scopes), - Values("Reduce %u32vec4_null"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotFind, GroupNonUniform, - Combine(Values("OpGroupNonUniformBallotFindLSB", - "OpGroupNonUniformBallotFindMSB"), - Values("%u32"), ValuesIn(scopes), - Values("%u32vec4_null"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformShuffle, GroupNonUniform, - Combine(Values("OpGroupNonUniformShuffle", - "OpGroupNonUniformShuffleXor", - "OpGroupNonUniformShuffleUp", - "OpGroupNonUniformShuffleDown"), - Values("%u32"), ValuesIn(scopes), - Values("%u32_0 %u32_0"), Values(""))); - -INSTANTIATE_TEST_SUITE_P( - GroupNonUniformIntegerArithmetic, GroupNonUniform, - Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul", - "OpGroupNonUniformSMin", "OpGroupNonUniformUMin", - "OpGroupNonUniformSMax", "OpGroupNonUniformUMax", - "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr", - "OpGroupNonUniformBitwiseXor"), - Values("%u32"), ValuesIn(scopes), Values("Reduce %u32_0"), - Values(""))); - -INSTANTIATE_TEST_SUITE_P( - GroupNonUniformFloatArithmetic, GroupNonUniform, - Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul", - "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"), - Values("%float"), ValuesIn(scopes), Values("Reduce %float_0"), - Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformLogicalArithmetic, GroupNonUniform, - Combine(Values("OpGroupNonUniformLogicalAnd", - "OpGroupNonUniformLogicalOr", - "OpGroupNonUniformLogicalXor"), - Values("%bool"), ValuesIn(scopes), - Values("Reduce %true"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuad, GroupNonUniform, - Combine(Values("OpGroupNonUniformQuadBroadcast", - "OpGroupNonUniformQuadSwap"), - Values("%u32"), ValuesIn(scopes), - Values("%u32_0 %u32_0"), Values(""))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountScope, GroupNonUniform, - Combine(Values("OpGroupNonUniformBallotBitCount"), - Values("%u32"), ValuesIn(scopes), - Values("Reduce %u32vec4_null"), Values(""))); - -INSTANTIATE_TEST_SUITE_P( - GroupNonUniformBallotBitCountBadResultType, GroupNonUniform, - Combine( - Values("OpGroupNonUniformBallotBitCount"), Values("%float", "%int"), - Values(SpvScopeSubgroup), Values("Reduce %u32vec4_null"), - Values("Expected Result Type to be an unsigned integer type scalar."))); - -INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountBadValue, GroupNonUniform, - Combine(Values("OpGroupNonUniformBallotBitCount"), - Values("%u32"), Values(SpvScopeSubgroup), - Values("Reduce %u32vec3_null", "Reduce %u32_0", - "Reduce %float_0"), - Values("Expected Value to be a vector of four " - "components of integer type scalar"))); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_opencl_test.cpp b/3rdparty/spirv-tools/test/val/val_opencl_test.cpp deleted file mode 100644 index 10641587f..000000000 --- a/3rdparty/spirv-tools/test/val/val_opencl_test.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) 2019 The Khronos Group 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. - -// Validation tests for OpenCL env specific checks - -#include - -#include "gmock/gmock.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using testing::HasSubstr; - -using ValidateOpenCL = spvtest::ValidateBase; - -TEST_F(ValidateOpenCL, NonPhysicalAddressingModelBad) { - std::string spirv = R"( - OpCapability Kernel - OpMemoryModel Logical OpenCL -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Addressing model must be Physical32 or Physical64 " - "in the OpenCL environment.\n OpMemoryModel Logical " - "OpenCL\n")); -} - -TEST_F(ValidateOpenCL, NonOpenCLMemoryModelBad) { - std::string spirv = R"( - OpCapability Kernel - OpCapability Addresses - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Physical32 VulkanKHR -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Memory model must be OpenCL in the OpenCL environment.")); -} - -TEST_F(ValidateOpenCL, NonVoidSampledTypeImageBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical32 OpenCL - %1 = OpTypeInt 32 0 - %2 = OpTypeImage %1 2D 0 0 0 0 Unknown ReadOnly -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Sampled Type must be OpTypeVoid in the OpenCL environment." - "\n %2 = OpTypeImage %uint 2D 0 0 0 0 Unknown ReadOnly\n")); -} - -TEST_F(ValidateOpenCL, NonZeroMSImageBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical32 OpenCL - %1 = OpTypeVoid - %2 = OpTypeImage %1 2D 0 0 1 0 Unknown ReadOnly -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("MS must be 0 in the OpenCL environement." - "\n %2 = OpTypeImage %void 2D 0 0 1 0 Unknown ReadOnly\n")); -} - -TEST_F(ValidateOpenCL, Non1D2DArrayedImageBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical32 OpenCL - %1 = OpTypeVoid - %2 = OpTypeImage %1 3D 0 1 0 0 Unknown ReadOnly -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("In the OpenCL environment, Arrayed may only be set to 1 " - "when Dim is either 1D or 2D." - "\n %2 = OpTypeImage %void 3D 0 1 0 0 Unknown ReadOnly\n")); -} - -TEST_F(ValidateOpenCL, NonZeroSampledImageBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical32 OpenCL - %1 = OpTypeVoid - %2 = OpTypeImage %1 3D 0 0 0 1 Unknown ReadOnly -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Sampled must be 0 in the OpenCL environment." - "\n %2 = OpTypeImage %void 3D 0 0 0 1 Unknown ReadOnly\n")); -} - -TEST_F(ValidateOpenCL, NoAccessQualifierImageBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpMemoryModel Physical32 OpenCL - %1 = OpTypeVoid - %2 = OpTypeImage %1 3D 0 0 0 0 Unknown -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("In the OpenCL environment, the optional " - "Access Qualifier must be present." - "\n %2 = OpTypeImage %void 3D 0 0 0 0 Unknown\n")); -} - -TEST_F(ValidateOpenCL, ImageWriteWithOptionalImageOperandsBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpCapability ImageBasic - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %5 "test" - %uint = OpTypeInt 32 0 - %uint_7 = OpConstant %uint 7 - %uint_3 = OpConstant %uint 3 - %uint_1 = OpConstant %uint 1 - %uint_2 = OpConstant %uint 2 - %uint_4 = OpConstant %uint 4 - %void = OpTypeVoid - %3 = OpTypeImage %void 2D 0 0 0 0 Unknown WriteOnly - %4 = OpTypeFunction %void %3 - %v2uint = OpTypeVector %uint 2 - %v4uint = OpTypeVector %uint 4 - %12 = OpConstantComposite %v2uint %uint_7 %uint_3 - %17 = OpConstantComposite %v4uint %uint_1 %uint_2 %uint_3 %uint_4 - %5 = OpFunction %void None %4 - %img = OpFunctionParameter %3 - %entry = OpLabel - OpImageWrite %img %12 %17 ConstOffset %12 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Optional Image Operands are not allowed in the " - "OpenCL environment." - "\n OpImageWrite %15 %13 %14 ConstOffset %13\n")); -} - -TEST_F(ValidateOpenCL, ImageReadWithConstOffsetBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpCapability ImageBasic - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %5 "image_kernel" - OpName %img "img" - OpName %coord "coord" - OpName %call "call" - %uint = OpTypeInt 32 0 - %uint_7 = OpConstant %uint 7 - %uint_3 = OpConstant %uint 3 - %void = OpTypeVoid - %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly - %4 = OpTypeFunction %void %3 - %v4uint = OpTypeVector %uint 4 - %v2uint = OpTypeVector %uint 2 - %coord = OpConstantComposite %v2uint %uint_7 %uint_3 - %5 = OpFunction %void None %4 - %img = OpFunctionParameter %3 - %entry = OpLabel - %call = OpImageRead %v4uint %img %coord ConstOffset %coord - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ConstOffset image operand not allowed in the OpenCL environment." - "\n %call = OpImageRead %v4uint %img %coord ConstOffset %coord\n")); -} - -TEST_F(ValidateOpenCL, ImageSampleExplicitLodWithConstOffsetBad) { - std::string spirv = R"( - OpCapability Addresses - OpCapability Kernel - OpCapability ImageBasic - OpCapability LiteralSampler - OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %5 "image_kernel" - OpName %img "img" - OpName %coord "coord" - OpName %call "call" - %uint = OpTypeInt 32 0 - %uint_7 = OpConstant %uint 7 - %uint_3 = OpConstant %uint 3 - %void = OpTypeVoid - %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly - %4 = OpTypeFunction %void %3 - %8 = OpTypeSampler - %10 = OpTypeSampledImage %3 - %v4uint = OpTypeVector %uint 4 - %v2uint = OpTypeVector %uint 2 - %float = OpTypeFloat 32 - %9 = OpConstantSampler %8 None 0 Nearest - %coord = OpConstantComposite %v2uint %uint_7 %uint_3 - %float_0 = OpConstant %float 0 - %5 = OpFunction %void None %4 - %6 = OpFunctionParameter %3 - %entry = OpLabel - %img = OpSampledImage %10 %6 %9 - %call = OpImageSampleExplicitLod %v4uint %img %coord - Lod|ConstOffset %float_0 %coord - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "ConstOffset image operand not allowed in the OpenCL environment." - "\n %call = OpImageSampleExplicitLod %v4uint %img " - "%coord Lod|ConstOffset %float_0 %coord\n")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_primitives_test.cpp b/3rdparty/spirv-tools/test/val/val_primitives_test.cpp deleted file mode 100644 index 04d0a4f8a..000000000 --- a/3rdparty/spirv-tools/test/val/val_primitives_test.cpp +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) 2017 LunarG 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 "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidatePrimitives = spvtest::ValidateBase; - -std::string GenerateShaderCode( - const std::string& body, - const std::string& capabilities_and_extensions = - "OpCapability GeometryStreams", - const std::string& execution_model = "Geometry") { - std::ostringstream ss; - ss << capabilities_and_extensions << "\n"; - ss << "OpMemoryModel Logical GLSL450\n"; - ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; - if (execution_model == "Geometry") { - ss << "OpExecutionMode %main InputPoints\n"; - ss << "OpExecutionMode %main OutputPoints\n"; - } - - ss << R"( -%void = OpTypeVoid -%func = OpTypeFunction %void -%f32 = OpTypeFloat 32 -%u32 = OpTypeInt 32 0 -%u32vec4 = OpTypeVector %u32 4 - -%f32_0 = OpConstant %f32 0 -%u32_0 = OpConstant %u32 0 -%u32_1 = OpConstant %u32 1 -%u32_2 = OpConstant %u32 2 -%u32_3 = OpConstant %u32 3 -%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 - -%main = OpFunction %void None %func -%main_entry = OpLabel -)"; - - ss << body; - - ss << R"( -OpReturn -OpFunctionEnd)"; - - return ss.str(); -} - -// Returns SPIR-V assembly fragment representing a function call, -// the end of the callee body, and the preamble and body of the called -// function with the given body, but missing the final return and -// function-end. The result is of the form where it can be used in the -// |body| argument to GenerateShaderCode. -std::string CallAndCallee(const std::string& body) { - std::ostringstream ss; - ss << R"( -%dummy = OpFunctionCall %void %foo -OpReturn -OpFunctionEnd - -%foo = OpFunction %void None %func -%foo_entry = OpLabel -)"; - - ss << body; - - return ss.str(); -} - -// OpEmitVertex doesn't have any parameters, so other validation -// is handled by the binary parser, and generic dominance checks. -TEST_F(ValidatePrimitives, EmitVertexSuccess) { - CompileSuccessfully( - GenerateShaderCode("OpEmitVertex", "OpCapability Geometry")); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidatePrimitives, EmitVertexFailMissingCapability) { - CompileSuccessfully( - GenerateShaderCode("OpEmitVertex", "OpCapability Shader", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Opcode EmitVertex requires one of these capabilities: Geometry")); -} - -TEST_F(ValidatePrimitives, EmitVertexFailWrongExecutionMode) { - CompileSuccessfully( - GenerateShaderCode("OpEmitVertex", "OpCapability Geometry", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("EmitVertex instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, EmitVertexFailWrongExecutionModeNestedFunction) { - CompileSuccessfully(GenerateShaderCode(CallAndCallee("OpEmitVertex"), - "OpCapability Geometry", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("EmitVertex instructions require Geometry execution model")); -} - -// OpEndPrimitive doesn't have any parameters, so other validation -// is handled by the binary parser, and generic dominance checks. -TEST_F(ValidatePrimitives, EndPrimitiveSuccess) { - CompileSuccessfully( - GenerateShaderCode("OpEndPrimitive", "OpCapability Geometry")); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidatePrimitives, EndPrimitiveFailMissingCapability) { - CompileSuccessfully( - GenerateShaderCode("OpEndPrimitive", "OpCapability Shader", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Opcode EndPrimitive requires one of these capabilities: Geometry")); -} - -TEST_F(ValidatePrimitives, EndPrimitiveFailWrongExecutionMode) { - CompileSuccessfully( - GenerateShaderCode("OpEndPrimitive", "OpCapability Geometry", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("EndPrimitive instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, EndPrimitiveFailWrongExecutionModeNestedFunction) { - CompileSuccessfully(GenerateShaderCode(CallAndCallee("OpEndPrimitive"), - "OpCapability Geometry", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("EndPrimitive instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, EmitStreamVertexSuccess) { - const std::string body = R"( -OpEmitStreamVertex %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidatePrimitives, EmitStreamVertexFailMissingCapability) { - CompileSuccessfully(GenerateShaderCode("OpEmitStreamVertex %u32_0", - "OpCapability Shader", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Opcode EmitStreamVertex requires one of these " - "capabilities: GeometryStreams")); -} - -TEST_F(ValidatePrimitives, EmitStreamVertexFailWrongExecutionMode) { - CompileSuccessfully(GenerateShaderCode( - "OpEmitStreamVertex %u32_0", "OpCapability GeometryStreams", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "EmitStreamVertex instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, - EmitStreamVertexFailWrongExecutionModeNestedFunction) { - CompileSuccessfully( - GenerateShaderCode(CallAndCallee("OpEmitStreamVertex %u32_0"), - "OpCapability GeometryStreams", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "EmitStreamVertex instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, EmitStreamVertexNonInt) { - const std::string body = R"( -OpEmitStreamVertex %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("EmitStreamVertex: " - "expected Stream to be int scalar")); -} - -TEST_F(ValidatePrimitives, EmitStreamVertexNonScalar) { - const std::string body = R"( -OpEmitStreamVertex %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("EmitStreamVertex: " - "expected Stream to be int scalar")); -} - -TEST_F(ValidatePrimitives, EmitStreamVertexNonConstant) { - const std::string body = R"( -%val1 = OpIAdd %u32 %u32_0 %u32_1 -OpEmitStreamVertex %val1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("EmitStreamVertex: " - "expected Stream to be constant instruction")); -} - -TEST_F(ValidatePrimitives, EndStreamPrimitiveSuccess) { - const std::string body = R"( -OpEndStreamPrimitive %u32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidatePrimitives, EndStreamPrimitiveFailMissingCapability) { - CompileSuccessfully(GenerateShaderCode("OpEndStreamPrimitive %u32_0", - "OpCapability Shader", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Opcode EndStreamPrimitive requires one of these " - "capabilities: GeometryStreams")); -} - -TEST_F(ValidatePrimitives, EndStreamPrimitiveFailWrongExecutionMode) { - CompileSuccessfully(GenerateShaderCode( - "OpEndStreamPrimitive %u32_0", "OpCapability GeometryStreams", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "EndStreamPrimitive instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, - EndStreamPrimitiveFailWrongExecutionModeNestedFunction) { - CompileSuccessfully( - GenerateShaderCode(CallAndCallee("OpEndStreamPrimitive %u32_0"), - "OpCapability GeometryStreams", "Vertex")); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "EndStreamPrimitive instructions require Geometry execution model")); -} - -TEST_F(ValidatePrimitives, EndStreamPrimitiveNonInt) { - const std::string body = R"( -OpEndStreamPrimitive %f32_0 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("EndStreamPrimitive: " - "expected Stream to be int scalar")); -} - -TEST_F(ValidatePrimitives, EndStreamPrimitiveNonScalar) { - const std::string body = R"( -OpEndStreamPrimitive %u32vec4_0123 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("EndStreamPrimitive: " - "expected Stream to be int scalar")); -} - -TEST_F(ValidatePrimitives, EndStreamPrimitiveNonConstant) { - const std::string body = R"( -%val1 = OpIAdd %u32 %u32_0 %u32_1 -OpEndStreamPrimitive %val1 -)"; - - CompileSuccessfully(GenerateShaderCode(body)); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("EndStreamPrimitive: " - "expected Stream to be constant instruction")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_small_type_uses_test.cpp b/3rdparty/spirv-tools/test/val/val_small_type_uses_test.cpp deleted file mode 100644 index b950af5b0..000000000 --- a/3rdparty/spirv-tools/test/val/val_small_type_uses_test.cpp +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// 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. - -// Validation tests for 8- and 16-bit type uses. - -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_code_generator.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Values; - -using ValidateSmallTypeUses = spvtest::ValidateBase; - -CodeGenerator GetSmallTypesGenerator() { - CodeGenerator generator; - generator.capabilities_ = R"( -OpCapability Shader -OpCapability StorageBuffer16BitAccess -OpCapability StorageBuffer8BitAccess -)"; - generator.extensions_ = R"( -OpExtension "SPV_KHR_16bit_storage" -OpExtension "SPV_KHR_8bit_storage" -OpExtension "SPV_KHR_storage_buffer_storage_class" -%ext = OpExtInstImport "GLSL.std.450" -)"; - generator.memory_model_ = "OpMemoryModel Logical GLSL450\n"; - std::string body = R"( -%short_gep = OpAccessChain %ptr_ssbo_short %var %int_0 %int_0 -%ld_short = OpLoad %short %short_gep -%short_to_int = OpSConvert %int %ld_short -%short_to_uint = OpUConvert %int %ld_short -%short_to_char = OpSConvert %char %ld_short -%short_to_uchar = OpSConvert %char %ld_short -%short2_gep = OpAccessChain %ptr_ssbo_short2 %var %int_0 -%ld_short2 = OpLoad %short2 %short2_gep -%short2_to_int2 = OpSConvert %int2 %ld_short2 -%short2_to_uint2 = OpUConvert %int2 %ld_short2 -%short2_to_char2 = OpSConvert %char2 %ld_short2 -%short2_to_uchar2 = OpSConvert %char2 %ld_short2 - -%char_gep = OpAccessChain %ptr_ssbo_char %var %int_2 %int_0 -%ld_char = OpLoad %char %char_gep -%char_to_int = OpSConvert %int %ld_char -%char_to_uint = OpUConvert %int %ld_char -%char_to_short = OpSConvert %short %ld_char -%char_to_ushort = OpSConvert %short %ld_char -%char2_gep = OpAccessChain %ptr_ssbo_char2 %var %int_2 -%ld_char2 = OpLoad %char2 %char2_gep -%char2_to_int2 = OpSConvert %int2 %ld_char2 -%char2_to_uint2 = OpUConvert %int2 %ld_char2 -%char2_to_short2 = OpSConvert %short2 %ld_char2 -%char2_to_ushort2 = OpSConvert %short2 %ld_char2 - -%half_gep = OpAccessChain %ptr_ssbo_half %var %int_1 %int_0 -%ld_half = OpLoad %half %half_gep -%half_to_float = OpFConvert %float %ld_half -%half2_gep = OpAccessChain %ptr_ssbo_half2 %var %int_1 -%ld_half2 = OpLoad %half2 %half2_gep -%half2_to_float2 = OpFConvert %float2 %ld_half2 - -%int_to_short = OpSConvert %short %int_0 -%int_to_ushort = OpUConvert %short %int_0 -%int_to_char = OpSConvert %char %int_0 -%int_to_uchar = OpUConvert %char %int_0 -%int2_to_short2 = OpSConvert %short2 %int2_0 -%int2_to_ushort2 = OpUConvert %short2 %int2_0 -%int2_to_char2 = OpSConvert %char2 %int2_0 -%int2_to_uchar2 = OpUConvert %char2 %int2_0 -%int_gep = OpAccessChain %ptr_ssbo_int %var %int_3 %int_0 -%int2_gep = OpAccessChain %ptr_ssbo_int2 %var %int_3 - -%float_to_half = OpFConvert %half %float_0 -%float2_to_half2 = OpFConvert %half2 %float2_0 -%float_gep = OpAccessChain %ptr_ssbo_float %var %int_4 %int_0 -%float2_gep = OpAccessChain %ptr_ssbo_float2 %var %int_4 -)"; - generator.entry_points_.push_back( - {"foo", "GLCompute", "OpExecutionMode %foo LocalSize 1 1 1", body, ""}); - generator.before_types_ = R"( -OpDecorate %block Block -OpMemberDecorate %block 0 Offset 0 -OpMemberDecorate %block 1 Offset 8 -OpMemberDecorate %block 2 Offset 16 -OpMemberDecorate %block 3 Offset 32 -OpMemberDecorate %block 4 Offset 64 -)"; - generator.types_ = R"( -%void = OpTypeVoid -%int = OpTypeInt 32 0 -%int2 = OpTypeVector %int 2 -%float = OpTypeFloat 32 -%float2 = OpTypeVector %float 2 -%bool = OpTypeBool -%bool2 = OpTypeVector %bool 2 -%char = OpTypeInt 8 0 -%char2 = OpTypeVector %char 2 -%ptr_ssbo_char = OpTypePointer StorageBuffer %char -%ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2 -%short = OpTypeInt 16 0 -%short2 = OpTypeVector %short 2 -%ptr_ssbo_short = OpTypePointer StorageBuffer %short -%ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2 -%half = OpTypeFloat 16 -%half2 = OpTypeVector %half 2 -%ptr_ssbo_half = OpTypePointer StorageBuffer %half -%ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2 -%ptr_ssbo_int = OpTypePointer StorageBuffer %int -%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2 -%ptr_ssbo_float = OpTypePointer StorageBuffer %float -%ptr_ssbo_float2 = OpTypePointer StorageBuffer %float2 -%block = OpTypeStruct %short2 %half2 %char2 %int2 %float2 -%ptr_ssbo_block = OpTypePointer StorageBuffer %block -%func = OpTypeFunction %void -)"; - generator.after_types_ = R"( -%var = OpVariable %ptr_ssbo_block StorageBuffer -%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 -%int2_0 = OpConstantComposite %int2 %int_0 %int_0 -%float_0 = OpConstant %float 0 -%float2_0 = OpConstantComposite %float2 %float_0 %float_0 - -%short_func_ty = OpTypeFunction %void %short -%char_func_ty = OpTypeFunction %void %char -%half_func_ty = OpTypeFunction %void %half -)"; - generator.add_at_the_end_ = R"( -%short_func = OpFunction %void None %short_func_ty -%short_param = OpFunctionParameter %short -%short_func_entry = OpLabel -OpReturn -OpFunctionEnd -%char_func = OpFunction %void None %char_func_ty -%char_param = OpFunctionParameter %char -%char_func_entry = OpLabel -OpReturn -OpFunctionEnd -%half_func = OpFunction %void None %half_func_ty -%half_param = OpFunctionParameter %half -%half_func_entry = OpLabel -OpReturn -OpFunctionEnd -)"; - - return generator; -} - -TEST_F(ValidateSmallTypeUses, BadCharPhi) { - CodeGenerator generator = GetSmallTypesGenerator(); - generator.entry_points_[0].body += R"( -OpBranch %next_block -%next_block = OpLabel -%phi = OpPhi %char %ld_char %foo_entry -)"; - - CompileSuccessfully(generator.Build()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid use of 8- or 16-bit result")); -} - -TEST_F(ValidateSmallTypeUses, BadShortPhi) { - CodeGenerator generator = GetSmallTypesGenerator(); - generator.entry_points_[0].body += R"( -OpBranch %next_block -%next_block = OpLabel -%phi = OpPhi %short %ld_short %foo_entry -)"; - - CompileSuccessfully(generator.Build()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid use of 8- or 16-bit result")); -} - -TEST_F(ValidateSmallTypeUses, BadHalfPhi) { - CodeGenerator generator = GetSmallTypesGenerator(); - generator.entry_points_[0].body += R"( -OpBranch %next_block -%next_block = OpLabel -%phi = OpPhi %half %ld_half %foo_entry -)"; - - CompileSuccessfully(generator.Build()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid use of 8- or 16-bit result")); -} - -using ValidateGoodUses = spvtest::ValidateBase; - -TEST_P(ValidateGoodUses, Inst) { - const std::string inst = GetParam(); - CodeGenerator generator = GetSmallTypesGenerator(); - generator.entry_points_[0].body += inst + "\n"; - - CompileSuccessfully(generator.Build()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -INSTANTIATE_TEST_SUITE_P( - SmallTypeUsesValid, ValidateGoodUses, - Values( - "%inst = OpIAdd %int %short_to_int %int_0", - "%inst = OpIAdd %int %short_to_uint %int_0", - "%inst = OpIAdd %int2 %short2_to_int2 %int2_0", - "%inst = OpIAdd %int2 %short2_to_uint2 %int2_0", - "%inst = OpIAdd %int %char_to_int %int_0", - "%inst = OpIAdd %int %char_to_uint %int_0", - "%inst = OpIAdd %int2 %char2_to_int2 %int2_0", - "%inst = OpIAdd %int2 %char2_to_uint2 %int2_0", - "%inst = OpUConvert %int %ld_short", - "%inst = OpSConvert %int %ld_short", - "%inst = OpUConvert %char %ld_short", - "%inst = OpSConvert %char %ld_short", - "%inst = OpUConvert %int %ld_char", "%inst = OpSConvert %int %ld_char", - "%inst = OpUConvert %short %ld_char", - "%inst = OpSConvert %short %ld_char", - "%inst = OpUConvert %int2 %ld_short2", - "%inst = OpSConvert %int2 %ld_short2", - "%inst = OpUConvert %char2 %ld_short2", - "%inst = OpSConvert %char2 %ld_short2", - "%inst = OpUConvert %int2 %ld_char2", - "%inst = OpSConvert %int2 %ld_char2", - "%inst = OpUConvert %short2 %ld_char2", - "%inst = OpSConvert %short2 %ld_char2", - "OpStore %short_gep %int_to_short", "OpStore %short_gep %int_to_ushort", - "OpStore %short_gep %char_to_short", - "OpStore %short_gep %char_to_ushort", - "OpStore %short2_gep %int2_to_short2", - "OpStore %short2_gep %int2_to_ushort2", - "OpStore %short2_gep %char2_to_short2", - "OpStore %short2_gep %char2_to_ushort2", - "OpStore %char_gep %int_to_char", "OpStore %char_gep %int_to_uchar", - "OpStore %char_gep %short_to_char", "OpStore %char_gep %short_to_uchar", - "OpStore %char2_gep %int2_to_char2", - "OpStore %char2_gep %int2_to_uchar2", - "OpStore %char2_gep %short2_to_char2", - "OpStore %char2_gep %short2_to_uchar2", - "OpStore %int_gep %short_to_int", "OpStore %int_gep %short_to_uint", - "OpStore %int_gep %char_to_int", "OpStore %int2_gep %char2_to_uint2", - "OpStore %int2_gep %short2_to_int2", - "OpStore %int2_gep %short2_to_uint2", - "OpStore %int2_gep %char2_to_int2", "OpStore %int2_gep %char2_to_uint2", - "%inst = OpFAdd %float %half_to_float %float_0", - "%inst = OpFAdd %float2 %half2_to_float2 %float2_0", - "%inst = OpFConvert %float %ld_half", - "%inst = OpFConvert %float2 %ld_half2", - "OpStore %half_gep %float_to_half", "OpStore %half_gep %ld_half", - "OpStore %half2_gep %float2_to_half2", "OpStore %half2_gep %ld_half2", - "OpStore %float_gep %half_to_float", - "OpStore %float2_gep %half2_to_float2")); - -using ValidateBadUses = spvtest::ValidateBase; - -TEST_P(ValidateBadUses, Inst) { - const std::string inst = GetParam(); - CodeGenerator generator = GetSmallTypesGenerator(); - generator.entry_points_[0].body += inst + "\n"; - - CompileSuccessfully(generator.Build()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Invalid use of 8- or 16-bit result")); -} - -// A smattering of unacceptable use cases. Far too vast to cover exhaustively. -INSTANTIATE_TEST_SUITE_P( - SmallTypeUsesInvalid, ValidateBadUses, - Values("%inst = OpIAdd %short %ld_short %ld_short", - "%inst = OpIAdd %short %char_to_short %char_to_short", - "%inst = OpIAdd %short %char_to_ushort %char_to_ushort", - "%inst = OpIAdd %short %int_to_short %int_to_short", - "%inst = OpIAdd %short %int_to_ushort %int_to_ushort", - "%inst = OpIAdd %short2 %ld_short2 %ld_short2", - "%inst = OpIAdd %short2 %char2_to_short2 %char2_to_short2", - "%inst = OpIAdd %short2 %char2_to_ushort2 %char2_to_ushort2", - "%inst = OpIAdd %short2 %int2_to_short2 %int2_to_short2", - "%inst = OpIAdd %short2 %int2_to_ushort2 %int2_to_ushort2", - "%inst = OpIEqual %bool %ld_short %ld_short", - "%inst = OpIEqual %bool %char_to_short %char_to_short", - "%inst = OpIEqual %bool %char_to_ushort %char_to_ushort", - "%inst = OpIEqual %bool %int_to_short %int_to_short", - "%inst = OpIEqual %bool %int_to_ushort %int_to_ushort", - "%inst = OpIEqual %bool2 %ld_short2 %ld_short2", - "%inst = OpIEqual %bool2 %char2_to_short2 %char2_to_short2", - "%inst = OpIEqual %bool2 %char2_to_ushort2 %char2_to_ushort2", - "%inst = OpIEqual %bool2 %int2_to_short2 %int2_to_short2", - "%inst = OpIEqual %bool2 %int2_to_ushort2 %int2_to_ushort2", - "%inst = OpFAdd %half %ld_half %ld_half", - "%inst = OpFAdd %half %float_to_half %float_to_half", - "%inst = OpFAdd %half2 %ld_half2 %ld_half2", - "%inst = OpFAdd %half2 %float2_to_half2 %float2_to_half2", - "%inst = OpFOrdGreaterThan %bool %ld_half %ld_half", - "%inst = OpFOrdGreaterThan %bool %float_to_half %float_to_half", - "%inst = OpFOrdGreaterThan %bool2 %ld_half2 %ld_half2", - "%inst = OpFOrdGreaterThan %bool2 %float2_to_half2 %float2_to_half2", - "%inst = OpFunctionCall %void %short_func %ld_short", - "%inst = OpFunctionCall %void %short_func %char_to_short", - "%inst = OpFunctionCall %void %short_func %char_to_ushort", - "%inst = OpFunctionCall %void %short_func %int_to_short", - "%inst = OpFunctionCall %void %short_func %int_to_ushort", - "%inst = OpFunctionCall %void %char_func %ld_char", - "%inst = OpFunctionCall %void %char_func %short_to_char", - "%inst = OpFunctionCall %void %char_func %short_to_uchar", - "%inst = OpFunctionCall %void %char_func %int_to_char", - "%inst = OpFunctionCall %void %char_func %int_to_uchar", - "%inst = OpFunctionCall %void %half_func %ld_half", - "%inst = OpFunctionCall %void %half_func %float_to_half")); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_ssa_test.cpp b/3rdparty/spirv-tools/test/val/val_ssa_test.cpp deleted file mode 100644 index 035c710a2..000000000 --- a/3rdparty/spirv-tools/test/val/val_ssa_test.cpp +++ /dev/null @@ -1,1450 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Validation tests for SSA - -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::MatchesRegex; - -using ValidateSSA = spvtest::ValidateBase>; - -TEST_F(ValidateSSA, Default) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %3 "" - OpExecutionMode %3 LocalSize 1 1 1 -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, IdUndefinedBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%func = OpFunction %vfunct None %missing -%flabel = OpLabel - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, IdRedefinedBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %2 "redefined" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%2 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); -} - -TEST_F(ValidateSSA, DominateUsageBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %1 "not_dominant" -%2 = OpTypeFunction %1 ; uses %1 before it's definition -%1 = OpTypeVoid -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("not_dominant")); -} - -TEST_F(ValidateSSA, DominateUsageWithinBlockBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %bad "bad" -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%uintt = OpTypeInt 32 0 -%one = OpConstant %uintt 1 -%func = OpFunction %voidt None %funct -%entry = OpLabel -%sum = OpIAdd %uintt %one %bad -%bad = OpCopyObject %uintt %sum - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("ID .\\[%bad\\] has not been defined\n" - " %8 = OpIAdd %uint %uint_1 %bad\n")); -} - -TEST_F(ValidateSSA, DominateUsageSameInstructionBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %sum "sum" -%voidt = OpTypeVoid -%funct = OpTypeFunction %voidt -%uintt = OpTypeInt 32 0 -%one = OpConstant %uintt 1 -%func = OpFunction %voidt None %funct -%entry = OpLabel -%sum = OpIAdd %uintt %one %sum - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("ID .\\[%sum\\] has not been defined\n" - " %sum = OpIAdd %uint %uint_1 %sum\n")); -} - -TEST_F(ValidateSSA, ForwardNameGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %3 "main" -%1 = OpTypeVoid -%2 = OpTypeFunction %1 -%3 = OpFunction %1 None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardNameMissingTargetBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %5 "main" ; Target never defined -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("main")); -} - -TEST_F(ValidateSSA, ForwardMemberNameGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpMemberName %struct 0 "value" - OpMemberName %struct 1 "size" -%intt = OpTypeInt 32 1 -%uintt = OpTypeInt 32 0 -%struct = OpTypeStruct %intt %uintt -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardMemberNameMissingTargetBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpMemberName %struct 0 "value" - OpMemberName %bad 1 "size" ; Target is not defined -%intt = OpTypeInt 32 1 -%uintt = OpTypeInt 32 0 -%struct = OpTypeStruct %intt %uintt -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The following forward referenced IDs have not been " - "defined:\n2[%2]")); -} - -TEST_F(ValidateSSA, ForwardDecorateGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %var Restrict -%intt = OpTypeInt 32 1 -%ptrt = OpTypePointer UniformConstant %intt -%var = OpVariable %ptrt UniformConstant -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardDecorateInvalidIDBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" - OpDecorate %missing Restrict ;Missing ID -%voidt = OpTypeVoid -%intt = OpTypeInt 32 1 -%ptrt = OpTypePointer UniformConstant %intt -%var = OpVariable %ptrt UniformConstant -%2 = OpTypeFunction %voidt -%3 = OpFunction %voidt None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, ForwardMemberDecorateGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpMemberDecorate %struct 1 RowMajor -%intt = OpTypeInt 32 1 -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 3 -%struct = OpTypeStruct %intt %mat33 -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" - OpMemberDecorate %missing 1 RowMajor ; Target not defined -%intt = OpTypeInt 32 1 -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%mat33 = OpTypeMatrix %vec3 3 -%struct = OpTypeStruct %intt %mat33 -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, ForwardGroupDecorateGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpDecorate %dgrp RowMajor -%dgrp = OpDecorationGroup - OpGroupDecorate %dgrp %mat33 %mat44 -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%vec4 = OpTypeVector %f32 4 -%mat33 = OpTypeMatrix %vec3 3 -%mat44 = OpTypeMatrix %vec4 4 -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardGroupDecorateMissingGroupBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" - OpDecorate %dgrp RowMajor -%dgrp = OpDecorationGroup - OpGroupDecorate %missing %mat33 %mat44 ; Target not defined -%intt = OpTypeInt 32 1 -%vec3 = OpTypeVector %intt 3 -%vec4 = OpTypeVector %intt 4 -%mat33 = OpTypeMatrix %vec3 3 -%mat44 = OpTypeMatrix %vec4 4 -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" - OpDecorate %dgrp RowMajor -%dgrp = OpDecorationGroup - OpGroupDecorate %dgrp %missing %mat44 ; Target not defined -%f32 = OpTypeFloat 32 -%vec3 = OpTypeVector %f32 3 -%vec4 = OpTypeVector %f32 4 -%mat33 = OpTypeMatrix %vec3 3 -%mat44 = OpTypeMatrix %vec4 4 -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, ForwardGroupDecorateDecorationGroupDominateBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %dgrp "group" - OpDecorate %dgrp RowMajor - OpGroupDecorate %dgrp %mat33 %mat44 ; Decoration group does not dominate usage -%dgrp = OpDecorationGroup -%intt = OpTypeInt 32 1 -%vec3 = OpTypeVector %intt 3 -%vec4 = OpTypeVector %intt 4 -%mat33 = OpTypeMatrix %vec3 3 -%mat44 = OpTypeMatrix %vec4 4 -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("group")); -} - -TEST_F(ValidateSSA, ForwardDecorateInvalidIdBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" - OpDecorate %missing Restrict ; Missing target -%voidt = OpTypeVoid -%intt = OpTypeInt 32 1 -%ptrt = OpTypePointer UniformConstant %intt -%var = OpVariable %ptrt UniformConstant -%2 = OpTypeFunction %voidt -%3 = OpFunction %voidt None %2 -%4 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, FunctionCallGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 1 -%3 = OpTypeInt 32 0 -%4 = OpTypeFunction %1 -%8 = OpTypeFunction %1 %2 %3 -%four = OpConstant %2 4 -%five = OpConstant %3 5 -%9 = OpFunction %1 None %8 -%10 = OpFunctionParameter %2 -%11 = OpFunctionParameter %3 -%12 = OpLabel - OpReturn - OpFunctionEnd -%5 = OpFunction %1 None %4 -%6 = OpLabel -%7 = OpFunctionCall %1 %9 %four %five - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardFunctionCallGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%1 = OpTypeVoid -%2 = OpTypeInt 32 1 -%3 = OpTypeInt 32 0 -%four = OpConstant %2 4 -%five = OpConstant %3 5 -%8 = OpTypeFunction %1 %2 %3 -%4 = OpTypeFunction %1 -%5 = OpFunction %1 None %4 -%6 = OpLabel -%7 = OpFunctionCall %1 %9 %four %five - OpReturn - OpFunctionEnd -%9 = OpFunction %1 None %8 -%10 = OpFunctionParameter %2 -%11 = OpFunctionParameter %3 -%12 = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardBranchConditionalGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%voidt = OpTypeVoid -%boolt = OpTypeBool -%vfunct = OpTypeFunction %voidt -%true = OpConstantTrue %boolt -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel - OpSelectionMerge %endl None - OpBranchConditional %true %truel %falsel -%truel = OpLabel - OpNop - OpBranch %endl -%falsel = OpLabel - OpNop - OpBranch %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardBranchConditionalWithWeightsGood) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%voidt = OpTypeVoid -%boolt = OpTypeBool -%vfunct = OpTypeFunction %voidt -%true = OpConstantTrue %boolt -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel - OpSelectionMerge %endl None - OpBranchConditional %true %truel %falsel 1 9 -%truel = OpLabel - OpNop - OpBranch %endl -%falsel = OpLabel - OpNop - OpBranch %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardBranchConditionalNonDominantConditionBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %tcpy "conditional" -%voidt = OpTypeVoid -%boolt = OpTypeBool -%vfunct = OpTypeFunction %voidt -%true = OpConstantTrue %boolt -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel - OpSelectionMerge %endl None - OpBranchConditional %tcpy %truel %falsel ; -%truel = OpLabel - OpNop - OpBranch %endl -%falsel = OpLabel - OpNop - OpBranch %endl -%endl = OpLabel -%tcpy = OpCopyObject %boolt %true - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("conditional")); -} - -TEST_F(ValidateSSA, ForwardBranchConditionalMissingTargetBad) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 - OpName %missing "missing" -%voidt = OpTypeVoid -%boolt = OpTypeBool -%vfunct = OpTypeFunction %voidt -%true = OpConstantTrue %boolt -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel - OpSelectionMerge %endl None - OpBranchConditional %true %missing %falsel -%truel = OpLabel - OpNop - OpBranch %endl -%falsel = OpLabel - OpNop - OpBranch %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -// Since Int8 requires the Kernel capability, the signedness of int types may -// not be "1". -const std::string kHeader = R"( -OpCapability Int8 -OpCapability DeviceEnqueue -OpCapability Linkage -OpMemoryModel Logical OpenCL -)"; - -const std::string kBasicTypes = R"( -%voidt = OpTypeVoid -%boolt = OpTypeBool -%int8t = OpTypeInt 8 0 -%uintt = OpTypeInt 32 0 -%vfunct = OpTypeFunction %voidt -%intptrt = OpTypePointer UniformConstant %uintt -%zero = OpConstant %uintt 0 -%one = OpConstant %uintt 1 -%ten = OpConstant %uintt 10 -%false = OpConstantFalse %boolt -)"; - -const std::string kKernelTypesAndConstants = R"( -%queuet = OpTypeQueue - -%three = OpConstant %uintt 3 -%arr3t = OpTypeArray %uintt %three -%ndt = OpTypeStruct %uintt %arr3t %arr3t %arr3t - -%eventt = OpTypeEvent - -%offset = OpConstant %uintt 0 -%local = OpConstant %uintt 1 -%gl = OpConstant %uintt 1 - -%nevent = OpConstant %uintt 0 -%event = OpConstantNull %eventt - -%firstp = OpConstant %int8t 0 -%psize = OpConstant %uintt 0 -%palign = OpConstant %uintt 32 -%lsize = OpConstant %uintt 1 -%flags = OpConstant %uintt 0 ; NoWait - -%kfunct = OpTypeFunction %voidt %intptrt -)"; - -const std::string kKernelSetup = R"( -%dqueue = OpGetDefaultQueue %queuet -%ndval = OpBuildNDRange %ndt %gl %local %offset -%revent = OpUndef %eventt - -)"; - -const std::string kKernelDefinition = R"( -%kfunc = OpFunction %voidt None %kfunct -%iparam = OpFunctionParameter %intptrt -%kfuncl = OpLabel - OpNop - OpReturn - OpFunctionEnd -)"; - -TEST_F(ValidateSSA, EnqueueKernelGood) { - std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + - kKernelDefinition + R"( - %main = OpFunction %voidt None %vfunct - %mainl = OpLabel - )" + kKernelSetup + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp %psize - %palign %lsize - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelGood) { - std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + R"( - %main = OpFunction %voidt None %vfunct - %mainl = OpLabel - )" + - kKernelSetup + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp %psize - %palign %lsize - OpReturn - OpFunctionEnd - )" + kKernelDefinition; - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, EnqueueMissingFunctionBad) { - std::string str = kHeader + "OpName %kfunc \"kfunc\"" + kBasicTypes + - kKernelTypesAndConstants + R"( - %main = OpFunction %voidt None %vfunct - %mainl = OpLabel - )" + kKernelSetup + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp %psize - %palign %lsize - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("kfunc")); -} - -std::string forwardKernelNonDominantParameterBaseCode( - std::string name = std::string()) { - std::string op_name; - if (name.empty()) { - op_name = ""; - } else { - op_name = "\nOpName %" + name + " \"" + name + "\"\n"; - } - std::string out = kHeader + op_name + kBasicTypes + kKernelTypesAndConstants + - kKernelDefinition + - R"( - %main = OpFunction %voidt None %vfunct - %mainl = OpLabel - )" + kKernelSetup; - return out; -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelMissingParameter1Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("missing") + R"( - %err = OpEnqueueKernel %missing %dqueue %flags %ndval - %nevent %event %revent %kfunc %firstp - %psize %palign %lsize - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter2Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("dqueue2") + R"( - %err = OpEnqueueKernel %uintt %dqueue2 %flags %ndval - %nevent %event %revent %kfunc - %firstp %psize %palign %lsize - %dqueue2 = OpGetDefaultQueue %queuet - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("dqueue2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter3Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("ndval2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval2 - %nevent %event %revent %kfunc %firstp - %psize %palign %lsize - %ndval2 = OpBuildNDRange %ndt %gl %local %offset - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter4Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("nevent2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent2 - %event %revent %kfunc %firstp %psize - %palign %lsize - %nevent2 = OpCopyObject %uintt %nevent - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("nevent2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter5Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("event2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event2 %revent %kfunc %firstp %psize - %palign %lsize - %event2 = OpCopyObject %eventt %event - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("event2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter6Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("revent2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent2 %kfunc %firstp %psize - %palign %lsize - %revent2 = OpCopyObject %eventt %revent - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("revent2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter8Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("firstp2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp2 %psize - %palign %lsize - %firstp2 = OpCopyObject %int8t %firstp - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter9Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("psize2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp %psize2 - %palign %lsize - %psize2 = OpCopyObject %uintt %psize - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter10Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("palign2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp %psize - %palign2 %lsize - %palign2 = OpCopyObject %uintt %palign - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2")); -} - -TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter11Bad) { - std::string str = forwardKernelNonDominantParameterBaseCode("lsize2") + R"( - %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent - %event %revent %kfunc %firstp %psize - %palign %lsize2 - %lsize2 = OpCopyObject %uintt %lsize - OpReturn - OpFunctionEnd - )"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("lsize2")); -} - -static const bool kWithNDrange = true; -static const bool kNoNDrange = false; -std::pair cases[] = { - {"OpGetKernelNDrangeSubGroupCount", kWithNDrange}, - {"OpGetKernelNDrangeMaxSubGroupSize", kWithNDrange}, - {"OpGetKernelWorkGroupSize", kNoNDrange}, - {"OpGetKernelPreferredWorkGroupSizeMultiple", kNoNDrange}}; - -INSTANTIATE_TEST_SUITE_P(KernelArgs, ValidateSSA, ::testing::ValuesIn(cases)); - -static const std::string return_instructions = R"( - OpReturn - OpFunctionEnd -)"; - -TEST_P(ValidateSSA, GetKernelGood) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode() + " %numsg = " - << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign" - << return_instructions; - // clang-format on - - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateSSA, ForwardGetKernelGood) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - // clang-format off - std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + - R"( - %main = OpFunction %voidt None %vfunct - %mainl = OpLabel - )" - + kKernelSetup + " %numsg = " - + instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign" - + return_instructions + kKernelDefinition; - // clang-format on - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_P(ValidateSSA, ForwardGetKernelMissingDefinitionBad) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = " - << instruction + " %uintt" + ndrange_param + "%missing %firstp %psize %palign" - << return_instructions; - // clang-format on - - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_P(ValidateSSA, ForwardGetKernelNDrangeSubGroupCountMissingParameter1Bad) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = " - << instruction + " %missing" + ndrange_param + "%kfunc %firstp %psize %palign" - << return_instructions; - // clang-format on - - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_P(ValidateSSA, - ForwardGetKernelNDrangeSubGroupCountNonDominantParameter2Bad) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval2 " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode("ndval2") + " %numsg = " - << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign" - << "\n %ndval2 = OpBuildNDRange %ndt %gl %local %offset" - << return_instructions; - // clang-format on - - if (GetParam().second) { - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2")); - } -} - -TEST_P(ValidateSSA, - ForwardGetKernelNDrangeSubGroupCountNonDominantParameter4Bad) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode("firstp2") + " %numsg = " - << instruction + " %uintt" + ndrange_param + "%kfunc %firstp2 %psize %palign" - << "\n %firstp2 = OpCopyObject %int8t %firstp" - << return_instructions; - // clang-format on - - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2")); -} - -TEST_P(ValidateSSA, - ForwardGetKernelNDrangeSubGroupCountNonDominantParameter5Bad) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode("psize2") + " %numsg = " - << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize2 %palign" - << "\n %psize2 = OpCopyObject %uintt %psize" - << return_instructions; - // clang-format on - - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2")); -} - -TEST_P(ValidateSSA, - ForwardGetKernelNDrangeSubGroupCountNonDominantParameter6Bad) { - std::string instruction = GetParam().first; - bool with_ndrange = GetParam().second; - std::string ndrange_param = with_ndrange ? " %ndval " : " "; - - std::stringstream ss; - // clang-format off - ss << forwardKernelNonDominantParameterBaseCode("palign2") + " %numsg = " - << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign2" - << "\n %palign2 = OpCopyObject %uintt %palign" - << return_instructions; - // clang-format on - - if (GetParam().second) { - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2")); - } -} - -TEST_F(ValidateSSA, PhiGood) { - std::string str = kHeader + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%preheader = OpLabel -%init = OpCopyObject %uintt %zero - OpBranch %loop -%loop = OpLabel -%i = OpPhi %uintt %init %preheader %loopi %loop -%loopi = OpIAdd %uintt %i %one - OpNop -%cond = OpSLessThan %boolt %i %ten - OpLoopMerge %endl %loop None - OpBranchConditional %cond %loop %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, PhiMissingTypeBad) { - std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%preheader = OpLabel -%init = OpCopyObject %uintt %zero - OpBranch %loop -%loop = OpLabel -%i = OpPhi %missing %init %preheader %loopi %loop -%loopi = OpIAdd %uintt %i %one - OpNop -%cond = OpSLessThan %boolt %i %ten - OpLoopMerge %endl %loop None - OpBranchConditional %cond %loop %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, PhiMissingIdBad) { - std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%preheader = OpLabel -%init = OpCopyObject %uintt %zero - OpBranch %loop -%loop = OpLabel -%i = OpPhi %uintt %missing %preheader %loopi %loop -%loopi = OpIAdd %uintt %i %one - OpNop -%cond = OpSLessThan %boolt %i %ten - OpLoopMerge %endl %loop None - OpBranchConditional %cond %loop %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, PhiMissingLabelBad) { - std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%preheader = OpLabel -%init = OpCopyObject %uintt %zero - OpBranch %loop -%loop = OpLabel -%i = OpPhi %uintt %init %missing %loopi %loop -%loopi = OpIAdd %uintt %i %one - OpNop -%cond = OpSLessThan %boolt %i %ten - OpLoopMerge %endl %loop None - OpBranchConditional %cond %loop %endl -%endl = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); -} - -TEST_F(ValidateSSA, IdDominatesItsUseGood) { - std::string str = kHeader + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel -%cond = OpSLessThan %boolt %one %ten -%eleven = OpIAdd %uintt %one %ten - OpSelectionMerge %merge None - OpBranchConditional %cond %t %f -%t = OpLabel -%twelve = OpIAdd %uintt %eleven %one - OpBranch %merge -%f = OpLabel -%twentytwo = OpIAdd %uintt %eleven %ten - OpBranch %merge -%merge = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, IdDoesNotDominateItsUseBad) { - std::string str = kHeader + - "OpName %eleven \"eleven\"\n" - "OpName %true_block \"true_block\"\n" - "OpName %false_block \"false_block\"" + - kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel -%cond = OpSLessThan %boolt %one %ten - OpSelectionMerge %merge None - OpBranchConditional %cond %true_block %false_block -%true_block = OpLabel -%eleven = OpIAdd %uintt %one %ten -%twelve = OpIAdd %uintt %eleven %one - OpBranch %merge -%false_block = OpLabel -%twentytwo = OpIAdd %uintt %eleven %ten - OpBranch %merge -%merge = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("ID .\\[%eleven\\] defined in block .\\[%true_block\\] " - "does not dominate its use in block .\\[%false_block\\]\n" - " %false_block = OpLabel\n")); -} - -TEST_F(ValidateSSA, PhiUseDoesntDominateDefinitionGood) { - std::string str = kHeader + kBasicTypes + - R"( -%funcintptrt = OpTypePointer Function %uintt -%func = OpFunction %voidt None %vfunct -%entry = OpLabel -%var_one = OpVariable %funcintptrt Function %one -%one_val = OpLoad %uintt %var_one - OpBranch %loop -%loop = OpLabel -%i = OpPhi %uintt %one_val %entry %inew %cont -%cond = OpSLessThan %boolt %one %ten - OpLoopMerge %merge %cont None - OpBranchConditional %cond %body %merge -%body = OpLabel - OpBranch %cont -%cont = OpLabel -%inew = OpIAdd %uintt %i %one - OpBranch %loop -%merge = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, - PhiUseDoesntDominateUseOfPhiOperandUsedBeforeDefinitionBad) { - std::string str = kHeader + "OpName %inew \"inew\"" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel -%var_one = OpVariable %intptrt Function %one -%one_val = OpLoad %uintt %var_one - OpBranch %loop -%loop = OpLabel -%i = OpPhi %uintt %one_val %entry %inew %cont -%bad = OpIAdd %uintt %inew %one -%cond = OpSLessThan %boolt %one %ten - OpLoopMerge %merge %cont None - OpBranchConditional %cond %body %merge -%body = OpLabel - OpBranch %cont -%cont = OpLabel -%inew = OpIAdd %uintt %i %one - OpBranch %loop -%merge = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - MatchesRegex("ID .\\[%inew\\] has not been defined\n" - " %19 = OpIAdd %uint %inew %uint_1\n")); -} - -TEST_F(ValidateSSA, PhiUseMayComeFromNonDominatingBlockGood) { - std::string str = kHeader + "OpName %if_true \"if_true\"\n" + - "OpName %exit \"exit\"\n" + "OpName %copy \"copy\"\n" + - kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel - OpBranchConditional %false %if_true %exit - -%if_true = OpLabel -%copy = OpCopyObject %boolt %false - OpBranch %exit - -; The use of %copy here is ok, even though it was defined -; in a block that does not dominate %exit. That's the point -; of an OpPhi. -%exit = OpLabel -%value = OpPhi %boolt %false %entry %copy %if_true - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateSSA, PhiUsesItsOwnDefinitionGood) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/415 - // - // Non-phi instructions can't use their own definitions, as - // already checked in test DominateUsageSameInstructionBad. - std::string str = kHeader + "OpName %loop \"loop\"\n" + - "OpName %value \"value\"\n" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel - OpBranch %loop - -%loop = OpLabel -%value = OpPhi %boolt %false %entry %value %loop - OpBranch %loop - - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateSSA, PhiVariableDefNotDominatedByParentBlockBad) { - std::string str = kHeader + "OpName %if_true \"if_true\"\n" + - "OpName %if_false \"if_false\"\n" + - "OpName %exit \"exit\"\n" + "OpName %value \"phi\"\n" + - "OpName %true_copy \"true_copy\"\n" + - "OpName %false_copy \"false_copy\"\n" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel - OpBranchConditional %false %if_true %if_false - -%if_true = OpLabel -%true_copy = OpCopyObject %boolt %false - OpBranch %exit - -%if_false = OpLabel -%false_copy = OpCopyObject %boolt %false - OpBranch %exit - -; The (variable,Id) pairs are swapped. -%exit = OpLabel -%value = OpPhi %boolt %true_copy %if_false %false_copy %if_true - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("In OpPhi instruction .\\[%phi\\], ID .\\[%true_copy\\] " - "definition does not dominate its parent .\\[%if_false\\]\n" - " %phi = OpPhi %bool %true_copy %if_false %false_copy " - "%if_true\n")); -} - -TEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) { - std::string str = kHeader + "OpName %if_true \"if_true\"\n" + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel - OpBranchConditional %false %if_true %if_false - -%if_true = OpLabel -%true_copy = OpCopyObject %boolt %false - OpBranch %if_tnext -%if_tnext = OpLabel - OpBranch %exit - -%if_false = OpLabel -%false_copy = OpCopyObject %boolt %false - OpBranch %if_fnext -%if_fnext = OpLabel - OpBranch %exit - -%exit = OpLabel -%value = OpPhi %boolt %true_copy %if_tnext %false_copy %if_fnext - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, - DominanceCheckIgnoresUsesInUnreachableBlocksDefInBlockGood) { - std::string str = kHeader + kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel -%def = OpCopyObject %boolt %false - OpReturn - -%unreach = OpLabel -%use = OpCopyObject %boolt %def - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateSSA, PhiVariableUnreachableDefNotInParentBlock) { - std::string str = kHeader + "OpName %unreachable \"unreachable\"\n" + - kBasicTypes + - R"( -%func = OpFunction %voidt None %vfunct -%entry = OpLabel - OpBranch %if_false - -%unreachable = OpLabel -%copy = OpCopyObject %boolt %false - OpBranch %if_tnext -%if_tnext = OpLabel - OpBranch %exit - -%if_false = OpLabel -%false_copy = OpCopyObject %boolt %false - OpBranch %if_fnext -%if_fnext = OpLabel - OpBranch %exit - -%exit = OpLabel -%value = OpPhi %boolt %copy %if_tnext %false_copy %if_fnext - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, - DominanceCheckIgnoresUsesInUnreachableBlocksDefIsParamGood) { - std::string str = kHeader + kBasicTypes + - R"( -%void_fn_int = OpTypeFunction %voidt %uintt -%func = OpFunction %voidt None %void_fn_int -%int_param = OpFunctionParameter %uintt -%entry = OpLabel - OpReturn - -%unreach = OpLabel -%use = OpCopyObject %uintt %int_param - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); -} - -TEST_F(ValidateSSA, UseFunctionParameterFromOtherFunctionBad) { - std::string str = kHeader + - "OpName %first \"first\"\n" - "OpName %func \"func\"\n" + - "OpName %func2 \"func2\"\n" + kBasicTypes + - R"( -%viifunct = OpTypeFunction %voidt %uintt %uintt -%func = OpFunction %voidt None %viifunct -%first = OpFunctionParameter %uintt -%second = OpFunctionParameter %uintt - OpFunctionEnd -%func2 = OpFunction %voidt None %viifunct -%first2 = OpFunctionParameter %uintt -%second2 = OpFunctionParameter %uintt -%entry2 = OpLabel -%baduse = OpIAdd %uintt %first %first2 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - MatchesRegex("ID .\\[%first\\] used in function .\\[%func2\\] is used " - "outside of it's defining function .\\[%func\\]\n" - " %func = OpFunction %void None %14\n")); -} - -TEST_F(ValidateSSA, TypeForwardPointerForwardReference) { - // See https://github.com/KhronosGroup/SPIRV-Tools/issues/429 - // - // ForwardPointers can references instructions that have not been defined - std::string str = R"( - OpCapability Kernel - OpCapability Addresses - OpCapability Linkage - OpMemoryModel Logical OpenCL - OpName %intptrt "intptrt" - OpTypeForwardPointer %intptrt UniformConstant - %uint = OpTypeInt 32 0 - %struct = OpTypeStruct %uint - %intptrt = OpTypePointer UniformConstant %struct -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateSSA, TypeStructForwardReference) { - std::string str = R"( - OpCapability Kernel - OpCapability Addresses - OpCapability Linkage - OpMemoryModel Logical OpenCL - OpName %structptr "structptr" - OpTypeForwardPointer %structptr UniformConstant - %uint = OpTypeInt 32 0 - %structt1 = OpTypeStruct %structptr %uint - %structt2 = OpTypeStruct %uint %structptr - %structt3 = OpTypeStruct %uint %uint %structptr - %structt4 = OpTypeStruct %uint %uint %uint %structptr - %structptr = OpTypePointer UniformConstant %structt1 -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// TODO(umar): OpGroupMemberDecorate - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_state_test.cpp b/3rdparty/spirv-tools/test/val/val_state_test.cpp deleted file mode 100644 index 18a4ef99e..000000000 --- a/3rdparty/spirv-tools/test/val/val_state_test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// 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. - -// Unit tests for ValidationState_t. - -#include - -#include "gtest/gtest.h" -#include "source/latest_version_spirv_header.h" - -#include "source/enum_set.h" -#include "source/extensions.h" -#include "source/spirv_validator_options.h" -#include "source/val/construct.h" -#include "source/val/function.h" -#include "source/val/validate.h" -#include "source/val/validation_state.h" - -namespace spvtools { -namespace val { -namespace { - -// This is all we need for these tests. -static uint32_t kFakeBinary[] = {0}; - -// A test with a ValidationState_t member transparently. -class ValidationStateTest : public testing::Test { - public: - ValidationStateTest() - : context_(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)), - options_(spvValidatorOptionsCreate()), - state_(context_, options_, kFakeBinary, 0, 1) {} - - ~ValidationStateTest() { - spvContextDestroy(context_); - spvValidatorOptionsDestroy(options_); - } - - protected: - spv_context context_; - spv_validator_options options_; - ValidationState_t state_; -}; - -// A test of ValidationState_t::HasAnyOfCapabilities(). -using ValidationState_HasAnyOfCapabilities = ValidationStateTest; - -TEST_F(ValidationState_HasAnyOfCapabilities, EmptyMask) { - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); - state_.RegisterCapability(SpvCapabilityMatrix); - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); - state_.RegisterCapability(SpvCapabilityImageMipmap); - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); - state_.RegisterCapability(SpvCapabilityPipes); - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); - state_.RegisterCapability(SpvCapabilityStorageImageArrayDynamicIndexing); - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); - state_.RegisterCapability(SpvCapabilityClipDistance); - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); - state_.RegisterCapability(SpvCapabilityStorageImageWriteWithoutFormat); - EXPECT_TRUE(state_.HasAnyOfCapabilities({})); -} - -TEST_F(ValidationState_HasAnyOfCapabilities, SingleCapMask) { - EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix})); - EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap})); - state_.RegisterCapability(SpvCapabilityMatrix); - EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix})); - EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap})); - state_.RegisterCapability(SpvCapabilityImageMipmap); - EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix})); - EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap})); -} - -TEST_F(ValidationState_HasAnyOfCapabilities, MultiCapMask) { - const auto set1 = - CapabilitySet{SpvCapabilitySampledRect, SpvCapabilityImageBuffer}; - const auto set2 = CapabilitySet{SpvCapabilityStorageImageWriteWithoutFormat, - SpvCapabilityStorageImageReadWithoutFormat, - SpvCapabilityGeometryStreams}; - EXPECT_FALSE(state_.HasAnyOfCapabilities(set1)); - EXPECT_FALSE(state_.HasAnyOfCapabilities(set2)); - state_.RegisterCapability(SpvCapabilityImageBuffer); - EXPECT_TRUE(state_.HasAnyOfCapabilities(set1)); - EXPECT_FALSE(state_.HasAnyOfCapabilities(set2)); -} - -// A test of ValidationState_t::HasAnyOfExtensions(). -using ValidationState_HasAnyOfExtensions = ValidationStateTest; - -TEST_F(ValidationState_HasAnyOfExtensions, EmptyMask) { - EXPECT_TRUE(state_.HasAnyOfExtensions({})); - state_.RegisterExtension(Extension::kSPV_KHR_shader_ballot); - EXPECT_TRUE(state_.HasAnyOfExtensions({})); - state_.RegisterExtension(Extension::kSPV_KHR_16bit_storage); - EXPECT_TRUE(state_.HasAnyOfExtensions({})); - state_.RegisterExtension(Extension::kSPV_NV_viewport_array2); - EXPECT_TRUE(state_.HasAnyOfExtensions({})); -} - -TEST_F(ValidationState_HasAnyOfExtensions, SingleCapMask) { - EXPECT_FALSE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_shader_ballot})); - EXPECT_FALSE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_16bit_storage})); - state_.RegisterExtension(Extension::kSPV_KHR_shader_ballot); - EXPECT_TRUE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_shader_ballot})); - EXPECT_FALSE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_16bit_storage})); - state_.RegisterExtension(Extension::kSPV_KHR_16bit_storage); - EXPECT_TRUE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_shader_ballot})); - EXPECT_TRUE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_16bit_storage})); -} - -TEST_F(ValidationState_HasAnyOfExtensions, MultiCapMask) { - const auto set1 = ExtensionSet{Extension::kSPV_KHR_multiview, - Extension::kSPV_KHR_16bit_storage}; - const auto set2 = ExtensionSet{Extension::kSPV_KHR_shader_draw_parameters, - Extension::kSPV_NV_stereo_view_rendering, - Extension::kSPV_KHR_shader_ballot}; - EXPECT_FALSE(state_.HasAnyOfExtensions(set1)); - EXPECT_FALSE(state_.HasAnyOfExtensions(set2)); - state_.RegisterExtension(Extension::kSPV_KHR_multiview); - EXPECT_TRUE(state_.HasAnyOfExtensions(set1)); - EXPECT_FALSE(state_.HasAnyOfExtensions(set2)); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_storage_test.cpp b/3rdparty/spirv-tools/test/val/val_storage_test.cpp deleted file mode 100644 index fe37a93c6..000000000 --- a/3rdparty/spirv-tools/test/val/val_storage_test.cpp +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group 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. - -// Validation tests for OpVariable storage class - -#include -#include -#include - -#include "gmock/gmock.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Values; -using ValidateStorage = spvtest::ValidateBase; -using ValidateStorageClass = - spvtest::ValidateBase>; - -TEST_F(ValidateStorage, FunctionStorageInsideFunction) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%ptrt = OpTypePointer Function %intt -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel -%var = OpVariable %ptrt Function - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateStorage, FunctionStorageOutsideFunction) { - char str[] = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%ptrt = OpTypePointer Function %intt -%var = OpVariable %ptrt Function -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Variables can not have a function[7] storage class " - "outside of a function")); -} - -TEST_F(ValidateStorage, OtherStorageOutsideFunction) { - char str[] = R"( - OpCapability Shader - OpCapability Kernel - OpCapability AtomicStorage - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%intt = OpTypeInt 32 0 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%uniconptrt = OpTypePointer UniformConstant %intt -%unicon = OpVariable %uniconptrt UniformConstant -%inputptrt = OpTypePointer Input %intt -%input = OpVariable %inputptrt Input -%unifptrt = OpTypePointer Uniform %intt -%unif = OpVariable %unifptrt Uniform -%outputptrt = OpTypePointer Output %intt -%output = OpVariable %outputptrt Output -%wgroupptrt = OpTypePointer Workgroup %intt -%wgroup = OpVariable %wgroupptrt Workgroup -%xwgrpptrt = OpTypePointer CrossWorkgroup %intt -%xwgrp = OpVariable %xwgrpptrt CrossWorkgroup -%privptrt = OpTypePointer Private %intt -%priv = OpVariable %privptrt Private -%pushcoptrt = OpTypePointer PushConstant %intt -%pushco = OpVariable %pushcoptrt PushConstant -%atomcptrt = OpTypePointer AtomicCounter %intt -%atomct = OpVariable %atomcptrt AtomicCounter -%imageptrt = OpTypePointer Image %intt -%image = OpVariable %imageptrt Image -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(str); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// clang-format off -TEST_P(ValidateStorage, OtherStorageInsideFunction) { - std::stringstream ss; - ss << R"( - OpCapability Shader - OpCapability Kernel - OpCapability AtomicStorage - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%intt = OpTypeInt 32 0 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%ptrt = OpTypePointer Function %intt -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel -%var = OpVariable %ptrt )" << GetParam() << R"( - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(ss.str()); - ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr( - "Variables must have a function[7] storage class inside of a function")); -} - -INSTANTIATE_TEST_SUITE_P(MatrixOp, ValidateStorage, - ::testing::Values( - "Input", - "Uniform", - "Output", - "Workgroup", - "CrossWorkgroup", - "Private", - "PushConstant", - "AtomicCounter", - "Image")); -// clang-format on - -TEST_F(ValidateStorage, GenericVariableOutsideFunction) { - const auto str = R"( - OpCapability Kernel - OpCapability Linkage - OpCapability GenericPointer - OpMemoryModel Logical OpenCL -%intt = OpTypeInt 32 0 -%ptrt = OpTypePointer Function %intt -%var = OpVariable %ptrt Generic -)"; - CompileSuccessfully(str); - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpVariable storage class cannot be Generic")); -} - -TEST_F(ValidateStorage, GenericVariableInsideFunction) { - const auto str = R"( - OpCapability Shader - OpCapability Linkage - OpCapability GenericPointer - OpMemoryModel Logical GLSL450 -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%ptrt = OpTypePointer Function %intt -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel -%var = OpVariable %ptrt Generic - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpVariable storage class cannot be Generic")); -} - -TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParam) { - const auto str = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%ptrt = OpTypePointer Function %intt -%vfunct = OpTypeFunction %voidt -%vifunct = OpTypeFunction %voidt %ptrt -%wgroupptrt = OpTypePointer Workgroup %intt -%wgroup = OpVariable %wgroupptrt Workgroup -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel -%ret = OpFunctionCall %voidt %func %wgroup - OpReturn - OpFunctionEnd -%func = OpFunction %voidt None %vifunct -%arg = OpFunctionParameter %ptrt -%funcl = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - getValidatorOptions()->before_hlsl_legalization = true; - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParamBad) { - const auto str = R"( - OpCapability Shader - OpCapability Linkage - OpMemoryModel Logical GLSL450 -%floatt = OpTypeFloat 32 -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%ptrt = OpTypePointer Function %intt -%vfunct = OpTypeFunction %voidt -%vifunct = OpTypeFunction %voidt %ptrt -%wgroupptrt = OpTypePointer Workgroup %floatt -%wgroup = OpVariable %wgroupptrt Workgroup -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel -%ret = OpFunctionCall %voidt %func %wgroup - OpReturn - OpFunctionEnd -%func = OpFunction %voidt None %vifunct -%arg = OpFunctionParameter %ptrt -%funcl = OpLabel - OpReturn - OpFunctionEnd -)"; - CompileSuccessfully(str); - getValidatorOptions()->relax_logical_pointer = true; - ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpFunctionCall Argument '")); -} - -std::string GetVarDeclStr(const std::string& storage_class) { - if (storage_class != "Output" && storage_class != "Private" && - storage_class != "Function") { - return "%var = OpVariable %ptrt " + storage_class + "\n"; - } else { - return "%var = OpVariable %ptrt " + storage_class + " %null\n"; - } -} - -TEST_P(ValidateStorageClass, WebGPU) { - std::string storage_class = std::get<0>(GetParam()); - bool is_local = std::get<1>(GetParam()); - bool is_valid = std::get<2>(GetParam()); - std::string error = std::get<3>(GetParam()); - - std::string str = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Fragment %func "func" - OpExecutionMode %func OriginUpperLeft -%intt = OpTypeInt 32 1 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%null = OpConstantNull %intt -)"; - str += "%ptrt = OpTypePointer " + storage_class + " %intt\n"; - if (!is_local) str += GetVarDeclStr(storage_class); - str += R"( -%func = OpFunction %voidt None %vfunct -%funcl = OpLabel -)"; - if (is_local) str += GetVarDeclStr(storage_class); - str += R"( -OpReturn -OpFunctionEnd -)"; - - CompileSuccessfully(str, SPV_ENV_WEBGPU_0); - if (is_valid) { - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); - } else { - ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), HasSubstr(error)); - } -} - -INSTANTIATE_TEST_SUITE_P( - StorageClass, ValidateStorageClass, - Values(std::make_tuple("UniformConstant", false, true, ""), - std::make_tuple("Uniform", false, true, ""), - std::make_tuple("StorageBuffer", false, true, ""), - std::make_tuple("Input", false, true, ""), - std::make_tuple("Output", false, true, ""), - std::make_tuple("Image", false, true, ""), - std::make_tuple("Workgroup", false, true, ""), - std::make_tuple("Private", false, true, ""), - std::make_tuple("Function", true, true, ""), - std::make_tuple("CrossWorkgroup", false, false, - "Invalid storage class for target environment"), - std::make_tuple("PushConstant", false, false, - "Invalid storage class for target environment"))); - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_type_unique_test.cpp b/3rdparty/spirv-tools/test/val/val_type_unique_test.cpp deleted file mode 100644 index 45a4d5048..000000000 --- a/3rdparty/spirv-tools/test/val/val_type_unique_test.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) 2017 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. - -// Tests for unique type declaration rules validator. - -#include - -#include "gmock/gmock.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; -using ::testing::Not; - -using ValidateTypeUnique = spvtest::ValidateBase; - -const spv_result_t kDuplicateTypeError = SPV_ERROR_INVALID_DATA; - -const std::string& GetHeader() { - static const std::string header = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%floatt = OpTypeFloat 32 -%vec2t = OpTypeVector %floatt 2 -%vec3t = OpTypeVector %floatt 3 -%vec4t = OpTypeVector %floatt 4 -%mat22t = OpTypeMatrix %vec2t 2 -%mat33t = OpTypeMatrix %vec3t 3 -%mat44t = OpTypeMatrix %vec4t 4 -%intt = OpTypeInt 32 1 -%uintt = OpTypeInt 32 0 -%num3 = OpConstant %uintt 3 -%const3 = OpConstant %uintt 3 -%val3 = OpConstant %uintt 3 -%array = OpTypeArray %vec3t %num3 -%struct = OpTypeStruct %floatt %floatt %vec3t -%boolt = OpTypeBool -%array2 = OpTypeArray %vec3t %num3 -%voidt = OpTypeVoid -%vfunct = OpTypeFunction %voidt -%struct2 = OpTypeStruct %floatt %floatt %vec3t -%false = OpConstantFalse %boolt -%true = OpConstantTrue %boolt -%runtime_arrayt = OpTypeRuntimeArray %floatt -%runtime_arrayt2 = OpTypeRuntimeArray %floatt -)"; - - return header; -} - -const std::string& GetBody() { - static const std::string body = R"( -%main = OpFunction %voidt None %vfunct -%mainl = OpLabel -%a = OpIAdd %uintt %const3 %val3 -%b = OpIAdd %uintt %const3 %val3 -OpSelectionMerge %endl None -OpBranchConditional %true %truel %falsel -%truel = OpLabel -%add1 = OpIAdd %uintt %a %b -%add2 = OpIAdd %uintt %a %b -OpBranch %endl -%falsel = OpLabel -%sub1 = OpISub %uintt %a %b -%sub2 = OpISub %uintt %a %b -OpBranch %endl -%endl = OpLabel -OpReturn -OpFunctionEnd -)"; - - return body; -} - -// Returns expected error string if |opcode| produces a duplicate type -// declaration. -std::string GetErrorString(SpvOp opcode) { - return "Duplicate non-aggregate type declarations are not allowed. Opcode: " + - std::string(spvOpcodeString(opcode)); -} - -TEST_F(ValidateTypeUnique, success) { - std::string str = GetHeader() + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateTypeUnique, duplicate_void) { - std::string str = GetHeader() + R"( -%boolt2 = OpTypeVoid -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeVoid))); -} - -TEST_F(ValidateTypeUnique, duplicate_bool) { - std::string str = GetHeader() + R"( -%boolt2 = OpTypeBool -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeBool))); -} - -TEST_F(ValidateTypeUnique, duplicate_int) { - std::string str = GetHeader() + R"( -%uintt2 = OpTypeInt 32 0 -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeInt))); -} - -TEST_F(ValidateTypeUnique, duplicate_float) { - std::string str = GetHeader() + R"( -%floatt2 = OpTypeFloat 32 -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeFloat))); -} - -TEST_F(ValidateTypeUnique, duplicate_vec3) { - std::string str = GetHeader() + R"( -%vec3t2 = OpTypeVector %floatt 3 -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(GetErrorString(SpvOpTypeVector))); -} - -TEST_F(ValidateTypeUnique, duplicate_mat33) { - std::string str = GetHeader() + R"( -%mat33t2 = OpTypeMatrix %vec3t 3 -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(GetErrorString(SpvOpTypeMatrix))); -} - -TEST_F(ValidateTypeUnique, duplicate_vfunc) { - std::string str = GetHeader() + R"( -%vfunct2 = OpTypeFunction %voidt -)" + GetBody(); - CompileSuccessfully(str.c_str()); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(GetErrorString(SpvOpTypeFunction))); -} - -TEST_F(ValidateTypeUnique, duplicate_pipe_storage) { - std::string str = R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability Pipes -OpCapability PipeStorage -OpMemoryModel Physical32 OpenCL -%ps = OpTypePipeStorage -%ps2 = OpTypePipeStorage -)"; - CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(GetErrorString(SpvOpTypePipeStorage))); -} - -TEST_F(ValidateTypeUnique, duplicate_named_barrier) { - std::string str = R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability NamedBarrier -OpMemoryModel Physical32 OpenCL -%nb = OpTypeNamedBarrier -%nb2 = OpTypeNamedBarrier -)"; - CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_1); - ASSERT_EQ(kDuplicateTypeError, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr(GetErrorString(SpvOpTypeNamedBarrier))); -} - -TEST_F(ValidateTypeUnique, duplicate_forward_pointer) { - std::string str = R"( -OpCapability Addresses -OpCapability Kernel -OpCapability GenericPointer -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -OpTypeForwardPointer %ptr Generic -OpTypeForwardPointer %ptr2 Generic -%intt = OpTypeInt 32 0 -%int_struct = OpTypeStruct %intt -%floatt = OpTypeFloat 32 -%ptr = OpTypePointer Generic %int_struct -%float_struct = OpTypeStruct %floatt -%ptr2 = OpTypePointer Generic %float_struct -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateTypeUnique, duplicate_void_with_extension) { - std::string str = R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpCapability Pipes -OpExtension "SPV_VALIDATOR_ignore_type_decl_unique" -OpMemoryModel Physical32 OpenCL -%voidt = OpTypeVoid -%voidt2 = OpTypeVoid -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - Not(HasSubstr(GetErrorString(SpvOpTypeVoid)))); -} - -TEST_F(ValidateTypeUnique, DuplicatePointerTypesNoExtension) { - std::string str = R"( -OpCapability Shader -OpCapability Linkage -OpMemoryModel Logical GLSL450 -%u32 = OpTypeInt 32 0 -%ptr1 = OpTypePointer Input %u32 -%ptr2 = OpTypePointer Input %u32 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -TEST_F(ValidateTypeUnique, DuplicatePointerTypesWithExtension) { - std::string str = R"( -OpCapability Shader -OpCapability Linkage -OpExtension "SPV_KHR_variable_pointers" -OpMemoryModel Logical GLSL450 -%u32 = OpTypeInt 32 0 -%ptr1 = OpTypePointer Input %u32 -%ptr2 = OpTypePointer Input %u32 -)"; - CompileSuccessfully(str.c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - Not(HasSubstr(GetErrorString(SpvOpTypePointer)))); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_validation_state_test.cpp b/3rdparty/spirv-tools/test/val/val_validation_state_test.cpp deleted file mode 100644 index 458157902..000000000 --- a/3rdparty/spirv-tools/test/val/val_validation_state_test.cpp +++ /dev/null @@ -1,361 +0,0 @@ -// 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. - -// Basic tests for the ValidationState_t datastructure. - -#include - -#include "gmock/gmock.h" -#include "source/spirv_validator_options.h" -#include "test/unit_spirv.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; - -using ValidationStateTest = spvtest::ValidateBase; - -const char kHeader[] = - " OpCapability Shader" - " OpCapability Linkage" - " OpMemoryModel Logical GLSL450 "; - -const char kVulkanMemoryHeader[] = - " OpCapability Shader" - " OpCapability VulkanMemoryModelKHR" - " OpExtension \"SPV_KHR_vulkan_memory_model\"" - " OpMemoryModel Logical VulkanKHR "; - -const char kVoidFVoid[] = - " %void = OpTypeVoid" - " %void_f = OpTypeFunction %void" - " %func = OpFunction %void None %void_f" - " %label = OpLabel" - " OpReturn" - " OpFunctionEnd "; - -// k*RecursiveBody examples originally from test/opt/function_test.cpp -const char* kNonRecursiveBody = R"( -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%null = OpConstantNull %_struct_6 -%7 = OpTypeFunction %_struct_6 -%12 = OpFunction %_struct_6 None %7 -%13 = OpLabel -OpReturnValue %null -OpFunctionEnd -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %12 -OpReturnValue %null -OpFunctionEnd -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -)"; - -const char* kDirectlyRecursiveBody = R"( -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%7 = OpTypeFunction %_struct_6 -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpReturn -OpFunctionEnd -)"; - -const char* kIndirectlyRecursiveBody = R"( -OpEntryPoint Fragment %1 "main" -OpExecutionMode %1 OriginUpperLeft -%void = OpTypeVoid -%4 = OpTypeFunction %void -%float = OpTypeFloat 32 -%_struct_6 = OpTypeStruct %float %float -%null = OpConstantNull %_struct_6 -%7 = OpTypeFunction %_struct_6 -%9 = OpFunction %_struct_6 None %7 -%10 = OpLabel -%11 = OpFunctionCall %_struct_6 %12 -OpReturnValue %null -OpFunctionEnd -%12 = OpFunction %_struct_6 None %7 -%13 = OpLabel -%14 = OpFunctionCall %_struct_6 %9 -OpReturnValue %null -OpFunctionEnd -%1 = OpFunction %void Pure|Const %4 -%8 = OpLabel -%2 = OpFunctionCall %_struct_6 %9 -OpKill -OpFunctionEnd -)"; - -// Tests that the instruction count in ValidationState is correct. -TEST_F(ValidationStateTest, CheckNumInstructions) { - std::string spirv = std::string(kHeader) + "%int = OpTypeInt 32 0"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_EQ(size_t(4), vstate_->ordered_instructions().size()); -} - -// Tests that the number of global variables in ValidationState is correct. -TEST_F(ValidationStateTest, CheckNumGlobalVars) { - std::string spirv = std::string(kHeader) + R"( - %int = OpTypeInt 32 0 -%_ptr_int = OpTypePointer Input %int - %var_1 = OpVariable %_ptr_int Input - %var_2 = OpVariable %_ptr_int Input - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_EQ(unsigned(2), vstate_->num_global_vars()); -} - -// Tests that the number of local variables in ValidationState is correct. -TEST_F(ValidationStateTest, CheckNumLocalVars) { - std::string spirv = std::string(kHeader) + R"( - %int = OpTypeInt 32 0 - %_ptr_int = OpTypePointer Function %int - %voidt = OpTypeVoid - %funct = OpTypeFunction %voidt - %main = OpFunction %voidt None %funct - %entry = OpLabel - %var_1 = OpVariable %_ptr_int Function - %var_2 = OpVariable %_ptr_int Function - %var_3 = OpVariable %_ptr_int Function - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_EQ(unsigned(3), vstate_->num_local_vars()); -} - -// Tests that the "id bound" in ValidationState is correct. -TEST_F(ValidationStateTest, CheckIdBound) { - std::string spirv = std::string(kHeader) + R"( - %int = OpTypeInt 32 0 - %voidt = OpTypeVoid - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_EQ(unsigned(3), vstate_->getIdBound()); -} - -// Tests that the entry_points in ValidationState is correct. -TEST_F(ValidationStateTest, CheckEntryPoints) { - std::string spirv = std::string(kHeader) + - " OpEntryPoint Vertex %func \"shader\"" + - std::string(kVoidFVoid); - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); - EXPECT_EQ(size_t(1), vstate_->entry_points().size()); - EXPECT_EQ(SpvOpFunction, - vstate_->FindDef(vstate_->entry_points()[0])->opcode()); -} - -TEST_F(ValidationStateTest, CheckStructMemberLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_struct_members, 32000u); - EXPECT_EQ(32000u, options_->universal_limits_.max_struct_members); -} - -TEST_F(ValidationStateTest, CheckNumGlobalVarsLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_global_variables, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_global_variables); -} - -TEST_F(ValidationStateTest, CheckNumLocalVarsLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_local_variables, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_local_variables); -} - -TEST_F(ValidationStateTest, CheckStructDepthLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_struct_depth, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_struct_depth); -} - -TEST_F(ValidationStateTest, CheckSwitchBranchesLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_switch_branches, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_switch_branches); -} - -TEST_F(ValidationStateTest, CheckFunctionArgsLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_function_args, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_function_args); -} - -TEST_F(ValidationStateTest, CheckCFGDepthLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_control_flow_nesting_depth, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_control_flow_nesting_depth); -} - -TEST_F(ValidationStateTest, CheckAccessChainIndexesLimitOption) { - spvValidatorOptionsSetUniversalLimit( - options_, spv_validator_limit_max_access_chain_indexes, 100u); - EXPECT_EQ(100u, options_->universal_limits_.max_access_chain_indexes); -} - -TEST_F(ValidationStateTest, CheckNonRecursiveBodyGood) { - std::string spirv = std::string(kHeader) + kNonRecursiveBody; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidationStateTest, CheckVulkanNonRecursiveBodyGood) { - std::string spirv = std::string(kVulkanMemoryHeader) + kNonRecursiveBody; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_SUCCESS, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); -} - -TEST_F(ValidationStateTest, CheckWebGPUNonRecursiveBodyGood) { - std::string spirv = std::string(kVulkanMemoryHeader) + kNonRecursiveBody; - CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidationStateTest, CheckDirectlyRecursiveBodyGood) { - std::string spirv = std::string(kHeader) + kDirectlyRecursiveBody; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidationStateTest, CheckVulkanDirectlyRecursiveBodyBad) { - std::string spirv = std::string(kVulkanMemoryHeader) + kDirectlyRecursiveBody; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Entry points may not have a call graph with cycles.\n " - " %1 = OpFunction %void Pure|Const %3\n")); -} - -TEST_F(ValidationStateTest, CheckWebGPUDirectlyRecursiveBodyBad) { - std::string spirv = std::string(kVulkanMemoryHeader) + kDirectlyRecursiveBody; - CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Entry points may not have a call graph with cycles.\n " - " %1 = OpFunction %void Pure|Const %3\n")); -} - -TEST_F(ValidationStateTest, CheckIndirectlyRecursiveBodyGood) { - std::string spirv = std::string(kHeader) + kIndirectlyRecursiveBody; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState()); -} - -TEST_F(ValidationStateTest, CheckVulkanIndirectlyRecursiveBodyBad) { - std::string spirv = - std::string(kVulkanMemoryHeader) + kIndirectlyRecursiveBody; - CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Entry points may not have a call graph with cycles.\n " - " %1 = OpFunction %void Pure|Const %3\n")); -} - -// Indirectly recursive functions are caught by the function definition layout -// rules, because they cause a situation where there are 2 functions that have -// to be before each other, and layout is checked earlier. -TEST_F(ValidationStateTest, CheckWebGPUIndirectlyRecursiveBodyBad) { - std::string spirv = - std::string(kVulkanMemoryHeader) + kIndirectlyRecursiveBody; - CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, - ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, functions need to be defined before being " - "called.\n %10 = OpFunctionCall %_struct_5 %11\n")); -} - -TEST_F(ValidationStateTest, - CheckWebGPUDuplicateEntryNamesDifferentFunctionsBad) { - std::string spirv = std::string(kVulkanMemoryHeader) + R"( -OpEntryPoint Fragment %func_1 "main" -OpEntryPoint Vertex %func_2 "main" -OpExecutionMode %func_1 OriginUpperLeft -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%func_1 = OpFunction %void None %void_f -%label_1 = OpLabel - OpReturn - OpFunctionEnd -%func_2 = OpFunction %void None %void_f -%label_2 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Entry point name \"main\" is not unique, which is not allow " - "in WebGPU env.\n %1 = OpFunction %void None %4\n")); -} - -TEST_F(ValidationStateTest, CheckWebGPUDuplicateEntryNamesSameFunctionBad) { - std::string spirv = std::string(kVulkanMemoryHeader) + R"( -OpEntryPoint GLCompute %func_1 "main" -OpEntryPoint Vertex %func_1 "main" -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%func_1 = OpFunction %void None %void_f -%label_1 = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, - ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0)); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Entry point name \"main\" is not unique, which is not allow " - "in WebGPU env.\n %1 = OpFunction %void None %3\n")); -} - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_version_test.cpp b/3rdparty/spirv-tools/test/val/val_version_test.cpp deleted file mode 100644 index 2b9542a12..000000000 --- a/3rdparty/spirv-tools/test/val/val_version_test.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (c) 2018 Google LLC. -// -// 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 "gmock/gmock.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using ::testing::HasSubstr; - -using ValidateVersion = spvtest::ValidateBase< - std::tuple>; - -const std::string vulkan_spirv = R"( -OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - -const std::string webgpu_spirv = R"( -OpCapability Shader -OpCapability VulkanMemoryModelKHR -OpExtension "SPV_KHR_vulkan_memory_model" -OpMemoryModel Logical VulkanKHR -OpEntryPoint Fragment %func "func" -OpExecutionMode %func OriginUpperLeft -%void = OpTypeVoid -%functy = OpTypeFunction %void -%func = OpFunction %void None %functy -%1 = OpLabel -OpReturn -OpFunctionEnd -)"; - -const std::string opencl_spirv = R"( -OpCapability Addresses -OpCapability Kernel -OpCapability Linkage -OpMemoryModel Physical32 OpenCL -)"; - -std::string version(spv_target_env env) { - switch (env) { - case SPV_ENV_UNIVERSAL_1_0: - case SPV_ENV_VULKAN_1_0: - case SPV_ENV_OPENGL_4_0: - case SPV_ENV_OPENGL_4_1: - case SPV_ENV_OPENGL_4_2: - case SPV_ENV_OPENGL_4_3: - case SPV_ENV_OPENGL_4_5: - case SPV_ENV_OPENCL_1_2: - case SPV_ENV_OPENCL_2_0: - case SPV_ENV_OPENCL_EMBEDDED_2_0: - return "1.0"; - case SPV_ENV_UNIVERSAL_1_1: - case SPV_ENV_OPENCL_2_1: - case SPV_ENV_OPENCL_EMBEDDED_2_1: - return "1.1"; - case SPV_ENV_UNIVERSAL_1_2: - case SPV_ENV_OPENCL_2_2: - case SPV_ENV_OPENCL_EMBEDDED_2_2: - return "1.2"; - case SPV_ENV_UNIVERSAL_1_3: - case SPV_ENV_VULKAN_1_1: - case SPV_ENV_WEBGPU_0: - return "1.3"; - case SPV_ENV_UNIVERSAL_1_4: - case SPV_ENV_VULKAN_1_1_SPIRV_1_4: - return "1.4"; - default: - return "0"; - } -} - -TEST_P(ValidateVersion, version) { - CompileSuccessfully(std::get<2>(GetParam()), std::get<0>(GetParam())); - spv_result_t res = ValidateInstructions(std::get<1>(GetParam())); - if (std::get<3>(GetParam())) { - ASSERT_EQ(SPV_SUCCESS, res); - } else { - ASSERT_EQ(SPV_ERROR_WRONG_VERSION, res); - - std::string msg = "Invalid SPIR-V binary version "; - msg += version(std::get<0>(GetParam())); - msg += " for target environment "; - msg += spvTargetEnvDescription(std::get<1>(GetParam())); - EXPECT_THAT(getDiagnosticString(), HasSubstr(msg)); - } -} - -// clang-format off -INSTANTIATE_TEST_SUITE_P(Universal, ValidateVersion, - ::testing::Values( - // Binary version, Target environment - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_0, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_0, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_2, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_5, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_WEBGPU_0, webgpu_spirv, true), - - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_2, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_3, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_5, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_WEBGPU_0, webgpu_spirv, true), - - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_2, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_3, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_5, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_WEBGPU_0, webgpu_spirv, true), - - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_2, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_3, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_5, vulkan_spirv, false), - std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_WEBGPU_0, webgpu_spirv, true) - ) -); - -INSTANTIATE_TEST_SUITE_P(Vulkan, ValidateVersion, - ::testing::Values( - // Binary version, Target environment - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_0, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_2, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_5, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true), - - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1, vulkan_spirv, true), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_0, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_1, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_2, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_3, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_5, vulkan_spirv, false), - std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true) - ) -); - -INSTANTIATE_TEST_SUITE_P(OpenCL, ValidateVersion, - ::testing::Values( - // Binary version, Target environment - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_1_2, opencl_spirv, true), - - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_1_2, opencl_spirv, true), - - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_2_0, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_2_1, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_1_2, opencl_spirv, false), - - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_1_2, opencl_spirv, true) - ) -); - -INSTANTIATE_TEST_SUITE_P(OpenCLEmbedded, ValidateVersion, - ::testing::Values( - // Binary version, Target environment - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_0, SPV_ENV_OPENCL_1_2, opencl_spirv, true), - - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_1, SPV_ENV_OPENCL_1_2, opencl_spirv, true), - - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_UNIVERSAL_1_0, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_UNIVERSAL_1_1, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_UNIVERSAL_1_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_UNIVERSAL_1_3, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_2_0, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_2_1, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, false), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true), - std::make_tuple(SPV_ENV_OPENCL_EMBEDDED_2_2, SPV_ENV_OPENCL_1_2, opencl_spirv, false) - ) -); -// clang-format on - -} // namespace -} // namespace val -} // namespace spvtools diff --git a/3rdparty/spirv-tools/test/val/val_webgpu_test.cpp b/3rdparty/spirv-tools/test/val/val_webgpu_test.cpp deleted file mode 100644 index e81fc7ce3..000000000 --- a/3rdparty/spirv-tools/test/val/val_webgpu_test.cpp +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright (c) 2018 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. - -// Validation tests for WebGPU env specific checks - -#include - -#include "gmock/gmock.h" -#include "test/val/val_fixtures.h" - -namespace spvtools { -namespace val { -namespace { - -using testing::HasSubstr; - -using ValidateWebGPU = spvtest::ValidateBase; - -TEST_F(ValidateWebGPU, OpUndefIsDisallowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" -%float = OpTypeFloat 32 -%1 = OpUndef %float -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%func = OpFunction %void None %void_f -%label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - - // Control case: OpUndef is allowed in SPIR-V 1.3 - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); - - // Control case: OpUndef is disallowed in the WebGPU env - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), HasSubstr("OpUndef is disallowed")); -} - -TEST_F(ValidateWebGPU, OpNameIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - OpName %1 "foo" - %1 = OpTypeFloat 32 - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpMemberNameIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - OpMemberName %2 0 "foo" - %1 = OpTypeFloat 32 - %2 = OpTypeStruct %1 - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd - -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpSourceIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - OpSource GLSL 450 - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpSourceContinuedIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - OpSource GLSL 450 - OpSourceContinued "I am a happy shader! Yay! ;" - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpSourceExtensionIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - OpSourceExtension "bar" - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpStringIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - %1 = OpString "foo" - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpLineIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - %1 = OpString "minimal.vert" - OpLine %1 1 1 - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, OpNoLineIsAllowed) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" - OpNoLine - %void = OpTypeVoid - %void_f = OpTypeFunction %void - %func = OpFunction %void None %void_f - %label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, LogicalAddressingVulkanKHRMemoryGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%func = OpFunction %void None %void_f -%label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, NonVulkanKHRMemoryModelBad) { - std::string spirv = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpNoLine -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Memory model must be VulkanKHR for WebGPU " - "environment.\n OpMemoryModel Logical GLSL450\n")); -} - -TEST_F(ValidateWebGPU, WhitelistedExtendedInstructionsImportGood) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" -%1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical VulkanKHR - OpEntryPoint Vertex %func "shader" -%void = OpTypeVoid -%void_f = OpTypeFunction %void -%func = OpFunction %void None %void_f -%label = OpLabel - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, NonWhitelistedExtendedInstructionsImportBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_vulkan_memory_model" -%1 = OpExtInstImport "OpenCL.std" - OpMemoryModel Logical VulkanKHR -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, the only valid parameter to " - "OpExtInstImport is \"GLSL.std.450\".\n %1 = " - "OpExtInstImport \"OpenCL.std\"\n")); -} - -TEST_F(ValidateWebGPU, NonVulkanKHRMemoryModelExtensionBad) { - std::string spirv = R"( - OpCapability Shader - OpCapability VulkanMemoryModelKHR - OpExtension "SPV_KHR_8bit_storage" - OpExtension "SPV_KHR_vulkan_memory_model" - OpMemoryModel Logical VulkanKHR -)"; - - CompileSuccessfully(spirv); - - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("For WebGPU, the only valid parameter to OpExtension " - "is \"SPV_KHR_vulkan_memory_model\".\n OpExtension " - "\"SPV_KHR_8bit_storage\"\n")); -} - -spv_binary GenerateTrivialBinary(bool need_little_endian) { - // Smallest possible valid WebGPU SPIR-V binary in little endian. Contains all - // the required boilerplate and a trivial entry point function. - static const uint8_t binary_bytes[] = { - // clang-format off - 0x03, 0x02, 0x23, 0x07, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0xE1, 0x14, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x53, 0x50, 0x56, 0x5F, 0x4B, 0x48, 0x52, 0x5F, - 0x76, 0x75, 0x6C, 0x6B, 0x61, 0x6E, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, - 0x79, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x6C, 0x00, 0x0E, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x64, - 0x65, 0x72, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x04, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 - // clang-format on - }; - static const size_t word_count = sizeof(binary_bytes) / sizeof(uint32_t); - std::unique_ptr result(new spv_binary_t); - if (!result) return nullptr; - - result->wordCount = word_count; - result->code = new uint32_t[word_count]; - if (!result->code) return nullptr; - - if (need_little_endian) { - memcpy(result->code, binary_bytes, sizeof(binary_bytes)); - } else { - uint8_t* code_bytes = reinterpret_cast(result->code); - for (size_t word = 0; word < word_count; ++word) { - code_bytes[4 * word] = binary_bytes[4 * word + 3]; - code_bytes[4 * word + 1] = binary_bytes[4 * word + 2]; - code_bytes[4 * word + 2] = binary_bytes[4 * word + 1]; - code_bytes[4 * word + 3] = binary_bytes[4 * word]; - } - } - - return result.release(); -} - -TEST_F(ValidateWebGPU, LittleEndianGood) { - DestroyBinary(); - binary_ = GenerateTrivialBinary(true); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); -} - -TEST_F(ValidateWebGPU, BigEndianBad) { - DestroyBinary(); - binary_ = GenerateTrivialBinary(false); - EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0)); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("WebGPU requires SPIR-V to be little endian.")); -} - -} // namespace -} // namespace val -} // namespace spvtools