// 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 "spirv-tools/optimizer.hpp" #include "build_module.h" #include "make_unique.h" #include "pass_manager.h" #include "passes.h" namespace spvtools { struct Optimizer::PassToken::Impl { Impl(std::unique_ptr p) : pass(std::move(p)) {} std::unique_ptr pass; // Internal implementation pass. }; Optimizer::PassToken::PassToken( std::unique_ptr impl) : impl_(std::move(impl)) {} Optimizer::PassToken::PassToken(PassToken&& that) : impl_(std::move(that.impl_)) {} Optimizer::PassToken& Optimizer::PassToken::operator=(PassToken&& that) { impl_ = std::move(that.impl_); return *this; } Optimizer::PassToken::~PassToken() {} struct Optimizer::Impl { explicit Impl(spv_target_env env) : target_env(env), pass_manager() {} const spv_target_env target_env; // Target environment. opt::PassManager pass_manager; // Internal implementation pass manager. }; Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {} Optimizer::~Optimizer() {} void Optimizer::SetMessageConsumer(MessageConsumer c) { // All passes' message consumer needs to be updated. for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); ++i) { impl_->pass_manager.GetPass(i)->SetMessageConsumer(c); } impl_->pass_manager.SetMessageConsumer(std::move(c)); } Optimizer& Optimizer::RegisterPass(PassToken&& p) { // Change to use the pass manager's consumer. p.impl_->pass->SetMessageConsumer(impl_->pass_manager.consumer()); impl_->pass_manager.AddPass(std::move(p.impl_->pass)); return *this; } bool Optimizer::Run(const uint32_t* original_binary, const size_t original_binary_size, std::vector* optimized_binary) const { std::unique_ptr module = BuildModule(impl_->target_env, impl_->pass_manager.consumer(), original_binary, original_binary_size); if (module == nullptr) return false; auto status = impl_->pass_manager.Run(module.get()); if (status == opt::Pass::Status::SuccessWithChange) { optimized_binary->clear(); module->ToBinary(optimized_binary, /* skip_nop = */ true); } return status != opt::Pass::Status::Failure; } Optimizer::PassToken CreateNullPass() { return MakeUnique(MakeUnique()); } Optimizer::PassToken CreateStripDebugInfoPass() { return MakeUnique( MakeUnique()); } Optimizer::PassToken CreateSetSpecConstantDefaultValuePass( const std::unordered_map& id_value_map) { return MakeUnique( MakeUnique(id_value_map)); } Optimizer::PassToken CreateFreezeSpecConstantValuePass() { return MakeUnique( MakeUnique()); } Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass() { return MakeUnique( MakeUnique()); } Optimizer::PassToken CreateUnifyConstantPass() { return MakeUnique( MakeUnique()); } Optimizer::PassToken CreateEliminateDeadConstantPass() { return MakeUnique( MakeUnique()); } } // namespace spvtools