Add option to validate after each pass (#2462)
* New command-line option to opt: --validate-after-all * Pass manager will validate after each pass it runs
This commit is contained in:
Родитель
fb0753640a
Коммит
42e6f1aa62
|
@ -199,6 +199,9 @@ class Optimizer {
|
|||
// |out| output stream.
|
||||
Optimizer& SetTimeReport(std::ostream* out);
|
||||
|
||||
// Sets the option to validate the module after each pass.
|
||||
Optimizer& SetValidateAfterAll(bool validate);
|
||||
|
||||
private:
|
||||
struct Impl; // Opaque struct for holding internal data.
|
||||
std::unique_ptr<Impl> impl_; // Unique pointer to internal data.
|
||||
|
|
|
@ -507,6 +507,8 @@ bool Optimizer::Run(const uint32_t* original_binary,
|
|||
|
||||
context->set_max_id_bound(opt_options->max_id_bound_);
|
||||
|
||||
impl_->pass_manager.SetValidatorOptions(&opt_options->val_options_);
|
||||
impl_->pass_manager.SetTargetEnv(impl_->target_env);
|
||||
auto status = impl_->pass_manager.Run(context.get());
|
||||
if (status == opt::Pass::Status::SuccessWithChange ||
|
||||
(status == opt::Pass::Status::SuccessWithoutChange &&
|
||||
|
@ -529,6 +531,11 @@ Optimizer& Optimizer::SetTimeReport(std::ostream* out) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
Optimizer& Optimizer::SetValidateAfterAll(bool validate) {
|
||||
impl_->pass_manager.SetValidateAfterAll(validate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateNullPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
|
||||
}
|
||||
|
|
|
@ -51,6 +51,20 @@ Pass::Status PassManager::Run(IRContext* context) {
|
|||
if (one_status == Pass::Status::Failure) return one_status;
|
||||
if (one_status == Pass::Status::SuccessWithChange) status = one_status;
|
||||
|
||||
if (validate_after_all_) {
|
||||
spvtools::SpirvTools tools(target_env_);
|
||||
tools.SetMessageConsumer(consumer());
|
||||
std::vector<uint32_t> binary;
|
||||
context->module()->ToBinary(&binary, true);
|
||||
if (!tools.Validate(binary.data(), binary.size(), val_options_)) {
|
||||
std::string msg = "Validation failed after pass ";
|
||||
msg += pass->name();
|
||||
spv_position_t null_pos{0, 0, 0};
|
||||
consumer()(SPV_MSG_INTERNAL_ERROR, "", null_pos, msg.c_str());
|
||||
return Pass::Status::Failure;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the pass to free any memory used by the pass.
|
||||
pass.reset(nullptr);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,10 @@ class PassManager {
|
|||
PassManager()
|
||||
: consumer_(nullptr),
|
||||
print_all_stream_(nullptr),
|
||||
time_report_stream_(nullptr) {}
|
||||
time_report_stream_(nullptr),
|
||||
target_env_(SPV_ENV_UNIVERSAL_1_2),
|
||||
val_options_(nullptr),
|
||||
validate_after_all_(false) {}
|
||||
|
||||
// Sets the message consumer to the given |consumer|.
|
||||
void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
|
||||
|
@ -89,6 +92,24 @@ class PassManager {
|
|||
return *this;
|
||||
}
|
||||
|
||||
// Sets the target environment for validation.
|
||||
PassManager& SetTargetEnv(spv_target_env env) {
|
||||
target_env_ = env;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the validation options.
|
||||
PassManager& SetValidatorOptions(spv_validator_options options) {
|
||||
val_options_ = options;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the option to validate after each pass.
|
||||
PassManager& SetValidateAfterAll(bool validate) {
|
||||
validate_after_all_ = validate;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// Consumer for messages.
|
||||
MessageConsumer consumer_;
|
||||
|
@ -100,6 +121,12 @@ class PassManager {
|
|||
// The output stream to write the resource utilization of each pass. If this
|
||||
// is null, no output is generated.
|
||||
std::ostream* time_report_stream_;
|
||||
// The target environment.
|
||||
spv_target_env target_env_;
|
||||
// The validator options (used when validating each pass).
|
||||
spv_validator_options val_options_;
|
||||
// Controls whether validation occurs after every pass.
|
||||
bool validate_after_all_;
|
||||
};
|
||||
|
||||
inline void PassManager::AddPass(std::unique_ptr<Pass> pass) {
|
||||
|
|
|
@ -384,6 +384,8 @@ Options (in lexicographical order):
|
|||
Current workarounds: Avoid OpUnreachable in loops.
|
||||
--unify-const
|
||||
Remove the duplicated constants.
|
||||
--validate-after-all
|
||||
Validate the module after each pass is performed.
|
||||
-h, --help
|
||||
Print this help.
|
||||
--version
|
||||
|
@ -628,6 +630,8 @@ OptStatus ParseFlags(int argc, const char** argv,
|
|||
|
||||
optimizer->SetTargetEnv(SPV_ENV_WEBGPU_0);
|
||||
optimizer->RegisterWebGPUPasses();
|
||||
} else if (0 == strcmp(cur_arg, "--validate-after-all")) {
|
||||
optimizer->SetValidateAfterAll(true);
|
||||
} else {
|
||||
// Some passes used to accept the form '--pass arg', canonicalize them
|
||||
// to '--pass=arg'.
|
||||
|
|
Загрузка…
Ссылка в новой задаче