1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_pass.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include <algorithm> 18fd4e5da5Sopenharmony_ci 19fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h" 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_cinamespace spvtools { 22fd4e5da5Sopenharmony_cinamespace reduce { 23fd4e5da5Sopenharmony_ci 24fd4e5da5Sopenharmony_cistd::vector<uint32_t> ReductionPass::TryApplyReduction( 25fd4e5da5Sopenharmony_ci const std::vector<uint32_t>& binary, uint32_t target_function) { 26fd4e5da5Sopenharmony_ci // We represent modules as binaries because (a) attempts at reduction need to 27fd4e5da5Sopenharmony_ci // end up in binary form to be passed on to SPIR-V-consuming tools, and (b) 28fd4e5da5Sopenharmony_ci // when we apply a reduction step we need to do it on a fresh version of the 29fd4e5da5Sopenharmony_ci // module as if the reduction step proves to be uninteresting we need to 30fd4e5da5Sopenharmony_ci // backtrack; re-parsing from binary provides a very clean way of cloning the 31fd4e5da5Sopenharmony_ci // module. 32fd4e5da5Sopenharmony_ci std::unique_ptr<opt::IRContext> context = 33fd4e5da5Sopenharmony_ci BuildModule(target_env_, consumer_, binary.data(), binary.size()); 34fd4e5da5Sopenharmony_ci assert(context); 35fd4e5da5Sopenharmony_ci 36fd4e5da5Sopenharmony_ci std::vector<std::unique_ptr<ReductionOpportunity>> opportunities = 37fd4e5da5Sopenharmony_ci finder_->GetAvailableOpportunities(context.get(), target_function); 38fd4e5da5Sopenharmony_ci 39fd4e5da5Sopenharmony_ci // There is no point in having a granularity larger than the number of 40fd4e5da5Sopenharmony_ci // opportunities, so reduce the granularity in this case. 41fd4e5da5Sopenharmony_ci if (granularity_ > opportunities.size()) { 42fd4e5da5Sopenharmony_ci granularity_ = std::max((uint32_t)1, (uint32_t)opportunities.size()); 43fd4e5da5Sopenharmony_ci } 44fd4e5da5Sopenharmony_ci 45fd4e5da5Sopenharmony_ci assert(granularity_ > 0); 46fd4e5da5Sopenharmony_ci 47fd4e5da5Sopenharmony_ci if (index_ >= opportunities.size()) { 48fd4e5da5Sopenharmony_ci // We have reached the end of the available opportunities and, therefore, 49fd4e5da5Sopenharmony_ci // the end of the round for this pass, so reset the index and decrease the 50fd4e5da5Sopenharmony_ci // granularity for the next round. Return an empty vector to signal the end 51fd4e5da5Sopenharmony_ci // of the round. 52fd4e5da5Sopenharmony_ci index_ = 0; 53fd4e5da5Sopenharmony_ci granularity_ = std::max((uint32_t)1, granularity_ / 2); 54fd4e5da5Sopenharmony_ci return std::vector<uint32_t>(); 55fd4e5da5Sopenharmony_ci } 56fd4e5da5Sopenharmony_ci 57fd4e5da5Sopenharmony_ci for (uint32_t i = index_; 58fd4e5da5Sopenharmony_ci i < std::min(index_ + granularity_, (uint32_t)opportunities.size()); 59fd4e5da5Sopenharmony_ci ++i) { 60fd4e5da5Sopenharmony_ci opportunities[i]->TryToApply(); 61fd4e5da5Sopenharmony_ci } 62fd4e5da5Sopenharmony_ci 63fd4e5da5Sopenharmony_ci std::vector<uint32_t> result; 64fd4e5da5Sopenharmony_ci context->module()->ToBinary(&result, false); 65fd4e5da5Sopenharmony_ci return result; 66fd4e5da5Sopenharmony_ci} 67fd4e5da5Sopenharmony_ci 68fd4e5da5Sopenharmony_civoid ReductionPass::SetMessageConsumer(MessageConsumer consumer) { 69fd4e5da5Sopenharmony_ci consumer_ = std::move(consumer); 70fd4e5da5Sopenharmony_ci} 71fd4e5da5Sopenharmony_ci 72fd4e5da5Sopenharmony_cibool ReductionPass::ReachedMinimumGranularity() const { 73fd4e5da5Sopenharmony_ci assert(granularity_ != 0); 74fd4e5da5Sopenharmony_ci return granularity_ == 1; 75fd4e5da5Sopenharmony_ci} 76fd4e5da5Sopenharmony_ci 77fd4e5da5Sopenharmony_cistd::string ReductionPass::GetName() const { return finder_->GetName(); } 78fd4e5da5Sopenharmony_ci 79fd4e5da5Sopenharmony_civoid ReductionPass::NotifyInteresting(bool interesting) { 80fd4e5da5Sopenharmony_ci if (!interesting) { 81fd4e5da5Sopenharmony_ci index_ += granularity_; 82fd4e5da5Sopenharmony_ci } 83fd4e5da5Sopenharmony_ci} 84fd4e5da5Sopenharmony_ci 85fd4e5da5Sopenharmony_ci} // namespace reduce 86fd4e5da5Sopenharmony_ci} // namespace spvtools 87