Add —preserve-bindings and —preserve-spec-constants (#2693)
Add optimizer options to for preservation of spec constants and variable with binding decorations. They are to be preserved even if they are unused.
This commit is contained in:
Родитель
86e45efe15
Коммит
cd153db8ed
|
@ -574,6 +574,15 @@ SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetValidatorOptions(
|
|||
SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetMaxIdBound(
|
||||
spv_optimizer_options options, uint32_t val);
|
||||
|
||||
// Records whether all bindings within the module should be preserved.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetPreserveBindings(
|
||||
spv_optimizer_options options, bool val);
|
||||
|
||||
// Records whether all specialization constants within the module
|
||||
// should be preserved.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetPreserveSpecConstants(
|
||||
spv_optimizer_options options, bool val);
|
||||
|
||||
// Creates a reducer options object with default options. Returns a valid
|
||||
// options object. The object remains valid until it is passed into
|
||||
// |spvReducerOptionsDestroy|.
|
||||
|
|
|
@ -161,6 +161,18 @@ class OptimizerOptions {
|
|||
spvOptimizerOptionsSetMaxIdBound(options_, new_bound);
|
||||
}
|
||||
|
||||
// Records whether all bindings within the module should be preserved.
|
||||
void set_preserve_bindings(bool preserve_bindings) {
|
||||
spvOptimizerOptionsSetPreserveBindings(options_, preserve_bindings);
|
||||
}
|
||||
|
||||
// Records whether all specialization constants within the module
|
||||
// should be preserved.
|
||||
void set_preserve_spec_constants(bool preserve_spec_constants) {
|
||||
spvOptimizerOptionsSetPreserveSpecConstants(options_,
|
||||
preserve_spec_constants);
|
||||
}
|
||||
|
||||
private:
|
||||
spv_optimizer_options options_;
|
||||
};
|
||||
|
|
|
@ -570,13 +570,28 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
|
|||
AddToWorklist(&entry);
|
||||
}
|
||||
}
|
||||
// Keep workgroup size.
|
||||
for (auto& anno : get_module()->annotations()) {
|
||||
if (anno.opcode() == SpvOpDecorate) {
|
||||
// Keep workgroup size.
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn &&
|
||||
anno.GetSingleWordInOperand(2u) == SpvBuiltInWorkgroupSize) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
|
||||
if (context()->preserve_bindings()) {
|
||||
// Keep all bindings.
|
||||
if ((anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet) ||
|
||||
(anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
}
|
||||
|
||||
if (context()->preserve_spec_constants()) {
|
||||
// Keep all specialization constant instructions
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationSpecId) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,9 @@ class IRContext {
|
|||
constant_mgr_(nullptr),
|
||||
type_mgr_(nullptr),
|
||||
id_to_name_(nullptr),
|
||||
max_id_bound_(kDefaultMaxIdBound) {
|
||||
max_id_bound_(kDefaultMaxIdBound),
|
||||
preserve_bindings_(false),
|
||||
preserve_spec_constants_(false) {
|
||||
SetContextMessageConsumer(syntax_context_, consumer_);
|
||||
module_->SetContext(this);
|
||||
}
|
||||
|
@ -115,7 +117,9 @@ class IRContext {
|
|||
valid_analyses_(kAnalysisNone),
|
||||
type_mgr_(nullptr),
|
||||
id_to_name_(nullptr),
|
||||
max_id_bound_(kDefaultMaxIdBound) {
|
||||
max_id_bound_(kDefaultMaxIdBound),
|
||||
preserve_bindings_(false),
|
||||
preserve_spec_constants_(false) {
|
||||
SetContextMessageConsumer(syntax_context_, consumer_);
|
||||
module_->SetContext(this);
|
||||
InitializeCombinators();
|
||||
|
@ -491,6 +495,16 @@ class IRContext {
|
|||
uint32_t max_id_bound() const { return max_id_bound_; }
|
||||
void set_max_id_bound(uint32_t new_bound) { max_id_bound_ = new_bound; }
|
||||
|
||||
bool preserve_bindings() const { return preserve_bindings_; }
|
||||
void set_preserve_bindings(bool should_preserve_bindings) {
|
||||
preserve_bindings_ = should_preserve_bindings;
|
||||
}
|
||||
|
||||
bool preserve_spec_constants() const { return preserve_spec_constants_; }
|
||||
void set_preserve_spec_constants(bool should_preserve_spec_constants) {
|
||||
preserve_spec_constants_ = should_preserve_spec_constants;
|
||||
}
|
||||
|
||||
// Return id of input variable only decorated with |builtin|, if in module.
|
||||
// Create variable and return its id otherwise. If builtin not currently
|
||||
// supported, return 0.
|
||||
|
@ -750,6 +764,13 @@ class IRContext {
|
|||
|
||||
// The maximum legal value for the id bound.
|
||||
uint32_t max_id_bound_;
|
||||
|
||||
// Whether all bindings within |module_| should be preserved.
|
||||
bool preserve_bindings_;
|
||||
|
||||
// Whether all specialization constants within |module_|
|
||||
// should be preserved.
|
||||
bool preserve_spec_constants_;
|
||||
};
|
||||
|
||||
inline IRContext::Analysis operator|(IRContext::Analysis lhs,
|
||||
|
|
|
@ -528,6 +528,8 @@ bool Optimizer::Run(const uint32_t* original_binary,
|
|||
if (context == nullptr) return false;
|
||||
|
||||
context->set_max_id_bound(opt_options->max_id_bound_);
|
||||
context->set_preserve_bindings(opt_options->preserve_bindings_);
|
||||
context->set_preserve_spec_constants(opt_options->preserve_spec_constants_);
|
||||
|
||||
impl_->pass_manager.SetValidatorOptions(&opt_options->val_options_);
|
||||
impl_->pass_manager.SetTargetEnv(impl_->target_env);
|
||||
|
|
|
@ -39,3 +39,13 @@ SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetMaxIdBound(
|
|||
spv_optimizer_options options, uint32_t val) {
|
||||
options->max_id_bound_ = val;
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetPreserveBindings(
|
||||
spv_optimizer_options options, bool val) {
|
||||
options->preserve_bindings_ = val;
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetPreserveSpecConstants(
|
||||
spv_optimizer_options options, bool val) {
|
||||
options->preserve_spec_constants_ = val;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ struct spv_optimizer_options_t {
|
|||
spv_optimizer_options_t()
|
||||
: run_validator_(true),
|
||||
val_options_(),
|
||||
max_id_bound_(kDefaultMaxIdBound) {}
|
||||
max_id_bound_(kDefaultMaxIdBound),
|
||||
preserve_bindings_(false),
|
||||
preserve_spec_constants_(false) {}
|
||||
|
||||
// When true the validator will be run before optimizations are run.
|
||||
bool run_validator_;
|
||||
|
@ -36,5 +38,12 @@ struct spv_optimizer_options_t {
|
|||
// this value must be at least 0x3FFFFF, but implementations can allow for a
|
||||
// higher value.
|
||||
uint32_t max_id_bound_;
|
||||
|
||||
// When true, all binding declarations within the module should be preserved.
|
||||
bool preserve_bindings_;
|
||||
|
||||
// When true, all specialization constants within the module should be
|
||||
// preserved.
|
||||
bool preserve_spec_constants_;
|
||||
};
|
||||
#endif // SOURCE_SPIRV_OPTIMIZER_OPTIONS_H_
|
||||
|
|
|
@ -6496,6 +6496,70 @@ OpFunctionEnd
|
|||
SinglePassRunAndMatch<AggressiveDCEPass>(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<AggressiveDCEPass>(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<AggressiveDCEPass>(spirv, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Check that logical addressing required
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#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"
|
||||
|
@ -67,6 +68,10 @@ class PassTest : public TestT {
|
|||
return std::make_tuple(std::vector<uint32_t>(), 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<uint32_t> binary;
|
||||
|
@ -206,6 +211,10 @@ class PassTest : public TestT {
|
|||
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_);
|
||||
|
||||
manager_->Run(context());
|
||||
|
||||
std::vector<uint32_t> binary;
|
||||
|
@ -232,6 +241,8 @@ class PassTest : public TestT {
|
|||
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; }
|
||||
|
@ -242,6 +253,7 @@ class PassTest : public TestT {
|
|||
std::unique_ptr<PassManager> 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_;
|
||||
};
|
||||
|
|
|
@ -357,6 +357,14 @@ Options (in lexicographical order):)",
|
|||
--merge-blocks followed by all the transformations implied by
|
||||
-O.)");
|
||||
printf(R"(
|
||||
--preserve-bindings
|
||||
Ensure that the optimizer preserves all bindings declared within
|
||||
the module, even when those bindings are unused.)");
|
||||
printf(R"(
|
||||
--preserve-spec-constants
|
||||
Ensure that the optimizer preserves all specialization constants declared
|
||||
within the module, even when those constants are unused.)");
|
||||
printf(R"(
|
||||
--print-all
|
||||
Print SPIR-V assembly to standard error output before each pass
|
||||
and after the last pass.)");
|
||||
|
@ -693,6 +701,10 @@ OptStatus ParseFlags(int argc, const char** argv,
|
|||
optimizer_options->set_run_validator(false);
|
||||
} else if (0 == strcmp(cur_arg, "--print-all")) {
|
||||
optimizer->SetPrintAll(&std::cerr);
|
||||
} else if (0 == strcmp(cur_arg, "--preserve-bindings")) {
|
||||
optimizer_options->set_preserve_bindings(true);
|
||||
} else if (0 == strcmp(cur_arg, "--preserve-spec-constants")) {
|
||||
optimizer_options->set_preserve_spec_constants(true);
|
||||
} else if (0 == strcmp(cur_arg, "--time-report")) {
|
||||
optimizer->SetTimeReport(&std::cerr);
|
||||
} else if (0 == strcmp(cur_arg, "--relax-struct-store")) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче