Add C interface for Optimizer (#5030)

This commit is contained in:
Daniel Story 2023-02-01 05:58:52 -08:00 committed by GitHub
parent 8a0fe779e5
commit 0994ca45b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 689 additions and 2 deletions

View File

@ -441,6 +441,8 @@ typedef struct spv_reducer_options_t spv_reducer_options_t;
typedef struct spv_fuzzer_options_t spv_fuzzer_options_t;
typedef struct spv_optimizer_t spv_optimizer_t;
// Type Definitions
typedef spv_const_binary_t* spv_const_binary;
@ -900,6 +902,63 @@ SPIRV_TOOLS_EXPORT spv_result_t spvBinaryParse(
const size_t num_words, spv_parsed_header_fn_t parse_header,
spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic);
// The optimizer interface.
// A pointer to a function that accepts a log message from an optimizer.
typedef void (*spv_message_consumer)(
spv_message_level_t, const char*, const spv_position_t*, const char*);
// Creates and returns an optimizer object. This object must be passed to
// optimizer APIs below and is valid until passed to spvOptimizerDestroy.
SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env);
// Destroys the given optimizer object.
SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer);
// Sets an spv_message_consumer on an optimizer object.
SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
spv_optimizer_t* optimizer, spv_message_consumer consumer);
// Registers passes that attempt to legalize the generated code.
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
spv_optimizer_t* optimizer);
// Registers passes that attempt to improve performance of generated code.
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
spv_optimizer_t* optimizer);
// Registers passes that attempt to improve the size of generated code.
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
spv_optimizer_t* optimizer);
// Registers a pass specified by a flag in an optimizer object.
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
spv_optimizer_t* optimizer, const char* flag);
// Registers passes specified by length number of flags in an optimizer object.
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
spv_optimizer_t* optimizer, const char** flags, const size_t flag_count);
// Optimizes the SPIR-V code of size |word_count| pointed to by |binary| and
// returns an optimized spv_binary in |optimized_binary|.
//
// Returns SPV_SUCCESS on successful optimization, whether or not the module is
// modified. Returns an SPV_ERROR_* if the module fails to validate or if
// errors occur when processing using any of the registered passes. In that
// case, no further passes are executed and the |optimized_binary| contents may
// be invalid.
//
// By default, the binary is validated before any transforms are performed,
// and optionally after each transform. Validation uses SPIR-V spec rules
// for the SPIR-V version named in the binary's header (at word offset 1).
// Additionally, if the target environment is a client API (such as
// Vulkan 1.1), then validate for that client API version, to the extent
// that it is verifiable from data in the binary itself, or from the
// validator options set on the optimizer options.
SPIRV_TOOLS_EXPORT spv_result_t spvOptimizerRun(
spv_optimizer_t* optimizer, const uint32_t* binary, const size_t word_count,
spv_binary* optimized_binary, const spv_optimizer_options options);
#ifdef __cplusplus
}
#endif

View File

@ -1065,3 +1065,95 @@ Optimizer::PassToken CreateFixFuncCallArgumentsPass() {
MakeUnique<opt::FixFuncCallArgumentsPass>());
}
} // namespace spvtools
extern "C" {
SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env) {
return reinterpret_cast<spv_optimizer_t*>(new spvtools::Optimizer(env));
}
SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer) {
delete reinterpret_cast<spvtools::Optimizer*>(optimizer);
}
SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
spv_optimizer_t* optimizer, spv_message_consumer consumer) {
reinterpret_cast<spvtools::Optimizer*>(optimizer)->
SetMessageConsumer(
[consumer](spv_message_level_t level, const char* source,
const spv_position_t& position, const char* message) {
return consumer(level, source, &position, message);
});
}
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
spv_optimizer_t* optimizer) {
reinterpret_cast<spvtools::Optimizer*>(optimizer)->
RegisterLegalizationPasses();
}
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
spv_optimizer_t* optimizer) {
reinterpret_cast<spvtools::Optimizer*>(optimizer)->
RegisterPerformancePasses();
}
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
spv_optimizer_t* optimizer) {
reinterpret_cast<spvtools::Optimizer*>(optimizer)->RegisterSizePasses();
}
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
spv_optimizer_t* optimizer, const char* flag)
{
return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
RegisterPassFromFlag(flag);
}
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
spv_optimizer_t* optimizer, const char** flags, const size_t flag_count) {
std::vector<std::string> opt_flags;
for (uint32_t i = 0; i < flag_count; i++) {
opt_flags.emplace_back(flags[i]);
}
return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
RegisterPassesFromFlags(opt_flags);
}
SPIRV_TOOLS_EXPORT
spv_result_t spvOptimizerRun(spv_optimizer_t* optimizer,
const uint32_t* binary,
const size_t word_count,
spv_binary* optimized_binary,
const spv_optimizer_options options) {
std::vector<uint32_t> optimized;
if (!reinterpret_cast<spvtools::Optimizer*>(optimizer)->
Run(binary, word_count, &optimized, options)) {
return SPV_ERROR_INTERNAL;
}
auto result_binary = new spv_binary_t();
if (!result_binary) {
*optimized_binary = nullptr;
return SPV_ERROR_OUT_OF_MEMORY;
}
result_binary->code = new uint32_t[optimized.size()];
if (!result_binary->code) {
delete result_binary;
*optimized_binary = nullptr;
return SPV_ERROR_OUT_OF_MEMORY;
}
result_binary->wordCount = optimized.size();
memcpy(result_binary->code, optimized.data(),
optimized.size() * sizeof(uint32_t));
*optimized_binary = result_binary;
return SPV_SUCCESS;
}
} // extern "C"

View File

@ -21,6 +21,7 @@ add_spvtools_unittest(TARGET opt
analyze_live_input_test.cpp
assembly_builder_test.cpp
block_merge_test.cpp
c_interface_test.cpp
ccp_test.cpp
cfg_cleanup_test.cpp
cfg_test.cpp

View File

@ -0,0 +1,534 @@
// Copyright (c) 2023 Nintendo
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT 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 <string>
#include <iostream>
#include "gtest/gtest.h"
#include "spirv-tools/libspirv.h"
namespace spvtools {
namespace {
TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForInvalidInput) {
const uint32_t spirv[] = {
0xDEADFEED, // Invalid Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x01000000, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
// Do not register any passes
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, true);
spv_binary binary = nullptr;
EXPECT_NE(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_EQ(binary, nullptr);
spvOptimizerOptionsDestroy(options);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, SpecifyConsumerWithValidationNoPassesForInvalidInput) {
const uint32_t spirv[] = {
0xDEADFEED, // Invalid Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x01000000, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
spvOptimizerSetMessageConsumer(
optimizer,
[](spv_message_level_t, const char*, const spv_position_t*,
const char* message) {
std::cout << message << std::endl;
});
// Do not register any passes
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, true);
testing::internal::CaptureStdout();
spv_binary binary = nullptr;
EXPECT_NE(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_EQ(binary, nullptr);
auto output = testing::internal::GetCapturedStdout();
EXPECT_STRNE(output.c_str(), "");
spvOptimizerOptionsDestroy(options);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000001, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
// Do not register any passes
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, true);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Should remain unchanged
EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t));
EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0);
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerNoPassesForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000003, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001, // GLSL450
0x00040015, // OpTypeInt
0x00000001, // %1
0x00000020, // 32 Bits
0x00000000, // Unsigned
0x0004002B, // OpConstant
0x00000001, // %1
0x00000002, // %2
0x00000001 // 1
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
// Do not register any passes
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, true);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Should remain unchanged
EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t));
EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0);
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerLegalizationPassesForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000003, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001, // GLSL450
0x00040015, // OpTypeInt
0x00000001, // %1
0x00000020, // 32 Bits
0x00000000, // Unsigned
0x0004002B, // OpConstant
0x00000001, // %1
0x00000002, // %2
0x00000001 // 1
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
spvOptimizerRegisterLegalizationPasses(optimizer);
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, false);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Only check that SPV_SUCCESS is returned, do not verify output
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerPerformancePassesForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000003, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001, // GLSL450
0x00040015, // OpTypeInt
0x00000001, // %1
0x00000020, // 32 Bits
0x00000000, // Unsigned
0x0004002B, // OpConstant
0x00000001, // %1
0x00000002, // %2
0x00000001 // 1
};
const uint32_t expected_spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000001, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
spvOptimizerRegisterPerformancePasses(optimizer);
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, false);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Unreferenced OpTypeInt and OpConstant should be removed
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
EXPECT_EQ(memcmp(binary->code, expected_spirv,
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerSizePassesForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000003, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001, // GLSL450
0x00040015, // OpTypeInt
0x00000001, // %1
0x00000020, // 32 Bits
0x00000000, // Unsigned
0x0004002B, // OpConstant
0x00000001, // %1
0x00000002, // %2
0x00000001 // 1
};
const uint32_t expected_spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000001, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
spvOptimizerRegisterSizePasses(optimizer);
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, false);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Unreferenced OpTypeInt and OpConstant should be removed
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
EXPECT_EQ(memcmp(binary->code, expected_spirv,
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerPassFromFlagForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000003, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001, // GLSL450
0x00040015, // OpTypeInt
0x00000001, // %1
0x00000020, // 32 Bits
0x00000000, // Unsigned
0x0004002B, // OpConstant
0x00000001, // %1
0x00000002, // %2
0x00000001 // 1
};
const uint32_t expected_spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000001, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
EXPECT_TRUE(spvOptimizerRegisterPassFromFlag(
optimizer, "--eliminate-dead-code-aggressive"));
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, false);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Unreferenced OpTypeInt and OpConstant should be removed
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
EXPECT_EQ(memcmp(binary->code, expected_spirv,
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerPassesFromFlagsForValidInput) {
const uint32_t spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000003, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001, // GLSL450
0x00040015, // OpTypeInt
0x00000001, // %1
0x00000020, // 32 Bits
0x00000000, // Unsigned
0x0004002B, // OpConstant
0x00000001, // %1
0x00000002, // %2
0x00000001 // 1
};
const uint32_t expected_spirv[] = {
0x07230203, // Magic
0x00010100, // Version 1.1
0x00000000, // No Generator
0x00000001, // Bound
0x00000000, // Schema
0x00020011, // OpCapability
0x00000001, // Shader
0x00020011, // OpCapability
0x00000005, // Linkage
0x0003000E, // OpMemoryModel
0x00000000, // Logical
0x00000001 // GLSL450
};
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
const char* flags[2] = {
"--eliminate-dead-const",
"--eliminate-dead-code-aggressive"
};
EXPECT_TRUE(spvOptimizerRegisterPassesFromFlags(
optimizer, flags, sizeof(flags) / sizeof(const char*)));
auto options = spvOptimizerOptionsCreate();
ASSERT_NE(options, nullptr);
spvOptimizerOptionsSetRunValidator(options, false);
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS,
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
&binary, options));
ASSERT_NE(binary, nullptr);
spvOptimizerOptionsDestroy(options);
// Unreferenced OpTypeInt and OpConstant should be removed
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
EXPECT_EQ(memcmp(binary->code, expected_spirv,
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
spvBinaryDestroy(binary);
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerInvalidPassFromFlag) {
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
EXPECT_FALSE(spvOptimizerRegisterPassFromFlag(
optimizer, "--this-is-not-a-valid-pass"));
spvOptimizerDestroy(optimizer);
}
TEST(OptimizerCInterface, DefaultConsumerInvalidPassesFromFlags) {
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
ASSERT_NE(optimizer, nullptr);
const char* flags[2] = {
"--eliminate-dead-const",
"--this-is-not-a-valid-pass"
};
EXPECT_FALSE(spvOptimizerRegisterPassesFromFlags(
optimizer, flags, sizeof(flags) / sizeof(const char*)));
spvOptimizerDestroy(optimizer);
}
} // namespace
} // namespace spvtools

View File

@ -41,8 +41,9 @@ AUTHORS = ['The Khronos Group Inc.',
'Alastair F. Donaldson',
'Mostafa Ashraf',
'Shiyu Liu',
'ZHOU He']
CURRENT_YEAR = 2022
'ZHOU He',
'Nintendo']
CURRENT_YEAR = 2023
FIRST_YEAR = 2014
FINAL_YEAR = CURRENT_YEAR + 5