// Copyright (c) 2018 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 "operand_to_dominating_id_reduction_pass.h"
#include "change_operand_reduction_opportunity.h"
#include "source/opt/instruction.h"

namespace spvtools {
namespace reduce {

using namespace opt;

std::vector<std::unique_ptr<ReductionOpportunity>>
OperandToDominatingIdReductionPass::GetAvailableOpportunities(
    opt::IRContext* context) const {
  std::vector<std::unique_ptr<ReductionOpportunity>> result;

  // Go through every instruction in every block, considering it as a potential
  // dominator of other instructions.  We choose this order for two reasons:
  //
  // (1) it is profitable for multiple opportunities to replace the same id x by
  // different dominating ids y and z to be discontiguous, as they are
  // incompatible.
  //
  // (2) We want to prioritise opportunities to replace an id with a more
  // distant dominator.  Intuitively, in a human-readable programming language
  // if we have a complex expression e with many sub-expressions, we would like
  // to prioritise replacing e with its smallest sub-expressions; generalising
  // this idea to dominating ids this roughly corresponds to more distant
  // dominators.
  for (auto& function : *context->module()) {
    for (auto dominating_block = function.begin();
         dominating_block != function.end(); ++dominating_block) {
      for (auto& dominating_inst : *dominating_block) {
        if (dominating_inst.HasResultId() && dominating_inst.type_id()) {
          // Consider replacing any operand with matching type in a dominated
          // instruction with the id generated by this instruction.
          GetOpportunitiesForDominatingInst(
              &result, &dominating_inst, dominating_block, &function, context);
        }
      }
    }
  }
  return result;
}

void OperandToDominatingIdReductionPass::GetOpportunitiesForDominatingInst(
    std::vector<std::unique_ptr<ReductionOpportunity>>* opportunities,
    opt::Instruction* candidate_dominator,
    opt::Function::iterator candidate_dominator_block, opt::Function* function,
    opt::IRContext* context) const {
  assert(candidate_dominator->HasResultId());
  assert(candidate_dominator->type_id());
  auto dominator_analysis = context->GetDominatorAnalysis(function);
  // SPIR-V requires a block to precede all blocks it dominates, so it suffices
  // to search from the candidate dominator block onwards.
  for (auto block = candidate_dominator_block; block != function->end();
       ++block) {
    if (!dominator_analysis->Dominates(&*candidate_dominator_block, &*block)) {
      // If the candidate dominator block doesn't dominate this block then there
      // cannot be any of the desired reduction opportunities in this block.
      continue;
    }
    for (auto& inst : *block) {
      // We iterate through the operands using an explicit index (rather
      // than using a lambda) so that we use said index in the construction
      // of a ChangeOperandReductionOpportunity
      for (uint32_t index = 0; index < inst.NumOperands(); index++) {
        const auto& operand = inst.GetOperand(index);
        if (spvIsInIdType(operand.type)) {
          const auto id = operand.words[0];
          auto def = context->get_def_use_mgr()->GetDef(id);
          assert(def);
          if (!context->get_instr_block(def)) {
            // The definition does not come from a block; e.g. it might be a
            // constant.  It is thus not relevant to this pass.
            continue;
          }
          // Sanity check that we don't get here if the argument is a constant.
          assert(!context->get_constant_mgr()->GetConstantFromInst(def));
          if (def->type_id() != candidate_dominator->type_id()) {
            // The types need to match.
            continue;
          }
          if (candidate_dominator != def &&
              dominator_analysis->Dominates(candidate_dominator, def)) {
            // A hit: the candidate dominator strictly dominates the definition.
            opportunities->push_back(
                MakeUnique<ChangeOperandReductionOpportunity>(
                    &inst, index, candidate_dominator->result_id()));
          }
        }
      }
    }
  }
}

std::string OperandToDominatingIdReductionPass::GetName() const {
  return "OperandToDominatingIdReductionPass";
}

}  // namespace reduce
}  // namespace spvtools
