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