// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/backend/move-optimizer.h"

#include "src/codegen/register-configuration.h"

namespace v8 {
namespace internal {
namespace compiler {

namespace {

struct MoveKey {
  InstructionOperand source;
  InstructionOperand destination;
};

struct MoveKeyCompare {
  bool operator()(const MoveKey& a, const MoveKey& b) const {
    if (a.source.EqualsCanonicalized(b.source)) {
      return a.destination.CompareCanonicalized(b.destination);
    }
    return a.source.CompareCanonicalized(b.source);
  }
};

using MoveMap = ZoneMap<MoveKey, unsigned, MoveKeyCompare>;

class OperandSet {
 public:
  explicit OperandSet(ZoneVector<InstructionOperand>* buffer)
      : set_(buffer), fp_reps_(0) {
    buffer->clear();
  }

  void InsertOp(const InstructionOperand& op) {
    set_->push_back(op);

    if (!kSimpleFPAliasing && op.IsFPRegister())
      fp_reps_ |= RepresentationBit(LocationOperand::cast(op).representation());
  }

  bool Contains(const InstructionOperand& op) const {
    for (const InstructionOperand& elem : *set_) {
      if (elem.EqualsCanonicalized(op)) return true;
    }
    return false;
  }

  bool ContainsOpOrAlias(const InstructionOperand& op) const {
    if (Contains(op)) return true;

    if (!kSimpleFPAliasing && op.IsFPRegister()) {
      // Platforms where FP registers have complex aliasing need extra checks.
      const LocationOperand& loc = LocationOperand::cast(op);
      MachineRepresentation rep = loc.representation();
      // If haven't encountered mixed rep FP registers, skip the extra checks.
      if (!HasMixedFPReps(fp_reps_ | RepresentationBit(rep))) return false;

      // Check register against aliasing registers of other FP representations.
      MachineRepresentation other_rep1, other_rep2;
      switch (rep) {
        case MachineRepresentation::kFloat32:
          other_rep1 = MachineRepresentation::kFloat64;
          other_rep2 = MachineRepresentation::kSimd128;
          break;
        case MachineRepresentation::kFloat64:
          other_rep1 = MachineRepresentation::kFloat32;
          other_rep2 = MachineRepresentation::kSimd128;
          break;
        case MachineRepresentation::kSimd128:
          other_rep1 = MachineRepresentation::kFloat32;
          other_rep2 = MachineRepresentation::kFloat64;
          break;
        default:
          UNREACHABLE();
          break;
      }
      const RegisterConfiguration* config = RegisterConfiguration::Default();
      int base = -1;
      int aliases =
          config->GetAliases(rep, loc.register_code(), other_rep1, &base);
      DCHECK(aliases > 0 || (aliases == 0 && base == -1));
      while (aliases--) {
        if (Contains(AllocatedOperand(LocationOperand::REGISTER, other_rep1,
                                      base + aliases))) {
          return true;
        }
      }
      aliases = config->GetAliases(rep, loc.register_code(), other_rep2, &base);
      DCHECK(aliases > 0 || (aliases == 0 && base == -1));
      while (aliases--) {
        if (Contains(AllocatedOperand(LocationOperand::REGISTER, other_rep2,
                                      base + aliases))) {
          return true;
        }
      }
    }
    return false;
  }

 private:
  static bool HasMixedFPReps(int reps) {
    return reps && !base::bits::IsPowerOfTwo(reps);
  }

  ZoneVector<InstructionOperand>* set_;
  int fp_reps_;
};

int FindFirstNonEmptySlot(const Instruction* instr) {
  int i = Instruction::FIRST_GAP_POSITION;
  for (; i <= Instruction::LAST_GAP_POSITION; i++) {
    ParallelMove* moves = instr->parallel_moves()[i];
    if (moves == nullptr) continue;
    for (MoveOperands* move : *moves) {
      if (!move->IsRedundant()) return i;
      move->Eliminate();
    }
    moves->clear();  // Clear this redundant move.
  }
  return i;
}

}  // namespace

MoveOptimizer::MoveOptimizer(Zone* local_zone, InstructionSequence* code)
    : local_zone_(local_zone),
      code_(code),
      local_vector_(local_zone),
      operand_buffer1(local_zone),
      operand_buffer2(local_zone) {}

void MoveOptimizer::Run() {
  for (Instruction* instruction : code()->instructions()) {
    CompressGaps(instruction);
  }
  for (InstructionBlock* block : code()->instruction_blocks()) {
    CompressBlock(block);
  }
  for (InstructionBlock* block : code()->instruction_blocks()) {
    if (block->PredecessorCount() <= 1) continue;
    if (!block->IsDeferred()) {
      bool has_only_deferred = true;
      for (RpoNumber& pred_id : block->predecessors()) {
        if (!code()->InstructionBlockAt(pred_id)->IsDeferred()) {
          has_only_deferred = false;
          break;
        }
      }
      // This would pull down common moves. If the moves occur in deferred
      // blocks, and the closest common successor is not deferred, we lose the
      // optimization of just spilling/filling in deferred blocks, when the
      // current block is not deferred.
      if (has_only_deferred) continue;
    }
    OptimizeMerge(block);
  }
  for (Instruction* gap : code()->instructions()) {
    FinalizeMoves(gap);
  }
}

void MoveOptimizer::RemoveClobberedDestinations(Instruction* instruction) {
  if (instruction->IsCall()) return;
  ParallelMove* moves = instruction->parallel_moves()[0];
  if (moves == nullptr) return;

  DCHECK(instruction->parallel_moves()[1] == nullptr ||
         instruction->parallel_moves()[1]->empty());

  OperandSet outputs(&operand_buffer1);
  OperandSet inputs(&operand_buffer2);

  // Outputs and temps are treated together as potentially clobbering a
  // destination operand.
  for (size_t i = 0; i < instruction->OutputCount(); ++i) {
    outputs.InsertOp(*instruction->OutputAt(i));
  }
  for (size_t i = 0; i < instruction->TempCount(); ++i) {
    outputs.InsertOp(*instruction->TempAt(i));
  }

  // Input operands block elisions.
  for (size_t i = 0; i < instruction->InputCount(); ++i) {
    inputs.InsertOp(*instruction->InputAt(i));
  }

  // Elide moves made redundant by the instruction.
  for (MoveOperands* move : *moves) {
    if (outputs.ContainsOpOrAlias(move->destination()) &&
        !inputs.ContainsOpOrAlias(move->destination())) {
      move->Eliminate();
    }
  }

  // The ret instruction makes any assignment before it unnecessary, except for
  // the one for its input.
  if (instruction->IsRet() || instruction->IsTailCall()) {
    for (MoveOperands* move : *moves) {
      if (!inputs.ContainsOpOrAlias(move->destination())) {
        move->Eliminate();
      }
    }
  }
}

void MoveOptimizer::MigrateMoves(Instruction* to, Instruction* from) {
  if (from->IsCall()) return;

  ParallelMove* from_moves = from->parallel_moves()[0];
  if (from_moves == nullptr || from_moves->empty()) return;

  OperandSet dst_cant_be(&operand_buffer1);
  OperandSet src_cant_be(&operand_buffer2);

  // If an operand is an input to the instruction, we cannot move assignments
  // where it appears on the LHS.
  for (size_t i = 0; i < from->InputCount(); ++i) {
    dst_cant_be.InsertOp(*from->InputAt(i));
  }
  // If an operand is output to the instruction, we cannot move assignments
  // where it appears on the RHS, because we would lose its value before the
  // instruction.
  // Same for temp operands.
  // The output can't appear on the LHS because we performed
  // RemoveClobberedDestinations for the "from" instruction.
  for (size_t i = 0; i < from->OutputCount(); ++i) {
    src_cant_be.InsertOp(*from->OutputAt(i));
  }
  for (size_t i = 0; i < from->TempCount(); ++i) {
    src_cant_be.InsertOp(*from->TempAt(i));
  }
  for (MoveOperands* move : *from_moves) {
    if (move->IsRedundant()) continue;
    // Assume dest has a value "V". If we have a "dest = y" move, then we can't
    // move "z = dest", because z would become y rather than "V".
    // We assume CompressMoves has happened before this, which means we don't
    // have more than one assignment to dest.
    src_cant_be.InsertOp(move->destination());
  }

  ZoneSet<MoveKey, MoveKeyCompare> move_candidates(local_zone());
  // We start with all the moves that don't have conflicting source or
  // destination operands are eligible for being moved down.
  for (MoveOperands* move : *from_moves) {
    if (move->IsRedundant()) continue;
    if (!dst_cant_be.ContainsOpOrAlias(move->destination())) {
      MoveKey key = {move->source(), move->destination()};
      move_candidates.insert(key);
    }
  }
  if (move_candidates.empty()) return;

  // Stabilize the candidate set.
  bool changed = false;
  do {
    changed = false;
    for (auto iter = move_candidates.begin(); iter != move_candidates.end();) {
      auto current = iter;
      ++iter;
      InstructionOperand src = current->source;
      if (src_cant_be.ContainsOpOrAlias(src)) {
        src_cant_be.InsertOp(current->destination);
        move_candidates.erase(current);
        changed = true;
      }
    }
  } while (changed);

  ParallelMove to_move(local_zone());
  for (MoveOperands* move : *from_moves) {
    if (move->IsRedundant()) continue;
    MoveKey key = {move->source(), move->destination()};
    if (move_candidates.find(key) != move_candidates.end()) {
      to_move.AddMove(move->source(), move->destination(), code_zone());
      move->Eliminate();
    }
  }
  if (to_move.empty()) return;

  ParallelMove* dest =
      to->GetOrCreateParallelMove(Instruction::GapPosition::START, code_zone());

  CompressMoves(&to_move, dest);
  DCHECK(dest->empty());
  for (MoveOperands* m : to_move) {
    dest->push_back(m);
  }
}

void MoveOptimizer::CompressMoves(ParallelMove* left, MoveOpVector* right) {
  if (right == nullptr) return;

  MoveOpVector& eliminated = local_vector();
  DCHECK(eliminated.empty());

  if (!left->empty()) {
    // Modify the right moves in place and collect moves that will be killed by
    // merging the two gaps.
    for (MoveOperands* move : *right) {
      if (move->IsRedundant()) continue;
      left->PrepareInsertAfter(move, &eliminated);
    }
    // Eliminate dead moves.
    for (MoveOperands* to_eliminate : eliminated) {
      to_eliminate->Eliminate();
    }
    eliminated.clear();
  }
  // Add all possibly modified moves from right side.
  for (MoveOperands* move : *right) {
    if (move->IsRedundant()) continue;
    left->push_back(move);
  }
  // Nuke right.
  right->clear();
  DCHECK(eliminated.empty());
}

void MoveOptimizer::CompressGaps(Instruction* instruction) {
  int i = FindFirstNonEmptySlot(instruction);
  bool has_moves = i <= Instruction::LAST_GAP_POSITION;
  USE(has_moves);

  if (i == Instruction::LAST_GAP_POSITION) {
    std::swap(instruction->parallel_moves()[Instruction::FIRST_GAP_POSITION],
              instruction->parallel_moves()[Instruction::LAST_GAP_POSITION]);
  } else if (i == Instruction::FIRST_GAP_POSITION) {
    CompressMoves(
        instruction->parallel_moves()[Instruction::FIRST_GAP_POSITION],
        instruction->parallel_moves()[Instruction::LAST_GAP_POSITION]);
  }
  // We either have no moves, or, after swapping or compressing, we have
  // all the moves in the first gap position, and none in the second/end gap
  // position.
  ParallelMove* first =
      instruction->parallel_moves()[Instruction::FIRST_GAP_POSITION];
  ParallelMove* last =
      instruction->parallel_moves()[Instruction::LAST_GAP_POSITION];
  USE(first);
  USE(last);

  DCHECK(!has_moves ||
         (first != nullptr && (last == nullptr || last->empty())));
}

void MoveOptimizer::CompressBlock(InstructionBlock* block) {
  int first_instr_index = block->first_instruction_index();
  int last_instr_index = block->last_instruction_index();

  // Start by removing gap assignments where the output of the subsequent
  // instruction appears on LHS, as long as they are not needed by its input.
  Instruction* prev_instr = code()->instructions()[first_instr_index];
  RemoveClobberedDestinations(prev_instr);

  for (int index = first_instr_index + 1; index <= last_instr_index; ++index) {
    Instruction* instr = code()->instructions()[index];
    // Migrate to the gap of prev_instr eligible moves from instr.
    MigrateMoves(instr, prev_instr);
    // Remove gap assignments clobbered by instr's output.
    RemoveClobberedDestinations(instr);
    prev_instr = instr;
  }
}

const Instruction* MoveOptimizer::LastInstruction(
    const InstructionBlock* block) const {
  return code()->instructions()[block->last_instruction_index()];
}

void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
  DCHECK_LT(1, block->PredecessorCount());
  // Ensure that the last instruction in all incoming blocks don't contain
  // things that would prevent moving gap moves across them.
  for (RpoNumber& pred_index : block->predecessors()) {
    const InstructionBlock* pred = code()->InstructionBlockAt(pred_index);

    // If the predecessor has more than one successor, we shouldn't attempt to
    // move down to this block (one of the successors) any of the gap moves,
    // because their effect may be necessary to the other successors.
    if (pred->SuccessorCount() > 1) return;

    const Instruction* last_instr =
        code()->instructions()[pred->last_instruction_index()];
    if (last_instr->IsCall()) return;
    if (last_instr->TempCount() != 0) return;
    if (last_instr->OutputCount() != 0) return;
    for (size_t i = 0; i < last_instr->InputCount(); ++i) {
      const InstructionOperand* op = last_instr->InputAt(i);
      if (!op->IsConstant() && !op->IsImmediate()) return;
    }
  }
  // TODO(dcarney): pass a ZoneStats down for this?
  MoveMap move_map(local_zone());
  size_t correct_counts = 0;
  // Accumulate set of shared moves.
  for (RpoNumber& pred_index : block->predecessors()) {
    const InstructionBlock* pred = code()->InstructionBlockAt(pred_index);
    const Instruction* instr = LastInstruction(pred);
    if (instr->parallel_moves()[0] == nullptr ||
        instr->parallel_moves()[0]->empty()) {
      return;
    }
    for (const MoveOperands* move : *instr->parallel_moves()[0]) {
      if (move->IsRedundant()) continue;
      InstructionOperand src = move->source();
      InstructionOperand dst = move->destination();
      MoveKey key = {src, dst};
      auto res = move_map.insert(std::make_pair(key, 1));
      if (!res.second) {
        res.first->second++;
        if (res.first->second == block->PredecessorCount()) {
          correct_counts++;
        }
      }
    }
  }
  if (move_map.empty() || correct_counts == 0) return;

  // Find insertion point.
  Instruction* instr = code()->instructions()[block->first_instruction_index()];

  if (correct_counts != move_map.size()) {
    // Moves that are unique to each predecessor won't be pushed to the common
    // successor.
    OperandSet conflicting_srcs(&operand_buffer1);
    for (auto iter = move_map.begin(), end = move_map.end(); iter != end;) {
      auto current = iter;
      ++iter;
      if (current->second != block->PredecessorCount()) {
        InstructionOperand dest = current->first.destination;
        // Not all the moves in all the gaps are the same. Maybe some are. If
        // there are such moves, we could move them, but the destination of the
        // moves staying behind can't appear as a source of a common move,
        // because the move staying behind will clobber this destination.
        conflicting_srcs.InsertOp(dest);
        move_map.erase(current);
      }
    }

    bool changed = false;
    do {
      // If a common move can't be pushed to the common successor, then its
      // destination also can't appear as source to any move being pushed.
      changed = false;
      for (auto iter = move_map.begin(), end = move_map.end(); iter != end;) {
        auto current = iter;
        ++iter;
        DCHECK_EQ(block->PredecessorCount(), current->second);
        if (conflicting_srcs.ContainsOpOrAlias(current->first.source)) {
          conflicting_srcs.InsertOp(current->first.destination);
          move_map.erase(current);
          changed = true;
        }
      }
    } while (changed);
  }

  if (move_map.empty()) return;

  DCHECK_NOT_NULL(instr);
  bool gap_initialized = true;
  if (instr->parallel_moves()[0] != nullptr &&
      !instr->parallel_moves()[0]->empty()) {
    // Will compress after insertion.
    gap_initialized = false;
    std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]);
  }
  ParallelMove* moves = instr->GetOrCreateParallelMove(
      static_cast<Instruction::GapPosition>(0), code_zone());
  // Delete relevant entries in predecessors and move everything to block.
  bool first_iteration = true;
  for (RpoNumber& pred_index : block->predecessors()) {
    const InstructionBlock* pred = code()->InstructionBlockAt(pred_index);
    for (MoveOperands* move : *LastInstruction(pred)->parallel_moves()[0]) {
      if (move->IsRedundant()) continue;
      MoveKey key = {move->source(), move->destination()};
      auto it = move_map.find(key);
      if (it != move_map.end()) {
        if (first_iteration) {
          moves->AddMove(move->source(), move->destination());
        }
        move->Eliminate();
      }
    }
    first_iteration = false;
  }
  // Compress.
  if (!gap_initialized) {
    CompressMoves(instr->parallel_moves()[0], instr->parallel_moves()[1]);
  }
  CompressBlock(block);
}

namespace {

bool IsSlot(const InstructionOperand& op) {
  return op.IsStackSlot() || op.IsFPStackSlot();
}

bool LoadCompare(const MoveOperands* a, const MoveOperands* b) {
  if (!a->source().EqualsCanonicalized(b->source())) {
    return a->source().CompareCanonicalized(b->source());
  }
  if (IsSlot(a->destination()) && !IsSlot(b->destination())) return false;
  if (!IsSlot(a->destination()) && IsSlot(b->destination())) return true;
  return a->destination().CompareCanonicalized(b->destination());
}

}  // namespace

// Split multiple loads of the same constant or stack slot off into the second
// slot and keep remaining moves in the first slot.
void MoveOptimizer::FinalizeMoves(Instruction* instr) {
  MoveOpVector& loads = local_vector();
  DCHECK(loads.empty());

  ParallelMove* parallel_moves = instr->parallel_moves()[0];
  if (parallel_moves == nullptr) return;
  // Find all the loads.
  for (MoveOperands* move : *parallel_moves) {
    if (move->IsRedundant()) continue;
    if (move->source().IsConstant() || IsSlot(move->source())) {
      loads.push_back(move);
    }
  }
  if (loads.empty()) return;
  // Group the loads by source, moving the preferred destination to the
  // beginning of the group.
  std::sort(loads.begin(), loads.end(), LoadCompare);
  MoveOperands* group_begin = nullptr;
  for (MoveOperands* load : loads) {
    // New group.
    if (group_begin == nullptr ||
        !load->source().EqualsCanonicalized(group_begin->source())) {
      group_begin = load;
      continue;
    }
    // Nothing to be gained from splitting here.
    if (IsSlot(group_begin->destination())) continue;
    // Insert new move into slot 1.
    ParallelMove* slot_1 = instr->GetOrCreateParallelMove(
        static_cast<Instruction::GapPosition>(1), code_zone());
    slot_1->AddMove(group_begin->destination(), load->destination());
    load->Eliminate();
  }
  loads.clear();
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
