// 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 "source/reduce/operand_to_dominating_id_reduction_opportunity_finder.h"

#include "source/opt/instruction.h"
#include "source/reduce/change_operand_reduction_opportunity.h"

namespace spvtools {
namespace reduce {

std::vector<std::unique_ptr<ReductionOpportunity>>
OperandToDominatingIdReductionOpportunityFinder::GetAvailableOpportunities(
    opt::IRContext* context, uint32_t target_function) 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 : GetTargetFunctions(context, target_function)) {
    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 OperandToDominatingIdReductionOpportunityFinder::
    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;
          }
          assert(!context->get_constant_mgr()->GetConstantFromInst(def) &&
                 "We should not get here if the argument is a constant.");
          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 OperandToDominatingIdReductionOpportunityFinder::GetName() const {
  return "OperandToDominatingIdReductionOpportunityFinder";
}

}  // namespace reduce
}  // namespace spvtools
