11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/compiler/backend/register-allocator.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <iomanip>
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "src/base/iterator.h"
101cb0ef41Sopenharmony_ci#include "src/base/small-vector.h"
111cb0ef41Sopenharmony_ci#include "src/base/vector.h"
121cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h"
131cb0ef41Sopenharmony_ci#include "src/codegen/tick-counter.h"
141cb0ef41Sopenharmony_ci#include "src/compiler/backend/spill-placer.h"
151cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h"
161cb0ef41Sopenharmony_ci#include "src/strings/string-stream.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace v8 {
191cb0ef41Sopenharmony_cinamespace internal {
201cb0ef41Sopenharmony_cinamespace compiler {
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#define TRACE_COND(cond, ...)      \
231cb0ef41Sopenharmony_ci  do {                             \
241cb0ef41Sopenharmony_ci    if (cond) PrintF(__VA_ARGS__); \
251cb0ef41Sopenharmony_ci  } while (false)
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#define TRACE(...) TRACE_COND(data()->is_trace_alloc(), __VA_ARGS__)
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cinamespace {
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cistatic constexpr int kFloat32Bit =
321cb0ef41Sopenharmony_ci    RepresentationBit(MachineRepresentation::kFloat32);
331cb0ef41Sopenharmony_cistatic constexpr int kSimd128Bit =
341cb0ef41Sopenharmony_ci    RepresentationBit(MachineRepresentation::kSimd128);
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ciconst InstructionBlock* GetContainingLoop(const InstructionSequence* sequence,
381cb0ef41Sopenharmony_ci                                          const InstructionBlock* block) {
391cb0ef41Sopenharmony_ci  RpoNumber index = block->loop_header();
401cb0ef41Sopenharmony_ci  if (!index.IsValid()) return nullptr;
411cb0ef41Sopenharmony_ci  return sequence->InstructionBlockAt(index);
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciconst InstructionBlock* GetInstructionBlock(const InstructionSequence* code,
451cb0ef41Sopenharmony_ci                                            LifetimePosition pos) {
461cb0ef41Sopenharmony_ci  return code->GetInstructionBlock(pos.ToInstructionIndex());
471cb0ef41Sopenharmony_ci}
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciInstruction* GetLastInstruction(InstructionSequence* code,
501cb0ef41Sopenharmony_ci                                const InstructionBlock* block) {
511cb0ef41Sopenharmony_ci  return code->InstructionAt(block->last_instruction_index());
521cb0ef41Sopenharmony_ci}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci}  // namespace
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_civoid LiveRangeBoundArray::Initialize(Zone* zone, TopLevelLiveRange* range) {
571cb0ef41Sopenharmony_ci  size_t max_child_count = range->GetMaxChildCount();
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  start_ = zone->NewArray<LiveRangeBound>(max_child_count);
601cb0ef41Sopenharmony_ci  length_ = 0;
611cb0ef41Sopenharmony_ci  LiveRangeBound* curr = start_;
621cb0ef41Sopenharmony_ci  // The primary loop in ResolveControlFlow is not responsible for inserting
631cb0ef41Sopenharmony_ci  // connecting moves for spilled ranges.
641cb0ef41Sopenharmony_ci  for (LiveRange* i = range; i != nullptr; i = i->next(), ++curr, ++length_) {
651cb0ef41Sopenharmony_ci    new (curr) LiveRangeBound(i, i->spilled());
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciLiveRangeBound* LiveRangeBoundArray::Find(
701cb0ef41Sopenharmony_ci    const LifetimePosition position) const {
711cb0ef41Sopenharmony_ci  size_t left_index = 0;
721cb0ef41Sopenharmony_ci  size_t right_index = length_;
731cb0ef41Sopenharmony_ci  while (true) {
741cb0ef41Sopenharmony_ci    size_t current_index = left_index + (right_index - left_index) / 2;
751cb0ef41Sopenharmony_ci    DCHECK(right_index > current_index);
761cb0ef41Sopenharmony_ci    LiveRangeBound* bound = &start_[current_index];
771cb0ef41Sopenharmony_ci    if (bound->start_ <= position) {
781cb0ef41Sopenharmony_ci      if (position < bound->end_) return bound;
791cb0ef41Sopenharmony_ci      DCHECK(left_index < current_index);
801cb0ef41Sopenharmony_ci      left_index = current_index;
811cb0ef41Sopenharmony_ci    } else {
821cb0ef41Sopenharmony_ci      right_index = current_index;
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciLiveRangeBound* LiveRangeBoundArray::FindPred(const InstructionBlock* pred) {
881cb0ef41Sopenharmony_ci  LifetimePosition pred_end = LifetimePosition::InstructionFromInstructionIndex(
891cb0ef41Sopenharmony_ci      pred->last_instruction_index());
901cb0ef41Sopenharmony_ci  return Find(pred_end);
911cb0ef41Sopenharmony_ci}
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ciLiveRangeBound* LiveRangeBoundArray::FindSucc(const InstructionBlock* succ) {
941cb0ef41Sopenharmony_ci  LifetimePosition succ_start = LifetimePosition::GapFromInstructionIndex(
951cb0ef41Sopenharmony_ci      succ->first_instruction_index());
961cb0ef41Sopenharmony_ci  return Find(succ_start);
971cb0ef41Sopenharmony_ci}
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_cibool LiveRangeBoundArray::FindConnectableSubranges(
1001cb0ef41Sopenharmony_ci    const InstructionBlock* block, const InstructionBlock* pred,
1011cb0ef41Sopenharmony_ci    FindResult* result) const {
1021cb0ef41Sopenharmony_ci  LifetimePosition pred_end = LifetimePosition::InstructionFromInstructionIndex(
1031cb0ef41Sopenharmony_ci      pred->last_instruction_index());
1041cb0ef41Sopenharmony_ci  LiveRangeBound* bound = Find(pred_end);
1051cb0ef41Sopenharmony_ci  result->pred_cover_ = bound->range_;
1061cb0ef41Sopenharmony_ci  LifetimePosition cur_start = LifetimePosition::GapFromInstructionIndex(
1071cb0ef41Sopenharmony_ci      block->first_instruction_index());
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  if (bound->CanCover(cur_start)) {
1101cb0ef41Sopenharmony_ci    // Both blocks are covered by the same range, so there is nothing to
1111cb0ef41Sopenharmony_ci    // connect.
1121cb0ef41Sopenharmony_ci    return false;
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci  bound = Find(cur_start);
1151cb0ef41Sopenharmony_ci  if (bound->skip_) {
1161cb0ef41Sopenharmony_ci    return false;
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci  result->cur_cover_ = bound->range_;
1191cb0ef41Sopenharmony_ci  DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr);
1201cb0ef41Sopenharmony_ci  return (result->cur_cover_ != result->pred_cover_);
1211cb0ef41Sopenharmony_ci}
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ciLiveRangeFinder::LiveRangeFinder(const TopTierRegisterAllocationData* data,
1241cb0ef41Sopenharmony_ci                                 Zone* zone)
1251cb0ef41Sopenharmony_ci    : data_(data),
1261cb0ef41Sopenharmony_ci      bounds_length_(static_cast<int>(data_->live_ranges().size())),
1271cb0ef41Sopenharmony_ci      bounds_(zone->NewArray<LiveRangeBoundArray>(bounds_length_)),
1281cb0ef41Sopenharmony_ci      zone_(zone) {
1291cb0ef41Sopenharmony_ci  for (int i = 0; i < bounds_length_; ++i) {
1301cb0ef41Sopenharmony_ci    new (&bounds_[i]) LiveRangeBoundArray();
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ciLiveRangeBoundArray* LiveRangeFinder::ArrayFor(int operand_index) {
1351cb0ef41Sopenharmony_ci  DCHECK(operand_index < bounds_length_);
1361cb0ef41Sopenharmony_ci  TopLevelLiveRange* range = data_->live_ranges()[operand_index];
1371cb0ef41Sopenharmony_ci  DCHECK(range != nullptr && !range->IsEmpty());
1381cb0ef41Sopenharmony_ci  DCHECK_EQ(range->vreg(), operand_index);
1391cb0ef41Sopenharmony_ci  LiveRangeBoundArray* array = &bounds_[operand_index];
1401cb0ef41Sopenharmony_ci  if (array->ShouldInitialize()) {
1411cb0ef41Sopenharmony_ci    array->Initialize(zone_, range);
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci  return array;
1441cb0ef41Sopenharmony_ci}
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ciusing DelayedInsertionMapKey = std::pair<ParallelMove*, InstructionOperand>;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_cistruct DelayedInsertionMapCompare {
1491cb0ef41Sopenharmony_ci  bool operator()(const DelayedInsertionMapKey& a,
1501cb0ef41Sopenharmony_ci                  const DelayedInsertionMapKey& b) const {
1511cb0ef41Sopenharmony_ci    if (a.first == b.first) {
1521cb0ef41Sopenharmony_ci      return a.second.Compare(b.second);
1531cb0ef41Sopenharmony_ci    }
1541cb0ef41Sopenharmony_ci    return a.first < b.first;
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci};
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciusing DelayedInsertionMap = ZoneMap<DelayedInsertionMapKey, InstructionOperand,
1591cb0ef41Sopenharmony_ci                                    DelayedInsertionMapCompare>;
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ciUsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
1621cb0ef41Sopenharmony_ci                         void* hint, UsePositionHintType hint_type)
1631cb0ef41Sopenharmony_ci    : operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) {
1641cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone);
1651cb0ef41Sopenharmony_ci  bool register_beneficial = true;
1661cb0ef41Sopenharmony_ci  UsePositionType type = UsePositionType::kRegisterOrSlot;
1671cb0ef41Sopenharmony_ci  if (operand_ != nullptr && operand_->IsUnallocated()) {
1681cb0ef41Sopenharmony_ci    const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_);
1691cb0ef41Sopenharmony_ci    if (unalloc->HasRegisterPolicy()) {
1701cb0ef41Sopenharmony_ci      type = UsePositionType::kRequiresRegister;
1711cb0ef41Sopenharmony_ci    } else if (unalloc->HasSlotPolicy()) {
1721cb0ef41Sopenharmony_ci      type = UsePositionType::kRequiresSlot;
1731cb0ef41Sopenharmony_ci      register_beneficial = false;
1741cb0ef41Sopenharmony_ci    } else if (unalloc->HasRegisterOrSlotOrConstantPolicy()) {
1751cb0ef41Sopenharmony_ci      type = UsePositionType::kRegisterOrSlotOrConstant;
1761cb0ef41Sopenharmony_ci      register_beneficial = false;
1771cb0ef41Sopenharmony_ci    } else {
1781cb0ef41Sopenharmony_ci      register_beneficial = !unalloc->HasRegisterOrSlotPolicy();
1791cb0ef41Sopenharmony_ci    }
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci  flags_ = TypeField::encode(type) | HintTypeField::encode(hint_type) |
1821cb0ef41Sopenharmony_ci           RegisterBeneficialField::encode(register_beneficial) |
1831cb0ef41Sopenharmony_ci           AssignedRegisterField::encode(kUnassignedRegister);
1841cb0ef41Sopenharmony_ci  DCHECK(pos_.IsValid());
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_cibool UsePosition::HasHint() const {
1881cb0ef41Sopenharmony_ci  int hint_register;
1891cb0ef41Sopenharmony_ci  return HintRegister(&hint_register);
1901cb0ef41Sopenharmony_ci}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_cibool UsePosition::HintRegister(int* register_code) const {
1931cb0ef41Sopenharmony_ci  if (hint_ == nullptr) return false;
1941cb0ef41Sopenharmony_ci  switch (HintTypeField::decode(flags_)) {
1951cb0ef41Sopenharmony_ci    case UsePositionHintType::kNone:
1961cb0ef41Sopenharmony_ci    case UsePositionHintType::kUnresolved:
1971cb0ef41Sopenharmony_ci      return false;
1981cb0ef41Sopenharmony_ci    case UsePositionHintType::kUsePos: {
1991cb0ef41Sopenharmony_ci      UsePosition* use_pos = reinterpret_cast<UsePosition*>(hint_);
2001cb0ef41Sopenharmony_ci      int assigned_register = AssignedRegisterField::decode(use_pos->flags_);
2011cb0ef41Sopenharmony_ci      if (assigned_register == kUnassignedRegister) return false;
2021cb0ef41Sopenharmony_ci      *register_code = assigned_register;
2031cb0ef41Sopenharmony_ci      return true;
2041cb0ef41Sopenharmony_ci    }
2051cb0ef41Sopenharmony_ci    case UsePositionHintType::kOperand: {
2061cb0ef41Sopenharmony_ci      InstructionOperand* operand =
2071cb0ef41Sopenharmony_ci          reinterpret_cast<InstructionOperand*>(hint_);
2081cb0ef41Sopenharmony_ci      *register_code = LocationOperand::cast(operand)->register_code();
2091cb0ef41Sopenharmony_ci      return true;
2101cb0ef41Sopenharmony_ci    }
2111cb0ef41Sopenharmony_ci    case UsePositionHintType::kPhi: {
2121cb0ef41Sopenharmony_ci      TopTierRegisterAllocationData::PhiMapValue* phi =
2131cb0ef41Sopenharmony_ci          reinterpret_cast<TopTierRegisterAllocationData::PhiMapValue*>(hint_);
2141cb0ef41Sopenharmony_ci      int assigned_register = phi->assigned_register();
2151cb0ef41Sopenharmony_ci      if (assigned_register == kUnassignedRegister) return false;
2161cb0ef41Sopenharmony_ci      *register_code = assigned_register;
2171cb0ef41Sopenharmony_ci      return true;
2181cb0ef41Sopenharmony_ci    }
2191cb0ef41Sopenharmony_ci  }
2201cb0ef41Sopenharmony_ci  UNREACHABLE();
2211cb0ef41Sopenharmony_ci}
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ciUsePositionHintType UsePosition::HintTypeForOperand(
2241cb0ef41Sopenharmony_ci    const InstructionOperand& op) {
2251cb0ef41Sopenharmony_ci  switch (op.kind()) {
2261cb0ef41Sopenharmony_ci    case InstructionOperand::CONSTANT:
2271cb0ef41Sopenharmony_ci    case InstructionOperand::IMMEDIATE:
2281cb0ef41Sopenharmony_ci      return UsePositionHintType::kNone;
2291cb0ef41Sopenharmony_ci    case InstructionOperand::UNALLOCATED:
2301cb0ef41Sopenharmony_ci      return UsePositionHintType::kUnresolved;
2311cb0ef41Sopenharmony_ci    case InstructionOperand::ALLOCATED:
2321cb0ef41Sopenharmony_ci      if (op.IsRegister() || op.IsFPRegister()) {
2331cb0ef41Sopenharmony_ci        return UsePositionHintType::kOperand;
2341cb0ef41Sopenharmony_ci      } else {
2351cb0ef41Sopenharmony_ci        DCHECK(op.IsStackSlot() || op.IsFPStackSlot());
2361cb0ef41Sopenharmony_ci        return UsePositionHintType::kNone;
2371cb0ef41Sopenharmony_ci      }
2381cb0ef41Sopenharmony_ci    case InstructionOperand::PENDING:
2391cb0ef41Sopenharmony_ci    case InstructionOperand::INVALID:
2401cb0ef41Sopenharmony_ci      break;
2411cb0ef41Sopenharmony_ci  }
2421cb0ef41Sopenharmony_ci  UNREACHABLE();
2431cb0ef41Sopenharmony_ci}
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_civoid UsePosition::SetHint(UsePosition* use_pos) {
2461cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(use_pos);
2471cb0ef41Sopenharmony_ci  hint_ = use_pos;
2481cb0ef41Sopenharmony_ci  flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos);
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_civoid UsePosition::ResolveHint(UsePosition* use_pos) {
2521cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(use_pos);
2531cb0ef41Sopenharmony_ci  if (HintTypeField::decode(flags_) != UsePositionHintType::kUnresolved) return;
2541cb0ef41Sopenharmony_ci  hint_ = use_pos;
2551cb0ef41Sopenharmony_ci  flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos);
2561cb0ef41Sopenharmony_ci}
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_civoid UsePosition::set_type(UsePositionType type, bool register_beneficial) {
2591cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial);
2601cb0ef41Sopenharmony_ci  DCHECK_EQ(kUnassignedRegister, AssignedRegisterField::decode(flags_));
2611cb0ef41Sopenharmony_ci  flags_ = TypeField::encode(type) |
2621cb0ef41Sopenharmony_ci           RegisterBeneficialField::encode(register_beneficial) |
2631cb0ef41Sopenharmony_ci           HintTypeField::encode(HintTypeField::decode(flags_)) |
2641cb0ef41Sopenharmony_ci           AssignedRegisterField::encode(kUnassignedRegister);
2651cb0ef41Sopenharmony_ci}
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ciUseInterval* UseInterval::SplitAt(LifetimePosition pos, Zone* zone) {
2681cb0ef41Sopenharmony_ci  DCHECK(Contains(pos) && pos != start());
2691cb0ef41Sopenharmony_ci  UseInterval* after = zone->New<UseInterval>(pos, end_);
2701cb0ef41Sopenharmony_ci  after->next_ = next_;
2711cb0ef41Sopenharmony_ci  next_ = nullptr;
2721cb0ef41Sopenharmony_ci  end_ = pos;
2731cb0ef41Sopenharmony_ci  return after;
2741cb0ef41Sopenharmony_ci}
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_civoid LifetimePosition::Print() const { StdoutStream{} << *this << std::endl; }
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const LifetimePosition pos) {
2791cb0ef41Sopenharmony_ci  os << '@' << pos.ToInstructionIndex();
2801cb0ef41Sopenharmony_ci  if (pos.IsGapPosition()) {
2811cb0ef41Sopenharmony_ci    os << 'g';
2821cb0ef41Sopenharmony_ci  } else {
2831cb0ef41Sopenharmony_ci    os << 'i';
2841cb0ef41Sopenharmony_ci  }
2851cb0ef41Sopenharmony_ci  if (pos.IsStart()) {
2861cb0ef41Sopenharmony_ci    os << 's';
2871cb0ef41Sopenharmony_ci  } else {
2881cb0ef41Sopenharmony_ci    os << 'e';
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci  return os;
2911cb0ef41Sopenharmony_ci}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ciLiveRange::LiveRange(int relative_id, MachineRepresentation rep,
2941cb0ef41Sopenharmony_ci                     TopLevelLiveRange* top_level)
2951cb0ef41Sopenharmony_ci    : relative_id_(relative_id),
2961cb0ef41Sopenharmony_ci      bits_(0),
2971cb0ef41Sopenharmony_ci      last_interval_(nullptr),
2981cb0ef41Sopenharmony_ci      first_interval_(nullptr),
2991cb0ef41Sopenharmony_ci      first_pos_(nullptr),
3001cb0ef41Sopenharmony_ci      top_level_(top_level),
3011cb0ef41Sopenharmony_ci      next_(nullptr),
3021cb0ef41Sopenharmony_ci      current_interval_(nullptr),
3031cb0ef41Sopenharmony_ci      last_processed_use_(nullptr),
3041cb0ef41Sopenharmony_ci      current_hint_position_(nullptr) {
3051cb0ef41Sopenharmony_ci  DCHECK(AllocatedOperand::IsSupportedRepresentation(rep));
3061cb0ef41Sopenharmony_ci  bits_ = AssignedRegisterField::encode(kUnassignedRegister) |
3071cb0ef41Sopenharmony_ci          RepresentationField::encode(rep) |
3081cb0ef41Sopenharmony_ci          ControlFlowRegisterHint::encode(kUnassignedRegister);
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_civoid LiveRange::VerifyPositions() const {
3121cb0ef41Sopenharmony_ci  // Walk the positions, verifying that each is in an interval.
3131cb0ef41Sopenharmony_ci  UseInterval* interval = first_interval_;
3141cb0ef41Sopenharmony_ci  for (UsePosition* pos = first_pos_; pos != nullptr; pos = pos->next()) {
3151cb0ef41Sopenharmony_ci    CHECK(Start() <= pos->pos());
3161cb0ef41Sopenharmony_ci    CHECK(pos->pos() <= End());
3171cb0ef41Sopenharmony_ci    CHECK_NOT_NULL(interval);
3181cb0ef41Sopenharmony_ci    while (!interval->Contains(pos->pos()) && interval->end() != pos->pos()) {
3191cb0ef41Sopenharmony_ci      interval = interval->next();
3201cb0ef41Sopenharmony_ci      CHECK_NOT_NULL(interval);
3211cb0ef41Sopenharmony_ci    }
3221cb0ef41Sopenharmony_ci  }
3231cb0ef41Sopenharmony_ci}
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_civoid LiveRange::VerifyIntervals() const {
3261cb0ef41Sopenharmony_ci  DCHECK(first_interval()->start() == Start());
3271cb0ef41Sopenharmony_ci  LifetimePosition last_end = first_interval()->end();
3281cb0ef41Sopenharmony_ci  for (UseInterval* interval = first_interval()->next(); interval != nullptr;
3291cb0ef41Sopenharmony_ci       interval = interval->next()) {
3301cb0ef41Sopenharmony_ci    DCHECK(last_end <= interval->start());
3311cb0ef41Sopenharmony_ci    last_end = interval->end();
3321cb0ef41Sopenharmony_ci  }
3331cb0ef41Sopenharmony_ci  DCHECK(last_end == End());
3341cb0ef41Sopenharmony_ci}
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_civoid LiveRange::set_assigned_register(int reg) {
3371cb0ef41Sopenharmony_ci  DCHECK(!HasRegisterAssigned() && !spilled());
3381cb0ef41Sopenharmony_ci  bits_ = AssignedRegisterField::update(bits_, reg);
3391cb0ef41Sopenharmony_ci}
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_civoid LiveRange::UnsetAssignedRegister() {
3421cb0ef41Sopenharmony_ci  DCHECK(HasRegisterAssigned() && !spilled());
3431cb0ef41Sopenharmony_ci  bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister);
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_civoid LiveRange::AttachToNext() {
3471cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(next_);
3481cb0ef41Sopenharmony_ci  DCHECK_NE(TopLevel()->last_child_covers_, next_);
3491cb0ef41Sopenharmony_ci  last_interval_->set_next(next_->first_interval());
3501cb0ef41Sopenharmony_ci  next_->first_interval_ = nullptr;
3511cb0ef41Sopenharmony_ci  last_interval_ = next_->last_interval_;
3521cb0ef41Sopenharmony_ci  next_->last_interval_ = nullptr;
3531cb0ef41Sopenharmony_ci  if (first_pos() == nullptr) {
3541cb0ef41Sopenharmony_ci    first_pos_ = next_->first_pos();
3551cb0ef41Sopenharmony_ci  } else {
3561cb0ef41Sopenharmony_ci    UsePosition* ptr = first_pos_;
3571cb0ef41Sopenharmony_ci    while (ptr->next() != nullptr) {
3581cb0ef41Sopenharmony_ci      ptr = ptr->next();
3591cb0ef41Sopenharmony_ci    }
3601cb0ef41Sopenharmony_ci    ptr->set_next(next_->first_pos());
3611cb0ef41Sopenharmony_ci  }
3621cb0ef41Sopenharmony_ci  next_->first_pos_ = nullptr;
3631cb0ef41Sopenharmony_ci  LiveRange* old_next = next_;
3641cb0ef41Sopenharmony_ci  next_ = next_->next_;
3651cb0ef41Sopenharmony_ci  old_next->next_ = nullptr;
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_civoid LiveRange::Unspill() {
3691cb0ef41Sopenharmony_ci  DCHECK(spilled());
3701cb0ef41Sopenharmony_ci  set_spilled(false);
3711cb0ef41Sopenharmony_ci  bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister);
3721cb0ef41Sopenharmony_ci}
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_civoid LiveRange::Spill() {
3751cb0ef41Sopenharmony_ci  DCHECK(!spilled());
3761cb0ef41Sopenharmony_ci  DCHECK(!TopLevel()->HasNoSpillType());
3771cb0ef41Sopenharmony_ci  set_spilled(true);
3781cb0ef41Sopenharmony_ci  bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister);
3791cb0ef41Sopenharmony_ci}
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ciRegisterKind LiveRange::kind() const {
3821cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kIndependent &&
3831cb0ef41Sopenharmony_ci      IsSimd128(representation())) {
3841cb0ef41Sopenharmony_ci    return RegisterKind::kSimd128;
3851cb0ef41Sopenharmony_ci  } else {
3861cb0ef41Sopenharmony_ci    return IsFloatingPoint(representation()) ? RegisterKind::kDouble
3871cb0ef41Sopenharmony_ci                                             : RegisterKind::kGeneral;
3881cb0ef41Sopenharmony_ci  }
3891cb0ef41Sopenharmony_ci}
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ciUsePosition* LiveRange::FirstHintPosition(int* register_index) {
3921cb0ef41Sopenharmony_ci  if (!first_pos_) return nullptr;
3931cb0ef41Sopenharmony_ci  if (current_hint_position_) {
3941cb0ef41Sopenharmony_ci    if (current_hint_position_->pos() < first_pos_->pos()) {
3951cb0ef41Sopenharmony_ci      current_hint_position_ = first_pos_;
3961cb0ef41Sopenharmony_ci    }
3971cb0ef41Sopenharmony_ci    if (current_hint_position_->pos() > End()) {
3981cb0ef41Sopenharmony_ci      current_hint_position_ = nullptr;
3991cb0ef41Sopenharmony_ci    }
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci  bool needs_revisit = false;
4021cb0ef41Sopenharmony_ci  UsePosition* pos = current_hint_position_;
4031cb0ef41Sopenharmony_ci  for (; pos != nullptr; pos = pos->next()) {
4041cb0ef41Sopenharmony_ci    if (pos->HintRegister(register_index)) {
4051cb0ef41Sopenharmony_ci      break;
4061cb0ef41Sopenharmony_ci    }
4071cb0ef41Sopenharmony_ci    // Phi and use position hints can be assigned during allocation which
4081cb0ef41Sopenharmony_ci    // would invalidate the cached hint position. Make sure we revisit them.
4091cb0ef41Sopenharmony_ci    needs_revisit = needs_revisit ||
4101cb0ef41Sopenharmony_ci                    pos->hint_type() == UsePositionHintType::kPhi ||
4111cb0ef41Sopenharmony_ci                    pos->hint_type() == UsePositionHintType::kUsePos;
4121cb0ef41Sopenharmony_ci  }
4131cb0ef41Sopenharmony_ci  if (!needs_revisit) {
4141cb0ef41Sopenharmony_ci    current_hint_position_ = pos;
4151cb0ef41Sopenharmony_ci  }
4161cb0ef41Sopenharmony_ci#ifdef DEBUG
4171cb0ef41Sopenharmony_ci  UsePosition* pos_check = first_pos_;
4181cb0ef41Sopenharmony_ci  for (; pos_check != nullptr; pos_check = pos_check->next()) {
4191cb0ef41Sopenharmony_ci    if (pos_check->HasHint()) {
4201cb0ef41Sopenharmony_ci      break;
4211cb0ef41Sopenharmony_ci    }
4221cb0ef41Sopenharmony_ci  }
4231cb0ef41Sopenharmony_ci  CHECK_EQ(pos, pos_check);
4241cb0ef41Sopenharmony_ci#endif
4251cb0ef41Sopenharmony_ci  return pos;
4261cb0ef41Sopenharmony_ci}
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ciUsePosition* LiveRange::NextUsePosition(LifetimePosition start) const {
4291cb0ef41Sopenharmony_ci  UsePosition* use_pos = last_processed_use_;
4301cb0ef41Sopenharmony_ci  if (use_pos == nullptr || use_pos->pos() > start) {
4311cb0ef41Sopenharmony_ci    use_pos = first_pos();
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci  while (use_pos != nullptr && use_pos->pos() < start) {
4341cb0ef41Sopenharmony_ci    use_pos = use_pos->next();
4351cb0ef41Sopenharmony_ci  }
4361cb0ef41Sopenharmony_ci  last_processed_use_ = use_pos;
4371cb0ef41Sopenharmony_ci  return use_pos;
4381cb0ef41Sopenharmony_ci}
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ciUsePosition* LiveRange::NextUsePositionRegisterIsBeneficial(
4411cb0ef41Sopenharmony_ci    LifetimePosition start) const {
4421cb0ef41Sopenharmony_ci  UsePosition* pos = NextUsePosition(start);
4431cb0ef41Sopenharmony_ci  while (pos != nullptr && !pos->RegisterIsBeneficial()) {
4441cb0ef41Sopenharmony_ci    pos = pos->next();
4451cb0ef41Sopenharmony_ci  }
4461cb0ef41Sopenharmony_ci  return pos;
4471cb0ef41Sopenharmony_ci}
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ciLifetimePosition LiveRange::NextLifetimePositionRegisterIsBeneficial(
4501cb0ef41Sopenharmony_ci    const LifetimePosition& start) const {
4511cb0ef41Sopenharmony_ci  UsePosition* next_use = NextUsePositionRegisterIsBeneficial(start);
4521cb0ef41Sopenharmony_ci  if (next_use == nullptr) return End();
4531cb0ef41Sopenharmony_ci  return next_use->pos();
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ciUsePosition* LiveRange::PreviousUsePositionRegisterIsBeneficial(
4571cb0ef41Sopenharmony_ci    LifetimePosition start) const {
4581cb0ef41Sopenharmony_ci  UsePosition* pos = first_pos();
4591cb0ef41Sopenharmony_ci  UsePosition* prev = nullptr;
4601cb0ef41Sopenharmony_ci  while (pos != nullptr && pos->pos() < start) {
4611cb0ef41Sopenharmony_ci    if (pos->RegisterIsBeneficial()) prev = pos;
4621cb0ef41Sopenharmony_ci    pos = pos->next();
4631cb0ef41Sopenharmony_ci  }
4641cb0ef41Sopenharmony_ci  return prev;
4651cb0ef41Sopenharmony_ci}
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ciUsePosition* LiveRange::NextUsePositionSpillDetrimental(
4681cb0ef41Sopenharmony_ci    LifetimePosition start) const {
4691cb0ef41Sopenharmony_ci  UsePosition* pos = NextUsePosition(start);
4701cb0ef41Sopenharmony_ci  while (pos != nullptr && pos->type() != UsePositionType::kRequiresRegister &&
4711cb0ef41Sopenharmony_ci         !pos->SpillDetrimental()) {
4721cb0ef41Sopenharmony_ci    pos = pos->next();
4731cb0ef41Sopenharmony_ci  }
4741cb0ef41Sopenharmony_ci  return pos;
4751cb0ef41Sopenharmony_ci}
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ciUsePosition* LiveRange::NextRegisterPosition(LifetimePosition start) const {
4781cb0ef41Sopenharmony_ci  UsePosition* pos = NextUsePosition(start);
4791cb0ef41Sopenharmony_ci  while (pos != nullptr && pos->type() != UsePositionType::kRequiresRegister) {
4801cb0ef41Sopenharmony_ci    pos = pos->next();
4811cb0ef41Sopenharmony_ci  }
4821cb0ef41Sopenharmony_ci  return pos;
4831cb0ef41Sopenharmony_ci}
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_cibool LiveRange::CanBeSpilled(LifetimePosition pos) const {
4861cb0ef41Sopenharmony_ci  // We cannot spill a live range that has a use requiring a register
4871cb0ef41Sopenharmony_ci  // at the current or the immediate next position.
4881cb0ef41Sopenharmony_ci  UsePosition* use_pos = NextRegisterPosition(pos);
4891cb0ef41Sopenharmony_ci  if (use_pos == nullptr) return true;
4901cb0ef41Sopenharmony_ci  return use_pos->pos() > pos.NextStart().End();
4911cb0ef41Sopenharmony_ci}
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_cibool LiveRange::IsTopLevel() const { return top_level_ == this; }
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ciInstructionOperand LiveRange::GetAssignedOperand() const {
4961cb0ef41Sopenharmony_ci  DCHECK(!IsEmpty());
4971cb0ef41Sopenharmony_ci  if (HasRegisterAssigned()) {
4981cb0ef41Sopenharmony_ci    DCHECK(!spilled());
4991cb0ef41Sopenharmony_ci    return AllocatedOperand(LocationOperand::REGISTER, representation(),
5001cb0ef41Sopenharmony_ci                            assigned_register());
5011cb0ef41Sopenharmony_ci  }
5021cb0ef41Sopenharmony_ci  DCHECK(spilled());
5031cb0ef41Sopenharmony_ci  DCHECK(!HasRegisterAssigned());
5041cb0ef41Sopenharmony_ci  if (TopLevel()->HasSpillOperand()) {
5051cb0ef41Sopenharmony_ci    InstructionOperand* op = TopLevel()->GetSpillOperand();
5061cb0ef41Sopenharmony_ci    DCHECK(!op->IsUnallocated());
5071cb0ef41Sopenharmony_ci    return *op;
5081cb0ef41Sopenharmony_ci  }
5091cb0ef41Sopenharmony_ci  return TopLevel()->GetSpillRangeOperand();
5101cb0ef41Sopenharmony_ci}
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ciUseInterval* LiveRange::FirstSearchIntervalForPosition(
5131cb0ef41Sopenharmony_ci    LifetimePosition position) const {
5141cb0ef41Sopenharmony_ci  if (current_interval_ == nullptr) return first_interval_;
5151cb0ef41Sopenharmony_ci  if (current_interval_->start() > position) {
5161cb0ef41Sopenharmony_ci    current_interval_ = nullptr;
5171cb0ef41Sopenharmony_ci    return first_interval_;
5181cb0ef41Sopenharmony_ci  }
5191cb0ef41Sopenharmony_ci  return current_interval_;
5201cb0ef41Sopenharmony_ci}
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_civoid LiveRange::AdvanceLastProcessedMarker(
5231cb0ef41Sopenharmony_ci    UseInterval* to_start_of, LifetimePosition but_not_past) const {
5241cb0ef41Sopenharmony_ci  if (to_start_of == nullptr) return;
5251cb0ef41Sopenharmony_ci  if (to_start_of->start() > but_not_past) return;
5261cb0ef41Sopenharmony_ci  LifetimePosition start = current_interval_ == nullptr
5271cb0ef41Sopenharmony_ci                               ? LifetimePosition::Invalid()
5281cb0ef41Sopenharmony_ci                               : current_interval_->start();
5291cb0ef41Sopenharmony_ci  if (to_start_of->start() > start) {
5301cb0ef41Sopenharmony_ci    current_interval_ = to_start_of;
5311cb0ef41Sopenharmony_ci  }
5321cb0ef41Sopenharmony_ci}
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ciLiveRange* LiveRange::SplitAt(LifetimePosition position, Zone* zone) {
5351cb0ef41Sopenharmony_ci  int new_id = TopLevel()->GetNextChildId();
5361cb0ef41Sopenharmony_ci  LiveRange* child = zone->New<LiveRange>(new_id, representation(), TopLevel());
5371cb0ef41Sopenharmony_ci  child->set_bundle(bundle_);
5381cb0ef41Sopenharmony_ci  // If we split, we do so because we're about to switch registers or move
5391cb0ef41Sopenharmony_ci  // to/from a slot, so there's no value in connecting hints.
5401cb0ef41Sopenharmony_ci  DetachAt(position, child, zone, DoNotConnectHints);
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  child->top_level_ = TopLevel();
5431cb0ef41Sopenharmony_ci  child->next_ = next_;
5441cb0ef41Sopenharmony_ci  next_ = child;
5451cb0ef41Sopenharmony_ci  return child;
5461cb0ef41Sopenharmony_ci}
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ciUsePosition* LiveRange::DetachAt(LifetimePosition position, LiveRange* result,
5491cb0ef41Sopenharmony_ci                                 Zone* zone,
5501cb0ef41Sopenharmony_ci                                 HintConnectionOption connect_hints) {
5511cb0ef41Sopenharmony_ci  DCHECK(Start() < position);
5521cb0ef41Sopenharmony_ci  DCHECK(End() > position);
5531cb0ef41Sopenharmony_ci  DCHECK(result->IsEmpty());
5541cb0ef41Sopenharmony_ci  // Find the last interval that ends before the position. If the
5551cb0ef41Sopenharmony_ci  // position is contained in one of the intervals in the chain, we
5561cb0ef41Sopenharmony_ci  // split that interval and use the first part.
5571cb0ef41Sopenharmony_ci  UseInterval* current = FirstSearchIntervalForPosition(position);
5581cb0ef41Sopenharmony_ci
5591cb0ef41Sopenharmony_ci  // If the split position coincides with the beginning of a use interval
5601cb0ef41Sopenharmony_ci  // we need to split use positons in a special way.
5611cb0ef41Sopenharmony_ci  bool split_at_start = false;
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci  if (current->start() == position) {
5641cb0ef41Sopenharmony_ci    // When splitting at start we need to locate the previous use interval.
5651cb0ef41Sopenharmony_ci    current = first_interval_;
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci  UseInterval* after = nullptr;
5691cb0ef41Sopenharmony_ci  while (current != nullptr) {
5701cb0ef41Sopenharmony_ci    if (current->Contains(position)) {
5711cb0ef41Sopenharmony_ci      after = current->SplitAt(position, zone);
5721cb0ef41Sopenharmony_ci      break;
5731cb0ef41Sopenharmony_ci    }
5741cb0ef41Sopenharmony_ci    UseInterval* next = current->next();
5751cb0ef41Sopenharmony_ci    if (next->start() >= position) {
5761cb0ef41Sopenharmony_ci      split_at_start = (next->start() == position);
5771cb0ef41Sopenharmony_ci      after = next;
5781cb0ef41Sopenharmony_ci      current->set_next(nullptr);
5791cb0ef41Sopenharmony_ci      break;
5801cb0ef41Sopenharmony_ci    }
5811cb0ef41Sopenharmony_ci    current = next;
5821cb0ef41Sopenharmony_ci  }
5831cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(after);
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  // Partition original use intervals to the two live ranges.
5861cb0ef41Sopenharmony_ci  UseInterval* before = current;
5871cb0ef41Sopenharmony_ci  result->last_interval_ =
5881cb0ef41Sopenharmony_ci      (last_interval_ == before)
5891cb0ef41Sopenharmony_ci          ? after            // Only interval in the range after split.
5901cb0ef41Sopenharmony_ci          : last_interval_;  // Last interval of the original range.
5911cb0ef41Sopenharmony_ci  result->first_interval_ = after;
5921cb0ef41Sopenharmony_ci  last_interval_ = before;
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci  // Find the last use position before the split and the first use
5951cb0ef41Sopenharmony_ci  // position after it.
5961cb0ef41Sopenharmony_ci  UsePosition* use_after = first_pos();
5971cb0ef41Sopenharmony_ci  UsePosition* use_before = nullptr;
5981cb0ef41Sopenharmony_ci  if (split_at_start) {
5991cb0ef41Sopenharmony_ci    // The split position coincides with the beginning of a use interval (the
6001cb0ef41Sopenharmony_ci    // end of a lifetime hole). Use at this position should be attributed to
6011cb0ef41Sopenharmony_ci    // the split child because split child owns use interval covering it.
6021cb0ef41Sopenharmony_ci    while (use_after != nullptr && use_after->pos() < position) {
6031cb0ef41Sopenharmony_ci      use_before = use_after;
6041cb0ef41Sopenharmony_ci      use_after = use_after->next();
6051cb0ef41Sopenharmony_ci    }
6061cb0ef41Sopenharmony_ci  } else {
6071cb0ef41Sopenharmony_ci    while (use_after != nullptr && use_after->pos() <= position) {
6081cb0ef41Sopenharmony_ci      use_before = use_after;
6091cb0ef41Sopenharmony_ci      use_after = use_after->next();
6101cb0ef41Sopenharmony_ci    }
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci  // Partition original use positions to the two live ranges.
6141cb0ef41Sopenharmony_ci  if (use_before != nullptr) {
6151cb0ef41Sopenharmony_ci    use_before->set_next(nullptr);
6161cb0ef41Sopenharmony_ci  } else {
6171cb0ef41Sopenharmony_ci    first_pos_ = nullptr;
6181cb0ef41Sopenharmony_ci  }
6191cb0ef41Sopenharmony_ci  result->first_pos_ = use_after;
6201cb0ef41Sopenharmony_ci  result->current_hint_position_ = current_hint_position_;
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  // Discard cached iteration state. It might be pointing
6231cb0ef41Sopenharmony_ci  // to the use that no longer belongs to this live range.
6241cb0ef41Sopenharmony_ci  last_processed_use_ = nullptr;
6251cb0ef41Sopenharmony_ci  current_interval_ = nullptr;
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci  if (connect_hints == ConnectHints && use_before != nullptr &&
6281cb0ef41Sopenharmony_ci      use_after != nullptr) {
6291cb0ef41Sopenharmony_ci    use_after->SetHint(use_before);
6301cb0ef41Sopenharmony_ci    result->current_hint_position_ = use_after;
6311cb0ef41Sopenharmony_ci  }
6321cb0ef41Sopenharmony_ci#ifdef DEBUG
6331cb0ef41Sopenharmony_ci  VerifyChildStructure();
6341cb0ef41Sopenharmony_ci  result->VerifyChildStructure();
6351cb0ef41Sopenharmony_ci#endif
6361cb0ef41Sopenharmony_ci  return use_before;
6371cb0ef41Sopenharmony_ci}
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_civoid LiveRange::UpdateParentForAllChildren(TopLevelLiveRange* new_top_level) {
6401cb0ef41Sopenharmony_ci  LiveRange* child = this;
6411cb0ef41Sopenharmony_ci  for (; child != nullptr; child = child->next()) {
6421cb0ef41Sopenharmony_ci    child->top_level_ = new_top_level;
6431cb0ef41Sopenharmony_ci  }
6441cb0ef41Sopenharmony_ci}
6451cb0ef41Sopenharmony_ci
6461cb0ef41Sopenharmony_civoid LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
6471cb0ef41Sopenharmony_ci                                     const InstructionOperand& spill_op) {
6481cb0ef41Sopenharmony_ci  for (UsePosition* pos = first_pos(); pos != nullptr; pos = pos->next()) {
6491cb0ef41Sopenharmony_ci    DCHECK(Start() <= pos->pos() && pos->pos() <= End());
6501cb0ef41Sopenharmony_ci    if (!pos->HasOperand()) continue;
6511cb0ef41Sopenharmony_ci    switch (pos->type()) {
6521cb0ef41Sopenharmony_ci      case UsePositionType::kRequiresSlot:
6531cb0ef41Sopenharmony_ci        DCHECK(spill_op.IsStackSlot() || spill_op.IsFPStackSlot());
6541cb0ef41Sopenharmony_ci        InstructionOperand::ReplaceWith(pos->operand(), &spill_op);
6551cb0ef41Sopenharmony_ci        break;
6561cb0ef41Sopenharmony_ci      case UsePositionType::kRequiresRegister:
6571cb0ef41Sopenharmony_ci        DCHECK(op.IsRegister() || op.IsFPRegister());
6581cb0ef41Sopenharmony_ci        V8_FALLTHROUGH;
6591cb0ef41Sopenharmony_ci      case UsePositionType::kRegisterOrSlot:
6601cb0ef41Sopenharmony_ci      case UsePositionType::kRegisterOrSlotOrConstant:
6611cb0ef41Sopenharmony_ci        InstructionOperand::ReplaceWith(pos->operand(), &op);
6621cb0ef41Sopenharmony_ci        break;
6631cb0ef41Sopenharmony_ci    }
6641cb0ef41Sopenharmony_ci  }
6651cb0ef41Sopenharmony_ci}
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci// This implements an ordering on live ranges so that they are ordered by their
6681cb0ef41Sopenharmony_ci// start positions.  This is needed for the correctness of the register
6691cb0ef41Sopenharmony_ci// allocation algorithm.  If two live ranges start at the same offset then there
6701cb0ef41Sopenharmony_ci// is a tie breaker based on where the value is first used.  This part of the
6711cb0ef41Sopenharmony_ci// ordering is merely a heuristic.
6721cb0ef41Sopenharmony_cibool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const {
6731cb0ef41Sopenharmony_ci  LifetimePosition start = Start();
6741cb0ef41Sopenharmony_ci  LifetimePosition other_start = other->Start();
6751cb0ef41Sopenharmony_ci  if (start == other_start) {
6761cb0ef41Sopenharmony_ci    // Prefer register that has a controlflow hint to make sure it gets
6771cb0ef41Sopenharmony_ci    // allocated first. This allows the control flow aware alloction to
6781cb0ef41Sopenharmony_ci    // just put ranges back into the queue without other ranges interfering.
6791cb0ef41Sopenharmony_ci    if (controlflow_hint() < other->controlflow_hint()) {
6801cb0ef41Sopenharmony_ci      return true;
6811cb0ef41Sopenharmony_ci    }
6821cb0ef41Sopenharmony_ci    // The other has a smaller hint.
6831cb0ef41Sopenharmony_ci    if (controlflow_hint() > other->controlflow_hint()) {
6841cb0ef41Sopenharmony_ci      return false;
6851cb0ef41Sopenharmony_ci    }
6861cb0ef41Sopenharmony_ci    // Both have the same hint or no hint at all. Use first use position.
6871cb0ef41Sopenharmony_ci    UsePosition* pos = first_pos();
6881cb0ef41Sopenharmony_ci    UsePosition* other_pos = other->first_pos();
6891cb0ef41Sopenharmony_ci    // To make the order total, handle the case where both positions are null.
6901cb0ef41Sopenharmony_ci    if (pos == other_pos) return TopLevel()->vreg() < other->TopLevel()->vreg();
6911cb0ef41Sopenharmony_ci    if (pos == nullptr) return false;
6921cb0ef41Sopenharmony_ci    if (other_pos == nullptr) return true;
6931cb0ef41Sopenharmony_ci    // To make the order total, handle the case where both positions are equal.
6941cb0ef41Sopenharmony_ci    if (pos->pos() == other_pos->pos())
6951cb0ef41Sopenharmony_ci      return TopLevel()->vreg() < other->TopLevel()->vreg();
6961cb0ef41Sopenharmony_ci    return pos->pos() < other_pos->pos();
6971cb0ef41Sopenharmony_ci  }
6981cb0ef41Sopenharmony_ci  return start < other_start;
6991cb0ef41Sopenharmony_ci}
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_civoid LiveRange::SetUseHints(int register_index) {
7021cb0ef41Sopenharmony_ci  for (UsePosition* pos = first_pos(); pos != nullptr; pos = pos->next()) {
7031cb0ef41Sopenharmony_ci    if (!pos->HasOperand()) continue;
7041cb0ef41Sopenharmony_ci    switch (pos->type()) {
7051cb0ef41Sopenharmony_ci      case UsePositionType::kRequiresSlot:
7061cb0ef41Sopenharmony_ci        break;
7071cb0ef41Sopenharmony_ci      case UsePositionType::kRequiresRegister:
7081cb0ef41Sopenharmony_ci      case UsePositionType::kRegisterOrSlot:
7091cb0ef41Sopenharmony_ci      case UsePositionType::kRegisterOrSlotOrConstant:
7101cb0ef41Sopenharmony_ci        pos->set_assigned_register(register_index);
7111cb0ef41Sopenharmony_ci        break;
7121cb0ef41Sopenharmony_ci    }
7131cb0ef41Sopenharmony_ci  }
7141cb0ef41Sopenharmony_ci}
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_cibool LiveRange::CanCover(LifetimePosition position) const {
7171cb0ef41Sopenharmony_ci  if (IsEmpty()) return false;
7181cb0ef41Sopenharmony_ci  return Start() <= position && position < End();
7191cb0ef41Sopenharmony_ci}
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_cibool LiveRange::Covers(LifetimePosition position) const {
7221cb0ef41Sopenharmony_ci  if (!CanCover(position)) return false;
7231cb0ef41Sopenharmony_ci  UseInterval* start_search = FirstSearchIntervalForPosition(position);
7241cb0ef41Sopenharmony_ci  for (UseInterval* interval = start_search; interval != nullptr;
7251cb0ef41Sopenharmony_ci       interval = interval->next()) {
7261cb0ef41Sopenharmony_ci    DCHECK(interval->next() == nullptr ||
7271cb0ef41Sopenharmony_ci           interval->next()->start() >= interval->start());
7281cb0ef41Sopenharmony_ci    AdvanceLastProcessedMarker(interval, position);
7291cb0ef41Sopenharmony_ci    if (interval->Contains(position)) return true;
7301cb0ef41Sopenharmony_ci    if (interval->start() > position) return false;
7311cb0ef41Sopenharmony_ci  }
7321cb0ef41Sopenharmony_ci  return false;
7331cb0ef41Sopenharmony_ci}
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ciLifetimePosition LiveRange::NextEndAfter(LifetimePosition position) const {
7361cb0ef41Sopenharmony_ci  UseInterval* start_search = FirstSearchIntervalForPosition(position);
7371cb0ef41Sopenharmony_ci  while (start_search->end() < position) {
7381cb0ef41Sopenharmony_ci    start_search = start_search->next();
7391cb0ef41Sopenharmony_ci  }
7401cb0ef41Sopenharmony_ci  return start_search->end();
7411cb0ef41Sopenharmony_ci}
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ciLifetimePosition LiveRange::NextStartAfter(LifetimePosition position) {
7441cb0ef41Sopenharmony_ci  UseInterval* start_search = FirstSearchIntervalForPosition(position);
7451cb0ef41Sopenharmony_ci  while (start_search->start() < position) {
7461cb0ef41Sopenharmony_ci    start_search = start_search->next();
7471cb0ef41Sopenharmony_ci  }
7481cb0ef41Sopenharmony_ci  next_start_ = start_search->start();
7491cb0ef41Sopenharmony_ci  return next_start_;
7501cb0ef41Sopenharmony_ci}
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ciLifetimePosition LiveRange::FirstIntersection(LiveRange* other) const {
7531cb0ef41Sopenharmony_ci  UseInterval* b = other->first_interval();
7541cb0ef41Sopenharmony_ci  if (b == nullptr) return LifetimePosition::Invalid();
7551cb0ef41Sopenharmony_ci  LifetimePosition advance_last_processed_up_to = b->start();
7561cb0ef41Sopenharmony_ci  UseInterval* a = FirstSearchIntervalForPosition(b->start());
7571cb0ef41Sopenharmony_ci  while (a != nullptr && b != nullptr) {
7581cb0ef41Sopenharmony_ci    if (a->start() > other->End()) break;
7591cb0ef41Sopenharmony_ci    if (b->start() > End()) break;
7601cb0ef41Sopenharmony_ci    LifetimePosition cur_intersection = a->Intersect(b);
7611cb0ef41Sopenharmony_ci    if (cur_intersection.IsValid()) {
7621cb0ef41Sopenharmony_ci      return cur_intersection;
7631cb0ef41Sopenharmony_ci    }
7641cb0ef41Sopenharmony_ci    if (a->start() < b->start()) {
7651cb0ef41Sopenharmony_ci      a = a->next();
7661cb0ef41Sopenharmony_ci      if (a == nullptr || a->start() > other->End()) break;
7671cb0ef41Sopenharmony_ci      AdvanceLastProcessedMarker(a, advance_last_processed_up_to);
7681cb0ef41Sopenharmony_ci    } else {
7691cb0ef41Sopenharmony_ci      b = b->next();
7701cb0ef41Sopenharmony_ci    }
7711cb0ef41Sopenharmony_ci  }
7721cb0ef41Sopenharmony_ci  return LifetimePosition::Invalid();
7731cb0ef41Sopenharmony_ci}
7741cb0ef41Sopenharmony_ci
7751cb0ef41Sopenharmony_civoid LiveRange::Print(const RegisterConfiguration* config,
7761cb0ef41Sopenharmony_ci                      bool with_children) const {
7771cb0ef41Sopenharmony_ci  StdoutStream os;
7781cb0ef41Sopenharmony_ci  PrintableLiveRange wrapper;
7791cb0ef41Sopenharmony_ci  wrapper.register_configuration_ = config;
7801cb0ef41Sopenharmony_ci  for (const LiveRange* i = this; i != nullptr; i = i->next()) {
7811cb0ef41Sopenharmony_ci    wrapper.range_ = i;
7821cb0ef41Sopenharmony_ci    os << wrapper << std::endl;
7831cb0ef41Sopenharmony_ci    if (!with_children) break;
7841cb0ef41Sopenharmony_ci  }
7851cb0ef41Sopenharmony_ci}
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_civoid LiveRange::Print(bool with_children) const {
7881cb0ef41Sopenharmony_ci  Print(RegisterConfiguration::Default(), with_children);
7891cb0ef41Sopenharmony_ci}
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_cibool LiveRange::RegisterFromBundle(int* hint) const {
7921cb0ef41Sopenharmony_ci  if (bundle_ == nullptr || bundle_->reg() == kUnassignedRegister) return false;
7931cb0ef41Sopenharmony_ci  *hint = bundle_->reg();
7941cb0ef41Sopenharmony_ci  return true;
7951cb0ef41Sopenharmony_ci}
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_civoid LiveRange::UpdateBundleRegister(int reg) const {
7981cb0ef41Sopenharmony_ci  if (bundle_ == nullptr || bundle_->reg() != kUnassignedRegister) return;
7991cb0ef41Sopenharmony_ci  bundle_->set_reg(reg);
8001cb0ef41Sopenharmony_ci}
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_cistruct TopLevelLiveRange::SpillMoveInsertionList : ZoneObject {
8031cb0ef41Sopenharmony_ci  SpillMoveInsertionList(int gap_index, InstructionOperand* operand,
8041cb0ef41Sopenharmony_ci                         SpillMoveInsertionList* next)
8051cb0ef41Sopenharmony_ci      : gap_index(gap_index), operand(operand), next(next) {}
8061cb0ef41Sopenharmony_ci  const int gap_index;
8071cb0ef41Sopenharmony_ci  InstructionOperand* const operand;
8081cb0ef41Sopenharmony_ci  SpillMoveInsertionList* next;
8091cb0ef41Sopenharmony_ci};
8101cb0ef41Sopenharmony_ci
8111cb0ef41Sopenharmony_ciTopLevelLiveRange::TopLevelLiveRange(int vreg, MachineRepresentation rep)
8121cb0ef41Sopenharmony_ci    : LiveRange(0, rep, this),
8131cb0ef41Sopenharmony_ci      vreg_(vreg),
8141cb0ef41Sopenharmony_ci      last_child_id_(0),
8151cb0ef41Sopenharmony_ci      spill_operand_(nullptr),
8161cb0ef41Sopenharmony_ci      spill_move_insertion_locations_(nullptr),
8171cb0ef41Sopenharmony_ci      spilled_in_deferred_blocks_(false),
8181cb0ef41Sopenharmony_ci      has_preassigned_slot_(false),
8191cb0ef41Sopenharmony_ci      spill_start_index_(kMaxInt),
8201cb0ef41Sopenharmony_ci      last_pos_(nullptr),
8211cb0ef41Sopenharmony_ci      last_child_covers_(this) {
8221cb0ef41Sopenharmony_ci  bits_ |= SpillTypeField::encode(SpillType::kNoSpillType);
8231cb0ef41Sopenharmony_ci}
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_civoid TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index,
8261cb0ef41Sopenharmony_ci                                            InstructionOperand* operand) {
8271cb0ef41Sopenharmony_ci  DCHECK(HasNoSpillType());
8281cb0ef41Sopenharmony_ci  spill_move_insertion_locations_ = zone->New<SpillMoveInsertionList>(
8291cb0ef41Sopenharmony_ci      gap_index, operand, spill_move_insertion_locations_);
8301cb0ef41Sopenharmony_ci}
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_civoid TopLevelLiveRange::CommitSpillMoves(TopTierRegisterAllocationData* data,
8331cb0ef41Sopenharmony_ci                                         const InstructionOperand& op) {
8341cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(op.IsConstant(),
8351cb0ef41Sopenharmony_ci                 GetSpillMoveInsertionLocations(data) == nullptr);
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_ci  if (HasGeneralSpillRange()) {
8381cb0ef41Sopenharmony_ci    SetLateSpillingSelected(false);
8391cb0ef41Sopenharmony_ci  }
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci  InstructionSequence* sequence = data->code();
8421cb0ef41Sopenharmony_ci  Zone* zone = sequence->zone();
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ci  for (SpillMoveInsertionList* to_spill = GetSpillMoveInsertionLocations(data);
8451cb0ef41Sopenharmony_ci       to_spill != nullptr; to_spill = to_spill->next) {
8461cb0ef41Sopenharmony_ci    Instruction* instr = sequence->InstructionAt(to_spill->gap_index);
8471cb0ef41Sopenharmony_ci    ParallelMove* move =
8481cb0ef41Sopenharmony_ci        instr->GetOrCreateParallelMove(Instruction::START, zone);
8491cb0ef41Sopenharmony_ci    move->AddMove(*to_spill->operand, op);
8501cb0ef41Sopenharmony_ci    instr->block()->mark_needs_frame();
8511cb0ef41Sopenharmony_ci  }
8521cb0ef41Sopenharmony_ci}
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_civoid TopLevelLiveRange::FilterSpillMoves(TopTierRegisterAllocationData* data,
8551cb0ef41Sopenharmony_ci                                         const InstructionOperand& op) {
8561cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(op.IsConstant(),
8571cb0ef41Sopenharmony_ci                 GetSpillMoveInsertionLocations(data) == nullptr);
8581cb0ef41Sopenharmony_ci  bool might_be_duplicated = has_slot_use() || spilled();
8591cb0ef41Sopenharmony_ci  InstructionSequence* sequence = data->code();
8601cb0ef41Sopenharmony_ci
8611cb0ef41Sopenharmony_ci  SpillMoveInsertionList* previous = nullptr;
8621cb0ef41Sopenharmony_ci  for (SpillMoveInsertionList* to_spill = GetSpillMoveInsertionLocations(data);
8631cb0ef41Sopenharmony_ci       to_spill != nullptr; previous = to_spill, to_spill = to_spill->next) {
8641cb0ef41Sopenharmony_ci    Instruction* instr = sequence->InstructionAt(to_spill->gap_index);
8651cb0ef41Sopenharmony_ci    ParallelMove* move = instr->GetParallelMove(Instruction::START);
8661cb0ef41Sopenharmony_ci    // Skip insertion if it's possible that the move exists already as a
8671cb0ef41Sopenharmony_ci    // constraint move from a fixed output register to a slot.
8681cb0ef41Sopenharmony_ci    bool found = false;
8691cb0ef41Sopenharmony_ci    if (move != nullptr && (might_be_duplicated || has_preassigned_slot())) {
8701cb0ef41Sopenharmony_ci      for (MoveOperands* move_op : *move) {
8711cb0ef41Sopenharmony_ci        if (move_op->IsEliminated()) continue;
8721cb0ef41Sopenharmony_ci        if (move_op->source().Equals(*to_spill->operand) &&
8731cb0ef41Sopenharmony_ci            move_op->destination().Equals(op)) {
8741cb0ef41Sopenharmony_ci          found = true;
8751cb0ef41Sopenharmony_ci          if (has_preassigned_slot()) move_op->Eliminate();
8761cb0ef41Sopenharmony_ci          break;
8771cb0ef41Sopenharmony_ci        }
8781cb0ef41Sopenharmony_ci      }
8791cb0ef41Sopenharmony_ci    }
8801cb0ef41Sopenharmony_ci    if (found || has_preassigned_slot()) {
8811cb0ef41Sopenharmony_ci      // Remove the item from the list.
8821cb0ef41Sopenharmony_ci      if (previous == nullptr) {
8831cb0ef41Sopenharmony_ci        spill_move_insertion_locations_ = to_spill->next;
8841cb0ef41Sopenharmony_ci      } else {
8851cb0ef41Sopenharmony_ci        previous->next = to_spill->next;
8861cb0ef41Sopenharmony_ci      }
8871cb0ef41Sopenharmony_ci      // Even though this location doesn't need a spill instruction, the
8881cb0ef41Sopenharmony_ci      // block does require a frame.
8891cb0ef41Sopenharmony_ci      instr->block()->mark_needs_frame();
8901cb0ef41Sopenharmony_ci    }
8911cb0ef41Sopenharmony_ci  }
8921cb0ef41Sopenharmony_ci}
8931cb0ef41Sopenharmony_ci
8941cb0ef41Sopenharmony_civoid TopLevelLiveRange::SetSpillOperand(InstructionOperand* operand) {
8951cb0ef41Sopenharmony_ci  DCHECK(HasNoSpillType());
8961cb0ef41Sopenharmony_ci  DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
8971cb0ef41Sopenharmony_ci  set_spill_type(SpillType::kSpillOperand);
8981cb0ef41Sopenharmony_ci  spill_operand_ = operand;
8991cb0ef41Sopenharmony_ci}
9001cb0ef41Sopenharmony_ci
9011cb0ef41Sopenharmony_civoid TopLevelLiveRange::SetSpillRange(SpillRange* spill_range) {
9021cb0ef41Sopenharmony_ci  DCHECK(!HasSpillOperand());
9031cb0ef41Sopenharmony_ci  DCHECK(spill_range);
9041cb0ef41Sopenharmony_ci  spill_range_ = spill_range;
9051cb0ef41Sopenharmony_ci}
9061cb0ef41Sopenharmony_ci
9071cb0ef41Sopenharmony_ciAllocatedOperand TopLevelLiveRange::GetSpillRangeOperand() const {
9081cb0ef41Sopenharmony_ci  SpillRange* spill_range = GetSpillRange();
9091cb0ef41Sopenharmony_ci  int index = spill_range->assigned_slot();
9101cb0ef41Sopenharmony_ci  return AllocatedOperand(LocationOperand::STACK_SLOT, representation(), index);
9111cb0ef41Sopenharmony_ci}
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_civoid TopLevelLiveRange::VerifyChildrenInOrder() const {
9141cb0ef41Sopenharmony_ci  LifetimePosition last_end = End();
9151cb0ef41Sopenharmony_ci  for (const LiveRange* child = this->next(); child != nullptr;
9161cb0ef41Sopenharmony_ci       child = child->next()) {
9171cb0ef41Sopenharmony_ci    DCHECK(last_end <= child->Start());
9181cb0ef41Sopenharmony_ci    last_end = child->End();
9191cb0ef41Sopenharmony_ci  }
9201cb0ef41Sopenharmony_ci}
9211cb0ef41Sopenharmony_ci
9221cb0ef41Sopenharmony_ciLiveRange* TopLevelLiveRange::GetChildCovers(LifetimePosition pos) {
9231cb0ef41Sopenharmony_ci  LiveRange* child = last_child_covers_;
9241cb0ef41Sopenharmony_ci  DCHECK_NE(child, nullptr);
9251cb0ef41Sopenharmony_ci  if (pos < child->Start()) {
9261cb0ef41Sopenharmony_ci    // Cached value has advanced too far; start from the top.
9271cb0ef41Sopenharmony_ci    child = this;
9281cb0ef41Sopenharmony_ci  }
9291cb0ef41Sopenharmony_ci  LiveRange* previous_child = nullptr;
9301cb0ef41Sopenharmony_ci  while (child != nullptr && child->End() <= pos) {
9311cb0ef41Sopenharmony_ci    previous_child = child;
9321cb0ef41Sopenharmony_ci    child = child->next();
9331cb0ef41Sopenharmony_ci  }
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_ci  // If we've walked past the end, cache the last child instead. This allows
9361cb0ef41Sopenharmony_ci  // future calls that are also past the end to be fast, since they will know
9371cb0ef41Sopenharmony_ci  // that there is no need to reset the search to the beginning.
9381cb0ef41Sopenharmony_ci  last_child_covers_ = child == nullptr ? previous_child : child;
9391cb0ef41Sopenharmony_ci
9401cb0ef41Sopenharmony_ci  return !child || !child->Covers(pos) ? nullptr : child;
9411cb0ef41Sopenharmony_ci}
9421cb0ef41Sopenharmony_ci
9431cb0ef41Sopenharmony_civoid TopLevelLiveRange::Verify() const {
9441cb0ef41Sopenharmony_ci  VerifyChildrenInOrder();
9451cb0ef41Sopenharmony_ci  for (const LiveRange* child = this; child != nullptr; child = child->next()) {
9461cb0ef41Sopenharmony_ci    VerifyChildStructure();
9471cb0ef41Sopenharmony_ci  }
9481cb0ef41Sopenharmony_ci}
9491cb0ef41Sopenharmony_ci
9501cb0ef41Sopenharmony_civoid TopLevelLiveRange::ShortenTo(LifetimePosition start, bool trace_alloc) {
9511cb0ef41Sopenharmony_ci  TRACE_COND(trace_alloc, "Shorten live range %d to [%d\n", vreg(),
9521cb0ef41Sopenharmony_ci             start.value());
9531cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(first_interval_);
9541cb0ef41Sopenharmony_ci  DCHECK(first_interval_->start() <= start);
9551cb0ef41Sopenharmony_ci  DCHECK(start < first_interval_->end());
9561cb0ef41Sopenharmony_ci  first_interval_->set_start(start);
9571cb0ef41Sopenharmony_ci}
9581cb0ef41Sopenharmony_ci
9591cb0ef41Sopenharmony_civoid TopLevelLiveRange::EnsureInterval(LifetimePosition start,
9601cb0ef41Sopenharmony_ci                                       LifetimePosition end, Zone* zone,
9611cb0ef41Sopenharmony_ci                                       bool trace_alloc) {
9621cb0ef41Sopenharmony_ci  TRACE_COND(trace_alloc, "Ensure live range %d in interval [%d %d[\n", vreg(),
9631cb0ef41Sopenharmony_ci             start.value(), end.value());
9641cb0ef41Sopenharmony_ci  LifetimePosition new_end = end;
9651cb0ef41Sopenharmony_ci  while (first_interval_ != nullptr && first_interval_->start() <= end) {
9661cb0ef41Sopenharmony_ci    if (first_interval_->end() > end) {
9671cb0ef41Sopenharmony_ci      new_end = first_interval_->end();
9681cb0ef41Sopenharmony_ci    }
9691cb0ef41Sopenharmony_ci    first_interval_ = first_interval_->next();
9701cb0ef41Sopenharmony_ci  }
9711cb0ef41Sopenharmony_ci
9721cb0ef41Sopenharmony_ci  UseInterval* new_interval = zone->New<UseInterval>(start, new_end);
9731cb0ef41Sopenharmony_ci  new_interval->set_next(first_interval_);
9741cb0ef41Sopenharmony_ci  first_interval_ = new_interval;
9751cb0ef41Sopenharmony_ci  if (new_interval->next() == nullptr) {
9761cb0ef41Sopenharmony_ci    last_interval_ = new_interval;
9771cb0ef41Sopenharmony_ci  }
9781cb0ef41Sopenharmony_ci}
9791cb0ef41Sopenharmony_ci
9801cb0ef41Sopenharmony_civoid TopLevelLiveRange::AddUseInterval(LifetimePosition start,
9811cb0ef41Sopenharmony_ci                                       LifetimePosition end, Zone* zone,
9821cb0ef41Sopenharmony_ci                                       bool trace_alloc) {
9831cb0ef41Sopenharmony_ci  TRACE_COND(trace_alloc, "Add to live range %d interval [%d %d[\n", vreg(),
9841cb0ef41Sopenharmony_ci             start.value(), end.value());
9851cb0ef41Sopenharmony_ci  if (first_interval_ == nullptr) {
9861cb0ef41Sopenharmony_ci    UseInterval* interval = zone->New<UseInterval>(start, end);
9871cb0ef41Sopenharmony_ci    first_interval_ = interval;
9881cb0ef41Sopenharmony_ci    last_interval_ = interval;
9891cb0ef41Sopenharmony_ci  } else {
9901cb0ef41Sopenharmony_ci    if (end == first_interval_->start()) {
9911cb0ef41Sopenharmony_ci      first_interval_->set_start(start);
9921cb0ef41Sopenharmony_ci    } else if (end < first_interval_->start()) {
9931cb0ef41Sopenharmony_ci      UseInterval* interval = zone->New<UseInterval>(start, end);
9941cb0ef41Sopenharmony_ci      interval->set_next(first_interval_);
9951cb0ef41Sopenharmony_ci      first_interval_ = interval;
9961cb0ef41Sopenharmony_ci    } else {
9971cb0ef41Sopenharmony_ci      // Order of instruction's processing (see ProcessInstructions) guarantees
9981cb0ef41Sopenharmony_ci      // that each new use interval either precedes, intersects with or touches
9991cb0ef41Sopenharmony_ci      // the last added interval.
10001cb0ef41Sopenharmony_ci      DCHECK(start <= first_interval_->end());
10011cb0ef41Sopenharmony_ci      first_interval_->set_start(std::min(start, first_interval_->start()));
10021cb0ef41Sopenharmony_ci      first_interval_->set_end(std::max(end, first_interval_->end()));
10031cb0ef41Sopenharmony_ci    }
10041cb0ef41Sopenharmony_ci  }
10051cb0ef41Sopenharmony_ci}
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_civoid TopLevelLiveRange::AddUsePosition(UsePosition* use_pos, bool trace_alloc) {
10081cb0ef41Sopenharmony_ci  LifetimePosition pos = use_pos->pos();
10091cb0ef41Sopenharmony_ci  TRACE_COND(trace_alloc, "Add to live range %d use position %d\n", vreg(),
10101cb0ef41Sopenharmony_ci             pos.value());
10111cb0ef41Sopenharmony_ci  UsePosition* prev_hint = nullptr;
10121cb0ef41Sopenharmony_ci  UsePosition* prev = nullptr;
10131cb0ef41Sopenharmony_ci  UsePosition* current = first_pos_;
10141cb0ef41Sopenharmony_ci  while (current != nullptr && current->pos() < pos) {
10151cb0ef41Sopenharmony_ci    prev_hint = current->HasHint() ? current : prev_hint;
10161cb0ef41Sopenharmony_ci    prev = current;
10171cb0ef41Sopenharmony_ci    current = current->next();
10181cb0ef41Sopenharmony_ci  }
10191cb0ef41Sopenharmony_ci
10201cb0ef41Sopenharmony_ci  if (prev == nullptr) {
10211cb0ef41Sopenharmony_ci    use_pos->set_next(first_pos_);
10221cb0ef41Sopenharmony_ci    first_pos_ = use_pos;
10231cb0ef41Sopenharmony_ci  } else {
10241cb0ef41Sopenharmony_ci    use_pos->set_next(prev->next());
10251cb0ef41Sopenharmony_ci    prev->set_next(use_pos);
10261cb0ef41Sopenharmony_ci  }
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci  if (prev_hint == nullptr && use_pos->HasHint()) {
10291cb0ef41Sopenharmony_ci    current_hint_position_ = use_pos;
10301cb0ef41Sopenharmony_ci  }
10311cb0ef41Sopenharmony_ci}
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_cistatic bool AreUseIntervalsIntersecting(UseInterval* interval1,
10341cb0ef41Sopenharmony_ci                                        UseInterval* interval2) {
10351cb0ef41Sopenharmony_ci  while (interval1 != nullptr && interval2 != nullptr) {
10361cb0ef41Sopenharmony_ci    if (interval1->start() < interval2->start()) {
10371cb0ef41Sopenharmony_ci      if (interval1->end() > interval2->start()) {
10381cb0ef41Sopenharmony_ci        return true;
10391cb0ef41Sopenharmony_ci      }
10401cb0ef41Sopenharmony_ci      interval1 = interval1->next();
10411cb0ef41Sopenharmony_ci    } else {
10421cb0ef41Sopenharmony_ci      if (interval2->end() > interval1->start()) {
10431cb0ef41Sopenharmony_ci        return true;
10441cb0ef41Sopenharmony_ci      }
10451cb0ef41Sopenharmony_ci      interval2 = interval2->next();
10461cb0ef41Sopenharmony_ci    }
10471cb0ef41Sopenharmony_ci  }
10481cb0ef41Sopenharmony_ci  return false;
10491cb0ef41Sopenharmony_ci}
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os,
10521cb0ef41Sopenharmony_ci                         const PrintableLiveRange& printable_range) {
10531cb0ef41Sopenharmony_ci  const LiveRange* range = printable_range.range_;
10541cb0ef41Sopenharmony_ci  os << "Range: " << range->TopLevel()->vreg() << ":" << range->relative_id()
10551cb0ef41Sopenharmony_ci     << " ";
10561cb0ef41Sopenharmony_ci  if (range->TopLevel()->is_phi()) os << "phi ";
10571cb0ef41Sopenharmony_ci  if (range->TopLevel()->is_non_loop_phi()) os << "nlphi ";
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci  os << "{" << std::endl;
10601cb0ef41Sopenharmony_ci  UseInterval* interval = range->first_interval();
10611cb0ef41Sopenharmony_ci  UsePosition* use_pos = range->first_pos();
10621cb0ef41Sopenharmony_ci  while (use_pos != nullptr) {
10631cb0ef41Sopenharmony_ci    if (use_pos->HasOperand()) {
10641cb0ef41Sopenharmony_ci      os << *use_pos->operand() << use_pos->pos() << " ";
10651cb0ef41Sopenharmony_ci    }
10661cb0ef41Sopenharmony_ci    use_pos = use_pos->next();
10671cb0ef41Sopenharmony_ci  }
10681cb0ef41Sopenharmony_ci  os << std::endl;
10691cb0ef41Sopenharmony_ci
10701cb0ef41Sopenharmony_ci  while (interval != nullptr) {
10711cb0ef41Sopenharmony_ci    os << '[' << interval->start() << ", " << interval->end() << ')'
10721cb0ef41Sopenharmony_ci       << std::endl;
10731cb0ef41Sopenharmony_ci    interval = interval->next();
10741cb0ef41Sopenharmony_ci  }
10751cb0ef41Sopenharmony_ci  os << "}";
10761cb0ef41Sopenharmony_ci  return os;
10771cb0ef41Sopenharmony_ci}
10781cb0ef41Sopenharmony_ci
10791cb0ef41Sopenharmony_cinamespace {
10801cb0ef41Sopenharmony_civoid PrintBlockRow(std::ostream& os, const InstructionBlocks& blocks) {
10811cb0ef41Sopenharmony_ci  os << "     ";
10821cb0ef41Sopenharmony_ci  for (auto block : blocks) {
10831cb0ef41Sopenharmony_ci    LifetimePosition start_pos = LifetimePosition::GapFromInstructionIndex(
10841cb0ef41Sopenharmony_ci        block->first_instruction_index());
10851cb0ef41Sopenharmony_ci    LifetimePosition end_pos = LifetimePosition::GapFromInstructionIndex(
10861cb0ef41Sopenharmony_ci                                   block->last_instruction_index())
10871cb0ef41Sopenharmony_ci                                   .NextFullStart();
10881cb0ef41Sopenharmony_ci    int length = end_pos.value() - start_pos.value();
10891cb0ef41Sopenharmony_ci    constexpr int kMaxPrefixLength = 32;
10901cb0ef41Sopenharmony_ci    char buffer[kMaxPrefixLength];
10911cb0ef41Sopenharmony_ci    int rpo_number = block->rpo_number().ToInt();
10921cb0ef41Sopenharmony_ci    const char* deferred_marker = block->IsDeferred() ? "(deferred)" : "";
10931cb0ef41Sopenharmony_ci    int max_prefix_length = std::min(length, kMaxPrefixLength);
10941cb0ef41Sopenharmony_ci    int prefix = snprintf(buffer, max_prefix_length, "[-B%d-%s", rpo_number,
10951cb0ef41Sopenharmony_ci                          deferred_marker);
10961cb0ef41Sopenharmony_ci    os << buffer;
10971cb0ef41Sopenharmony_ci    int remaining = length - std::min(prefix, max_prefix_length) - 1;
10981cb0ef41Sopenharmony_ci    for (int i = 0; i < remaining; ++i) os << '-';
10991cb0ef41Sopenharmony_ci    os << ']';
11001cb0ef41Sopenharmony_ci  }
11011cb0ef41Sopenharmony_ci  os << '\n';
11021cb0ef41Sopenharmony_ci}
11031cb0ef41Sopenharmony_ci}  // namespace
11041cb0ef41Sopenharmony_ci
11051cb0ef41Sopenharmony_civoid LinearScanAllocator::PrintRangeRow(std::ostream& os,
11061cb0ef41Sopenharmony_ci                                        const TopLevelLiveRange* toplevel) {
11071cb0ef41Sopenharmony_ci  int position = 0;
11081cb0ef41Sopenharmony_ci  os << std::setw(3) << toplevel->vreg() << ": ";
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci  const char* kind_string;
11111cb0ef41Sopenharmony_ci  switch (toplevel->spill_type()) {
11121cb0ef41Sopenharmony_ci    case TopLevelLiveRange::SpillType::kSpillRange:
11131cb0ef41Sopenharmony_ci      kind_string = "ss";
11141cb0ef41Sopenharmony_ci      break;
11151cb0ef41Sopenharmony_ci    case TopLevelLiveRange::SpillType::kDeferredSpillRange:
11161cb0ef41Sopenharmony_ci      kind_string = "sd";
11171cb0ef41Sopenharmony_ci      break;
11181cb0ef41Sopenharmony_ci    case TopLevelLiveRange::SpillType::kSpillOperand:
11191cb0ef41Sopenharmony_ci      kind_string = "so";
11201cb0ef41Sopenharmony_ci      break;
11211cb0ef41Sopenharmony_ci    default:
11221cb0ef41Sopenharmony_ci      kind_string = "s?";
11231cb0ef41Sopenharmony_ci  }
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_ci  for (const LiveRange* range = toplevel; range != nullptr;
11261cb0ef41Sopenharmony_ci       range = range->next()) {
11271cb0ef41Sopenharmony_ci    for (UseInterval* interval = range->first_interval(); interval != nullptr;
11281cb0ef41Sopenharmony_ci         interval = interval->next()) {
11291cb0ef41Sopenharmony_ci      LifetimePosition start = interval->start();
11301cb0ef41Sopenharmony_ci      LifetimePosition end = interval->end();
11311cb0ef41Sopenharmony_ci      CHECK_GE(start.value(), position);
11321cb0ef41Sopenharmony_ci      for (; start.value() > position; position++) {
11331cb0ef41Sopenharmony_ci        os << ' ';
11341cb0ef41Sopenharmony_ci      }
11351cb0ef41Sopenharmony_ci      int length = end.value() - start.value();
11361cb0ef41Sopenharmony_ci      constexpr int kMaxPrefixLength = 32;
11371cb0ef41Sopenharmony_ci      char buffer[kMaxPrefixLength];
11381cb0ef41Sopenharmony_ci      int max_prefix_length = std::min(length + 1, kMaxPrefixLength);
11391cb0ef41Sopenharmony_ci      int prefix;
11401cb0ef41Sopenharmony_ci      if (range->spilled()) {
11411cb0ef41Sopenharmony_ci        prefix = snprintf(buffer, max_prefix_length, "|%s", kind_string);
11421cb0ef41Sopenharmony_ci      } else {
11431cb0ef41Sopenharmony_ci        prefix = snprintf(buffer, max_prefix_length, "|%s",
11441cb0ef41Sopenharmony_ci                          RegisterName(range->assigned_register()));
11451cb0ef41Sopenharmony_ci      }
11461cb0ef41Sopenharmony_ci      os << buffer;
11471cb0ef41Sopenharmony_ci      position += std::min(prefix, max_prefix_length - 1);
11481cb0ef41Sopenharmony_ci      CHECK_GE(end.value(), position);
11491cb0ef41Sopenharmony_ci      const char line_style = range->spilled() ? '-' : '=';
11501cb0ef41Sopenharmony_ci      for (; end.value() > position; position++) {
11511cb0ef41Sopenharmony_ci        os << line_style;
11521cb0ef41Sopenharmony_ci      }
11531cb0ef41Sopenharmony_ci    }
11541cb0ef41Sopenharmony_ci  }
11551cb0ef41Sopenharmony_ci  os << '\n';
11561cb0ef41Sopenharmony_ci}
11571cb0ef41Sopenharmony_ci
11581cb0ef41Sopenharmony_civoid LinearScanAllocator::PrintRangeOverview() {
11591cb0ef41Sopenharmony_ci  std::ostringstream os;
11601cb0ef41Sopenharmony_ci  PrintBlockRow(os, code()->instruction_blocks());
11611cb0ef41Sopenharmony_ci  for (auto const toplevel : data()->fixed_live_ranges()) {
11621cb0ef41Sopenharmony_ci    if (toplevel == nullptr) continue;
11631cb0ef41Sopenharmony_ci    PrintRangeRow(os, toplevel);
11641cb0ef41Sopenharmony_ci  }
11651cb0ef41Sopenharmony_ci  int rowcount = 0;
11661cb0ef41Sopenharmony_ci  for (auto toplevel : data()->live_ranges()) {
11671cb0ef41Sopenharmony_ci    if (!CanProcessRange(toplevel)) continue;
11681cb0ef41Sopenharmony_ci    if (rowcount++ % 10 == 0) PrintBlockRow(os, code()->instruction_blocks());
11691cb0ef41Sopenharmony_ci    PrintRangeRow(os, toplevel);
11701cb0ef41Sopenharmony_ci  }
11711cb0ef41Sopenharmony_ci  PrintF("%s\n", os.str().c_str());
11721cb0ef41Sopenharmony_ci}
11731cb0ef41Sopenharmony_ci
11741cb0ef41Sopenharmony_ciSpillRange::SpillRange(TopLevelLiveRange* parent, Zone* zone)
11751cb0ef41Sopenharmony_ci    : live_ranges_(zone),
11761cb0ef41Sopenharmony_ci      assigned_slot_(kUnassignedSlot),
11771cb0ef41Sopenharmony_ci      byte_width_(ByteWidthForStackSlot(parent->representation())) {
11781cb0ef41Sopenharmony_ci  // Spill ranges are created for top level. This is so that, when merging
11791cb0ef41Sopenharmony_ci  // decisions are made, we consider the full extent of the virtual register,
11801cb0ef41Sopenharmony_ci  // and avoid clobbering it.
11811cb0ef41Sopenharmony_ci  UseInterval* result = nullptr;
11821cb0ef41Sopenharmony_ci  UseInterval* node = nullptr;
11831cb0ef41Sopenharmony_ci  // Copy the intervals for all ranges.
11841cb0ef41Sopenharmony_ci  for (LiveRange* range = parent; range != nullptr; range = range->next()) {
11851cb0ef41Sopenharmony_ci    UseInterval* src = range->first_interval();
11861cb0ef41Sopenharmony_ci    while (src != nullptr) {
11871cb0ef41Sopenharmony_ci      UseInterval* new_node = zone->New<UseInterval>(src->start(), src->end());
11881cb0ef41Sopenharmony_ci      if (result == nullptr) {
11891cb0ef41Sopenharmony_ci        result = new_node;
11901cb0ef41Sopenharmony_ci      } else {
11911cb0ef41Sopenharmony_ci        node->set_next(new_node);
11921cb0ef41Sopenharmony_ci      }
11931cb0ef41Sopenharmony_ci      node = new_node;
11941cb0ef41Sopenharmony_ci      src = src->next();
11951cb0ef41Sopenharmony_ci    }
11961cb0ef41Sopenharmony_ci  }
11971cb0ef41Sopenharmony_ci  use_interval_ = result;
11981cb0ef41Sopenharmony_ci  live_ranges().push_back(parent);
11991cb0ef41Sopenharmony_ci  end_position_ = node->end();
12001cb0ef41Sopenharmony_ci  parent->SetSpillRange(this);
12011cb0ef41Sopenharmony_ci}
12021cb0ef41Sopenharmony_ci
12031cb0ef41Sopenharmony_cibool SpillRange::IsIntersectingWith(SpillRange* other) const {
12041cb0ef41Sopenharmony_ci  if (this->use_interval_ == nullptr || other->use_interval_ == nullptr ||
12051cb0ef41Sopenharmony_ci      this->End() <= other->use_interval_->start() ||
12061cb0ef41Sopenharmony_ci      other->End() <= this->use_interval_->start()) {
12071cb0ef41Sopenharmony_ci    return false;
12081cb0ef41Sopenharmony_ci  }
12091cb0ef41Sopenharmony_ci  return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
12101cb0ef41Sopenharmony_ci}
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_cibool SpillRange::TryMerge(SpillRange* other) {
12131cb0ef41Sopenharmony_ci  if (HasSlot() || other->HasSlot()) return false;
12141cb0ef41Sopenharmony_ci  if (byte_width() != other->byte_width() || IsIntersectingWith(other))
12151cb0ef41Sopenharmony_ci    return false;
12161cb0ef41Sopenharmony_ci
12171cb0ef41Sopenharmony_ci  LifetimePosition max = LifetimePosition::MaxPosition();
12181cb0ef41Sopenharmony_ci  if (End() < other->End() && other->End() != max) {
12191cb0ef41Sopenharmony_ci    end_position_ = other->End();
12201cb0ef41Sopenharmony_ci  }
12211cb0ef41Sopenharmony_ci  other->end_position_ = max;
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  MergeDisjointIntervals(other->use_interval_);
12241cb0ef41Sopenharmony_ci  other->use_interval_ = nullptr;
12251cb0ef41Sopenharmony_ci
12261cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* range : other->live_ranges()) {
12271cb0ef41Sopenharmony_ci    DCHECK(range->GetSpillRange() == other);
12281cb0ef41Sopenharmony_ci    range->SetSpillRange(this);
12291cb0ef41Sopenharmony_ci  }
12301cb0ef41Sopenharmony_ci
12311cb0ef41Sopenharmony_ci  live_ranges().insert(live_ranges().end(), other->live_ranges().begin(),
12321cb0ef41Sopenharmony_ci                       other->live_ranges().end());
12331cb0ef41Sopenharmony_ci  other->live_ranges().clear();
12341cb0ef41Sopenharmony_ci
12351cb0ef41Sopenharmony_ci  return true;
12361cb0ef41Sopenharmony_ci}
12371cb0ef41Sopenharmony_ci
12381cb0ef41Sopenharmony_civoid SpillRange::MergeDisjointIntervals(UseInterval* other) {
12391cb0ef41Sopenharmony_ci  UseInterval* tail = nullptr;
12401cb0ef41Sopenharmony_ci  UseInterval* current = use_interval_;
12411cb0ef41Sopenharmony_ci  while (other != nullptr) {
12421cb0ef41Sopenharmony_ci    // Make sure the 'current' list starts first
12431cb0ef41Sopenharmony_ci    if (current == nullptr || current->start() > other->start()) {
12441cb0ef41Sopenharmony_ci      std::swap(current, other);
12451cb0ef41Sopenharmony_ci    }
12461cb0ef41Sopenharmony_ci    // Check disjointness
12471cb0ef41Sopenharmony_ci    DCHECK(other == nullptr || current->end() <= other->start());
12481cb0ef41Sopenharmony_ci    // Append the 'current' node to the result accumulator and move forward
12491cb0ef41Sopenharmony_ci    if (tail == nullptr) {
12501cb0ef41Sopenharmony_ci      use_interval_ = current;
12511cb0ef41Sopenharmony_ci    } else {
12521cb0ef41Sopenharmony_ci      tail->set_next(current);
12531cb0ef41Sopenharmony_ci    }
12541cb0ef41Sopenharmony_ci    tail = current;
12551cb0ef41Sopenharmony_ci    current = current->next();
12561cb0ef41Sopenharmony_ci  }
12571cb0ef41Sopenharmony_ci  // Other list is empty => we are done
12581cb0ef41Sopenharmony_ci}
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_civoid SpillRange::Print() const {
12611cb0ef41Sopenharmony_ci  StdoutStream os;
12621cb0ef41Sopenharmony_ci  os << "{" << std::endl;
12631cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* range : live_ranges()) {
12641cb0ef41Sopenharmony_ci    os << range->vreg() << " ";
12651cb0ef41Sopenharmony_ci  }
12661cb0ef41Sopenharmony_ci  os << std::endl;
12671cb0ef41Sopenharmony_ci
12681cb0ef41Sopenharmony_ci  for (UseInterval* i = interval(); i != nullptr; i = i->next()) {
12691cb0ef41Sopenharmony_ci    os << '[' << i->start() << ", " << i->end() << ')' << std::endl;
12701cb0ef41Sopenharmony_ci  }
12711cb0ef41Sopenharmony_ci  os << "}" << std::endl;
12721cb0ef41Sopenharmony_ci}
12731cb0ef41Sopenharmony_ci
12741cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::PhiMapValue::PhiMapValue(
12751cb0ef41Sopenharmony_ci    PhiInstruction* phi, const InstructionBlock* block, Zone* zone)
12761cb0ef41Sopenharmony_ci    : phi_(phi),
12771cb0ef41Sopenharmony_ci      block_(block),
12781cb0ef41Sopenharmony_ci      incoming_operands_(zone),
12791cb0ef41Sopenharmony_ci      assigned_register_(kUnassignedRegister) {
12801cb0ef41Sopenharmony_ci  incoming_operands_.reserve(phi->operands().size());
12811cb0ef41Sopenharmony_ci}
12821cb0ef41Sopenharmony_ci
12831cb0ef41Sopenharmony_civoid TopTierRegisterAllocationData::PhiMapValue::AddOperand(
12841cb0ef41Sopenharmony_ci    InstructionOperand* operand) {
12851cb0ef41Sopenharmony_ci  incoming_operands_.push_back(operand);
12861cb0ef41Sopenharmony_ci}
12871cb0ef41Sopenharmony_ci
12881cb0ef41Sopenharmony_civoid TopTierRegisterAllocationData::PhiMapValue::CommitAssignment(
12891cb0ef41Sopenharmony_ci    const InstructionOperand& assigned) {
12901cb0ef41Sopenharmony_ci  for (InstructionOperand* operand : incoming_operands_) {
12911cb0ef41Sopenharmony_ci    InstructionOperand::ReplaceWith(operand, &assigned);
12921cb0ef41Sopenharmony_ci  }
12931cb0ef41Sopenharmony_ci}
12941cb0ef41Sopenharmony_ci
12951cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::TopTierRegisterAllocationData(
12961cb0ef41Sopenharmony_ci    const RegisterConfiguration* config, Zone* zone, Frame* frame,
12971cb0ef41Sopenharmony_ci    InstructionSequence* code, RegisterAllocationFlags flags,
12981cb0ef41Sopenharmony_ci    TickCounter* tick_counter, const char* debug_name)
12991cb0ef41Sopenharmony_ci    : RegisterAllocationData(Type::kTopTier),
13001cb0ef41Sopenharmony_ci      allocation_zone_(zone),
13011cb0ef41Sopenharmony_ci      frame_(frame),
13021cb0ef41Sopenharmony_ci      code_(code),
13031cb0ef41Sopenharmony_ci      debug_name_(debug_name),
13041cb0ef41Sopenharmony_ci      config_(config),
13051cb0ef41Sopenharmony_ci      phi_map_(allocation_zone()),
13061cb0ef41Sopenharmony_ci      live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
13071cb0ef41Sopenharmony_ci      live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
13081cb0ef41Sopenharmony_ci      live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
13091cb0ef41Sopenharmony_ci                   allocation_zone()),
13101cb0ef41Sopenharmony_ci      fixed_live_ranges_(kNumberOfFixedRangesPerRegister *
13111cb0ef41Sopenharmony_ci                             this->config()->num_general_registers(),
13121cb0ef41Sopenharmony_ci                         nullptr, allocation_zone()),
13131cb0ef41Sopenharmony_ci      fixed_float_live_ranges_(allocation_zone()),
13141cb0ef41Sopenharmony_ci      fixed_double_live_ranges_(kNumberOfFixedRangesPerRegister *
13151cb0ef41Sopenharmony_ci                                    this->config()->num_double_registers(),
13161cb0ef41Sopenharmony_ci                                nullptr, allocation_zone()),
13171cb0ef41Sopenharmony_ci      fixed_simd128_live_ranges_(allocation_zone()),
13181cb0ef41Sopenharmony_ci      spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()),
13191cb0ef41Sopenharmony_ci      delayed_references_(allocation_zone()),
13201cb0ef41Sopenharmony_ci      assigned_registers_(nullptr),
13211cb0ef41Sopenharmony_ci      assigned_double_registers_(nullptr),
13221cb0ef41Sopenharmony_ci      virtual_register_count_(code->VirtualRegisterCount()),
13231cb0ef41Sopenharmony_ci      preassigned_slot_ranges_(zone),
13241cb0ef41Sopenharmony_ci      spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone),
13251cb0ef41Sopenharmony_ci                   zone),
13261cb0ef41Sopenharmony_ci      flags_(flags),
13271cb0ef41Sopenharmony_ci      tick_counter_(tick_counter),
13281cb0ef41Sopenharmony_ci      slot_for_const_range_(zone) {
13291cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kCombine) {
13301cb0ef41Sopenharmony_ci    fixed_float_live_ranges_.resize(
13311cb0ef41Sopenharmony_ci        kNumberOfFixedRangesPerRegister * this->config()->num_float_registers(),
13321cb0ef41Sopenharmony_ci        nullptr);
13331cb0ef41Sopenharmony_ci    fixed_simd128_live_ranges_.resize(
13341cb0ef41Sopenharmony_ci        kNumberOfFixedRangesPerRegister *
13351cb0ef41Sopenharmony_ci            this->config()->num_simd128_registers(),
13361cb0ef41Sopenharmony_ci        nullptr);
13371cb0ef41Sopenharmony_ci  } else if (kFPAliasing == AliasingKind::kIndependent) {
13381cb0ef41Sopenharmony_ci    fixed_simd128_live_ranges_.resize(
13391cb0ef41Sopenharmony_ci        kNumberOfFixedRangesPerRegister *
13401cb0ef41Sopenharmony_ci            this->config()->num_simd128_registers(),
13411cb0ef41Sopenharmony_ci        nullptr);
13421cb0ef41Sopenharmony_ci  }
13431cb0ef41Sopenharmony_ci
13441cb0ef41Sopenharmony_ci  assigned_registers_ = code_zone()->New<BitVector>(
13451cb0ef41Sopenharmony_ci      this->config()->num_general_registers(), code_zone());
13461cb0ef41Sopenharmony_ci  assigned_double_registers_ = code_zone()->New<BitVector>(
13471cb0ef41Sopenharmony_ci      this->config()->num_double_registers(), code_zone());
13481cb0ef41Sopenharmony_ci  fixed_register_use_ = code_zone()->New<BitVector>(
13491cb0ef41Sopenharmony_ci      this->config()->num_general_registers(), code_zone());
13501cb0ef41Sopenharmony_ci  fixed_fp_register_use_ = code_zone()->New<BitVector>(
13511cb0ef41Sopenharmony_ci      this->config()->num_double_registers(), code_zone());
13521cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kIndependent) {
13531cb0ef41Sopenharmony_ci    assigned_simd128_registers_ = code_zone()->New<BitVector>(
13541cb0ef41Sopenharmony_ci        this->config()->num_simd128_registers(), code_zone());
13551cb0ef41Sopenharmony_ci    fixed_simd128_register_use_ = code_zone()->New<BitVector>(
13561cb0ef41Sopenharmony_ci        this->config()->num_simd128_registers(), code_zone());
13571cb0ef41Sopenharmony_ci  }
13581cb0ef41Sopenharmony_ci
13591cb0ef41Sopenharmony_ci  this->frame()->SetAllocatedRegisters(assigned_registers_);
13601cb0ef41Sopenharmony_ci  this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
13611cb0ef41Sopenharmony_ci}
13621cb0ef41Sopenharmony_ci
13631cb0ef41Sopenharmony_ciMoveOperands* TopTierRegisterAllocationData::AddGapMove(
13641cb0ef41Sopenharmony_ci    int index, Instruction::GapPosition position,
13651cb0ef41Sopenharmony_ci    const InstructionOperand& from, const InstructionOperand& to) {
13661cb0ef41Sopenharmony_ci  Instruction* instr = code()->InstructionAt(index);
13671cb0ef41Sopenharmony_ci  ParallelMove* moves = instr->GetOrCreateParallelMove(position, code_zone());
13681cb0ef41Sopenharmony_ci  return moves->AddMove(from, to);
13691cb0ef41Sopenharmony_ci}
13701cb0ef41Sopenharmony_ci
13711cb0ef41Sopenharmony_ciMachineRepresentation TopTierRegisterAllocationData::RepresentationFor(
13721cb0ef41Sopenharmony_ci    int virtual_register) {
13731cb0ef41Sopenharmony_ci  DCHECK_LT(virtual_register, code()->VirtualRegisterCount());
13741cb0ef41Sopenharmony_ci  return code()->GetRepresentation(virtual_register);
13751cb0ef41Sopenharmony_ci}
13761cb0ef41Sopenharmony_ci
13771cb0ef41Sopenharmony_ciTopLevelLiveRange* TopTierRegisterAllocationData::GetOrCreateLiveRangeFor(
13781cb0ef41Sopenharmony_ci    int index) {
13791cb0ef41Sopenharmony_ci  if (index >= static_cast<int>(live_ranges().size())) {
13801cb0ef41Sopenharmony_ci    live_ranges().resize(index + 1, nullptr);
13811cb0ef41Sopenharmony_ci  }
13821cb0ef41Sopenharmony_ci  TopLevelLiveRange* result = live_ranges()[index];
13831cb0ef41Sopenharmony_ci  if (result == nullptr) {
13841cb0ef41Sopenharmony_ci    result = NewLiveRange(index, RepresentationFor(index));
13851cb0ef41Sopenharmony_ci    live_ranges()[index] = result;
13861cb0ef41Sopenharmony_ci  }
13871cb0ef41Sopenharmony_ci  DCHECK_EQ(live_ranges()[index]->vreg(), index);
13881cb0ef41Sopenharmony_ci  return result;
13891cb0ef41Sopenharmony_ci}
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_ciTopLevelLiveRange* TopTierRegisterAllocationData::NewLiveRange(
13921cb0ef41Sopenharmony_ci    int index, MachineRepresentation rep) {
13931cb0ef41Sopenharmony_ci  return allocation_zone()->New<TopLevelLiveRange>(index, rep);
13941cb0ef41Sopenharmony_ci}
13951cb0ef41Sopenharmony_ci
13961cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::PhiMapValue*
13971cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::InitializePhiMap(const InstructionBlock* block,
13981cb0ef41Sopenharmony_ci                                                PhiInstruction* phi) {
13991cb0ef41Sopenharmony_ci  TopTierRegisterAllocationData::PhiMapValue* map_value =
14001cb0ef41Sopenharmony_ci      allocation_zone()->New<TopTierRegisterAllocationData::PhiMapValue>(
14011cb0ef41Sopenharmony_ci          phi, block, allocation_zone());
14021cb0ef41Sopenharmony_ci  auto res =
14031cb0ef41Sopenharmony_ci      phi_map_.insert(std::make_pair(phi->virtual_register(), map_value));
14041cb0ef41Sopenharmony_ci  DCHECK(res.second);
14051cb0ef41Sopenharmony_ci  USE(res);
14061cb0ef41Sopenharmony_ci  return map_value;
14071cb0ef41Sopenharmony_ci}
14081cb0ef41Sopenharmony_ci
14091cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::PhiMapValue*
14101cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::GetPhiMapValueFor(int virtual_register) {
14111cb0ef41Sopenharmony_ci  auto it = phi_map_.find(virtual_register);
14121cb0ef41Sopenharmony_ci  DCHECK(it != phi_map_.end());
14131cb0ef41Sopenharmony_ci  return it->second;
14141cb0ef41Sopenharmony_ci}
14151cb0ef41Sopenharmony_ci
14161cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::PhiMapValue*
14171cb0ef41Sopenharmony_ciTopTierRegisterAllocationData::GetPhiMapValueFor(TopLevelLiveRange* top_range) {
14181cb0ef41Sopenharmony_ci  return GetPhiMapValueFor(top_range->vreg());
14191cb0ef41Sopenharmony_ci}
14201cb0ef41Sopenharmony_ci
14211cb0ef41Sopenharmony_cibool TopTierRegisterAllocationData::ExistsUseWithoutDefinition() {
14221cb0ef41Sopenharmony_ci  bool found = false;
14231cb0ef41Sopenharmony_ci  for (int operand_index : *live_in_sets()[0]) {
14241cb0ef41Sopenharmony_ci    found = true;
14251cb0ef41Sopenharmony_ci    PrintF("Register allocator error: live v%d reached first block.\n",
14261cb0ef41Sopenharmony_ci           operand_index);
14271cb0ef41Sopenharmony_ci    LiveRange* range = GetOrCreateLiveRangeFor(operand_index);
14281cb0ef41Sopenharmony_ci    PrintF("  (first use is at %d)\n", range->first_pos()->pos().value());
14291cb0ef41Sopenharmony_ci    if (debug_name() == nullptr) {
14301cb0ef41Sopenharmony_ci      PrintF("\n");
14311cb0ef41Sopenharmony_ci    } else {
14321cb0ef41Sopenharmony_ci      PrintF("  (function: %s)\n", debug_name());
14331cb0ef41Sopenharmony_ci    }
14341cb0ef41Sopenharmony_ci  }
14351cb0ef41Sopenharmony_ci  return found;
14361cb0ef41Sopenharmony_ci}
14371cb0ef41Sopenharmony_ci
14381cb0ef41Sopenharmony_ci// If a range is defined in a deferred block, we can expect all the range
14391cb0ef41Sopenharmony_ci// to only cover positions in deferred blocks. Otherwise, a block on the
14401cb0ef41Sopenharmony_ci// hot path would be dominated by a deferred block, meaning it is unreachable
14411cb0ef41Sopenharmony_ci// without passing through the deferred block, which is contradictory.
14421cb0ef41Sopenharmony_ci// In particular, when such a range contributes a result back on the hot
14431cb0ef41Sopenharmony_ci// path, it will be as one of the inputs of a phi. In that case, the value
14441cb0ef41Sopenharmony_ci// will be transferred via a move in the Gap::END's of the last instruction
14451cb0ef41Sopenharmony_ci// of a deferred block.
14461cb0ef41Sopenharmony_cibool TopTierRegisterAllocationData::RangesDefinedInDeferredStayInDeferred() {
14471cb0ef41Sopenharmony_ci  const size_t live_ranges_size = live_ranges().size();
14481cb0ef41Sopenharmony_ci  for (const TopLevelLiveRange* range : live_ranges()) {
14491cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
14501cb0ef41Sopenharmony_ci             live_ranges().size());  // TODO(neis): crbug.com/831822
14511cb0ef41Sopenharmony_ci    if (range == nullptr || range->IsEmpty() ||
14521cb0ef41Sopenharmony_ci        !code()
14531cb0ef41Sopenharmony_ci             ->GetInstructionBlock(range->Start().ToInstructionIndex())
14541cb0ef41Sopenharmony_ci             ->IsDeferred()) {
14551cb0ef41Sopenharmony_ci      continue;
14561cb0ef41Sopenharmony_ci    }
14571cb0ef41Sopenharmony_ci    for (const UseInterval* i = range->first_interval(); i != nullptr;
14581cb0ef41Sopenharmony_ci         i = i->next()) {
14591cb0ef41Sopenharmony_ci      int first = i->FirstGapIndex();
14601cb0ef41Sopenharmony_ci      int last = i->LastGapIndex();
14611cb0ef41Sopenharmony_ci      for (int instr = first; instr <= last;) {
14621cb0ef41Sopenharmony_ci        const InstructionBlock* block = code()->GetInstructionBlock(instr);
14631cb0ef41Sopenharmony_ci        if (!block->IsDeferred()) return false;
14641cb0ef41Sopenharmony_ci        instr = block->last_instruction_index() + 1;
14651cb0ef41Sopenharmony_ci      }
14661cb0ef41Sopenharmony_ci    }
14671cb0ef41Sopenharmony_ci  }
14681cb0ef41Sopenharmony_ci  return true;
14691cb0ef41Sopenharmony_ci}
14701cb0ef41Sopenharmony_ci
14711cb0ef41Sopenharmony_ciSpillRange* TopTierRegisterAllocationData::AssignSpillRangeToLiveRange(
14721cb0ef41Sopenharmony_ci    TopLevelLiveRange* range, SpillMode spill_mode) {
14731cb0ef41Sopenharmony_ci  using SpillType = TopLevelLiveRange::SpillType;
14741cb0ef41Sopenharmony_ci  DCHECK(!range->HasSpillOperand());
14751cb0ef41Sopenharmony_ci
14761cb0ef41Sopenharmony_ci  SpillRange* spill_range = range->GetAllocatedSpillRange();
14771cb0ef41Sopenharmony_ci  if (spill_range == nullptr) {
14781cb0ef41Sopenharmony_ci    spill_range = allocation_zone()->New<SpillRange>(range, allocation_zone());
14791cb0ef41Sopenharmony_ci  }
14801cb0ef41Sopenharmony_ci  if (spill_mode == SpillMode::kSpillDeferred &&
14811cb0ef41Sopenharmony_ci      (range->spill_type() != SpillType::kSpillRange)) {
14821cb0ef41Sopenharmony_ci    range->set_spill_type(SpillType::kDeferredSpillRange);
14831cb0ef41Sopenharmony_ci  } else {
14841cb0ef41Sopenharmony_ci    range->set_spill_type(SpillType::kSpillRange);
14851cb0ef41Sopenharmony_ci  }
14861cb0ef41Sopenharmony_ci
14871cb0ef41Sopenharmony_ci  spill_ranges()[range->vreg()] = spill_range;
14881cb0ef41Sopenharmony_ci  return spill_range;
14891cb0ef41Sopenharmony_ci}
14901cb0ef41Sopenharmony_ci
14911cb0ef41Sopenharmony_civoid TopTierRegisterAllocationData::MarkFixedUse(MachineRepresentation rep,
14921cb0ef41Sopenharmony_ci                                                 int index) {
14931cb0ef41Sopenharmony_ci  switch (rep) {
14941cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
14951cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128:
14961cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kOverlap) {
14971cb0ef41Sopenharmony_ci        fixed_fp_register_use_->Add(index);
14981cb0ef41Sopenharmony_ci      } else if (kFPAliasing == AliasingKind::kIndependent) {
14991cb0ef41Sopenharmony_ci        if (rep == MachineRepresentation::kFloat32) {
15001cb0ef41Sopenharmony_ci          fixed_fp_register_use_->Add(index);
15011cb0ef41Sopenharmony_ci        } else {
15021cb0ef41Sopenharmony_ci          fixed_simd128_register_use_->Add(index);
15031cb0ef41Sopenharmony_ci        }
15041cb0ef41Sopenharmony_ci      } else {
15051cb0ef41Sopenharmony_ci        int alias_base_index = -1;
15061cb0ef41Sopenharmony_ci        int aliases = config()->GetAliases(
15071cb0ef41Sopenharmony_ci            rep, index, MachineRepresentation::kFloat64, &alias_base_index);
15081cb0ef41Sopenharmony_ci        DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
15091cb0ef41Sopenharmony_ci        while (aliases--) {
15101cb0ef41Sopenharmony_ci          int aliased_reg = alias_base_index + aliases;
15111cb0ef41Sopenharmony_ci          fixed_fp_register_use_->Add(aliased_reg);
15121cb0ef41Sopenharmony_ci        }
15131cb0ef41Sopenharmony_ci      }
15141cb0ef41Sopenharmony_ci      break;
15151cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
15161cb0ef41Sopenharmony_ci      fixed_fp_register_use_->Add(index);
15171cb0ef41Sopenharmony_ci      break;
15181cb0ef41Sopenharmony_ci    default:
15191cb0ef41Sopenharmony_ci      DCHECK(!IsFloatingPoint(rep));
15201cb0ef41Sopenharmony_ci      fixed_register_use_->Add(index);
15211cb0ef41Sopenharmony_ci      break;
15221cb0ef41Sopenharmony_ci  }
15231cb0ef41Sopenharmony_ci}
15241cb0ef41Sopenharmony_ci
15251cb0ef41Sopenharmony_cibool TopTierRegisterAllocationData::HasFixedUse(MachineRepresentation rep,
15261cb0ef41Sopenharmony_ci                                                int index) {
15271cb0ef41Sopenharmony_ci  switch (rep) {
15281cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
15291cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128: {
15301cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kOverlap) {
15311cb0ef41Sopenharmony_ci        return fixed_fp_register_use_->Contains(index);
15321cb0ef41Sopenharmony_ci      } else if (kFPAliasing == AliasingKind::kIndependent) {
15331cb0ef41Sopenharmony_ci        if (rep == MachineRepresentation::kFloat32) {
15341cb0ef41Sopenharmony_ci          return fixed_fp_register_use_->Contains(index);
15351cb0ef41Sopenharmony_ci        } else {
15361cb0ef41Sopenharmony_ci          return fixed_simd128_register_use_->Contains(index);
15371cb0ef41Sopenharmony_ci        }
15381cb0ef41Sopenharmony_ci      } else {
15391cb0ef41Sopenharmony_ci        int alias_base_index = -1;
15401cb0ef41Sopenharmony_ci        int aliases = config()->GetAliases(
15411cb0ef41Sopenharmony_ci            rep, index, MachineRepresentation::kFloat64, &alias_base_index);
15421cb0ef41Sopenharmony_ci        DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
15431cb0ef41Sopenharmony_ci        bool result = false;
15441cb0ef41Sopenharmony_ci        while (aliases-- && !result) {
15451cb0ef41Sopenharmony_ci          int aliased_reg = alias_base_index + aliases;
15461cb0ef41Sopenharmony_ci          result |= fixed_fp_register_use_->Contains(aliased_reg);
15471cb0ef41Sopenharmony_ci        }
15481cb0ef41Sopenharmony_ci        return result;
15491cb0ef41Sopenharmony_ci      }
15501cb0ef41Sopenharmony_ci    }
15511cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
15521cb0ef41Sopenharmony_ci      return fixed_fp_register_use_->Contains(index);
15531cb0ef41Sopenharmony_ci    default:
15541cb0ef41Sopenharmony_ci      DCHECK(!IsFloatingPoint(rep));
15551cb0ef41Sopenharmony_ci      return fixed_register_use_->Contains(index);
15561cb0ef41Sopenharmony_ci  }
15571cb0ef41Sopenharmony_ci}
15581cb0ef41Sopenharmony_ci
15591cb0ef41Sopenharmony_civoid TopTierRegisterAllocationData::MarkAllocated(MachineRepresentation rep,
15601cb0ef41Sopenharmony_ci                                                  int index) {
15611cb0ef41Sopenharmony_ci  switch (rep) {
15621cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
15631cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128:
15641cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kOverlap) {
15651cb0ef41Sopenharmony_ci        assigned_double_registers_->Add(index);
15661cb0ef41Sopenharmony_ci      } else if (kFPAliasing == AliasingKind::kIndependent) {
15671cb0ef41Sopenharmony_ci        if (rep == MachineRepresentation::kFloat32) {
15681cb0ef41Sopenharmony_ci          assigned_double_registers_->Add(index);
15691cb0ef41Sopenharmony_ci        } else {
15701cb0ef41Sopenharmony_ci          assigned_simd128_registers_->Add(index);
15711cb0ef41Sopenharmony_ci        }
15721cb0ef41Sopenharmony_ci      } else {
15731cb0ef41Sopenharmony_ci        int alias_base_index = -1;
15741cb0ef41Sopenharmony_ci        int aliases = config()->GetAliases(
15751cb0ef41Sopenharmony_ci            rep, index, MachineRepresentation::kFloat64, &alias_base_index);
15761cb0ef41Sopenharmony_ci        DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
15771cb0ef41Sopenharmony_ci        while (aliases--) {
15781cb0ef41Sopenharmony_ci          int aliased_reg = alias_base_index + aliases;
15791cb0ef41Sopenharmony_ci          assigned_double_registers_->Add(aliased_reg);
15801cb0ef41Sopenharmony_ci        }
15811cb0ef41Sopenharmony_ci      }
15821cb0ef41Sopenharmony_ci      break;
15831cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
15841cb0ef41Sopenharmony_ci      assigned_double_registers_->Add(index);
15851cb0ef41Sopenharmony_ci      break;
15861cb0ef41Sopenharmony_ci    default:
15871cb0ef41Sopenharmony_ci      DCHECK(!IsFloatingPoint(rep));
15881cb0ef41Sopenharmony_ci      assigned_registers_->Add(index);
15891cb0ef41Sopenharmony_ci      break;
15901cb0ef41Sopenharmony_ci  }
15911cb0ef41Sopenharmony_ci}
15921cb0ef41Sopenharmony_ci
15931cb0ef41Sopenharmony_cibool TopTierRegisterAllocationData::IsBlockBoundary(
15941cb0ef41Sopenharmony_ci    LifetimePosition pos) const {
15951cb0ef41Sopenharmony_ci  return pos.IsFullStart() &&
15961cb0ef41Sopenharmony_ci         (static_cast<size_t>(pos.ToInstructionIndex()) ==
15971cb0ef41Sopenharmony_ci              code()->instructions().size() ||
15981cb0ef41Sopenharmony_ci          code()->GetInstructionBlock(pos.ToInstructionIndex())->code_start() ==
15991cb0ef41Sopenharmony_ci              pos.ToInstructionIndex());
16001cb0ef41Sopenharmony_ci}
16011cb0ef41Sopenharmony_ci
16021cb0ef41Sopenharmony_ciConstraintBuilder::ConstraintBuilder(TopTierRegisterAllocationData* data)
16031cb0ef41Sopenharmony_ci    : data_(data) {}
16041cb0ef41Sopenharmony_ci
16051cb0ef41Sopenharmony_ciInstructionOperand* ConstraintBuilder::AllocateFixed(
16061cb0ef41Sopenharmony_ci    UnallocatedOperand* operand, int pos, bool is_tagged, bool is_input) {
16071cb0ef41Sopenharmony_ci  TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
16081cb0ef41Sopenharmony_ci  DCHECK(operand->HasFixedPolicy());
16091cb0ef41Sopenharmony_ci  InstructionOperand allocated;
16101cb0ef41Sopenharmony_ci  MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
16111cb0ef41Sopenharmony_ci  int virtual_register = operand->virtual_register();
16121cb0ef41Sopenharmony_ci  if (virtual_register != InstructionOperand::kInvalidVirtualRegister) {
16131cb0ef41Sopenharmony_ci    rep = data()->RepresentationFor(virtual_register);
16141cb0ef41Sopenharmony_ci  }
16151cb0ef41Sopenharmony_ci  if (operand->HasFixedSlotPolicy()) {
16161cb0ef41Sopenharmony_ci    allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, rep,
16171cb0ef41Sopenharmony_ci                                 operand->fixed_slot_index());
16181cb0ef41Sopenharmony_ci  } else if (operand->HasFixedRegisterPolicy()) {
16191cb0ef41Sopenharmony_ci    DCHECK(!IsFloatingPoint(rep));
16201cb0ef41Sopenharmony_ci    DCHECK(data()->config()->IsAllocatableGeneralCode(
16211cb0ef41Sopenharmony_ci        operand->fixed_register_index()));
16221cb0ef41Sopenharmony_ci    allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep,
16231cb0ef41Sopenharmony_ci                                 operand->fixed_register_index());
16241cb0ef41Sopenharmony_ci  } else if (operand->HasFixedFPRegisterPolicy()) {
16251cb0ef41Sopenharmony_ci    DCHECK(IsFloatingPoint(rep));
16261cb0ef41Sopenharmony_ci    DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register);
16271cb0ef41Sopenharmony_ci    allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep,
16281cb0ef41Sopenharmony_ci                                 operand->fixed_register_index());
16291cb0ef41Sopenharmony_ci  } else {
16301cb0ef41Sopenharmony_ci    UNREACHABLE();
16311cb0ef41Sopenharmony_ci  }
16321cb0ef41Sopenharmony_ci  if (is_input && allocated.IsAnyRegister()) {
16331cb0ef41Sopenharmony_ci    data()->MarkFixedUse(rep, operand->fixed_register_index());
16341cb0ef41Sopenharmony_ci  }
16351cb0ef41Sopenharmony_ci  InstructionOperand::ReplaceWith(operand, &allocated);
16361cb0ef41Sopenharmony_ci  if (is_tagged) {
16371cb0ef41Sopenharmony_ci    TRACE("Fixed reg is tagged at %d\n", pos);
16381cb0ef41Sopenharmony_ci    Instruction* instr = code()->InstructionAt(pos);
16391cb0ef41Sopenharmony_ci    if (instr->HasReferenceMap()) {
16401cb0ef41Sopenharmony_ci      instr->reference_map()->RecordReference(*AllocatedOperand::cast(operand));
16411cb0ef41Sopenharmony_ci    }
16421cb0ef41Sopenharmony_ci  }
16431cb0ef41Sopenharmony_ci  return operand;
16441cb0ef41Sopenharmony_ci}
16451cb0ef41Sopenharmony_ci
16461cb0ef41Sopenharmony_civoid ConstraintBuilder::MeetRegisterConstraints() {
16471cb0ef41Sopenharmony_ci  for (InstructionBlock* block : code()->instruction_blocks()) {
16481cb0ef41Sopenharmony_ci    data_->tick_counter()->TickAndMaybeEnterSafepoint();
16491cb0ef41Sopenharmony_ci    MeetRegisterConstraints(block);
16501cb0ef41Sopenharmony_ci  }
16511cb0ef41Sopenharmony_ci}
16521cb0ef41Sopenharmony_ci
16531cb0ef41Sopenharmony_civoid ConstraintBuilder::MeetRegisterConstraints(const InstructionBlock* block) {
16541cb0ef41Sopenharmony_ci  int start = block->first_instruction_index();
16551cb0ef41Sopenharmony_ci  int end = block->last_instruction_index();
16561cb0ef41Sopenharmony_ci  DCHECK_NE(-1, start);
16571cb0ef41Sopenharmony_ci  for (int i = start; i <= end; ++i) {
16581cb0ef41Sopenharmony_ci    MeetConstraintsBefore(i);
16591cb0ef41Sopenharmony_ci    if (i != end) MeetConstraintsAfter(i);
16601cb0ef41Sopenharmony_ci  }
16611cb0ef41Sopenharmony_ci  // Meet register constraints for the instruction in the end.
16621cb0ef41Sopenharmony_ci  MeetRegisterConstraintsForLastInstructionInBlock(block);
16631cb0ef41Sopenharmony_ci}
16641cb0ef41Sopenharmony_ci
16651cb0ef41Sopenharmony_civoid ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
16661cb0ef41Sopenharmony_ci    const InstructionBlock* block) {
16671cb0ef41Sopenharmony_ci  int end = block->last_instruction_index();
16681cb0ef41Sopenharmony_ci  Instruction* last_instruction = code()->InstructionAt(end);
16691cb0ef41Sopenharmony_ci  for (size_t i = 0; i < last_instruction->OutputCount(); i++) {
16701cb0ef41Sopenharmony_ci    InstructionOperand* output_operand = last_instruction->OutputAt(i);
16711cb0ef41Sopenharmony_ci    DCHECK(!output_operand->IsConstant());
16721cb0ef41Sopenharmony_ci    UnallocatedOperand* output = UnallocatedOperand::cast(output_operand);
16731cb0ef41Sopenharmony_ci    int output_vreg = output->virtual_register();
16741cb0ef41Sopenharmony_ci    TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg);
16751cb0ef41Sopenharmony_ci    bool assigned = false;
16761cb0ef41Sopenharmony_ci    if (output->HasFixedPolicy()) {
16771cb0ef41Sopenharmony_ci      AllocateFixed(output, -1, false, false);
16781cb0ef41Sopenharmony_ci      // This value is produced on the stack, we never need to spill it.
16791cb0ef41Sopenharmony_ci      if (output->IsStackSlot()) {
16801cb0ef41Sopenharmony_ci        DCHECK(LocationOperand::cast(output)->index() <
16811cb0ef41Sopenharmony_ci               data()->frame()->GetSpillSlotCount());
16821cb0ef41Sopenharmony_ci        range->SetSpillOperand(LocationOperand::cast(output));
16831cb0ef41Sopenharmony_ci        range->SetSpillStartIndex(end);
16841cb0ef41Sopenharmony_ci        assigned = true;
16851cb0ef41Sopenharmony_ci      }
16861cb0ef41Sopenharmony_ci
16871cb0ef41Sopenharmony_ci      for (const RpoNumber& succ : block->successors()) {
16881cb0ef41Sopenharmony_ci        const InstructionBlock* successor = code()->InstructionBlockAt(succ);
16891cb0ef41Sopenharmony_ci        DCHECK_EQ(1, successor->PredecessorCount());
16901cb0ef41Sopenharmony_ci        int gap_index = successor->first_instruction_index();
16911cb0ef41Sopenharmony_ci        // Create an unconstrained operand for the same virtual register
16921cb0ef41Sopenharmony_ci        // and insert a gap move from the fixed output to the operand.
16931cb0ef41Sopenharmony_ci        UnallocatedOperand output_copy(UnallocatedOperand::REGISTER_OR_SLOT,
16941cb0ef41Sopenharmony_ci                                       output_vreg);
16951cb0ef41Sopenharmony_ci        data()->AddGapMove(gap_index, Instruction::START, *output, output_copy);
16961cb0ef41Sopenharmony_ci      }
16971cb0ef41Sopenharmony_ci    }
16981cb0ef41Sopenharmony_ci
16991cb0ef41Sopenharmony_ci    if (!assigned) {
17001cb0ef41Sopenharmony_ci      for (const RpoNumber& succ : block->successors()) {
17011cb0ef41Sopenharmony_ci        const InstructionBlock* successor = code()->InstructionBlockAt(succ);
17021cb0ef41Sopenharmony_ci        DCHECK_EQ(1, successor->PredecessorCount());
17031cb0ef41Sopenharmony_ci        int gap_index = successor->first_instruction_index();
17041cb0ef41Sopenharmony_ci        range->RecordSpillLocation(allocation_zone(), gap_index, output);
17051cb0ef41Sopenharmony_ci        range->SetSpillStartIndex(gap_index);
17061cb0ef41Sopenharmony_ci      }
17071cb0ef41Sopenharmony_ci    }
17081cb0ef41Sopenharmony_ci  }
17091cb0ef41Sopenharmony_ci}
17101cb0ef41Sopenharmony_ci
17111cb0ef41Sopenharmony_civoid ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
17121cb0ef41Sopenharmony_ci  Instruction* first = code()->InstructionAt(instr_index);
17131cb0ef41Sopenharmony_ci  // Handle fixed temporaries.
17141cb0ef41Sopenharmony_ci  for (size_t i = 0; i < first->TempCount(); i++) {
17151cb0ef41Sopenharmony_ci    UnallocatedOperand* temp = UnallocatedOperand::cast(first->TempAt(i));
17161cb0ef41Sopenharmony_ci    if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false, false);
17171cb0ef41Sopenharmony_ci  }
17181cb0ef41Sopenharmony_ci  // Handle constant/fixed output operands.
17191cb0ef41Sopenharmony_ci  for (size_t i = 0; i < first->OutputCount(); i++) {
17201cb0ef41Sopenharmony_ci    InstructionOperand* output = first->OutputAt(i);
17211cb0ef41Sopenharmony_ci    if (output->IsConstant()) {
17221cb0ef41Sopenharmony_ci      int output_vreg = ConstantOperand::cast(output)->virtual_register();
17231cb0ef41Sopenharmony_ci      TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg);
17241cb0ef41Sopenharmony_ci      range->SetSpillStartIndex(instr_index + 1);
17251cb0ef41Sopenharmony_ci      range->SetSpillOperand(output);
17261cb0ef41Sopenharmony_ci      continue;
17271cb0ef41Sopenharmony_ci    }
17281cb0ef41Sopenharmony_ci    UnallocatedOperand* first_output = UnallocatedOperand::cast(output);
17291cb0ef41Sopenharmony_ci    TopLevelLiveRange* range =
17301cb0ef41Sopenharmony_ci        data()->GetOrCreateLiveRangeFor(first_output->virtual_register());
17311cb0ef41Sopenharmony_ci    bool assigned = false;
17321cb0ef41Sopenharmony_ci    if (first_output->HasFixedPolicy()) {
17331cb0ef41Sopenharmony_ci      int output_vreg = first_output->virtual_register();
17341cb0ef41Sopenharmony_ci      UnallocatedOperand output_copy(UnallocatedOperand::REGISTER_OR_SLOT,
17351cb0ef41Sopenharmony_ci                                     output_vreg);
17361cb0ef41Sopenharmony_ci      bool is_tagged = code()->IsReference(output_vreg);
17371cb0ef41Sopenharmony_ci      if (first_output->HasSecondaryStorage()) {
17381cb0ef41Sopenharmony_ci        range->MarkHasPreassignedSlot();
17391cb0ef41Sopenharmony_ci        data()->preassigned_slot_ranges().push_back(
17401cb0ef41Sopenharmony_ci            std::make_pair(range, first_output->GetSecondaryStorage()));
17411cb0ef41Sopenharmony_ci      }
17421cb0ef41Sopenharmony_ci      AllocateFixed(first_output, instr_index, is_tagged, false);
17431cb0ef41Sopenharmony_ci
17441cb0ef41Sopenharmony_ci      // This value is produced on the stack, we never need to spill it.
17451cb0ef41Sopenharmony_ci      if (first_output->IsStackSlot()) {
17461cb0ef41Sopenharmony_ci        DCHECK(LocationOperand::cast(first_output)->index() <
17471cb0ef41Sopenharmony_ci               data()->frame()->GetTotalFrameSlotCount());
17481cb0ef41Sopenharmony_ci        range->SetSpillOperand(LocationOperand::cast(first_output));
17491cb0ef41Sopenharmony_ci        range->SetSpillStartIndex(instr_index + 1);
17501cb0ef41Sopenharmony_ci        assigned = true;
17511cb0ef41Sopenharmony_ci      }
17521cb0ef41Sopenharmony_ci      data()->AddGapMove(instr_index + 1, Instruction::START, *first_output,
17531cb0ef41Sopenharmony_ci                         output_copy);
17541cb0ef41Sopenharmony_ci    }
17551cb0ef41Sopenharmony_ci    // Make sure we add a gap move for spilling (if we have not done
17561cb0ef41Sopenharmony_ci    // so already).
17571cb0ef41Sopenharmony_ci    if (!assigned) {
17581cb0ef41Sopenharmony_ci      range->RecordSpillLocation(allocation_zone(), instr_index + 1,
17591cb0ef41Sopenharmony_ci                                 first_output);
17601cb0ef41Sopenharmony_ci      range->SetSpillStartIndex(instr_index + 1);
17611cb0ef41Sopenharmony_ci    }
17621cb0ef41Sopenharmony_ci  }
17631cb0ef41Sopenharmony_ci}
17641cb0ef41Sopenharmony_ci
17651cb0ef41Sopenharmony_civoid ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
17661cb0ef41Sopenharmony_ci  Instruction* second = code()->InstructionAt(instr_index);
17671cb0ef41Sopenharmony_ci  // Handle fixed input operands of second instruction.
17681cb0ef41Sopenharmony_ci  ZoneVector<TopLevelLiveRange*>* spilled_consts = nullptr;
17691cb0ef41Sopenharmony_ci  for (size_t i = 0; i < second->InputCount(); i++) {
17701cb0ef41Sopenharmony_ci    InstructionOperand* input = second->InputAt(i);
17711cb0ef41Sopenharmony_ci    if (input->IsImmediate()) {
17721cb0ef41Sopenharmony_ci      continue;  // Ignore immediates.
17731cb0ef41Sopenharmony_ci    }
17741cb0ef41Sopenharmony_ci    UnallocatedOperand* cur_input = UnallocatedOperand::cast(input);
17751cb0ef41Sopenharmony_ci    if (cur_input->HasSlotPolicy()) {
17761cb0ef41Sopenharmony_ci      TopLevelLiveRange* range =
17771cb0ef41Sopenharmony_ci          data()->GetOrCreateLiveRangeFor(cur_input->virtual_register());
17781cb0ef41Sopenharmony_ci      if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) {
17791cb0ef41Sopenharmony_ci        bool already_spilled = false;
17801cb0ef41Sopenharmony_ci        if (spilled_consts == nullptr) {
17811cb0ef41Sopenharmony_ci          spilled_consts =
17821cb0ef41Sopenharmony_ci              allocation_zone()->New<ZoneVector<TopLevelLiveRange*>>(
17831cb0ef41Sopenharmony_ci                  allocation_zone());
17841cb0ef41Sopenharmony_ci        } else {
17851cb0ef41Sopenharmony_ci          auto it =
17861cb0ef41Sopenharmony_ci              std::find(spilled_consts->begin(), spilled_consts->end(), range);
17871cb0ef41Sopenharmony_ci          already_spilled = it != spilled_consts->end();
17881cb0ef41Sopenharmony_ci        }
17891cb0ef41Sopenharmony_ci        auto it = data()->slot_for_const_range().find(range);
17901cb0ef41Sopenharmony_ci        if (it == data()->slot_for_const_range().end()) {
17911cb0ef41Sopenharmony_ci          DCHECK(!already_spilled);
17921cb0ef41Sopenharmony_ci          int width = ByteWidthForStackSlot(range->representation());
17931cb0ef41Sopenharmony_ci          int index = data()->frame()->AllocateSpillSlot(width);
17941cb0ef41Sopenharmony_ci          auto* slot = AllocatedOperand::New(allocation_zone(),
17951cb0ef41Sopenharmony_ci                                             LocationOperand::STACK_SLOT,
17961cb0ef41Sopenharmony_ci                                             range->representation(), index);
17971cb0ef41Sopenharmony_ci          it = data()->slot_for_const_range().emplace(range, slot).first;
17981cb0ef41Sopenharmony_ci        }
17991cb0ef41Sopenharmony_ci        if (!already_spilled) {
18001cb0ef41Sopenharmony_ci          auto* slot = it->second;
18011cb0ef41Sopenharmony_ci          int input_vreg = cur_input->virtual_register();
18021cb0ef41Sopenharmony_ci          UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
18031cb0ef41Sopenharmony_ci                                        input_vreg);
18041cb0ef41Sopenharmony_ci          // Spill at every use position for simplicity, this case is very rare.
18051cb0ef41Sopenharmony_ci          data()->AddGapMove(instr_index, Instruction::END, input_copy, *slot);
18061cb0ef41Sopenharmony_ci          spilled_consts->push_back(range);
18071cb0ef41Sopenharmony_ci        }
18081cb0ef41Sopenharmony_ci      }
18091cb0ef41Sopenharmony_ci    }
18101cb0ef41Sopenharmony_ci    if (cur_input->HasFixedPolicy()) {
18111cb0ef41Sopenharmony_ci      int input_vreg = cur_input->virtual_register();
18121cb0ef41Sopenharmony_ci      UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
18131cb0ef41Sopenharmony_ci                                    input_vreg);
18141cb0ef41Sopenharmony_ci      bool is_tagged = code()->IsReference(input_vreg);
18151cb0ef41Sopenharmony_ci      AllocateFixed(cur_input, instr_index, is_tagged, true);
18161cb0ef41Sopenharmony_ci      data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input);
18171cb0ef41Sopenharmony_ci    }
18181cb0ef41Sopenharmony_ci  }
18191cb0ef41Sopenharmony_ci  // Handle "output same as input" for second instruction.
18201cb0ef41Sopenharmony_ci  for (size_t i = 0; i < second->OutputCount(); i++) {
18211cb0ef41Sopenharmony_ci    InstructionOperand* output = second->OutputAt(i);
18221cb0ef41Sopenharmony_ci    if (!output->IsUnallocated()) continue;
18231cb0ef41Sopenharmony_ci    UnallocatedOperand* second_output = UnallocatedOperand::cast(output);
18241cb0ef41Sopenharmony_ci    if (!second_output->HasSameAsInputPolicy()) continue;
18251cb0ef41Sopenharmony_ci    DCHECK_EQ(0, i);  // Only valid for first output.
18261cb0ef41Sopenharmony_ci    UnallocatedOperand* cur_input =
18271cb0ef41Sopenharmony_ci        UnallocatedOperand::cast(second->InputAt(second_output->input_index()));
18281cb0ef41Sopenharmony_ci    int output_vreg = second_output->virtual_register();
18291cb0ef41Sopenharmony_ci    int input_vreg = cur_input->virtual_register();
18301cb0ef41Sopenharmony_ci    UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
18311cb0ef41Sopenharmony_ci                                  input_vreg);
18321cb0ef41Sopenharmony_ci    *cur_input =
18331cb0ef41Sopenharmony_ci        UnallocatedOperand(*cur_input, second_output->virtual_register());
18341cb0ef41Sopenharmony_ci    MoveOperands* gap_move = data()->AddGapMove(instr_index, Instruction::END,
18351cb0ef41Sopenharmony_ci                                                input_copy, *cur_input);
18361cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(gap_move);
18371cb0ef41Sopenharmony_ci    if (code()->IsReference(input_vreg) && !code()->IsReference(output_vreg)) {
18381cb0ef41Sopenharmony_ci      if (second->HasReferenceMap()) {
18391cb0ef41Sopenharmony_ci        TopTierRegisterAllocationData::DelayedReference delayed_reference = {
18401cb0ef41Sopenharmony_ci            second->reference_map(), &gap_move->source()};
18411cb0ef41Sopenharmony_ci        data()->delayed_references().push_back(delayed_reference);
18421cb0ef41Sopenharmony_ci      }
18431cb0ef41Sopenharmony_ci    }
18441cb0ef41Sopenharmony_ci  }
18451cb0ef41Sopenharmony_ci}
18461cb0ef41Sopenharmony_ci
18471cb0ef41Sopenharmony_civoid ConstraintBuilder::ResolvePhis() {
18481cb0ef41Sopenharmony_ci  // Process the blocks in reverse order.
18491cb0ef41Sopenharmony_ci  for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) {
18501cb0ef41Sopenharmony_ci    data_->tick_counter()->TickAndMaybeEnterSafepoint();
18511cb0ef41Sopenharmony_ci    ResolvePhis(block);
18521cb0ef41Sopenharmony_ci  }
18531cb0ef41Sopenharmony_ci}
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_civoid ConstraintBuilder::ResolvePhis(const InstructionBlock* block) {
18561cb0ef41Sopenharmony_ci  for (PhiInstruction* phi : block->phis()) {
18571cb0ef41Sopenharmony_ci    int phi_vreg = phi->virtual_register();
18581cb0ef41Sopenharmony_ci    TopTierRegisterAllocationData::PhiMapValue* map_value =
18591cb0ef41Sopenharmony_ci        data()->InitializePhiMap(block, phi);
18601cb0ef41Sopenharmony_ci    InstructionOperand& output = phi->output();
18611cb0ef41Sopenharmony_ci    // Map the destination operands, so the commitment phase can find them.
18621cb0ef41Sopenharmony_ci    for (size_t i = 0; i < phi->operands().size(); ++i) {
18631cb0ef41Sopenharmony_ci      InstructionBlock* cur_block =
18641cb0ef41Sopenharmony_ci          code()->InstructionBlockAt(block->predecessors()[i]);
18651cb0ef41Sopenharmony_ci      UnallocatedOperand input(UnallocatedOperand::REGISTER_OR_SLOT,
18661cb0ef41Sopenharmony_ci                               phi->operands()[i]);
18671cb0ef41Sopenharmony_ci      MoveOperands* move = data()->AddGapMove(
18681cb0ef41Sopenharmony_ci          cur_block->last_instruction_index(), Instruction::END, input, output);
18691cb0ef41Sopenharmony_ci      map_value->AddOperand(&move->destination());
18701cb0ef41Sopenharmony_ci      DCHECK(!code()
18711cb0ef41Sopenharmony_ci                  ->InstructionAt(cur_block->last_instruction_index())
18721cb0ef41Sopenharmony_ci                  ->HasReferenceMap());
18731cb0ef41Sopenharmony_ci    }
18741cb0ef41Sopenharmony_ci    TopLevelLiveRange* live_range = data()->GetOrCreateLiveRangeFor(phi_vreg);
18751cb0ef41Sopenharmony_ci    int gap_index = block->first_instruction_index();
18761cb0ef41Sopenharmony_ci    live_range->RecordSpillLocation(allocation_zone(), gap_index, &output);
18771cb0ef41Sopenharmony_ci    live_range->SetSpillStartIndex(gap_index);
18781cb0ef41Sopenharmony_ci    // We use the phi-ness of some nodes in some later heuristics.
18791cb0ef41Sopenharmony_ci    live_range->set_is_phi(true);
18801cb0ef41Sopenharmony_ci    live_range->set_is_non_loop_phi(!block->IsLoopHeader());
18811cb0ef41Sopenharmony_ci  }
18821cb0ef41Sopenharmony_ci}
18831cb0ef41Sopenharmony_ci
18841cb0ef41Sopenharmony_ciLiveRangeBuilder::LiveRangeBuilder(TopTierRegisterAllocationData* data,
18851cb0ef41Sopenharmony_ci                                   Zone* local_zone)
18861cb0ef41Sopenharmony_ci    : data_(data), phi_hints_(local_zone) {}
18871cb0ef41Sopenharmony_ci
18881cb0ef41Sopenharmony_ciBitVector* LiveRangeBuilder::ComputeLiveOut(
18891cb0ef41Sopenharmony_ci    const InstructionBlock* block, TopTierRegisterAllocationData* data) {
18901cb0ef41Sopenharmony_ci  size_t block_index = block->rpo_number().ToSize();
18911cb0ef41Sopenharmony_ci  BitVector* live_out = data->live_out_sets()[block_index];
18921cb0ef41Sopenharmony_ci  if (live_out == nullptr) {
18931cb0ef41Sopenharmony_ci    // Compute live out for the given block, except not including backward
18941cb0ef41Sopenharmony_ci    // successor edges.
18951cb0ef41Sopenharmony_ci    Zone* zone = data->allocation_zone();
18961cb0ef41Sopenharmony_ci    const InstructionSequence* code = data->code();
18971cb0ef41Sopenharmony_ci
18981cb0ef41Sopenharmony_ci    live_out = zone->New<BitVector>(code->VirtualRegisterCount(), zone);
18991cb0ef41Sopenharmony_ci
19001cb0ef41Sopenharmony_ci    // Process all successor blocks.
19011cb0ef41Sopenharmony_ci    for (const RpoNumber& succ : block->successors()) {
19021cb0ef41Sopenharmony_ci      // Add values live on entry to the successor.
19031cb0ef41Sopenharmony_ci      if (succ <= block->rpo_number()) continue;
19041cb0ef41Sopenharmony_ci      BitVector* live_in = data->live_in_sets()[succ.ToSize()];
19051cb0ef41Sopenharmony_ci      if (live_in != nullptr) live_out->Union(*live_in);
19061cb0ef41Sopenharmony_ci
19071cb0ef41Sopenharmony_ci      // All phi input operands corresponding to this successor edge are live
19081cb0ef41Sopenharmony_ci      // out from this block.
19091cb0ef41Sopenharmony_ci      const InstructionBlock* successor = code->InstructionBlockAt(succ);
19101cb0ef41Sopenharmony_ci      size_t index = successor->PredecessorIndexOf(block->rpo_number());
19111cb0ef41Sopenharmony_ci      DCHECK(index < successor->PredecessorCount());
19121cb0ef41Sopenharmony_ci      for (PhiInstruction* phi : successor->phis()) {
19131cb0ef41Sopenharmony_ci        live_out->Add(phi->operands()[index]);
19141cb0ef41Sopenharmony_ci      }
19151cb0ef41Sopenharmony_ci    }
19161cb0ef41Sopenharmony_ci    data->live_out_sets()[block_index] = live_out;
19171cb0ef41Sopenharmony_ci  }
19181cb0ef41Sopenharmony_ci  return live_out;
19191cb0ef41Sopenharmony_ci}
19201cb0ef41Sopenharmony_ci
19211cb0ef41Sopenharmony_civoid LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block,
19221cb0ef41Sopenharmony_ci                                           BitVector* live_out) {
19231cb0ef41Sopenharmony_ci  // Add an interval that includes the entire block to the live range for
19241cb0ef41Sopenharmony_ci  // each live_out value.
19251cb0ef41Sopenharmony_ci  LifetimePosition start = LifetimePosition::GapFromInstructionIndex(
19261cb0ef41Sopenharmony_ci      block->first_instruction_index());
19271cb0ef41Sopenharmony_ci  LifetimePosition end = LifetimePosition::InstructionFromInstructionIndex(
19281cb0ef41Sopenharmony_ci                             block->last_instruction_index())
19291cb0ef41Sopenharmony_ci                             .NextStart();
19301cb0ef41Sopenharmony_ci  for (int operand_index : *live_out) {
19311cb0ef41Sopenharmony_ci    TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index);
19321cb0ef41Sopenharmony_ci    range->AddUseInterval(start, end, allocation_zone(),
19331cb0ef41Sopenharmony_ci                          data()->is_trace_alloc());
19341cb0ef41Sopenharmony_ci  }
19351cb0ef41Sopenharmony_ci}
19361cb0ef41Sopenharmony_ci
19371cb0ef41Sopenharmony_ciint LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
19381cb0ef41Sopenharmony_ci  int result = -index - 1;
19391cb0ef41Sopenharmony_ci  switch (rep) {
19401cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128:
19411cb0ef41Sopenharmony_ci      result -=
19421cb0ef41Sopenharmony_ci          kNumberOfFixedRangesPerRegister * config()->num_float_registers();
19431cb0ef41Sopenharmony_ci      V8_FALLTHROUGH;
19441cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
19451cb0ef41Sopenharmony_ci      result -=
19461cb0ef41Sopenharmony_ci          kNumberOfFixedRangesPerRegister * config()->num_double_registers();
19471cb0ef41Sopenharmony_ci      V8_FALLTHROUGH;
19481cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
19491cb0ef41Sopenharmony_ci      result -=
19501cb0ef41Sopenharmony_ci          kNumberOfFixedRangesPerRegister * config()->num_general_registers();
19511cb0ef41Sopenharmony_ci      break;
19521cb0ef41Sopenharmony_ci    default:
19531cb0ef41Sopenharmony_ci      UNREACHABLE();
19541cb0ef41Sopenharmony_ci  }
19551cb0ef41Sopenharmony_ci  return result;
19561cb0ef41Sopenharmony_ci}
19571cb0ef41Sopenharmony_ci
19581cb0ef41Sopenharmony_ciTopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index,
19591cb0ef41Sopenharmony_ci                                                       SpillMode spill_mode) {
19601cb0ef41Sopenharmony_ci  int offset = spill_mode == SpillMode::kSpillAtDefinition
19611cb0ef41Sopenharmony_ci                   ? 0
19621cb0ef41Sopenharmony_ci                   : config()->num_general_registers();
19631cb0ef41Sopenharmony_ci  DCHECK(index < config()->num_general_registers());
19641cb0ef41Sopenharmony_ci  TopLevelLiveRange* result = data()->fixed_live_ranges()[offset + index];
19651cb0ef41Sopenharmony_ci  if (result == nullptr) {
19661cb0ef41Sopenharmony_ci    MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
19671cb0ef41Sopenharmony_ci    result = data()->NewLiveRange(FixedLiveRangeID(offset + index), rep);
19681cb0ef41Sopenharmony_ci    DCHECK(result->IsFixed());
19691cb0ef41Sopenharmony_ci    result->set_assigned_register(index);
19701cb0ef41Sopenharmony_ci    data()->MarkAllocated(rep, index);
19711cb0ef41Sopenharmony_ci    if (spill_mode == SpillMode::kSpillDeferred) {
19721cb0ef41Sopenharmony_ci      result->set_deferred_fixed();
19731cb0ef41Sopenharmony_ci    }
19741cb0ef41Sopenharmony_ci    data()->fixed_live_ranges()[offset + index] = result;
19751cb0ef41Sopenharmony_ci  }
19761cb0ef41Sopenharmony_ci  return result;
19771cb0ef41Sopenharmony_ci}
19781cb0ef41Sopenharmony_ci
19791cb0ef41Sopenharmony_ciTopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
19801cb0ef41Sopenharmony_ci    int index, MachineRepresentation rep, SpillMode spill_mode) {
19811cb0ef41Sopenharmony_ci  int num_regs = config()->num_double_registers();
19821cb0ef41Sopenharmony_ci  ZoneVector<TopLevelLiveRange*>* live_ranges =
19831cb0ef41Sopenharmony_ci      &data()->fixed_double_live_ranges();
19841cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kCombine) {
19851cb0ef41Sopenharmony_ci    switch (rep) {
19861cb0ef41Sopenharmony_ci      case MachineRepresentation::kFloat32:
19871cb0ef41Sopenharmony_ci        num_regs = config()->num_float_registers();
19881cb0ef41Sopenharmony_ci        live_ranges = &data()->fixed_float_live_ranges();
19891cb0ef41Sopenharmony_ci        break;
19901cb0ef41Sopenharmony_ci      case MachineRepresentation::kSimd128:
19911cb0ef41Sopenharmony_ci        num_regs = config()->num_simd128_registers();
19921cb0ef41Sopenharmony_ci        live_ranges = &data()->fixed_simd128_live_ranges();
19931cb0ef41Sopenharmony_ci        break;
19941cb0ef41Sopenharmony_ci      default:
19951cb0ef41Sopenharmony_ci        break;
19961cb0ef41Sopenharmony_ci    }
19971cb0ef41Sopenharmony_ci  }
19981cb0ef41Sopenharmony_ci
19991cb0ef41Sopenharmony_ci  int offset = spill_mode == SpillMode::kSpillAtDefinition ? 0 : num_regs;
20001cb0ef41Sopenharmony_ci
20011cb0ef41Sopenharmony_ci  DCHECK(index < num_regs);
20021cb0ef41Sopenharmony_ci  USE(num_regs);
20031cb0ef41Sopenharmony_ci  TopLevelLiveRange* result = (*live_ranges)[offset + index];
20041cb0ef41Sopenharmony_ci  if (result == nullptr) {
20051cb0ef41Sopenharmony_ci    result = data()->NewLiveRange(FixedFPLiveRangeID(offset + index, rep), rep);
20061cb0ef41Sopenharmony_ci    DCHECK(result->IsFixed());
20071cb0ef41Sopenharmony_ci    result->set_assigned_register(index);
20081cb0ef41Sopenharmony_ci    data()->MarkAllocated(rep, index);
20091cb0ef41Sopenharmony_ci    if (spill_mode == SpillMode::kSpillDeferred) {
20101cb0ef41Sopenharmony_ci      result->set_deferred_fixed();
20111cb0ef41Sopenharmony_ci    }
20121cb0ef41Sopenharmony_ci    (*live_ranges)[offset + index] = result;
20131cb0ef41Sopenharmony_ci  }
20141cb0ef41Sopenharmony_ci  return result;
20151cb0ef41Sopenharmony_ci}
20161cb0ef41Sopenharmony_ci
20171cb0ef41Sopenharmony_ciTopLevelLiveRange* LiveRangeBuilder::FixedSIMD128LiveRangeFor(
20181cb0ef41Sopenharmony_ci    int index, SpillMode spill_mode) {
20191cb0ef41Sopenharmony_ci  DCHECK_EQ(kFPAliasing, AliasingKind::kIndependent);
20201cb0ef41Sopenharmony_ci  int num_regs = config()->num_simd128_registers();
20211cb0ef41Sopenharmony_ci  ZoneVector<TopLevelLiveRange*>* live_ranges =
20221cb0ef41Sopenharmony_ci      &data()->fixed_simd128_live_ranges();
20231cb0ef41Sopenharmony_ci  int offset = spill_mode == SpillMode::kSpillAtDefinition ? 0 : num_regs;
20241cb0ef41Sopenharmony_ci
20251cb0ef41Sopenharmony_ci  DCHECK(index < num_regs);
20261cb0ef41Sopenharmony_ci  USE(num_regs);
20271cb0ef41Sopenharmony_ci  TopLevelLiveRange* result = (*live_ranges)[offset + index];
20281cb0ef41Sopenharmony_ci  if (result == nullptr) {
20291cb0ef41Sopenharmony_ci    result = data()->NewLiveRange(
20301cb0ef41Sopenharmony_ci        FixedFPLiveRangeID(offset + index, MachineRepresentation::kSimd128),
20311cb0ef41Sopenharmony_ci        MachineRepresentation::kSimd128);
20321cb0ef41Sopenharmony_ci    DCHECK(result->IsFixed());
20331cb0ef41Sopenharmony_ci    result->set_assigned_register(index);
20341cb0ef41Sopenharmony_ci    data()->MarkAllocated(MachineRepresentation::kSimd128, index);
20351cb0ef41Sopenharmony_ci    if (spill_mode == SpillMode::kSpillDeferred) {
20361cb0ef41Sopenharmony_ci      result->set_deferred_fixed();
20371cb0ef41Sopenharmony_ci    }
20381cb0ef41Sopenharmony_ci    (*live_ranges)[offset + index] = result;
20391cb0ef41Sopenharmony_ci  }
20401cb0ef41Sopenharmony_ci  return result;
20411cb0ef41Sopenharmony_ci}
20421cb0ef41Sopenharmony_ci
20431cb0ef41Sopenharmony_ciTopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand,
20441cb0ef41Sopenharmony_ci                                                  SpillMode spill_mode) {
20451cb0ef41Sopenharmony_ci  if (operand->IsUnallocated()) {
20461cb0ef41Sopenharmony_ci    return data()->GetOrCreateLiveRangeFor(
20471cb0ef41Sopenharmony_ci        UnallocatedOperand::cast(operand)->virtual_register());
20481cb0ef41Sopenharmony_ci  } else if (operand->IsConstant()) {
20491cb0ef41Sopenharmony_ci    return data()->GetOrCreateLiveRangeFor(
20501cb0ef41Sopenharmony_ci        ConstantOperand::cast(operand)->virtual_register());
20511cb0ef41Sopenharmony_ci  } else if (operand->IsRegister()) {
20521cb0ef41Sopenharmony_ci    return FixedLiveRangeFor(
20531cb0ef41Sopenharmony_ci        LocationOperand::cast(operand)->GetRegister().code(), spill_mode);
20541cb0ef41Sopenharmony_ci  } else if (operand->IsFPRegister()) {
20551cb0ef41Sopenharmony_ci    LocationOperand* op = LocationOperand::cast(operand);
20561cb0ef41Sopenharmony_ci    if (kFPAliasing == AliasingKind::kIndependent &&
20571cb0ef41Sopenharmony_ci        op->representation() == MachineRepresentation::kSimd128) {
20581cb0ef41Sopenharmony_ci      return FixedSIMD128LiveRangeFor(op->register_code(), spill_mode);
20591cb0ef41Sopenharmony_ci    }
20601cb0ef41Sopenharmony_ci    return FixedFPLiveRangeFor(op->register_code(), op->representation(),
20611cb0ef41Sopenharmony_ci                               spill_mode);
20621cb0ef41Sopenharmony_ci  } else {
20631cb0ef41Sopenharmony_ci    return nullptr;
20641cb0ef41Sopenharmony_ci  }
20651cb0ef41Sopenharmony_ci}
20661cb0ef41Sopenharmony_ci
20671cb0ef41Sopenharmony_ciUsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos,
20681cb0ef41Sopenharmony_ci                                              InstructionOperand* operand,
20691cb0ef41Sopenharmony_ci                                              void* hint,
20701cb0ef41Sopenharmony_ci                                              UsePositionHintType hint_type) {
20711cb0ef41Sopenharmony_ci  return allocation_zone()->New<UsePosition>(pos, operand, hint, hint_type);
20721cb0ef41Sopenharmony_ci}
20731cb0ef41Sopenharmony_ci
20741cb0ef41Sopenharmony_ciUsePosition* LiveRangeBuilder::Define(LifetimePosition position,
20751cb0ef41Sopenharmony_ci                                      InstructionOperand* operand, void* hint,
20761cb0ef41Sopenharmony_ci                                      UsePositionHintType hint_type,
20771cb0ef41Sopenharmony_ci                                      SpillMode spill_mode) {
20781cb0ef41Sopenharmony_ci  TopLevelLiveRange* range = LiveRangeFor(operand, spill_mode);
20791cb0ef41Sopenharmony_ci  if (range == nullptr) return nullptr;
20801cb0ef41Sopenharmony_ci
20811cb0ef41Sopenharmony_ci  if (range->IsEmpty() || range->Start() > position) {
20821cb0ef41Sopenharmony_ci    // Can happen if there is a definition without use.
20831cb0ef41Sopenharmony_ci    range->AddUseInterval(position, position.NextStart(), allocation_zone(),
20841cb0ef41Sopenharmony_ci                          data()->is_trace_alloc());
20851cb0ef41Sopenharmony_ci    range->AddUsePosition(NewUsePosition(position.NextStart()),
20861cb0ef41Sopenharmony_ci                          data()->is_trace_alloc());
20871cb0ef41Sopenharmony_ci  } else {
20881cb0ef41Sopenharmony_ci    range->ShortenTo(position, data()->is_trace_alloc());
20891cb0ef41Sopenharmony_ci  }
20901cb0ef41Sopenharmony_ci  if (!operand->IsUnallocated()) return nullptr;
20911cb0ef41Sopenharmony_ci  UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
20921cb0ef41Sopenharmony_ci  UsePosition* use_pos =
20931cb0ef41Sopenharmony_ci      NewUsePosition(position, unalloc_operand, hint, hint_type);
20941cb0ef41Sopenharmony_ci  range->AddUsePosition(use_pos, data()->is_trace_alloc());
20951cb0ef41Sopenharmony_ci  return use_pos;
20961cb0ef41Sopenharmony_ci}
20971cb0ef41Sopenharmony_ci
20981cb0ef41Sopenharmony_ciUsePosition* LiveRangeBuilder::Use(LifetimePosition block_start,
20991cb0ef41Sopenharmony_ci                                   LifetimePosition position,
21001cb0ef41Sopenharmony_ci                                   InstructionOperand* operand, void* hint,
21011cb0ef41Sopenharmony_ci                                   UsePositionHintType hint_type,
21021cb0ef41Sopenharmony_ci                                   SpillMode spill_mode) {
21031cb0ef41Sopenharmony_ci  TopLevelLiveRange* range = LiveRangeFor(operand, spill_mode);
21041cb0ef41Sopenharmony_ci  if (range == nullptr) return nullptr;
21051cb0ef41Sopenharmony_ci  UsePosition* use_pos = nullptr;
21061cb0ef41Sopenharmony_ci  if (operand->IsUnallocated()) {
21071cb0ef41Sopenharmony_ci    UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
21081cb0ef41Sopenharmony_ci    use_pos = NewUsePosition(position, unalloc_operand, hint, hint_type);
21091cb0ef41Sopenharmony_ci    range->AddUsePosition(use_pos, data()->is_trace_alloc());
21101cb0ef41Sopenharmony_ci  }
21111cb0ef41Sopenharmony_ci  range->AddUseInterval(block_start, position, allocation_zone(),
21121cb0ef41Sopenharmony_ci                        data()->is_trace_alloc());
21131cb0ef41Sopenharmony_ci  return use_pos;
21141cb0ef41Sopenharmony_ci}
21151cb0ef41Sopenharmony_ci
21161cb0ef41Sopenharmony_civoid LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
21171cb0ef41Sopenharmony_ci                                           BitVector* live) {
21181cb0ef41Sopenharmony_ci  int block_start = block->first_instruction_index();
21191cb0ef41Sopenharmony_ci  LifetimePosition block_start_position =
21201cb0ef41Sopenharmony_ci      LifetimePosition::GapFromInstructionIndex(block_start);
21211cb0ef41Sopenharmony_ci  bool fixed_float_live_ranges = false;
21221cb0ef41Sopenharmony_ci  bool fixed_simd128_live_ranges = false;
21231cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kCombine) {
21241cb0ef41Sopenharmony_ci    int mask = data()->code()->representation_mask();
21251cb0ef41Sopenharmony_ci    fixed_float_live_ranges = (mask & kFloat32Bit) != 0;
21261cb0ef41Sopenharmony_ci    fixed_simd128_live_ranges = (mask & kSimd128Bit) != 0;
21271cb0ef41Sopenharmony_ci  } else if (kFPAliasing == AliasingKind::kIndependent) {
21281cb0ef41Sopenharmony_ci    int mask = data()->code()->representation_mask();
21291cb0ef41Sopenharmony_ci    fixed_simd128_live_ranges = (mask & kSimd128Bit) != 0;
21301cb0ef41Sopenharmony_ci  }
21311cb0ef41Sopenharmony_ci  SpillMode spill_mode = SpillModeForBlock(block);
21321cb0ef41Sopenharmony_ci
21331cb0ef41Sopenharmony_ci  for (int index = block->last_instruction_index(); index >= block_start;
21341cb0ef41Sopenharmony_ci       index--) {
21351cb0ef41Sopenharmony_ci    LifetimePosition curr_position =
21361cb0ef41Sopenharmony_ci        LifetimePosition::InstructionFromInstructionIndex(index);
21371cb0ef41Sopenharmony_ci    Instruction* instr = code()->InstructionAt(index);
21381cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(instr);
21391cb0ef41Sopenharmony_ci    DCHECK(curr_position.IsInstructionPosition());
21401cb0ef41Sopenharmony_ci    // Process output, inputs, and temps of this instruction.
21411cb0ef41Sopenharmony_ci    for (size_t i = 0; i < instr->OutputCount(); i++) {
21421cb0ef41Sopenharmony_ci      InstructionOperand* output = instr->OutputAt(i);
21431cb0ef41Sopenharmony_ci      if (output->IsUnallocated()) {
21441cb0ef41Sopenharmony_ci        // Unsupported.
21451cb0ef41Sopenharmony_ci        DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy());
21461cb0ef41Sopenharmony_ci        int out_vreg = UnallocatedOperand::cast(output)->virtual_register();
21471cb0ef41Sopenharmony_ci        live->Remove(out_vreg);
21481cb0ef41Sopenharmony_ci      } else if (output->IsConstant()) {
21491cb0ef41Sopenharmony_ci        int out_vreg = ConstantOperand::cast(output)->virtual_register();
21501cb0ef41Sopenharmony_ci        live->Remove(out_vreg);
21511cb0ef41Sopenharmony_ci      }
21521cb0ef41Sopenharmony_ci      if (block->IsHandler() && index == block_start && output->IsAllocated() &&
21531cb0ef41Sopenharmony_ci          output->IsRegister() &&
21541cb0ef41Sopenharmony_ci          AllocatedOperand::cast(output)->GetRegister() ==
21551cb0ef41Sopenharmony_ci              v8::internal::kReturnRegister0) {
21561cb0ef41Sopenharmony_ci        // The register defined here is blocked from gap start - it is the
21571cb0ef41Sopenharmony_ci        // exception value.
21581cb0ef41Sopenharmony_ci        // TODO(mtrofin): should we explore an explicit opcode for
21591cb0ef41Sopenharmony_ci        // the first instruction in the handler?
21601cb0ef41Sopenharmony_ci        Define(LifetimePosition::GapFromInstructionIndex(index), output,
21611cb0ef41Sopenharmony_ci               spill_mode);
21621cb0ef41Sopenharmony_ci      } else {
21631cb0ef41Sopenharmony_ci        Define(curr_position, output, spill_mode);
21641cb0ef41Sopenharmony_ci      }
21651cb0ef41Sopenharmony_ci    }
21661cb0ef41Sopenharmony_ci
21671cb0ef41Sopenharmony_ci    if (instr->ClobbersRegisters()) {
21681cb0ef41Sopenharmony_ci      for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) {
21691cb0ef41Sopenharmony_ci        // Create a UseInterval at this instruction for all fixed registers,
21701cb0ef41Sopenharmony_ci        // (including the instruction outputs). Adding another UseInterval here
21711cb0ef41Sopenharmony_ci        // is OK because AddUseInterval will just merge it with the existing
21721cb0ef41Sopenharmony_ci        // one at the end of the range.
21731cb0ef41Sopenharmony_ci        int code = config()->GetAllocatableGeneralCode(i);
21741cb0ef41Sopenharmony_ci        TopLevelLiveRange* range = FixedLiveRangeFor(code, spill_mode);
21751cb0ef41Sopenharmony_ci        range->AddUseInterval(curr_position, curr_position.End(),
21761cb0ef41Sopenharmony_ci                              allocation_zone(), data()->is_trace_alloc());
21771cb0ef41Sopenharmony_ci      }
21781cb0ef41Sopenharmony_ci    }
21791cb0ef41Sopenharmony_ci
21801cb0ef41Sopenharmony_ci    if (instr->ClobbersDoubleRegisters()) {
21811cb0ef41Sopenharmony_ci      for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) {
21821cb0ef41Sopenharmony_ci        // Add a UseInterval for all DoubleRegisters. See comment above for
21831cb0ef41Sopenharmony_ci        // general registers.
21841cb0ef41Sopenharmony_ci        int code = config()->GetAllocatableDoubleCode(i);
21851cb0ef41Sopenharmony_ci        TopLevelLiveRange* range = FixedFPLiveRangeFor(
21861cb0ef41Sopenharmony_ci            code, MachineRepresentation::kFloat64, spill_mode);
21871cb0ef41Sopenharmony_ci        range->AddUseInterval(curr_position, curr_position.End(),
21881cb0ef41Sopenharmony_ci                              allocation_zone(), data()->is_trace_alloc());
21891cb0ef41Sopenharmony_ci      }
21901cb0ef41Sopenharmony_ci      // Clobber fixed float registers on archs with non-simple aliasing.
21911cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kCombine) {
21921cb0ef41Sopenharmony_ci        if (fixed_float_live_ranges) {
21931cb0ef41Sopenharmony_ci          for (int i = 0; i < config()->num_allocatable_float_registers();
21941cb0ef41Sopenharmony_ci               ++i) {
21951cb0ef41Sopenharmony_ci            // Add a UseInterval for all FloatRegisters. See comment above for
21961cb0ef41Sopenharmony_ci            // general registers.
21971cb0ef41Sopenharmony_ci            int code = config()->GetAllocatableFloatCode(i);
21981cb0ef41Sopenharmony_ci            TopLevelLiveRange* range = FixedFPLiveRangeFor(
21991cb0ef41Sopenharmony_ci                code, MachineRepresentation::kFloat32, spill_mode);
22001cb0ef41Sopenharmony_ci            range->AddUseInterval(curr_position, curr_position.End(),
22011cb0ef41Sopenharmony_ci                                  allocation_zone(), data()->is_trace_alloc());
22021cb0ef41Sopenharmony_ci          }
22031cb0ef41Sopenharmony_ci        }
22041cb0ef41Sopenharmony_ci        if (fixed_simd128_live_ranges) {
22051cb0ef41Sopenharmony_ci          for (int i = 0; i < config()->num_allocatable_simd128_registers();
22061cb0ef41Sopenharmony_ci               ++i) {
22071cb0ef41Sopenharmony_ci            int code = config()->GetAllocatableSimd128Code(i);
22081cb0ef41Sopenharmony_ci            TopLevelLiveRange* range = FixedFPLiveRangeFor(
22091cb0ef41Sopenharmony_ci                code, MachineRepresentation::kSimd128, spill_mode);
22101cb0ef41Sopenharmony_ci            range->AddUseInterval(curr_position, curr_position.End(),
22111cb0ef41Sopenharmony_ci                                  allocation_zone(), data()->is_trace_alloc());
22121cb0ef41Sopenharmony_ci          }
22131cb0ef41Sopenharmony_ci        }
22141cb0ef41Sopenharmony_ci      } else if (kFPAliasing == AliasingKind::kIndependent) {
22151cb0ef41Sopenharmony_ci        if (fixed_simd128_live_ranges) {
22161cb0ef41Sopenharmony_ci          for (int i = 0; i < config()->num_allocatable_simd128_registers();
22171cb0ef41Sopenharmony_ci               ++i) {
22181cb0ef41Sopenharmony_ci            int code = config()->GetAllocatableSimd128Code(i);
22191cb0ef41Sopenharmony_ci            TopLevelLiveRange* range =
22201cb0ef41Sopenharmony_ci                FixedSIMD128LiveRangeFor(code, spill_mode);
22211cb0ef41Sopenharmony_ci            range->AddUseInterval(curr_position, curr_position.End(),
22221cb0ef41Sopenharmony_ci                                  allocation_zone(), data()->is_trace_alloc());
22231cb0ef41Sopenharmony_ci          }
22241cb0ef41Sopenharmony_ci        }
22251cb0ef41Sopenharmony_ci      }
22261cb0ef41Sopenharmony_ci    }
22271cb0ef41Sopenharmony_ci
22281cb0ef41Sopenharmony_ci    for (size_t i = 0; i < instr->InputCount(); i++) {
22291cb0ef41Sopenharmony_ci      InstructionOperand* input = instr->InputAt(i);
22301cb0ef41Sopenharmony_ci      if (input->IsImmediate()) {
22311cb0ef41Sopenharmony_ci        continue;  // Ignore immediates.
22321cb0ef41Sopenharmony_ci      }
22331cb0ef41Sopenharmony_ci      LifetimePosition use_pos;
22341cb0ef41Sopenharmony_ci      if (input->IsUnallocated() &&
22351cb0ef41Sopenharmony_ci          UnallocatedOperand::cast(input)->IsUsedAtStart()) {
22361cb0ef41Sopenharmony_ci        use_pos = curr_position;
22371cb0ef41Sopenharmony_ci      } else {
22381cb0ef41Sopenharmony_ci        use_pos = curr_position.End();
22391cb0ef41Sopenharmony_ci      }
22401cb0ef41Sopenharmony_ci
22411cb0ef41Sopenharmony_ci      if (input->IsUnallocated()) {
22421cb0ef41Sopenharmony_ci        UnallocatedOperand* unalloc = UnallocatedOperand::cast(input);
22431cb0ef41Sopenharmony_ci        int vreg = unalloc->virtual_register();
22441cb0ef41Sopenharmony_ci        live->Add(vreg);
22451cb0ef41Sopenharmony_ci        if (unalloc->HasSlotPolicy()) {
22461cb0ef41Sopenharmony_ci          data()->GetOrCreateLiveRangeFor(vreg)->register_slot_use(
22471cb0ef41Sopenharmony_ci              block->IsDeferred()
22481cb0ef41Sopenharmony_ci                  ? TopLevelLiveRange::SlotUseKind::kDeferredSlotUse
22491cb0ef41Sopenharmony_ci                  : TopLevelLiveRange::SlotUseKind::kGeneralSlotUse);
22501cb0ef41Sopenharmony_ci        }
22511cb0ef41Sopenharmony_ci      }
22521cb0ef41Sopenharmony_ci      Use(block_start_position, use_pos, input, spill_mode);
22531cb0ef41Sopenharmony_ci    }
22541cb0ef41Sopenharmony_ci
22551cb0ef41Sopenharmony_ci    for (size_t i = 0; i < instr->TempCount(); i++) {
22561cb0ef41Sopenharmony_ci      InstructionOperand* temp = instr->TempAt(i);
22571cb0ef41Sopenharmony_ci      // Unsupported.
22581cb0ef41Sopenharmony_ci      DCHECK_IMPLIES(temp->IsUnallocated(),
22591cb0ef41Sopenharmony_ci                     !UnallocatedOperand::cast(temp)->HasSlotPolicy());
22601cb0ef41Sopenharmony_ci      if (instr->ClobbersTemps()) {
22611cb0ef41Sopenharmony_ci        if (temp->IsRegister()) continue;
22621cb0ef41Sopenharmony_ci        if (temp->IsUnallocated()) {
22631cb0ef41Sopenharmony_ci          UnallocatedOperand* temp_unalloc = UnallocatedOperand::cast(temp);
22641cb0ef41Sopenharmony_ci          if (temp_unalloc->HasFixedPolicy()) {
22651cb0ef41Sopenharmony_ci            continue;
22661cb0ef41Sopenharmony_ci          }
22671cb0ef41Sopenharmony_ci        }
22681cb0ef41Sopenharmony_ci      }
22691cb0ef41Sopenharmony_ci      Use(block_start_position, curr_position.End(), temp, spill_mode);
22701cb0ef41Sopenharmony_ci      Define(curr_position, temp, spill_mode);
22711cb0ef41Sopenharmony_ci    }
22721cb0ef41Sopenharmony_ci
22731cb0ef41Sopenharmony_ci    // Process the moves of the instruction's gaps, making their sources live.
22741cb0ef41Sopenharmony_ci    const Instruction::GapPosition kPositions[] = {Instruction::END,
22751cb0ef41Sopenharmony_ci                                                   Instruction::START};
22761cb0ef41Sopenharmony_ci    curr_position = curr_position.PrevStart();
22771cb0ef41Sopenharmony_ci    DCHECK(curr_position.IsGapPosition());
22781cb0ef41Sopenharmony_ci    for (const Instruction::GapPosition& position : kPositions) {
22791cb0ef41Sopenharmony_ci      ParallelMove* move = instr->GetParallelMove(position);
22801cb0ef41Sopenharmony_ci      if (move == nullptr) continue;
22811cb0ef41Sopenharmony_ci      if (position == Instruction::END) {
22821cb0ef41Sopenharmony_ci        curr_position = curr_position.End();
22831cb0ef41Sopenharmony_ci      } else {
22841cb0ef41Sopenharmony_ci        curr_position = curr_position.Start();
22851cb0ef41Sopenharmony_ci      }
22861cb0ef41Sopenharmony_ci      for (MoveOperands* cur : *move) {
22871cb0ef41Sopenharmony_ci        InstructionOperand& from = cur->source();
22881cb0ef41Sopenharmony_ci        InstructionOperand& to = cur->destination();
22891cb0ef41Sopenharmony_ci        void* hint = &to;
22901cb0ef41Sopenharmony_ci        UsePositionHintType hint_type = UsePosition::HintTypeForOperand(to);
22911cb0ef41Sopenharmony_ci        UsePosition* to_use = nullptr;
22921cb0ef41Sopenharmony_ci        int phi_vreg = -1;
22931cb0ef41Sopenharmony_ci        if (to.IsUnallocated()) {
22941cb0ef41Sopenharmony_ci          int to_vreg = UnallocatedOperand::cast(to).virtual_register();
22951cb0ef41Sopenharmony_ci          TopLevelLiveRange* to_range =
22961cb0ef41Sopenharmony_ci              data()->GetOrCreateLiveRangeFor(to_vreg);
22971cb0ef41Sopenharmony_ci          if (to_range->is_phi()) {
22981cb0ef41Sopenharmony_ci            phi_vreg = to_vreg;
22991cb0ef41Sopenharmony_ci            if (to_range->is_non_loop_phi()) {
23001cb0ef41Sopenharmony_ci              hint = to_range->current_hint_position();
23011cb0ef41Sopenharmony_ci              hint_type = hint == nullptr ? UsePositionHintType::kNone
23021cb0ef41Sopenharmony_ci                                          : UsePositionHintType::kUsePos;
23031cb0ef41Sopenharmony_ci            } else {
23041cb0ef41Sopenharmony_ci              hint_type = UsePositionHintType::kPhi;
23051cb0ef41Sopenharmony_ci              hint = data()->GetPhiMapValueFor(to_vreg);
23061cb0ef41Sopenharmony_ci            }
23071cb0ef41Sopenharmony_ci          } else {
23081cb0ef41Sopenharmony_ci            if (live->Contains(to_vreg)) {
23091cb0ef41Sopenharmony_ci              to_use =
23101cb0ef41Sopenharmony_ci                  Define(curr_position, &to, &from,
23111cb0ef41Sopenharmony_ci                         UsePosition::HintTypeForOperand(from), spill_mode);
23121cb0ef41Sopenharmony_ci              live->Remove(to_vreg);
23131cb0ef41Sopenharmony_ci            } else {
23141cb0ef41Sopenharmony_ci              cur->Eliminate();
23151cb0ef41Sopenharmony_ci              continue;
23161cb0ef41Sopenharmony_ci            }
23171cb0ef41Sopenharmony_ci          }
23181cb0ef41Sopenharmony_ci        } else {
23191cb0ef41Sopenharmony_ci          Define(curr_position, &to, spill_mode);
23201cb0ef41Sopenharmony_ci        }
23211cb0ef41Sopenharmony_ci        UsePosition* from_use = Use(block_start_position, curr_position, &from,
23221cb0ef41Sopenharmony_ci                                    hint, hint_type, spill_mode);
23231cb0ef41Sopenharmony_ci        // Mark range live.
23241cb0ef41Sopenharmony_ci        if (from.IsUnallocated()) {
23251cb0ef41Sopenharmony_ci          live->Add(UnallocatedOperand::cast(from).virtual_register());
23261cb0ef41Sopenharmony_ci        }
23271cb0ef41Sopenharmony_ci        // When the value is moved to a register to meet input constraints,
23281cb0ef41Sopenharmony_ci        // we should consider this value use similar as a register use in the
23291cb0ef41Sopenharmony_ci        // backward spilling heuristics, even though this value use is not
23301cb0ef41Sopenharmony_ci        // register benefical at the AllocateBlockedReg stage.
23311cb0ef41Sopenharmony_ci        if (to.IsAnyRegister() ||
23321cb0ef41Sopenharmony_ci            (to.IsUnallocated() &&
23331cb0ef41Sopenharmony_ci             UnallocatedOperand::cast(&to)->HasRegisterPolicy())) {
23341cb0ef41Sopenharmony_ci          from_use->set_spill_detrimental();
23351cb0ef41Sopenharmony_ci        }
23361cb0ef41Sopenharmony_ci        // Resolve use position hints just created.
23371cb0ef41Sopenharmony_ci        if (to_use != nullptr && from_use != nullptr) {
23381cb0ef41Sopenharmony_ci          to_use->ResolveHint(from_use);
23391cb0ef41Sopenharmony_ci          from_use->ResolveHint(to_use);
23401cb0ef41Sopenharmony_ci        }
23411cb0ef41Sopenharmony_ci        DCHECK_IMPLIES(to_use != nullptr, to_use->IsResolved());
23421cb0ef41Sopenharmony_ci        DCHECK_IMPLIES(from_use != nullptr, from_use->IsResolved());
23431cb0ef41Sopenharmony_ci        // Potentially resolve phi hint.
23441cb0ef41Sopenharmony_ci        if (phi_vreg != -1) ResolvePhiHint(&from, from_use);
23451cb0ef41Sopenharmony_ci      }
23461cb0ef41Sopenharmony_ci    }
23471cb0ef41Sopenharmony_ci  }
23481cb0ef41Sopenharmony_ci}
23491cb0ef41Sopenharmony_ci
23501cb0ef41Sopenharmony_civoid LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
23511cb0ef41Sopenharmony_ci                                   BitVector* live) {
23521cb0ef41Sopenharmony_ci  for (PhiInstruction* phi : block->phis()) {
23531cb0ef41Sopenharmony_ci    // The live range interval already ends at the first instruction of the
23541cb0ef41Sopenharmony_ci    // block.
23551cb0ef41Sopenharmony_ci    int phi_vreg = phi->virtual_register();
23561cb0ef41Sopenharmony_ci    live->Remove(phi_vreg);
23571cb0ef41Sopenharmony_ci    // Select a hint from a predecessor block that precedes this block in the
23581cb0ef41Sopenharmony_ci    // rpo order. In order of priority:
23591cb0ef41Sopenharmony_ci    // - Avoid hints from deferred blocks.
23601cb0ef41Sopenharmony_ci    // - Prefer hints from allocated (or explicit) operands.
23611cb0ef41Sopenharmony_ci    // - Prefer hints from empty blocks (containing just parallel moves and a
23621cb0ef41Sopenharmony_ci    //   jump). In these cases, if we can elide the moves, the jump threader
23631cb0ef41Sopenharmony_ci    //   is likely to be able to elide the jump.
23641cb0ef41Sopenharmony_ci    // The enforcement of hinting in rpo order is required because hint
23651cb0ef41Sopenharmony_ci    // resolution that happens later in the compiler pipeline visits
23661cb0ef41Sopenharmony_ci    // instructions in reverse rpo order, relying on the fact that phis are
23671cb0ef41Sopenharmony_ci    // encountered before their hints.
23681cb0ef41Sopenharmony_ci    InstructionOperand* hint = nullptr;
23691cb0ef41Sopenharmony_ci    int hint_preference = 0;
23701cb0ef41Sopenharmony_ci
23711cb0ef41Sopenharmony_ci    // The cost of hinting increases with the number of predecessors. At the
23721cb0ef41Sopenharmony_ci    // same time, the typical benefit decreases, since this hinting only
23731cb0ef41Sopenharmony_ci    // optimises the execution path through one predecessor. A limit of 2 is
23741cb0ef41Sopenharmony_ci    // sufficient to hit the common if/else pattern.
23751cb0ef41Sopenharmony_ci    int predecessor_limit = 2;
23761cb0ef41Sopenharmony_ci
23771cb0ef41Sopenharmony_ci    for (RpoNumber predecessor : block->predecessors()) {
23781cb0ef41Sopenharmony_ci      const InstructionBlock* predecessor_block =
23791cb0ef41Sopenharmony_ci          code()->InstructionBlockAt(predecessor);
23801cb0ef41Sopenharmony_ci      DCHECK_EQ(predecessor_block->rpo_number(), predecessor);
23811cb0ef41Sopenharmony_ci
23821cb0ef41Sopenharmony_ci      // Only take hints from earlier rpo numbers.
23831cb0ef41Sopenharmony_ci      if (predecessor >= block->rpo_number()) continue;
23841cb0ef41Sopenharmony_ci
23851cb0ef41Sopenharmony_ci      // Look up the predecessor instruction.
23861cb0ef41Sopenharmony_ci      const Instruction* predecessor_instr =
23871cb0ef41Sopenharmony_ci          GetLastInstruction(code(), predecessor_block);
23881cb0ef41Sopenharmony_ci      InstructionOperand* predecessor_hint = nullptr;
23891cb0ef41Sopenharmony_ci      // Phis are assigned in the END position of the last instruction in each
23901cb0ef41Sopenharmony_ci      // predecessor block.
23911cb0ef41Sopenharmony_ci      for (MoveOperands* move :
23921cb0ef41Sopenharmony_ci           *predecessor_instr->GetParallelMove(Instruction::END)) {
23931cb0ef41Sopenharmony_ci        InstructionOperand& to = move->destination();
23941cb0ef41Sopenharmony_ci        if (to.IsUnallocated() &&
23951cb0ef41Sopenharmony_ci            UnallocatedOperand::cast(to).virtual_register() == phi_vreg) {
23961cb0ef41Sopenharmony_ci          predecessor_hint = &move->source();
23971cb0ef41Sopenharmony_ci          break;
23981cb0ef41Sopenharmony_ci        }
23991cb0ef41Sopenharmony_ci      }
24001cb0ef41Sopenharmony_ci      DCHECK_NOT_NULL(predecessor_hint);
24011cb0ef41Sopenharmony_ci
24021cb0ef41Sopenharmony_ci      // For each predecessor, generate a score according to the priorities
24031cb0ef41Sopenharmony_ci      // described above, and pick the best one. Flags in higher-order bits have
24041cb0ef41Sopenharmony_ci      // a higher priority than those in lower-order bits.
24051cb0ef41Sopenharmony_ci      int predecessor_hint_preference = 0;
24061cb0ef41Sopenharmony_ci      const int kNotDeferredBlockPreference = (1 << 2);
24071cb0ef41Sopenharmony_ci      const int kMoveIsAllocatedPreference = (1 << 1);
24081cb0ef41Sopenharmony_ci      const int kBlockIsEmptyPreference = (1 << 0);
24091cb0ef41Sopenharmony_ci
24101cb0ef41Sopenharmony_ci      // - Avoid hints from deferred blocks.
24111cb0ef41Sopenharmony_ci      if (!predecessor_block->IsDeferred()) {
24121cb0ef41Sopenharmony_ci        predecessor_hint_preference |= kNotDeferredBlockPreference;
24131cb0ef41Sopenharmony_ci      }
24141cb0ef41Sopenharmony_ci
24151cb0ef41Sopenharmony_ci      // - Prefer hints from allocated operands.
24161cb0ef41Sopenharmony_ci      //
24171cb0ef41Sopenharmony_ci      // Already-allocated operands are typically assigned using the parallel
24181cb0ef41Sopenharmony_ci      // moves on the last instruction. For example:
24191cb0ef41Sopenharmony_ci      //
24201cb0ef41Sopenharmony_ci      //      gap (v101 = [x0|R|w32]) (v100 = v101)
24211cb0ef41Sopenharmony_ci      //      ArchJmp
24221cb0ef41Sopenharmony_ci      //    ...
24231cb0ef41Sopenharmony_ci      //    phi: v100 = v101 v102
24241cb0ef41Sopenharmony_ci      //
24251cb0ef41Sopenharmony_ci      // We have already found the END move, so look for a matching START move
24261cb0ef41Sopenharmony_ci      // from an allocated operand.
24271cb0ef41Sopenharmony_ci      //
24281cb0ef41Sopenharmony_ci      // Note that we cannot simply look up data()->live_ranges()[vreg] here
24291cb0ef41Sopenharmony_ci      // because the live ranges are still being built when this function is
24301cb0ef41Sopenharmony_ci      // called.
24311cb0ef41Sopenharmony_ci      // TODO(v8): Find a way to separate hinting from live range analysis in
24321cb0ef41Sopenharmony_ci      // BuildLiveRanges so that we can use the O(1) live-range look-up.
24331cb0ef41Sopenharmony_ci      auto moves = predecessor_instr->GetParallelMove(Instruction::START);
24341cb0ef41Sopenharmony_ci      if (moves != nullptr) {
24351cb0ef41Sopenharmony_ci        for (MoveOperands* move : *moves) {
24361cb0ef41Sopenharmony_ci          InstructionOperand& to = move->destination();
24371cb0ef41Sopenharmony_ci          if (predecessor_hint->Equals(to)) {
24381cb0ef41Sopenharmony_ci            if (move->source().IsAllocated()) {
24391cb0ef41Sopenharmony_ci              predecessor_hint_preference |= kMoveIsAllocatedPreference;
24401cb0ef41Sopenharmony_ci            }
24411cb0ef41Sopenharmony_ci            break;
24421cb0ef41Sopenharmony_ci          }
24431cb0ef41Sopenharmony_ci        }
24441cb0ef41Sopenharmony_ci      }
24451cb0ef41Sopenharmony_ci
24461cb0ef41Sopenharmony_ci      // - Prefer hints from empty blocks.
24471cb0ef41Sopenharmony_ci      if (predecessor_block->last_instruction_index() ==
24481cb0ef41Sopenharmony_ci          predecessor_block->first_instruction_index()) {
24491cb0ef41Sopenharmony_ci        predecessor_hint_preference |= kBlockIsEmptyPreference;
24501cb0ef41Sopenharmony_ci      }
24511cb0ef41Sopenharmony_ci
24521cb0ef41Sopenharmony_ci      if ((hint == nullptr) ||
24531cb0ef41Sopenharmony_ci          (predecessor_hint_preference > hint_preference)) {
24541cb0ef41Sopenharmony_ci        // Take the hint from this predecessor.
24551cb0ef41Sopenharmony_ci        hint = predecessor_hint;
24561cb0ef41Sopenharmony_ci        hint_preference = predecessor_hint_preference;
24571cb0ef41Sopenharmony_ci      }
24581cb0ef41Sopenharmony_ci
24591cb0ef41Sopenharmony_ci      if (--predecessor_limit <= 0) break;
24601cb0ef41Sopenharmony_ci    }
24611cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(hint);
24621cb0ef41Sopenharmony_ci
24631cb0ef41Sopenharmony_ci    LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex(
24641cb0ef41Sopenharmony_ci        block->first_instruction_index());
24651cb0ef41Sopenharmony_ci    UsePosition* use_pos = Define(block_start, &phi->output(), hint,
24661cb0ef41Sopenharmony_ci                                  UsePosition::HintTypeForOperand(*hint),
24671cb0ef41Sopenharmony_ci                                  SpillModeForBlock(block));
24681cb0ef41Sopenharmony_ci    MapPhiHint(hint, use_pos);
24691cb0ef41Sopenharmony_ci  }
24701cb0ef41Sopenharmony_ci}
24711cb0ef41Sopenharmony_ci
24721cb0ef41Sopenharmony_civoid LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block,
24731cb0ef41Sopenharmony_ci                                         BitVector* live) {
24741cb0ef41Sopenharmony_ci  DCHECK(block->IsLoopHeader());
24751cb0ef41Sopenharmony_ci  // Add a live range stretching from the first loop instruction to the last
24761cb0ef41Sopenharmony_ci  // for each value live on entry to the header.
24771cb0ef41Sopenharmony_ci  LifetimePosition start = LifetimePosition::GapFromInstructionIndex(
24781cb0ef41Sopenharmony_ci      block->first_instruction_index());
24791cb0ef41Sopenharmony_ci  LifetimePosition end = LifetimePosition::GapFromInstructionIndex(
24801cb0ef41Sopenharmony_ci                             code()->LastLoopInstructionIndex(block))
24811cb0ef41Sopenharmony_ci                             .NextFullStart();
24821cb0ef41Sopenharmony_ci  for (int operand_index : *live) {
24831cb0ef41Sopenharmony_ci    TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index);
24841cb0ef41Sopenharmony_ci    range->EnsureInterval(start, end, allocation_zone(),
24851cb0ef41Sopenharmony_ci                          data()->is_trace_alloc());
24861cb0ef41Sopenharmony_ci  }
24871cb0ef41Sopenharmony_ci  // Insert all values into the live in sets of all blocks in the loop.
24881cb0ef41Sopenharmony_ci  for (int i = block->rpo_number().ToInt() + 1; i < block->loop_end().ToInt();
24891cb0ef41Sopenharmony_ci       ++i) {
24901cb0ef41Sopenharmony_ci    live_in_sets()[i]->Union(*live);
24911cb0ef41Sopenharmony_ci  }
24921cb0ef41Sopenharmony_ci}
24931cb0ef41Sopenharmony_ci
24941cb0ef41Sopenharmony_civoid LiveRangeBuilder::BuildLiveRanges() {
24951cb0ef41Sopenharmony_ci  // Process the blocks in reverse order.
24961cb0ef41Sopenharmony_ci  for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
24971cb0ef41Sopenharmony_ci       --block_id) {
24981cb0ef41Sopenharmony_ci    data_->tick_counter()->TickAndMaybeEnterSafepoint();
24991cb0ef41Sopenharmony_ci    InstructionBlock* block =
25001cb0ef41Sopenharmony_ci        code()->InstructionBlockAt(RpoNumber::FromInt(block_id));
25011cb0ef41Sopenharmony_ci    BitVector* live = ComputeLiveOut(block, data());
25021cb0ef41Sopenharmony_ci    // Initially consider all live_out values live for the entire block. We
25031cb0ef41Sopenharmony_ci    // will shorten these intervals if necessary.
25041cb0ef41Sopenharmony_ci    AddInitialIntervals(block, live);
25051cb0ef41Sopenharmony_ci    // Process the instructions in reverse order, generating and killing
25061cb0ef41Sopenharmony_ci    // live values.
25071cb0ef41Sopenharmony_ci    ProcessInstructions(block, live);
25081cb0ef41Sopenharmony_ci    // All phi output operands are killed by this block.
25091cb0ef41Sopenharmony_ci    ProcessPhis(block, live);
25101cb0ef41Sopenharmony_ci    // Now live is live_in for this block except not including values live
25111cb0ef41Sopenharmony_ci    // out on backward successor edges.
25121cb0ef41Sopenharmony_ci    if (block->IsLoopHeader()) ProcessLoopHeader(block, live);
25131cb0ef41Sopenharmony_ci    live_in_sets()[block_id] = live;
25141cb0ef41Sopenharmony_ci  }
25151cb0ef41Sopenharmony_ci  // Postprocess the ranges.
25161cb0ef41Sopenharmony_ci  const size_t live_ranges_size = data()->live_ranges().size();
25171cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* range : data()->live_ranges()) {
25181cb0ef41Sopenharmony_ci    data_->tick_counter()->TickAndMaybeEnterSafepoint();
25191cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
25201cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
25211cb0ef41Sopenharmony_ci    if (range == nullptr) continue;
25221cb0ef41Sopenharmony_ci    // Give slots to all ranges with a non fixed slot use.
25231cb0ef41Sopenharmony_ci    if (range->has_slot_use() && range->HasNoSpillType()) {
25241cb0ef41Sopenharmony_ci      SpillMode spill_mode =
25251cb0ef41Sopenharmony_ci          range->slot_use_kind() ==
25261cb0ef41Sopenharmony_ci                  TopLevelLiveRange::SlotUseKind::kDeferredSlotUse
25271cb0ef41Sopenharmony_ci              ? SpillMode::kSpillDeferred
25281cb0ef41Sopenharmony_ci              : SpillMode::kSpillAtDefinition;
25291cb0ef41Sopenharmony_ci      data()->AssignSpillRangeToLiveRange(range, spill_mode);
25301cb0ef41Sopenharmony_ci    }
25311cb0ef41Sopenharmony_ci    // TODO(bmeurer): This is a horrible hack to make sure that for constant
25321cb0ef41Sopenharmony_ci    // live ranges, every use requires the constant to be in a register.
25331cb0ef41Sopenharmony_ci    // Without this hack, all uses with "any" policy would get the constant
25341cb0ef41Sopenharmony_ci    // operand assigned.
25351cb0ef41Sopenharmony_ci    if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) {
25361cb0ef41Sopenharmony_ci      for (UsePosition* pos = range->first_pos(); pos != nullptr;
25371cb0ef41Sopenharmony_ci           pos = pos->next()) {
25381cb0ef41Sopenharmony_ci        if (pos->type() == UsePositionType::kRequiresSlot ||
25391cb0ef41Sopenharmony_ci            pos->type() == UsePositionType::kRegisterOrSlotOrConstant) {
25401cb0ef41Sopenharmony_ci          continue;
25411cb0ef41Sopenharmony_ci        }
25421cb0ef41Sopenharmony_ci        UsePositionType new_type = UsePositionType::kRegisterOrSlot;
25431cb0ef41Sopenharmony_ci        // Can't mark phis as needing a register.
25441cb0ef41Sopenharmony_ci        if (!pos->pos().IsGapPosition()) {
25451cb0ef41Sopenharmony_ci          new_type = UsePositionType::kRequiresRegister;
25461cb0ef41Sopenharmony_ci        }
25471cb0ef41Sopenharmony_ci        pos->set_type(new_type, true);
25481cb0ef41Sopenharmony_ci      }
25491cb0ef41Sopenharmony_ci    }
25501cb0ef41Sopenharmony_ci    range->ResetCurrentHintPosition();
25511cb0ef41Sopenharmony_ci  }
25521cb0ef41Sopenharmony_ci  for (auto preassigned : data()->preassigned_slot_ranges()) {
25531cb0ef41Sopenharmony_ci    TopLevelLiveRange* range = preassigned.first;
25541cb0ef41Sopenharmony_ci    int slot_id = preassigned.second;
25551cb0ef41Sopenharmony_ci    SpillRange* spill = range->HasSpillRange()
25561cb0ef41Sopenharmony_ci                            ? range->GetSpillRange()
25571cb0ef41Sopenharmony_ci                            : data()->AssignSpillRangeToLiveRange(
25581cb0ef41Sopenharmony_ci                                  range, SpillMode::kSpillAtDefinition);
25591cb0ef41Sopenharmony_ci    spill->set_assigned_slot(slot_id);
25601cb0ef41Sopenharmony_ci  }
25611cb0ef41Sopenharmony_ci#ifdef DEBUG
25621cb0ef41Sopenharmony_ci  Verify();
25631cb0ef41Sopenharmony_ci#endif
25641cb0ef41Sopenharmony_ci}
25651cb0ef41Sopenharmony_ci
25661cb0ef41Sopenharmony_civoid LiveRangeBuilder::MapPhiHint(InstructionOperand* operand,
25671cb0ef41Sopenharmony_ci                                  UsePosition* use_pos) {
25681cb0ef41Sopenharmony_ci  DCHECK(!use_pos->IsResolved());
25691cb0ef41Sopenharmony_ci  auto res = phi_hints_.insert(std::make_pair(operand, use_pos));
25701cb0ef41Sopenharmony_ci  DCHECK(res.second);
25711cb0ef41Sopenharmony_ci  USE(res);
25721cb0ef41Sopenharmony_ci}
25731cb0ef41Sopenharmony_ci
25741cb0ef41Sopenharmony_civoid LiveRangeBuilder::ResolvePhiHint(InstructionOperand* operand,
25751cb0ef41Sopenharmony_ci                                      UsePosition* use_pos) {
25761cb0ef41Sopenharmony_ci  auto it = phi_hints_.find(operand);
25771cb0ef41Sopenharmony_ci  if (it == phi_hints_.end()) return;
25781cb0ef41Sopenharmony_ci  DCHECK(!it->second->IsResolved());
25791cb0ef41Sopenharmony_ci  it->second->ResolveHint(use_pos);
25801cb0ef41Sopenharmony_ci}
25811cb0ef41Sopenharmony_ci
25821cb0ef41Sopenharmony_civoid LiveRangeBuilder::Verify() const {
25831cb0ef41Sopenharmony_ci  for (auto& hint : phi_hints_) {
25841cb0ef41Sopenharmony_ci    CHECK(hint.second->IsResolved());
25851cb0ef41Sopenharmony_ci  }
25861cb0ef41Sopenharmony_ci  for (const TopLevelLiveRange* current : data()->live_ranges()) {
25871cb0ef41Sopenharmony_ci    if (current != nullptr && !current->IsEmpty()) {
25881cb0ef41Sopenharmony_ci      // New LiveRanges should not be split.
25891cb0ef41Sopenharmony_ci      CHECK_NULL(current->next());
25901cb0ef41Sopenharmony_ci      // General integrity check.
25911cb0ef41Sopenharmony_ci      current->Verify();
25921cb0ef41Sopenharmony_ci      const UseInterval* first = current->first_interval();
25931cb0ef41Sopenharmony_ci      if (first->next() == nullptr) continue;
25941cb0ef41Sopenharmony_ci
25951cb0ef41Sopenharmony_ci      // Consecutive intervals should not end and start in the same block,
25961cb0ef41Sopenharmony_ci      // otherwise the intervals should have been joined, because the
25971cb0ef41Sopenharmony_ci      // variable is live throughout that block.
25981cb0ef41Sopenharmony_ci      CHECK(NextIntervalStartsInDifferentBlocks(first));
25991cb0ef41Sopenharmony_ci
26001cb0ef41Sopenharmony_ci      for (const UseInterval* i = first->next(); i != nullptr; i = i->next()) {
26011cb0ef41Sopenharmony_ci        // Except for the first interval, the other intevals must start at
26021cb0ef41Sopenharmony_ci        // a block boundary, otherwise data wouldn't flow to them.
26031cb0ef41Sopenharmony_ci        CHECK(IntervalStartsAtBlockBoundary(i));
26041cb0ef41Sopenharmony_ci        // The last instruction of the predecessors of the block the interval
26051cb0ef41Sopenharmony_ci        // starts must be covered by the range.
26061cb0ef41Sopenharmony_ci        CHECK(IntervalPredecessorsCoveredByRange(i, current));
26071cb0ef41Sopenharmony_ci        if (i->next() != nullptr) {
26081cb0ef41Sopenharmony_ci          // Check the consecutive intervals property, except for the last
26091cb0ef41Sopenharmony_ci          // interval, where it doesn't apply.
26101cb0ef41Sopenharmony_ci          CHECK(NextIntervalStartsInDifferentBlocks(i));
26111cb0ef41Sopenharmony_ci        }
26121cb0ef41Sopenharmony_ci      }
26131cb0ef41Sopenharmony_ci    }
26141cb0ef41Sopenharmony_ci  }
26151cb0ef41Sopenharmony_ci}
26161cb0ef41Sopenharmony_ci
26171cb0ef41Sopenharmony_cibool LiveRangeBuilder::IntervalStartsAtBlockBoundary(
26181cb0ef41Sopenharmony_ci    const UseInterval* interval) const {
26191cb0ef41Sopenharmony_ci  LifetimePosition start = interval->start();
26201cb0ef41Sopenharmony_ci  if (!start.IsFullStart()) return false;
26211cb0ef41Sopenharmony_ci  int instruction_index = start.ToInstructionIndex();
26221cb0ef41Sopenharmony_ci  const InstructionBlock* block =
26231cb0ef41Sopenharmony_ci      data()->code()->GetInstructionBlock(instruction_index);
26241cb0ef41Sopenharmony_ci  return block->first_instruction_index() == instruction_index;
26251cb0ef41Sopenharmony_ci}
26261cb0ef41Sopenharmony_ci
26271cb0ef41Sopenharmony_cibool LiveRangeBuilder::IntervalPredecessorsCoveredByRange(
26281cb0ef41Sopenharmony_ci    const UseInterval* interval, const TopLevelLiveRange* range) const {
26291cb0ef41Sopenharmony_ci  LifetimePosition start = interval->start();
26301cb0ef41Sopenharmony_ci  int instruction_index = start.ToInstructionIndex();
26311cb0ef41Sopenharmony_ci  const InstructionBlock* block =
26321cb0ef41Sopenharmony_ci      data()->code()->GetInstructionBlock(instruction_index);
26331cb0ef41Sopenharmony_ci  for (RpoNumber pred_index : block->predecessors()) {
26341cb0ef41Sopenharmony_ci    const InstructionBlock* predecessor =
26351cb0ef41Sopenharmony_ci        data()->code()->InstructionBlockAt(pred_index);
26361cb0ef41Sopenharmony_ci    LifetimePosition last_pos = LifetimePosition::GapFromInstructionIndex(
26371cb0ef41Sopenharmony_ci        predecessor->last_instruction_index());
26381cb0ef41Sopenharmony_ci    last_pos = last_pos.NextStart().End();
26391cb0ef41Sopenharmony_ci    if (!range->Covers(last_pos)) return false;
26401cb0ef41Sopenharmony_ci  }
26411cb0ef41Sopenharmony_ci  return true;
26421cb0ef41Sopenharmony_ci}
26431cb0ef41Sopenharmony_ci
26441cb0ef41Sopenharmony_cibool LiveRangeBuilder::NextIntervalStartsInDifferentBlocks(
26451cb0ef41Sopenharmony_ci    const UseInterval* interval) const {
26461cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(interval->next());
26471cb0ef41Sopenharmony_ci  LifetimePosition end = interval->end();
26481cb0ef41Sopenharmony_ci  LifetimePosition next_start = interval->next()->start();
26491cb0ef41Sopenharmony_ci  // Since end is not covered, but the previous position is, move back a
26501cb0ef41Sopenharmony_ci  // position
26511cb0ef41Sopenharmony_ci  end = end.IsStart() ? end.PrevStart().End() : end.Start();
26521cb0ef41Sopenharmony_ci  int last_covered_index = end.ToInstructionIndex();
26531cb0ef41Sopenharmony_ci  const InstructionBlock* block =
26541cb0ef41Sopenharmony_ci      data()->code()->GetInstructionBlock(last_covered_index);
26551cb0ef41Sopenharmony_ci  const InstructionBlock* next_block =
26561cb0ef41Sopenharmony_ci      data()->code()->GetInstructionBlock(next_start.ToInstructionIndex());
26571cb0ef41Sopenharmony_ci  return block->rpo_number() < next_block->rpo_number();
26581cb0ef41Sopenharmony_ci}
26591cb0ef41Sopenharmony_ci
26601cb0ef41Sopenharmony_civoid BundleBuilder::BuildBundles() {
26611cb0ef41Sopenharmony_ci  TRACE("Build bundles\n");
26621cb0ef41Sopenharmony_ci  // Process the blocks in reverse order.
26631cb0ef41Sopenharmony_ci  for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
26641cb0ef41Sopenharmony_ci       --block_id) {
26651cb0ef41Sopenharmony_ci    InstructionBlock* block =
26661cb0ef41Sopenharmony_ci        code()->InstructionBlockAt(RpoNumber::FromInt(block_id));
26671cb0ef41Sopenharmony_ci    TRACE("Block B%d\n", block_id);
26681cb0ef41Sopenharmony_ci    for (auto phi : block->phis()) {
26691cb0ef41Sopenharmony_ci      LiveRange* out_range =
26701cb0ef41Sopenharmony_ci          data()->GetOrCreateLiveRangeFor(phi->virtual_register());
26711cb0ef41Sopenharmony_ci      LiveRangeBundle* out = out_range->get_bundle();
26721cb0ef41Sopenharmony_ci      if (out == nullptr) {
26731cb0ef41Sopenharmony_ci        out = data()->allocation_zone()->New<LiveRangeBundle>(
26741cb0ef41Sopenharmony_ci            data()->allocation_zone(), next_bundle_id_++);
26751cb0ef41Sopenharmony_ci        out->TryAddRange(out_range);
26761cb0ef41Sopenharmony_ci      }
26771cb0ef41Sopenharmony_ci      TRACE("Processing phi for v%d with %d:%d\n", phi->virtual_register(),
26781cb0ef41Sopenharmony_ci            out_range->TopLevel()->vreg(), out_range->relative_id());
26791cb0ef41Sopenharmony_ci      bool phi_interferes_with_backedge_input = false;
26801cb0ef41Sopenharmony_ci      for (auto input : phi->operands()) {
26811cb0ef41Sopenharmony_ci        LiveRange* input_range = data()->GetOrCreateLiveRangeFor(input);
26821cb0ef41Sopenharmony_ci        TRACE("Input value v%d with range %d:%d\n", input,
26831cb0ef41Sopenharmony_ci              input_range->TopLevel()->vreg(), input_range->relative_id());
26841cb0ef41Sopenharmony_ci        LiveRangeBundle* input_bundle = input_range->get_bundle();
26851cb0ef41Sopenharmony_ci        if (input_bundle != nullptr) {
26861cb0ef41Sopenharmony_ci          TRACE("Merge\n");
26871cb0ef41Sopenharmony_ci          LiveRangeBundle* merged = LiveRangeBundle::TryMerge(
26881cb0ef41Sopenharmony_ci              out, input_bundle, data()->is_trace_alloc());
26891cb0ef41Sopenharmony_ci          if (merged != nullptr) {
26901cb0ef41Sopenharmony_ci            DCHECK_EQ(out_range->get_bundle(), merged);
26911cb0ef41Sopenharmony_ci            DCHECK_EQ(input_range->get_bundle(), merged);
26921cb0ef41Sopenharmony_ci            out = merged;
26931cb0ef41Sopenharmony_ci            TRACE("Merged %d and %d to %d\n", phi->virtual_register(), input,
26941cb0ef41Sopenharmony_ci                  out->id());
26951cb0ef41Sopenharmony_ci          } else if (input_range->Start() > out_range->Start()) {
26961cb0ef41Sopenharmony_ci            // We are only interested in values defined after the phi, because
26971cb0ef41Sopenharmony_ci            // those are values that will go over a back-edge.
26981cb0ef41Sopenharmony_ci            phi_interferes_with_backedge_input = true;
26991cb0ef41Sopenharmony_ci          }
27001cb0ef41Sopenharmony_ci        } else {
27011cb0ef41Sopenharmony_ci          TRACE("Add\n");
27021cb0ef41Sopenharmony_ci          if (out->TryAddRange(input_range)) {
27031cb0ef41Sopenharmony_ci            TRACE("Added %d and %d to %d\n", phi->virtual_register(), input,
27041cb0ef41Sopenharmony_ci                  out->id());
27051cb0ef41Sopenharmony_ci          } else if (input_range->Start() > out_range->Start()) {
27061cb0ef41Sopenharmony_ci            // We are only interested in values defined after the phi, because
27071cb0ef41Sopenharmony_ci            // those are values that will go over a back-edge.
27081cb0ef41Sopenharmony_ci            phi_interferes_with_backedge_input = true;
27091cb0ef41Sopenharmony_ci          }
27101cb0ef41Sopenharmony_ci        }
27111cb0ef41Sopenharmony_ci      }
27121cb0ef41Sopenharmony_ci      // Spilling the phi at the loop header is not beneficial if there is
27131cb0ef41Sopenharmony_ci      // a back-edge with an input for the phi that interferes with the phi's
27141cb0ef41Sopenharmony_ci      // value, because in case that input gets spilled it might introduce
27151cb0ef41Sopenharmony_ci      // a stack-to-stack move at the back-edge.
27161cb0ef41Sopenharmony_ci      if (phi_interferes_with_backedge_input)
27171cb0ef41Sopenharmony_ci        out_range->TopLevel()->set_spilling_at_loop_header_not_beneficial();
27181cb0ef41Sopenharmony_ci    }
27191cb0ef41Sopenharmony_ci    TRACE("Done block B%d\n", block_id);
27201cb0ef41Sopenharmony_ci  }
27211cb0ef41Sopenharmony_ci}
27221cb0ef41Sopenharmony_ci
27231cb0ef41Sopenharmony_cibool LiveRangeBundle::TryAddRange(LiveRange* range) {
27241cb0ef41Sopenharmony_ci  DCHECK_NULL(range->get_bundle());
27251cb0ef41Sopenharmony_ci  // We may only add a new live range if its use intervals do not
27261cb0ef41Sopenharmony_ci  // overlap with existing intervals in the bundle.
27271cb0ef41Sopenharmony_ci  if (UsesOverlap(range->first_interval())) return false;
27281cb0ef41Sopenharmony_ci  ranges_.insert(range);
27291cb0ef41Sopenharmony_ci  range->set_bundle(this);
27301cb0ef41Sopenharmony_ci  InsertUses(range->first_interval());
27311cb0ef41Sopenharmony_ci  return true;
27321cb0ef41Sopenharmony_ci}
27331cb0ef41Sopenharmony_ci
27341cb0ef41Sopenharmony_ciLiveRangeBundle* LiveRangeBundle::TryMerge(LiveRangeBundle* lhs,
27351cb0ef41Sopenharmony_ci                                           LiveRangeBundle* rhs,
27361cb0ef41Sopenharmony_ci                                           bool trace_alloc) {
27371cb0ef41Sopenharmony_ci  if (rhs == lhs) return lhs;
27381cb0ef41Sopenharmony_ci
27391cb0ef41Sopenharmony_ci  auto iter1 = lhs->uses_.begin();
27401cb0ef41Sopenharmony_ci  auto iter2 = rhs->uses_.begin();
27411cb0ef41Sopenharmony_ci
27421cb0ef41Sopenharmony_ci  while (iter1 != lhs->uses_.end() && iter2 != rhs->uses_.end()) {
27431cb0ef41Sopenharmony_ci    if (iter1->start >= iter2->end) {
27441cb0ef41Sopenharmony_ci      ++iter2;
27451cb0ef41Sopenharmony_ci    } else if (iter2->start >= iter1->end) {
27461cb0ef41Sopenharmony_ci      ++iter1;
27471cb0ef41Sopenharmony_ci    } else {
27481cb0ef41Sopenharmony_ci      TRACE_COND(trace_alloc, "No merge %d:%d %d:%d\n", iter1->start,
27491cb0ef41Sopenharmony_ci                 iter1->end, iter2->start, iter2->end);
27501cb0ef41Sopenharmony_ci      return nullptr;
27511cb0ef41Sopenharmony_ci    }
27521cb0ef41Sopenharmony_ci  }
27531cb0ef41Sopenharmony_ci  // Uses are disjoint, merging is possible.
27541cb0ef41Sopenharmony_ci  if (lhs->uses_.size() < rhs->uses_.size()) {
27551cb0ef41Sopenharmony_ci    // Merge the smallest bundle into the biggest.
27561cb0ef41Sopenharmony_ci    std::swap(lhs, rhs);
27571cb0ef41Sopenharmony_ci  }
27581cb0ef41Sopenharmony_ci  for (auto it = rhs->ranges_.begin(); it != rhs->ranges_.end(); ++it) {
27591cb0ef41Sopenharmony_ci    (*it)->set_bundle(lhs);
27601cb0ef41Sopenharmony_ci    lhs->InsertUses((*it)->first_interval());
27611cb0ef41Sopenharmony_ci  }
27621cb0ef41Sopenharmony_ci  lhs->ranges_.insert(rhs->ranges_.begin(), rhs->ranges_.end());
27631cb0ef41Sopenharmony_ci  rhs->ranges_.clear();
27641cb0ef41Sopenharmony_ci  return lhs;
27651cb0ef41Sopenharmony_ci}
27661cb0ef41Sopenharmony_ci
27671cb0ef41Sopenharmony_civoid LiveRangeBundle::MergeSpillRangesAndClear() {
27681cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(ranges_.empty(), uses_.empty());
27691cb0ef41Sopenharmony_ci  SpillRange* target = nullptr;
27701cb0ef41Sopenharmony_ci  for (auto range : ranges_) {
27711cb0ef41Sopenharmony_ci    if (range->TopLevel()->HasSpillRange()) {
27721cb0ef41Sopenharmony_ci      SpillRange* current = range->TopLevel()->GetSpillRange();
27731cb0ef41Sopenharmony_ci      if (target == nullptr) {
27741cb0ef41Sopenharmony_ci        target = current;
27751cb0ef41Sopenharmony_ci      } else if (target != current) {
27761cb0ef41Sopenharmony_ci        target->TryMerge(current);
27771cb0ef41Sopenharmony_ci      }
27781cb0ef41Sopenharmony_ci    }
27791cb0ef41Sopenharmony_ci  }
27801cb0ef41Sopenharmony_ci  // Clear the fields so that we don't try to merge the spill ranges again when
27811cb0ef41Sopenharmony_ci  // we hit the same bundle from a different LiveRange in AssignSpillSlots.
27821cb0ef41Sopenharmony_ci  // LiveRangeBundles are not used after this.
27831cb0ef41Sopenharmony_ci  ranges_.clear();
27841cb0ef41Sopenharmony_ci  uses_.clear();
27851cb0ef41Sopenharmony_ci}
27861cb0ef41Sopenharmony_ci
27871cb0ef41Sopenharmony_ciRegisterAllocator::RegisterAllocator(TopTierRegisterAllocationData* data,
27881cb0ef41Sopenharmony_ci                                     RegisterKind kind)
27891cb0ef41Sopenharmony_ci    : data_(data),
27901cb0ef41Sopenharmony_ci      mode_(kind),
27911cb0ef41Sopenharmony_ci      num_registers_(GetRegisterCount(data->config(), kind)),
27921cb0ef41Sopenharmony_ci      num_allocatable_registers_(
27931cb0ef41Sopenharmony_ci          GetAllocatableRegisterCount(data->config(), kind)),
27941cb0ef41Sopenharmony_ci      allocatable_register_codes_(
27951cb0ef41Sopenharmony_ci          GetAllocatableRegisterCodes(data->config(), kind)),
27961cb0ef41Sopenharmony_ci      check_fp_aliasing_(false) {
27971cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kCombine && kind == RegisterKind::kDouble) {
27981cb0ef41Sopenharmony_ci    check_fp_aliasing_ = (data->code()->representation_mask() &
27991cb0ef41Sopenharmony_ci                          (kFloat32Bit | kSimd128Bit)) != 0;
28001cb0ef41Sopenharmony_ci  }
28011cb0ef41Sopenharmony_ci}
28021cb0ef41Sopenharmony_ci
28031cb0ef41Sopenharmony_ciLifetimePosition RegisterAllocator::GetSplitPositionForInstruction(
28041cb0ef41Sopenharmony_ci    const LiveRange* range, int instruction_index) {
28051cb0ef41Sopenharmony_ci  LifetimePosition ret = LifetimePosition::Invalid();
28061cb0ef41Sopenharmony_ci
28071cb0ef41Sopenharmony_ci  ret = LifetimePosition::GapFromInstructionIndex(instruction_index);
28081cb0ef41Sopenharmony_ci  if (range->Start() >= ret || ret >= range->End()) {
28091cb0ef41Sopenharmony_ci    return LifetimePosition::Invalid();
28101cb0ef41Sopenharmony_ci  }
28111cb0ef41Sopenharmony_ci  return ret;
28121cb0ef41Sopenharmony_ci}
28131cb0ef41Sopenharmony_ci
28141cb0ef41Sopenharmony_civoid RegisterAllocator::SplitAndSpillRangesDefinedByMemoryOperand() {
28151cb0ef41Sopenharmony_ci  size_t initial_range_count = data()->live_ranges().size();
28161cb0ef41Sopenharmony_ci  for (size_t i = 0; i < initial_range_count; ++i) {
28171cb0ef41Sopenharmony_ci    CHECK_EQ(initial_range_count,
28181cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
28191cb0ef41Sopenharmony_ci    TopLevelLiveRange* range = data()->live_ranges()[i];
28201cb0ef41Sopenharmony_ci    if (!CanProcessRange(range)) continue;
28211cb0ef41Sopenharmony_ci    // Only assume defined by memory operand if we are guaranteed to spill it or
28221cb0ef41Sopenharmony_ci    // it has a spill operand.
28231cb0ef41Sopenharmony_ci    if (range->HasNoSpillType() ||
28241cb0ef41Sopenharmony_ci        (range->HasSpillRange() && !range->has_non_deferred_slot_use())) {
28251cb0ef41Sopenharmony_ci      continue;
28261cb0ef41Sopenharmony_ci    }
28271cb0ef41Sopenharmony_ci    LifetimePosition start = range->Start();
28281cb0ef41Sopenharmony_ci    TRACE("Live range %d:%d is defined by a spill operand.\n",
28291cb0ef41Sopenharmony_ci          range->TopLevel()->vreg(), range->relative_id());
28301cb0ef41Sopenharmony_ci    LifetimePosition next_pos = start;
28311cb0ef41Sopenharmony_ci    if (next_pos.IsGapPosition()) {
28321cb0ef41Sopenharmony_ci      next_pos = next_pos.NextStart();
28331cb0ef41Sopenharmony_ci    }
28341cb0ef41Sopenharmony_ci
28351cb0ef41Sopenharmony_ci    UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
28361cb0ef41Sopenharmony_ci    // If the range already has a spill operand and it doesn't need a
28371cb0ef41Sopenharmony_ci    // register immediately, split it and spill the first part of the range.
28381cb0ef41Sopenharmony_ci    if (pos == nullptr) {
28391cb0ef41Sopenharmony_ci      Spill(range, SpillMode::kSpillAtDefinition);
28401cb0ef41Sopenharmony_ci    } else if (pos->pos() > range->Start().NextStart()) {
28411cb0ef41Sopenharmony_ci      // Do not spill live range eagerly if use position that can benefit from
28421cb0ef41Sopenharmony_ci      // the register is too close to the start of live range.
28431cb0ef41Sopenharmony_ci      LifetimePosition split_pos = GetSplitPositionForInstruction(
28441cb0ef41Sopenharmony_ci          range, pos->pos().ToInstructionIndex());
28451cb0ef41Sopenharmony_ci      // There is no place to split, so we can't split and spill.
28461cb0ef41Sopenharmony_ci      if (!split_pos.IsValid()) continue;
28471cb0ef41Sopenharmony_ci
28481cb0ef41Sopenharmony_ci      split_pos =
28491cb0ef41Sopenharmony_ci          FindOptimalSplitPos(range->Start().NextFullStart(), split_pos);
28501cb0ef41Sopenharmony_ci
28511cb0ef41Sopenharmony_ci      SplitRangeAt(range, split_pos);
28521cb0ef41Sopenharmony_ci      Spill(range, SpillMode::kSpillAtDefinition);
28531cb0ef41Sopenharmony_ci    }
28541cb0ef41Sopenharmony_ci  }
28551cb0ef41Sopenharmony_ci}
28561cb0ef41Sopenharmony_ci
28571cb0ef41Sopenharmony_ciLiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range,
28581cb0ef41Sopenharmony_ci                                           LifetimePosition pos) {
28591cb0ef41Sopenharmony_ci  DCHECK(!range->TopLevel()->IsFixed());
28601cb0ef41Sopenharmony_ci  TRACE("Splitting live range %d:%d at %d\n", range->TopLevel()->vreg(),
28611cb0ef41Sopenharmony_ci        range->relative_id(), pos.value());
28621cb0ef41Sopenharmony_ci
28631cb0ef41Sopenharmony_ci  if (pos <= range->Start()) return range;
28641cb0ef41Sopenharmony_ci
28651cb0ef41Sopenharmony_ci  // We can't properly connect liveranges if splitting occurred at the end
28661cb0ef41Sopenharmony_ci  // a block.
28671cb0ef41Sopenharmony_ci  DCHECK(pos.IsStart() || pos.IsGapPosition() ||
28681cb0ef41Sopenharmony_ci         (GetInstructionBlock(code(), pos)->last_instruction_index() !=
28691cb0ef41Sopenharmony_ci          pos.ToInstructionIndex()));
28701cb0ef41Sopenharmony_ci
28711cb0ef41Sopenharmony_ci  LiveRange* result = range->SplitAt(pos, allocation_zone());
28721cb0ef41Sopenharmony_ci  return result;
28731cb0ef41Sopenharmony_ci}
28741cb0ef41Sopenharmony_ci
28751cb0ef41Sopenharmony_ciLiveRange* RegisterAllocator::SplitBetween(LiveRange* range,
28761cb0ef41Sopenharmony_ci                                           LifetimePosition start,
28771cb0ef41Sopenharmony_ci                                           LifetimePosition end) {
28781cb0ef41Sopenharmony_ci  DCHECK(!range->TopLevel()->IsFixed());
28791cb0ef41Sopenharmony_ci  TRACE("Splitting live range %d:%d in position between [%d, %d]\n",
28801cb0ef41Sopenharmony_ci        range->TopLevel()->vreg(), range->relative_id(), start.value(),
28811cb0ef41Sopenharmony_ci        end.value());
28821cb0ef41Sopenharmony_ci
28831cb0ef41Sopenharmony_ci  LifetimePosition split_pos = FindOptimalSplitPos(start, end);
28841cb0ef41Sopenharmony_ci  DCHECK(split_pos >= start);
28851cb0ef41Sopenharmony_ci  return SplitRangeAt(range, split_pos);
28861cb0ef41Sopenharmony_ci}
28871cb0ef41Sopenharmony_ci
28881cb0ef41Sopenharmony_ciLifetimePosition RegisterAllocator::FindOptimalSplitPos(LifetimePosition start,
28891cb0ef41Sopenharmony_ci                                                        LifetimePosition end) {
28901cb0ef41Sopenharmony_ci  int start_instr = start.ToInstructionIndex();
28911cb0ef41Sopenharmony_ci  int end_instr = end.ToInstructionIndex();
28921cb0ef41Sopenharmony_ci  DCHECK_LE(start_instr, end_instr);
28931cb0ef41Sopenharmony_ci
28941cb0ef41Sopenharmony_ci  // We have no choice
28951cb0ef41Sopenharmony_ci  if (start_instr == end_instr) return end;
28961cb0ef41Sopenharmony_ci
28971cb0ef41Sopenharmony_ci  const InstructionBlock* start_block = GetInstructionBlock(code(), start);
28981cb0ef41Sopenharmony_ci  const InstructionBlock* end_block = GetInstructionBlock(code(), end);
28991cb0ef41Sopenharmony_ci
29001cb0ef41Sopenharmony_ci  if (end_block == start_block) {
29011cb0ef41Sopenharmony_ci    // The interval is split in the same basic block. Split at the latest
29021cb0ef41Sopenharmony_ci    // possible position.
29031cb0ef41Sopenharmony_ci    return end;
29041cb0ef41Sopenharmony_ci  }
29051cb0ef41Sopenharmony_ci
29061cb0ef41Sopenharmony_ci  const InstructionBlock* block = end_block;
29071cb0ef41Sopenharmony_ci  // Find header of outermost loop.
29081cb0ef41Sopenharmony_ci  do {
29091cb0ef41Sopenharmony_ci    const InstructionBlock* loop = GetContainingLoop(code(), block);
29101cb0ef41Sopenharmony_ci    if (loop == nullptr ||
29111cb0ef41Sopenharmony_ci        loop->rpo_number().ToInt() <= start_block->rpo_number().ToInt()) {
29121cb0ef41Sopenharmony_ci      // No more loops or loop starts before the lifetime start.
29131cb0ef41Sopenharmony_ci      break;
29141cb0ef41Sopenharmony_ci    }
29151cb0ef41Sopenharmony_ci    block = loop;
29161cb0ef41Sopenharmony_ci  } while (true);
29171cb0ef41Sopenharmony_ci
29181cb0ef41Sopenharmony_ci  // We did not find any suitable outer loop. Split at the latest possible
29191cb0ef41Sopenharmony_ci  // position unless end_block is a loop header itself.
29201cb0ef41Sopenharmony_ci  if (block == end_block && !end_block->IsLoopHeader()) return end;
29211cb0ef41Sopenharmony_ci
29221cb0ef41Sopenharmony_ci  return LifetimePosition::GapFromInstructionIndex(
29231cb0ef41Sopenharmony_ci      block->first_instruction_index());
29241cb0ef41Sopenharmony_ci}
29251cb0ef41Sopenharmony_ci
29261cb0ef41Sopenharmony_ciLifetimePosition RegisterAllocator::FindOptimalSpillingPos(
29271cb0ef41Sopenharmony_ci    LiveRange* range, LifetimePosition pos, SpillMode spill_mode,
29281cb0ef41Sopenharmony_ci    LiveRange** begin_spill_out) {
29291cb0ef41Sopenharmony_ci  *begin_spill_out = range;
29301cb0ef41Sopenharmony_ci  // TODO(herhut): Be more clever here as long as we do not move pos out of
29311cb0ef41Sopenharmony_ci  // deferred code.
29321cb0ef41Sopenharmony_ci  if (spill_mode == SpillMode::kSpillDeferred) return pos;
29331cb0ef41Sopenharmony_ci  const InstructionBlock* block = GetInstructionBlock(code(), pos.Start());
29341cb0ef41Sopenharmony_ci  const InstructionBlock* loop_header =
29351cb0ef41Sopenharmony_ci      block->IsLoopHeader() ? block : GetContainingLoop(code(), block);
29361cb0ef41Sopenharmony_ci  if (loop_header == nullptr) return pos;
29371cb0ef41Sopenharmony_ci
29381cb0ef41Sopenharmony_ci  while (loop_header != nullptr) {
29391cb0ef41Sopenharmony_ci    // We are going to spill live range inside the loop.
29401cb0ef41Sopenharmony_ci    // If possible try to move spilling position backwards to loop header.
29411cb0ef41Sopenharmony_ci    // This will reduce number of memory moves on the back edge.
29421cb0ef41Sopenharmony_ci    LifetimePosition loop_start = LifetimePosition::GapFromInstructionIndex(
29431cb0ef41Sopenharmony_ci        loop_header->first_instruction_index());
29441cb0ef41Sopenharmony_ci    // Stop if we moved to a loop header before the value is defined or
29451cb0ef41Sopenharmony_ci    // at the define position that is not beneficial to spill.
29461cb0ef41Sopenharmony_ci    if (range->TopLevel()->Start() > loop_start ||
29471cb0ef41Sopenharmony_ci        (range->TopLevel()->Start() == loop_start &&
29481cb0ef41Sopenharmony_ci         range->TopLevel()->SpillAtLoopHeaderNotBeneficial()))
29491cb0ef41Sopenharmony_ci      return pos;
29501cb0ef41Sopenharmony_ci
29511cb0ef41Sopenharmony_ci    LiveRange* live_at_header = range->TopLevel()->GetChildCovers(loop_start);
29521cb0ef41Sopenharmony_ci
29531cb0ef41Sopenharmony_ci    if (live_at_header != nullptr && !live_at_header->spilled()) {
29541cb0ef41Sopenharmony_ci      for (LiveRange* check_use = live_at_header;
29551cb0ef41Sopenharmony_ci           check_use != nullptr && check_use->Start() < pos;
29561cb0ef41Sopenharmony_ci           check_use = check_use->next()) {
29571cb0ef41Sopenharmony_ci        // If we find a use for which spilling is detrimental, don't spill
29581cb0ef41Sopenharmony_ci        // at the loop header
29591cb0ef41Sopenharmony_ci        UsePosition* next_use =
29601cb0ef41Sopenharmony_ci            check_use->NextUsePositionSpillDetrimental(loop_start);
29611cb0ef41Sopenharmony_ci        // UsePosition at the end of a UseInterval may
29621cb0ef41Sopenharmony_ci        // have the same value as the start of next range.
29631cb0ef41Sopenharmony_ci        if (next_use != nullptr && next_use->pos() <= pos) {
29641cb0ef41Sopenharmony_ci          return pos;
29651cb0ef41Sopenharmony_ci        }
29661cb0ef41Sopenharmony_ci      }
29671cb0ef41Sopenharmony_ci      // No register beneficial use inside the loop before the pos.
29681cb0ef41Sopenharmony_ci      *begin_spill_out = live_at_header;
29691cb0ef41Sopenharmony_ci      pos = loop_start;
29701cb0ef41Sopenharmony_ci    }
29711cb0ef41Sopenharmony_ci
29721cb0ef41Sopenharmony_ci    // Try hoisting out to an outer loop.
29731cb0ef41Sopenharmony_ci    loop_header = GetContainingLoop(code(), loop_header);
29741cb0ef41Sopenharmony_ci  }
29751cb0ef41Sopenharmony_ci  return pos;
29761cb0ef41Sopenharmony_ci}
29771cb0ef41Sopenharmony_ci
29781cb0ef41Sopenharmony_civoid RegisterAllocator::Spill(LiveRange* range, SpillMode spill_mode) {
29791cb0ef41Sopenharmony_ci  DCHECK(!range->spilled());
29801cb0ef41Sopenharmony_ci  DCHECK(spill_mode == SpillMode::kSpillAtDefinition ||
29811cb0ef41Sopenharmony_ci         GetInstructionBlock(code(), range->Start())->IsDeferred());
29821cb0ef41Sopenharmony_ci  TopLevelLiveRange* first = range->TopLevel();
29831cb0ef41Sopenharmony_ci  TRACE("Spilling live range %d:%d mode %d\n", first->vreg(),
29841cb0ef41Sopenharmony_ci        range->relative_id(), spill_mode);
29851cb0ef41Sopenharmony_ci
29861cb0ef41Sopenharmony_ci  TRACE("Starting spill type is %d\n", static_cast<int>(first->spill_type()));
29871cb0ef41Sopenharmony_ci  if (first->HasNoSpillType()) {
29881cb0ef41Sopenharmony_ci    TRACE("New spill range needed");
29891cb0ef41Sopenharmony_ci    data()->AssignSpillRangeToLiveRange(first, spill_mode);
29901cb0ef41Sopenharmony_ci  }
29911cb0ef41Sopenharmony_ci  // Upgrade the spillmode, in case this was only spilled in deferred code so
29921cb0ef41Sopenharmony_ci  // far.
29931cb0ef41Sopenharmony_ci  if ((spill_mode == SpillMode::kSpillAtDefinition) &&
29941cb0ef41Sopenharmony_ci      (first->spill_type() ==
29951cb0ef41Sopenharmony_ci       TopLevelLiveRange::SpillType::kDeferredSpillRange)) {
29961cb0ef41Sopenharmony_ci    TRACE("Upgrading\n");
29971cb0ef41Sopenharmony_ci    first->set_spill_type(TopLevelLiveRange::SpillType::kSpillRange);
29981cb0ef41Sopenharmony_ci  }
29991cb0ef41Sopenharmony_ci  TRACE("Final spill type is %d\n", static_cast<int>(first->spill_type()));
30001cb0ef41Sopenharmony_ci  range->Spill();
30011cb0ef41Sopenharmony_ci}
30021cb0ef41Sopenharmony_ci
30031cb0ef41Sopenharmony_ciconst char* RegisterAllocator::RegisterName(int register_code) const {
30041cb0ef41Sopenharmony_ci  if (register_code == kUnassignedRegister) return "unassigned";
30051cb0ef41Sopenharmony_ci  switch (mode()) {
30061cb0ef41Sopenharmony_ci    case RegisterKind::kGeneral:
30071cb0ef41Sopenharmony_ci      return i::RegisterName(Register::from_code(register_code));
30081cb0ef41Sopenharmony_ci    case RegisterKind::kDouble:
30091cb0ef41Sopenharmony_ci      return i::RegisterName(DoubleRegister::from_code(register_code));
30101cb0ef41Sopenharmony_ci    case RegisterKind::kSimd128:
30111cb0ef41Sopenharmony_ci      return i::RegisterName(Simd128Register::from_code(register_code));
30121cb0ef41Sopenharmony_ci  }
30131cb0ef41Sopenharmony_ci}
30141cb0ef41Sopenharmony_ci
30151cb0ef41Sopenharmony_ciLinearScanAllocator::LinearScanAllocator(TopTierRegisterAllocationData* data,
30161cb0ef41Sopenharmony_ci                                         RegisterKind kind, Zone* local_zone)
30171cb0ef41Sopenharmony_ci    : RegisterAllocator(data, kind),
30181cb0ef41Sopenharmony_ci      unhandled_live_ranges_(local_zone),
30191cb0ef41Sopenharmony_ci      active_live_ranges_(local_zone),
30201cb0ef41Sopenharmony_ci      inactive_live_ranges_(num_registers(), InactiveLiveRangeQueue(local_zone),
30211cb0ef41Sopenharmony_ci                            local_zone),
30221cb0ef41Sopenharmony_ci      next_active_ranges_change_(LifetimePosition::Invalid()),
30231cb0ef41Sopenharmony_ci      next_inactive_ranges_change_(LifetimePosition::Invalid()) {
30241cb0ef41Sopenharmony_ci  active_live_ranges().reserve(8);
30251cb0ef41Sopenharmony_ci}
30261cb0ef41Sopenharmony_ci
30271cb0ef41Sopenharmony_civoid LinearScanAllocator::MaybeSpillPreviousRanges(LiveRange* begin_range,
30281cb0ef41Sopenharmony_ci                                                   LifetimePosition begin_pos,
30291cb0ef41Sopenharmony_ci                                                   LiveRange* end_range) {
30301cb0ef41Sopenharmony_ci  // Spill begin_range after begin_pos, then spill every live range of this
30311cb0ef41Sopenharmony_ci  // virtual register until but excluding end_range.
30321cb0ef41Sopenharmony_ci  DCHECK(begin_range->Covers(begin_pos));
30331cb0ef41Sopenharmony_ci  DCHECK_EQ(begin_range->TopLevel(), end_range->TopLevel());
30341cb0ef41Sopenharmony_ci
30351cb0ef41Sopenharmony_ci  if (begin_range != end_range) {
30361cb0ef41Sopenharmony_ci    DCHECK_LE(begin_range->End(), end_range->Start());
30371cb0ef41Sopenharmony_ci    if (!begin_range->spilled()) {
30381cb0ef41Sopenharmony_ci      SpillAfter(begin_range, begin_pos, SpillMode::kSpillAtDefinition);
30391cb0ef41Sopenharmony_ci    }
30401cb0ef41Sopenharmony_ci    for (LiveRange* range = begin_range->next(); range != end_range;
30411cb0ef41Sopenharmony_ci         range = range->next()) {
30421cb0ef41Sopenharmony_ci      if (!range->spilled()) {
30431cb0ef41Sopenharmony_ci        range->Spill();
30441cb0ef41Sopenharmony_ci      }
30451cb0ef41Sopenharmony_ci    }
30461cb0ef41Sopenharmony_ci  }
30471cb0ef41Sopenharmony_ci}
30481cb0ef41Sopenharmony_ci
30491cb0ef41Sopenharmony_civoid LinearScanAllocator::MaybeUndoPreviousSplit(LiveRange* range) {
30501cb0ef41Sopenharmony_ci  if (range->next() != nullptr && range->next()->ShouldRecombine()) {
30511cb0ef41Sopenharmony_ci    LiveRange* to_remove = range->next();
30521cb0ef41Sopenharmony_ci    TRACE("Recombining %d:%d with %d\n", range->TopLevel()->vreg(),
30531cb0ef41Sopenharmony_ci          range->relative_id(), to_remove->relative_id());
30541cb0ef41Sopenharmony_ci
30551cb0ef41Sopenharmony_ci    // Remove the range from unhandled, as attaching it will change its
30561cb0ef41Sopenharmony_ci    // state and hence ordering in the unhandled set.
30571cb0ef41Sopenharmony_ci    auto removed_cnt = unhandled_live_ranges().erase(to_remove);
30581cb0ef41Sopenharmony_ci    DCHECK_EQ(removed_cnt, 1);
30591cb0ef41Sopenharmony_ci    USE(removed_cnt);
30601cb0ef41Sopenharmony_ci
30611cb0ef41Sopenharmony_ci    range->AttachToNext();
30621cb0ef41Sopenharmony_ci  } else if (range->next() != nullptr) {
30631cb0ef41Sopenharmony_ci    TRACE("No recombine for %d:%d to %d\n", range->TopLevel()->vreg(),
30641cb0ef41Sopenharmony_ci          range->relative_id(), range->next()->relative_id());
30651cb0ef41Sopenharmony_ci  }
30661cb0ef41Sopenharmony_ci}
30671cb0ef41Sopenharmony_ci
30681cb0ef41Sopenharmony_civoid LinearScanAllocator::SpillNotLiveRanges(RangeWithRegisterSet* to_be_live,
30691cb0ef41Sopenharmony_ci                                             LifetimePosition position,
30701cb0ef41Sopenharmony_ci                                             SpillMode spill_mode) {
30711cb0ef41Sopenharmony_ci  for (auto it = active_live_ranges().begin();
30721cb0ef41Sopenharmony_ci       it != active_live_ranges().end();) {
30731cb0ef41Sopenharmony_ci    LiveRange* active_range = *it;
30741cb0ef41Sopenharmony_ci    TopLevelLiveRange* toplevel = (*it)->TopLevel();
30751cb0ef41Sopenharmony_ci    auto found = to_be_live->find({toplevel, kUnassignedRegister});
30761cb0ef41Sopenharmony_ci    if (found == to_be_live->end()) {
30771cb0ef41Sopenharmony_ci      // Is not contained in {to_be_live}, spill it.
30781cb0ef41Sopenharmony_ci      // Fixed registers are exempt from this. They might have been
30791cb0ef41Sopenharmony_ci      // added from inactive at the block boundary but we know that
30801cb0ef41Sopenharmony_ci      // they cannot conflict as they are built before register
30811cb0ef41Sopenharmony_ci      // allocation starts. It would be algorithmically fine to split
30821cb0ef41Sopenharmony_ci      // them and reschedule but the code does not allow to do this.
30831cb0ef41Sopenharmony_ci      if (toplevel->IsFixed()) {
30841cb0ef41Sopenharmony_ci        TRACE("Keeping reactivated fixed range for %s\n",
30851cb0ef41Sopenharmony_ci              RegisterName(toplevel->assigned_register()));
30861cb0ef41Sopenharmony_ci        ++it;
30871cb0ef41Sopenharmony_ci      } else {
30881cb0ef41Sopenharmony_ci        // When spilling a previously spilled/reloaded range, we add back the
30891cb0ef41Sopenharmony_ci        // tail that we might have split off when we reloaded/spilled it
30901cb0ef41Sopenharmony_ci        // previously. Otherwise we might keep generating small split-offs.
30911cb0ef41Sopenharmony_ci        MaybeUndoPreviousSplit(active_range);
30921cb0ef41Sopenharmony_ci        TRACE("Putting back %d:%d\n", toplevel->vreg(),
30931cb0ef41Sopenharmony_ci              active_range->relative_id());
30941cb0ef41Sopenharmony_ci        LiveRange* split = SplitRangeAt(active_range, position);
30951cb0ef41Sopenharmony_ci        DCHECK_NE(split, active_range);
30961cb0ef41Sopenharmony_ci
30971cb0ef41Sopenharmony_ci        // Make sure we revisit this range once it has a use that requires
30981cb0ef41Sopenharmony_ci        // a register.
30991cb0ef41Sopenharmony_ci        UsePosition* next_use = split->NextRegisterPosition(position);
31001cb0ef41Sopenharmony_ci        if (next_use != nullptr) {
31011cb0ef41Sopenharmony_ci          // Move to the start of the gap before use so that we have a space
31021cb0ef41Sopenharmony_ci          // to perform the potential reload. Otherwise, do not spill but add
31031cb0ef41Sopenharmony_ci          // to unhandled for reallocation.
31041cb0ef41Sopenharmony_ci          LifetimePosition revisit_at = next_use->pos().FullStart();
31051cb0ef41Sopenharmony_ci          TRACE("Next use at %d\n", revisit_at.value());
31061cb0ef41Sopenharmony_ci          if (!data()->IsBlockBoundary(revisit_at)) {
31071cb0ef41Sopenharmony_ci            // Leave some space so we have enough gap room.
31081cb0ef41Sopenharmony_ci            revisit_at = revisit_at.PrevStart().FullStart();
31091cb0ef41Sopenharmony_ci          }
31101cb0ef41Sopenharmony_ci          // If this range became life right at the block boundary that we are
31111cb0ef41Sopenharmony_ci          // currently processing, we do not need to split it. Instead move it
31121cb0ef41Sopenharmony_ci          // to unhandled right away.
31131cb0ef41Sopenharmony_ci          if (position < revisit_at) {
31141cb0ef41Sopenharmony_ci            LiveRange* third_part = SplitRangeAt(split, revisit_at);
31151cb0ef41Sopenharmony_ci            DCHECK_NE(split, third_part);
31161cb0ef41Sopenharmony_ci            Spill(split, spill_mode);
31171cb0ef41Sopenharmony_ci            TRACE("Marking %d:%d to recombine\n", toplevel->vreg(),
31181cb0ef41Sopenharmony_ci                  third_part->relative_id());
31191cb0ef41Sopenharmony_ci            third_part->SetRecombine();
31201cb0ef41Sopenharmony_ci            AddToUnhandled(third_part);
31211cb0ef41Sopenharmony_ci          } else {
31221cb0ef41Sopenharmony_ci            AddToUnhandled(split);
31231cb0ef41Sopenharmony_ci          }
31241cb0ef41Sopenharmony_ci        } else {
31251cb0ef41Sopenharmony_ci          Spill(split, spill_mode);
31261cb0ef41Sopenharmony_ci        }
31271cb0ef41Sopenharmony_ci        it = ActiveToHandled(it);
31281cb0ef41Sopenharmony_ci      }
31291cb0ef41Sopenharmony_ci    } else {
31301cb0ef41Sopenharmony_ci      // This range is contained in {to_be_live}, so we can keep it.
31311cb0ef41Sopenharmony_ci      int expected_register = (*found).expected_register;
31321cb0ef41Sopenharmony_ci      to_be_live->erase(found);
31331cb0ef41Sopenharmony_ci      if (expected_register == active_range->assigned_register()) {
31341cb0ef41Sopenharmony_ci        // Was life and in correct register, simply pass through.
31351cb0ef41Sopenharmony_ci        TRACE("Keeping %d:%d in %s\n", toplevel->vreg(),
31361cb0ef41Sopenharmony_ci              active_range->relative_id(),
31371cb0ef41Sopenharmony_ci              RegisterName(active_range->assigned_register()));
31381cb0ef41Sopenharmony_ci        ++it;
31391cb0ef41Sopenharmony_ci      } else {
31401cb0ef41Sopenharmony_ci        // Was life but wrong register. Split and schedule for
31411cb0ef41Sopenharmony_ci        // allocation.
31421cb0ef41Sopenharmony_ci        TRACE("Scheduling %d:%d\n", toplevel->vreg(),
31431cb0ef41Sopenharmony_ci              active_range->relative_id());
31441cb0ef41Sopenharmony_ci        LiveRange* split = SplitRangeAt(active_range, position);
31451cb0ef41Sopenharmony_ci        split->set_controlflow_hint(expected_register);
31461cb0ef41Sopenharmony_ci        AddToUnhandled(split);
31471cb0ef41Sopenharmony_ci        it = ActiveToHandled(it);
31481cb0ef41Sopenharmony_ci      }
31491cb0ef41Sopenharmony_ci    }
31501cb0ef41Sopenharmony_ci  }
31511cb0ef41Sopenharmony_ci}
31521cb0ef41Sopenharmony_ci
31531cb0ef41Sopenharmony_ciLiveRange* LinearScanAllocator::AssignRegisterOnReload(LiveRange* range,
31541cb0ef41Sopenharmony_ci                                                       int reg) {
31551cb0ef41Sopenharmony_ci  // We know the register is currently free but it might be in
31561cb0ef41Sopenharmony_ci  // use by a currently inactive range. So we might not be able
31571cb0ef41Sopenharmony_ci  // to reload for the full distance. In such case, split here.
31581cb0ef41Sopenharmony_ci  // TODO(herhut):
31591cb0ef41Sopenharmony_ci  // It might be better if we could use the normal unhandled queue and
31601cb0ef41Sopenharmony_ci  // give reloading registers pecedence. That way we would compute the
31611cb0ef41Sopenharmony_ci  // intersection for the entire future.
31621cb0ef41Sopenharmony_ci  LifetimePosition new_end = range->End();
31631cb0ef41Sopenharmony_ci  for (int cur_reg = 0; cur_reg < num_registers(); ++cur_reg) {
31641cb0ef41Sopenharmony_ci    if ((kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) &&
31651cb0ef41Sopenharmony_ci        cur_reg != reg) {
31661cb0ef41Sopenharmony_ci      continue;
31671cb0ef41Sopenharmony_ci    }
31681cb0ef41Sopenharmony_ci    for (const LiveRange* cur_inactive : inactive_live_ranges(cur_reg)) {
31691cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kCombine && check_fp_aliasing() &&
31701cb0ef41Sopenharmony_ci          !data()->config()->AreAliases(cur_inactive->representation(), cur_reg,
31711cb0ef41Sopenharmony_ci                                        range->representation(), reg)) {
31721cb0ef41Sopenharmony_ci        continue;
31731cb0ef41Sopenharmony_ci      }
31741cb0ef41Sopenharmony_ci      if (new_end <= cur_inactive->NextStart()) {
31751cb0ef41Sopenharmony_ci        // Inactive ranges are sorted by their next start, so the remaining
31761cb0ef41Sopenharmony_ci        // ranges cannot contribute to new_end.
31771cb0ef41Sopenharmony_ci        break;
31781cb0ef41Sopenharmony_ci      }
31791cb0ef41Sopenharmony_ci      auto next_intersection = cur_inactive->FirstIntersection(range);
31801cb0ef41Sopenharmony_ci      if (!next_intersection.IsValid()) continue;
31811cb0ef41Sopenharmony_ci      new_end = std::min(new_end, next_intersection);
31821cb0ef41Sopenharmony_ci    }
31831cb0ef41Sopenharmony_ci  }
31841cb0ef41Sopenharmony_ci  if (new_end != range->End()) {
31851cb0ef41Sopenharmony_ci    TRACE("Found new end for %d:%d at %d\n", range->TopLevel()->vreg(),
31861cb0ef41Sopenharmony_ci          range->relative_id(), new_end.value());
31871cb0ef41Sopenharmony_ci    LiveRange* tail = SplitRangeAt(range, new_end);
31881cb0ef41Sopenharmony_ci    AddToUnhandled(tail);
31891cb0ef41Sopenharmony_ci  }
31901cb0ef41Sopenharmony_ci  SetLiveRangeAssignedRegister(range, reg);
31911cb0ef41Sopenharmony_ci  return range;
31921cb0ef41Sopenharmony_ci}
31931cb0ef41Sopenharmony_ci
31941cb0ef41Sopenharmony_civoid LinearScanAllocator::ReloadLiveRanges(
31951cb0ef41Sopenharmony_ci    RangeWithRegisterSet const& to_be_live, LifetimePosition position) {
31961cb0ef41Sopenharmony_ci  // Assumption: All ranges in {to_be_live} are currently spilled and there are
31971cb0ef41Sopenharmony_ci  // no conflicting registers in the active ranges.
31981cb0ef41Sopenharmony_ci  // The former is ensured by SpillNotLiveRanges, the latter is by construction
31991cb0ef41Sopenharmony_ci  // of the to_be_live set.
32001cb0ef41Sopenharmony_ci  for (RangeWithRegister range_with_register : to_be_live) {
32011cb0ef41Sopenharmony_ci    TopLevelLiveRange* range = range_with_register.range;
32021cb0ef41Sopenharmony_ci    int reg = range_with_register.expected_register;
32031cb0ef41Sopenharmony_ci    LiveRange* to_resurrect = range->GetChildCovers(position);
32041cb0ef41Sopenharmony_ci    if (to_resurrect == nullptr) {
32051cb0ef41Sopenharmony_ci      // While the range was life until the end of the predecessor block, it is
32061cb0ef41Sopenharmony_ci      // not live in this block. Either there is a lifetime gap or the range
32071cb0ef41Sopenharmony_ci      // died.
32081cb0ef41Sopenharmony_ci      TRACE("No candidate for %d at %d\n", range->vreg(), position.value());
32091cb0ef41Sopenharmony_ci    } else {
32101cb0ef41Sopenharmony_ci      // We might be resurrecting a range that we spilled until its next use
32111cb0ef41Sopenharmony_ci      // before. In such cases, we have to unsplit it before processing as
32121cb0ef41Sopenharmony_ci      // otherwise we might get register changes from one range to the other
32131cb0ef41Sopenharmony_ci      // in the middle of blocks.
32141cb0ef41Sopenharmony_ci      // If there is a gap between this range and the next, we can just keep
32151cb0ef41Sopenharmony_ci      // it as a register change won't hurt.
32161cb0ef41Sopenharmony_ci      MaybeUndoPreviousSplit(to_resurrect);
32171cb0ef41Sopenharmony_ci      if (to_resurrect->Start() == position) {
32181cb0ef41Sopenharmony_ci        // This range already starts at this block. It might have been spilled,
32191cb0ef41Sopenharmony_ci        // so we have to unspill it. Otherwise, it is already in the unhandled
32201cb0ef41Sopenharmony_ci        // queue waiting for processing.
32211cb0ef41Sopenharmony_ci        DCHECK(!to_resurrect->HasRegisterAssigned());
32221cb0ef41Sopenharmony_ci        TRACE("Reload %d:%d starting at %d itself\n", range->vreg(),
32231cb0ef41Sopenharmony_ci              to_resurrect->relative_id(), position.value());
32241cb0ef41Sopenharmony_ci        if (to_resurrect->spilled()) {
32251cb0ef41Sopenharmony_ci          to_resurrect->Unspill();
32261cb0ef41Sopenharmony_ci          to_resurrect->set_controlflow_hint(reg);
32271cb0ef41Sopenharmony_ci          AddToUnhandled(to_resurrect);
32281cb0ef41Sopenharmony_ci        } else {
32291cb0ef41Sopenharmony_ci          // Assign the preassigned register if we know. Otherwise, nothing to
32301cb0ef41Sopenharmony_ci          // do as already in unhandeled.
32311cb0ef41Sopenharmony_ci          if (reg != kUnassignedRegister) {
32321cb0ef41Sopenharmony_ci            auto erased_cnt = unhandled_live_ranges().erase(to_resurrect);
32331cb0ef41Sopenharmony_ci            DCHECK_EQ(erased_cnt, 1);
32341cb0ef41Sopenharmony_ci            USE(erased_cnt);
32351cb0ef41Sopenharmony_ci            // We know that there is no conflict with active ranges, so just
32361cb0ef41Sopenharmony_ci            // assign the register to the range.
32371cb0ef41Sopenharmony_ci            to_resurrect = AssignRegisterOnReload(to_resurrect, reg);
32381cb0ef41Sopenharmony_ci            AddToActive(to_resurrect);
32391cb0ef41Sopenharmony_ci          }
32401cb0ef41Sopenharmony_ci        }
32411cb0ef41Sopenharmony_ci      } else {
32421cb0ef41Sopenharmony_ci        // This range was spilled before. We have to split it and schedule the
32431cb0ef41Sopenharmony_ci        // second part for allocation (or assign the register if we know).
32441cb0ef41Sopenharmony_ci        DCHECK(to_resurrect->spilled());
32451cb0ef41Sopenharmony_ci        LiveRange* split = SplitRangeAt(to_resurrect, position);
32461cb0ef41Sopenharmony_ci        TRACE("Reload %d:%d starting at %d as %d\n", range->vreg(),
32471cb0ef41Sopenharmony_ci              to_resurrect->relative_id(), split->Start().value(),
32481cb0ef41Sopenharmony_ci              split->relative_id());
32491cb0ef41Sopenharmony_ci        DCHECK_NE(split, to_resurrect);
32501cb0ef41Sopenharmony_ci        if (reg != kUnassignedRegister) {
32511cb0ef41Sopenharmony_ci          // We know that there is no conflict with active ranges, so just
32521cb0ef41Sopenharmony_ci          // assign the register to the range.
32531cb0ef41Sopenharmony_ci          split = AssignRegisterOnReload(split, reg);
32541cb0ef41Sopenharmony_ci          AddToActive(split);
32551cb0ef41Sopenharmony_ci        } else {
32561cb0ef41Sopenharmony_ci          // Let normal register assignment find a suitable register.
32571cb0ef41Sopenharmony_ci          split->set_controlflow_hint(reg);
32581cb0ef41Sopenharmony_ci          AddToUnhandled(split);
32591cb0ef41Sopenharmony_ci        }
32601cb0ef41Sopenharmony_ci      }
32611cb0ef41Sopenharmony_ci    }
32621cb0ef41Sopenharmony_ci  }
32631cb0ef41Sopenharmony_ci}
32641cb0ef41Sopenharmony_ci
32651cb0ef41Sopenharmony_ciRpoNumber LinearScanAllocator::ChooseOneOfTwoPredecessorStates(
32661cb0ef41Sopenharmony_ci    InstructionBlock* current_block, LifetimePosition boundary) {
32671cb0ef41Sopenharmony_ci  using SmallRangeVector =
32681cb0ef41Sopenharmony_ci      base::SmallVector<TopLevelLiveRange*,
32691cb0ef41Sopenharmony_ci                        RegisterConfiguration::kMaxRegisters>;
32701cb0ef41Sopenharmony_ci  // Pick the state that would generate the least spill/reloads.
32711cb0ef41Sopenharmony_ci  // Compute vectors of ranges with imminent use for both sides.
32721cb0ef41Sopenharmony_ci  // As GetChildCovers is cached, it is cheaper to repeatedly
32731cb0ef41Sopenharmony_ci  // call is rather than compute a shared set first.
32741cb0ef41Sopenharmony_ci  auto& left = data()->GetSpillState(current_block->predecessors()[0]);
32751cb0ef41Sopenharmony_ci  auto& right = data()->GetSpillState(current_block->predecessors()[1]);
32761cb0ef41Sopenharmony_ci  SmallRangeVector left_used;
32771cb0ef41Sopenharmony_ci  for (const auto item : left) {
32781cb0ef41Sopenharmony_ci    LiveRange* at_next_block = item->TopLevel()->GetChildCovers(boundary);
32791cb0ef41Sopenharmony_ci    if (at_next_block != nullptr &&
32801cb0ef41Sopenharmony_ci        at_next_block->NextUsePositionRegisterIsBeneficial(boundary) !=
32811cb0ef41Sopenharmony_ci            nullptr) {
32821cb0ef41Sopenharmony_ci      left_used.emplace_back(item->TopLevel());
32831cb0ef41Sopenharmony_ci    }
32841cb0ef41Sopenharmony_ci  }
32851cb0ef41Sopenharmony_ci  SmallRangeVector right_used;
32861cb0ef41Sopenharmony_ci  for (const auto item : right) {
32871cb0ef41Sopenharmony_ci    LiveRange* at_next_block = item->TopLevel()->GetChildCovers(boundary);
32881cb0ef41Sopenharmony_ci    if (at_next_block != nullptr &&
32891cb0ef41Sopenharmony_ci        at_next_block->NextUsePositionRegisterIsBeneficial(boundary) !=
32901cb0ef41Sopenharmony_ci            nullptr) {
32911cb0ef41Sopenharmony_ci      right_used.emplace_back(item->TopLevel());
32921cb0ef41Sopenharmony_ci    }
32931cb0ef41Sopenharmony_ci  }
32941cb0ef41Sopenharmony_ci  if (left_used.empty() && right_used.empty()) {
32951cb0ef41Sopenharmony_ci    // There are no beneficial register uses. Look at any use at
32961cb0ef41Sopenharmony_ci    // all. We do not account for all uses, like flowing into a phi.
32971cb0ef41Sopenharmony_ci    // So we just look at ranges still being live.
32981cb0ef41Sopenharmony_ci    TRACE("Looking at only uses\n");
32991cb0ef41Sopenharmony_ci    for (const auto item : left) {
33001cb0ef41Sopenharmony_ci      LiveRange* at_next_block = item->TopLevel()->GetChildCovers(boundary);
33011cb0ef41Sopenharmony_ci      if (at_next_block != nullptr &&
33021cb0ef41Sopenharmony_ci          at_next_block->NextUsePosition(boundary) != nullptr) {
33031cb0ef41Sopenharmony_ci        left_used.emplace_back(item->TopLevel());
33041cb0ef41Sopenharmony_ci      }
33051cb0ef41Sopenharmony_ci    }
33061cb0ef41Sopenharmony_ci    for (const auto item : right) {
33071cb0ef41Sopenharmony_ci      LiveRange* at_next_block = item->TopLevel()->GetChildCovers(boundary);
33081cb0ef41Sopenharmony_ci      if (at_next_block != nullptr &&
33091cb0ef41Sopenharmony_ci          at_next_block->NextUsePosition(boundary) != nullptr) {
33101cb0ef41Sopenharmony_ci        right_used.emplace_back(item->TopLevel());
33111cb0ef41Sopenharmony_ci      }
33121cb0ef41Sopenharmony_ci    }
33131cb0ef41Sopenharmony_ci  }
33141cb0ef41Sopenharmony_ci  // Now left_used and right_used contains those ranges that matter.
33151cb0ef41Sopenharmony_ci  // Count which side matches this most.
33161cb0ef41Sopenharmony_ci  TRACE("Vote went %zu vs %zu\n", left_used.size(), right_used.size());
33171cb0ef41Sopenharmony_ci  return left_used.size() > right_used.size()
33181cb0ef41Sopenharmony_ci             ? current_block->predecessors()[0]
33191cb0ef41Sopenharmony_ci             : current_block->predecessors()[1];
33201cb0ef41Sopenharmony_ci}
33211cb0ef41Sopenharmony_ci
33221cb0ef41Sopenharmony_cibool LinearScanAllocator::CheckConflict(MachineRepresentation rep, int reg,
33231cb0ef41Sopenharmony_ci                                        RangeWithRegisterSet* to_be_live) {
33241cb0ef41Sopenharmony_ci  for (RangeWithRegister range_with_reg : *to_be_live) {
33251cb0ef41Sopenharmony_ci    if (data()->config()->AreAliases(range_with_reg.range->representation(),
33261cb0ef41Sopenharmony_ci                                     range_with_reg.expected_register, rep,
33271cb0ef41Sopenharmony_ci                                     reg)) {
33281cb0ef41Sopenharmony_ci      return true;
33291cb0ef41Sopenharmony_ci    }
33301cb0ef41Sopenharmony_ci  }
33311cb0ef41Sopenharmony_ci  return false;
33321cb0ef41Sopenharmony_ci}
33331cb0ef41Sopenharmony_ci
33341cb0ef41Sopenharmony_civoid LinearScanAllocator::ComputeStateFromManyPredecessors(
33351cb0ef41Sopenharmony_ci    InstructionBlock* current_block, RangeWithRegisterSet* to_be_live) {
33361cb0ef41Sopenharmony_ci  struct Vote {
33371cb0ef41Sopenharmony_ci    size_t count;
33381cb0ef41Sopenharmony_ci    int used_registers[RegisterConfiguration::kMaxRegisters];
33391cb0ef41Sopenharmony_ci  };
33401cb0ef41Sopenharmony_ci  struct TopLevelLiveRangeComparator {
33411cb0ef41Sopenharmony_ci    bool operator()(const TopLevelLiveRange* lhs,
33421cb0ef41Sopenharmony_ci                    const TopLevelLiveRange* rhs) const {
33431cb0ef41Sopenharmony_ci      return lhs->vreg() < rhs->vreg();
33441cb0ef41Sopenharmony_ci    }
33451cb0ef41Sopenharmony_ci  };
33461cb0ef41Sopenharmony_ci  ZoneMap<TopLevelLiveRange*, Vote, TopLevelLiveRangeComparator> counts(
33471cb0ef41Sopenharmony_ci      data()->allocation_zone());
33481cb0ef41Sopenharmony_ci  int deferred_blocks = 0;
33491cb0ef41Sopenharmony_ci  for (RpoNumber pred : current_block->predecessors()) {
33501cb0ef41Sopenharmony_ci    if (!ConsiderBlockForControlFlow(current_block, pred)) {
33511cb0ef41Sopenharmony_ci      // Back edges of a loop count as deferred here too.
33521cb0ef41Sopenharmony_ci      deferred_blocks++;
33531cb0ef41Sopenharmony_ci      continue;
33541cb0ef41Sopenharmony_ci    }
33551cb0ef41Sopenharmony_ci    const auto& pred_state = data()->GetSpillState(pred);
33561cb0ef41Sopenharmony_ci    for (LiveRange* range : pred_state) {
33571cb0ef41Sopenharmony_ci      // We might have spilled the register backwards, so the range we
33581cb0ef41Sopenharmony_ci      // stored might have lost its register. Ignore those.
33591cb0ef41Sopenharmony_ci      if (!range->HasRegisterAssigned()) continue;
33601cb0ef41Sopenharmony_ci      TopLevelLiveRange* toplevel = range->TopLevel();
33611cb0ef41Sopenharmony_ci      auto previous = counts.find(toplevel);
33621cb0ef41Sopenharmony_ci      if (previous == counts.end()) {
33631cb0ef41Sopenharmony_ci        auto result = counts.emplace(std::make_pair(toplevel, Vote{1, {0}}));
33641cb0ef41Sopenharmony_ci        CHECK(result.second);
33651cb0ef41Sopenharmony_ci        result.first->second.used_registers[range->assigned_register()]++;
33661cb0ef41Sopenharmony_ci      } else {
33671cb0ef41Sopenharmony_ci        previous->second.count++;
33681cb0ef41Sopenharmony_ci        previous->second.used_registers[range->assigned_register()]++;
33691cb0ef41Sopenharmony_ci      }
33701cb0ef41Sopenharmony_ci    }
33711cb0ef41Sopenharmony_ci  }
33721cb0ef41Sopenharmony_ci
33731cb0ef41Sopenharmony_ci  // Choose the live ranges from the majority.
33741cb0ef41Sopenharmony_ci  const size_t majority =
33751cb0ef41Sopenharmony_ci      (current_block->PredecessorCount() + 2 - deferred_blocks) / 2;
33761cb0ef41Sopenharmony_ci  bool taken_registers[RegisterConfiguration::kMaxRegisters] = {false};
33771cb0ef41Sopenharmony_ci  auto assign_to_live = [this, counts, majority](
33781cb0ef41Sopenharmony_ci                            std::function<bool(TopLevelLiveRange*)> filter,
33791cb0ef41Sopenharmony_ci                            RangeWithRegisterSet* to_be_live,
33801cb0ef41Sopenharmony_ci                            bool* taken_registers) {
33811cb0ef41Sopenharmony_ci    bool check_aliasing =
33821cb0ef41Sopenharmony_ci        kFPAliasing == AliasingKind::kCombine && check_fp_aliasing();
33831cb0ef41Sopenharmony_ci    for (const auto& val : counts) {
33841cb0ef41Sopenharmony_ci      if (!filter(val.first)) continue;
33851cb0ef41Sopenharmony_ci      if (val.second.count >= majority) {
33861cb0ef41Sopenharmony_ci        int register_max = 0;
33871cb0ef41Sopenharmony_ci        int reg = kUnassignedRegister;
33881cb0ef41Sopenharmony_ci        bool conflict = false;
33891cb0ef41Sopenharmony_ci        int num_regs = num_registers();
33901cb0ef41Sopenharmony_ci        int num_codes = num_allocatable_registers();
33911cb0ef41Sopenharmony_ci        const int* codes = allocatable_register_codes();
33921cb0ef41Sopenharmony_ci        MachineRepresentation rep = val.first->representation();
33931cb0ef41Sopenharmony_ci        if (check_aliasing && (rep == MachineRepresentation::kFloat32 ||
33941cb0ef41Sopenharmony_ci                               rep == MachineRepresentation::kSimd128))
33951cb0ef41Sopenharmony_ci          GetFPRegisterSet(rep, &num_regs, &num_codes, &codes);
33961cb0ef41Sopenharmony_ci        for (int idx = 0; idx < num_regs; idx++) {
33971cb0ef41Sopenharmony_ci          int uses = val.second.used_registers[idx];
33981cb0ef41Sopenharmony_ci          if (uses == 0) continue;
33991cb0ef41Sopenharmony_ci          if (uses > register_max || (conflict && uses == register_max)) {
34001cb0ef41Sopenharmony_ci            reg = idx;
34011cb0ef41Sopenharmony_ci            register_max = uses;
34021cb0ef41Sopenharmony_ci            conflict = check_aliasing ? CheckConflict(rep, reg, to_be_live)
34031cb0ef41Sopenharmony_ci                                      : taken_registers[reg];
34041cb0ef41Sopenharmony_ci          }
34051cb0ef41Sopenharmony_ci        }
34061cb0ef41Sopenharmony_ci        if (conflict) {
34071cb0ef41Sopenharmony_ci          reg = kUnassignedRegister;
34081cb0ef41Sopenharmony_ci        } else if (!check_aliasing) {
34091cb0ef41Sopenharmony_ci          taken_registers[reg] = true;
34101cb0ef41Sopenharmony_ci        }
34111cb0ef41Sopenharmony_ci        to_be_live->emplace(val.first, reg);
34121cb0ef41Sopenharmony_ci        TRACE("Reset %d as live due vote %zu in %s\n",
34131cb0ef41Sopenharmony_ci              val.first->TopLevel()->vreg(), val.second.count,
34141cb0ef41Sopenharmony_ci              RegisterName(reg));
34151cb0ef41Sopenharmony_ci      }
34161cb0ef41Sopenharmony_ci    }
34171cb0ef41Sopenharmony_ci  };
34181cb0ef41Sopenharmony_ci  // First round, process fixed registers, as these have precedence.
34191cb0ef41Sopenharmony_ci  // There is only one fixed range per register, so we cannot have
34201cb0ef41Sopenharmony_ci  // conflicts.
34211cb0ef41Sopenharmony_ci  assign_to_live([](TopLevelLiveRange* r) { return r->IsFixed(); }, to_be_live,
34221cb0ef41Sopenharmony_ci                 taken_registers);
34231cb0ef41Sopenharmony_ci  // Second round, process the rest.
34241cb0ef41Sopenharmony_ci  assign_to_live([](TopLevelLiveRange* r) { return !r->IsFixed(); }, to_be_live,
34251cb0ef41Sopenharmony_ci                 taken_registers);
34261cb0ef41Sopenharmony_ci}
34271cb0ef41Sopenharmony_ci
34281cb0ef41Sopenharmony_cibool LinearScanAllocator::ConsiderBlockForControlFlow(
34291cb0ef41Sopenharmony_ci    InstructionBlock* current_block, RpoNumber predecessor) {
34301cb0ef41Sopenharmony_ci  // We ignore predecessors on back edges when looking for control flow effects,
34311cb0ef41Sopenharmony_ci  // as those lie in the future of allocation and we have no data yet. Also,
34321cb0ef41Sopenharmony_ci  // deferred bocks are ignored on deferred to non-deferred boundaries, as we do
34331cb0ef41Sopenharmony_ci  // not want them to influence allocation of non deferred code.
34341cb0ef41Sopenharmony_ci  return (predecessor < current_block->rpo_number()) &&
34351cb0ef41Sopenharmony_ci         (current_block->IsDeferred() ||
34361cb0ef41Sopenharmony_ci          !code()->InstructionBlockAt(predecessor)->IsDeferred());
34371cb0ef41Sopenharmony_ci}
34381cb0ef41Sopenharmony_ci
34391cb0ef41Sopenharmony_civoid LinearScanAllocator::UpdateDeferredFixedRanges(SpillMode spill_mode,
34401cb0ef41Sopenharmony_ci                                                    InstructionBlock* block) {
34411cb0ef41Sopenharmony_ci  if (spill_mode == SpillMode::kSpillDeferred) {
34421cb0ef41Sopenharmony_ci    LifetimePosition max = LifetimePosition::InstructionFromInstructionIndex(
34431cb0ef41Sopenharmony_ci        LastDeferredInstructionIndex(block));
34441cb0ef41Sopenharmony_ci    // Adds range back to inactive, resolving resulting conflicts.
34451cb0ef41Sopenharmony_ci    auto add_to_inactive = [this, max](LiveRange* range) {
34461cb0ef41Sopenharmony_ci      AddToInactive(range);
34471cb0ef41Sopenharmony_ci      // Splits other if it conflicts with range. Other is placed in unhandled
34481cb0ef41Sopenharmony_ci      // for later reallocation.
34491cb0ef41Sopenharmony_ci      auto split_conflicting = [this, max](LiveRange* range, LiveRange* other,
34501cb0ef41Sopenharmony_ci                                           std::function<void(LiveRange*)>
34511cb0ef41Sopenharmony_ci                                               update_caches) {
34521cb0ef41Sopenharmony_ci        if (other->TopLevel()->IsFixed()) return;
34531cb0ef41Sopenharmony_ci        int reg = range->assigned_register();
34541cb0ef41Sopenharmony_ci        if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
34551cb0ef41Sopenharmony_ci          if (other->assigned_register() != reg) {
34561cb0ef41Sopenharmony_ci            return;
34571cb0ef41Sopenharmony_ci          }
34581cb0ef41Sopenharmony_ci        } else {
34591cb0ef41Sopenharmony_ci          if (!data()->config()->AreAliases(range->representation(), reg,
34601cb0ef41Sopenharmony_ci                                            other->representation(),
34611cb0ef41Sopenharmony_ci                                            other->assigned_register())) {
34621cb0ef41Sopenharmony_ci            return;
34631cb0ef41Sopenharmony_ci          }
34641cb0ef41Sopenharmony_ci        }
34651cb0ef41Sopenharmony_ci        // The inactive range might conflict, so check whether we need to
34661cb0ef41Sopenharmony_ci        // split and spill. We can look for the first intersection, as there
34671cb0ef41Sopenharmony_ci        // cannot be any intersections in the past, as those would have been a
34681cb0ef41Sopenharmony_ci        // conflict then.
34691cb0ef41Sopenharmony_ci        LifetimePosition next_start = range->FirstIntersection(other);
34701cb0ef41Sopenharmony_ci        if (!next_start.IsValid() || (next_start > max)) {
34711cb0ef41Sopenharmony_ci          // There is no conflict or the conflict is outside of the current
34721cb0ef41Sopenharmony_ci          // stretch of deferred code. In either case we can ignore the
34731cb0ef41Sopenharmony_ci          // inactive range.
34741cb0ef41Sopenharmony_ci          return;
34751cb0ef41Sopenharmony_ci        }
34761cb0ef41Sopenharmony_ci        // They overlap. So we need to split active and reschedule it
34771cb0ef41Sopenharmony_ci        // for allocation.
34781cb0ef41Sopenharmony_ci        TRACE("Resolving conflict of %d with deferred fixed for register %s\n",
34791cb0ef41Sopenharmony_ci              other->TopLevel()->vreg(),
34801cb0ef41Sopenharmony_ci              RegisterName(other->assigned_register()));
34811cb0ef41Sopenharmony_ci        LiveRange* split_off =
34821cb0ef41Sopenharmony_ci            other->SplitAt(next_start, data()->allocation_zone());
34831cb0ef41Sopenharmony_ci        // Try to get the same register after the deferred block.
34841cb0ef41Sopenharmony_ci        split_off->set_controlflow_hint(other->assigned_register());
34851cb0ef41Sopenharmony_ci        DCHECK_NE(split_off, other);
34861cb0ef41Sopenharmony_ci        AddToUnhandled(split_off);
34871cb0ef41Sopenharmony_ci        update_caches(other);
34881cb0ef41Sopenharmony_ci      };
34891cb0ef41Sopenharmony_ci      // Now check for conflicts in active and inactive ranges. We might have
34901cb0ef41Sopenharmony_ci      // conflicts in inactive, as we do not do this check on every block
34911cb0ef41Sopenharmony_ci      // boundary but only on deferred/non-deferred changes but inactive
34921cb0ef41Sopenharmony_ci      // live ranges might become live on any block boundary.
34931cb0ef41Sopenharmony_ci      for (auto active : active_live_ranges()) {
34941cb0ef41Sopenharmony_ci        split_conflicting(range, active, [this](LiveRange* updated) {
34951cb0ef41Sopenharmony_ci          next_active_ranges_change_ =
34961cb0ef41Sopenharmony_ci              std::min(updated->End(), next_active_ranges_change_);
34971cb0ef41Sopenharmony_ci        });
34981cb0ef41Sopenharmony_ci      }
34991cb0ef41Sopenharmony_ci      for (int reg = 0; reg < num_registers(); ++reg) {
35001cb0ef41Sopenharmony_ci        if ((kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) &&
35011cb0ef41Sopenharmony_ci            reg != range->assigned_register()) {
35021cb0ef41Sopenharmony_ci          continue;
35031cb0ef41Sopenharmony_ci        }
35041cb0ef41Sopenharmony_ci        for (auto inactive : inactive_live_ranges(reg)) {
35051cb0ef41Sopenharmony_ci          if (inactive->NextStart() > max) break;
35061cb0ef41Sopenharmony_ci          split_conflicting(range, inactive, [this](LiveRange* updated) {
35071cb0ef41Sopenharmony_ci            next_inactive_ranges_change_ =
35081cb0ef41Sopenharmony_ci                std::min(updated->End(), next_inactive_ranges_change_);
35091cb0ef41Sopenharmony_ci          });
35101cb0ef41Sopenharmony_ci        }
35111cb0ef41Sopenharmony_ci      }
35121cb0ef41Sopenharmony_ci    };
35131cb0ef41Sopenharmony_ci    if (mode() == RegisterKind::kGeneral) {
35141cb0ef41Sopenharmony_ci      for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
35151cb0ef41Sopenharmony_ci        if (current != nullptr) {
35161cb0ef41Sopenharmony_ci          if (current->IsDeferredFixed()) {
35171cb0ef41Sopenharmony_ci            add_to_inactive(current);
35181cb0ef41Sopenharmony_ci          }
35191cb0ef41Sopenharmony_ci        }
35201cb0ef41Sopenharmony_ci      }
35211cb0ef41Sopenharmony_ci    } else if (mode() == RegisterKind::kDouble) {
35221cb0ef41Sopenharmony_ci      for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
35231cb0ef41Sopenharmony_ci        if (current != nullptr) {
35241cb0ef41Sopenharmony_ci          if (current->IsDeferredFixed()) {
35251cb0ef41Sopenharmony_ci            add_to_inactive(current);
35261cb0ef41Sopenharmony_ci          }
35271cb0ef41Sopenharmony_ci        }
35281cb0ef41Sopenharmony_ci      }
35291cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kCombine && check_fp_aliasing()) {
35301cb0ef41Sopenharmony_ci        for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
35311cb0ef41Sopenharmony_ci          if (current != nullptr) {
35321cb0ef41Sopenharmony_ci            if (current->IsDeferredFixed()) {
35331cb0ef41Sopenharmony_ci              add_to_inactive(current);
35341cb0ef41Sopenharmony_ci            }
35351cb0ef41Sopenharmony_ci          }
35361cb0ef41Sopenharmony_ci        }
35371cb0ef41Sopenharmony_ci        for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
35381cb0ef41Sopenharmony_ci          if (current != nullptr) {
35391cb0ef41Sopenharmony_ci            if (current->IsDeferredFixed()) {
35401cb0ef41Sopenharmony_ci              add_to_inactive(current);
35411cb0ef41Sopenharmony_ci            }
35421cb0ef41Sopenharmony_ci          }
35431cb0ef41Sopenharmony_ci        }
35441cb0ef41Sopenharmony_ci      }
35451cb0ef41Sopenharmony_ci    } else {
35461cb0ef41Sopenharmony_ci      DCHECK_EQ(mode(), RegisterKind::kSimd128);
35471cb0ef41Sopenharmony_ci      for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
35481cb0ef41Sopenharmony_ci        if (current != nullptr) {
35491cb0ef41Sopenharmony_ci          if (current->IsDeferredFixed()) {
35501cb0ef41Sopenharmony_ci            add_to_inactive(current);
35511cb0ef41Sopenharmony_ci          }
35521cb0ef41Sopenharmony_ci        }
35531cb0ef41Sopenharmony_ci      }
35541cb0ef41Sopenharmony_ci    }
35551cb0ef41Sopenharmony_ci  } else {
35561cb0ef41Sopenharmony_ci    // Remove all ranges.
35571cb0ef41Sopenharmony_ci    for (int reg = 0; reg < num_registers(); ++reg) {
35581cb0ef41Sopenharmony_ci      for (auto it = inactive_live_ranges(reg).begin();
35591cb0ef41Sopenharmony_ci           it != inactive_live_ranges(reg).end();) {
35601cb0ef41Sopenharmony_ci        if ((*it)->TopLevel()->IsDeferredFixed()) {
35611cb0ef41Sopenharmony_ci          it = inactive_live_ranges(reg).erase(it);
35621cb0ef41Sopenharmony_ci        } else {
35631cb0ef41Sopenharmony_ci          ++it;
35641cb0ef41Sopenharmony_ci        }
35651cb0ef41Sopenharmony_ci      }
35661cb0ef41Sopenharmony_ci    }
35671cb0ef41Sopenharmony_ci  }
35681cb0ef41Sopenharmony_ci}
35691cb0ef41Sopenharmony_ci
35701cb0ef41Sopenharmony_cibool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred(
35711cb0ef41Sopenharmony_ci    const InstructionBlock* block) {
35721cb0ef41Sopenharmony_ci  if (block->IsDeferred()) return true;
35731cb0ef41Sopenharmony_ci  if (block->PredecessorCount() == 0) return true;
35741cb0ef41Sopenharmony_ci  bool pred_is_deferred = false;
35751cb0ef41Sopenharmony_ci  for (auto pred : block->predecessors()) {
35761cb0ef41Sopenharmony_ci    if (pred.IsNext(block->rpo_number())) {
35771cb0ef41Sopenharmony_ci      pred_is_deferred = code()->InstructionBlockAt(pred)->IsDeferred();
35781cb0ef41Sopenharmony_ci      break;
35791cb0ef41Sopenharmony_ci    }
35801cb0ef41Sopenharmony_ci  }
35811cb0ef41Sopenharmony_ci  return !pred_is_deferred;
35821cb0ef41Sopenharmony_ci}
35831cb0ef41Sopenharmony_ci
35841cb0ef41Sopenharmony_cibool LinearScanAllocator::HasNonDeferredPredecessor(InstructionBlock* block) {
35851cb0ef41Sopenharmony_ci  for (auto pred : block->predecessors()) {
35861cb0ef41Sopenharmony_ci    InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
35871cb0ef41Sopenharmony_ci    if (!pred_block->IsDeferred()) return true;
35881cb0ef41Sopenharmony_ci  }
35891cb0ef41Sopenharmony_ci  return false;
35901cb0ef41Sopenharmony_ci}
35911cb0ef41Sopenharmony_ci
35921cb0ef41Sopenharmony_civoid LinearScanAllocator::AllocateRegisters() {
35931cb0ef41Sopenharmony_ci  DCHECK(unhandled_live_ranges().empty());
35941cb0ef41Sopenharmony_ci  DCHECK(active_live_ranges().empty());
35951cb0ef41Sopenharmony_ci  for (int reg = 0; reg < num_registers(); ++reg) {
35961cb0ef41Sopenharmony_ci    DCHECK(inactive_live_ranges(reg).empty());
35971cb0ef41Sopenharmony_ci  }
35981cb0ef41Sopenharmony_ci
35991cb0ef41Sopenharmony_ci  SplitAndSpillRangesDefinedByMemoryOperand();
36001cb0ef41Sopenharmony_ci  data()->ResetSpillState();
36011cb0ef41Sopenharmony_ci
36021cb0ef41Sopenharmony_ci  if (data()->is_trace_alloc()) {
36031cb0ef41Sopenharmony_ci    PrintRangeOverview();
36041cb0ef41Sopenharmony_ci  }
36051cb0ef41Sopenharmony_ci
36061cb0ef41Sopenharmony_ci  const size_t live_ranges_size = data()->live_ranges().size();
36071cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* range : data()->live_ranges()) {
36081cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
36091cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
36101cb0ef41Sopenharmony_ci    if (!CanProcessRange(range)) continue;
36111cb0ef41Sopenharmony_ci    for (LiveRange* to_add = range; to_add != nullptr;
36121cb0ef41Sopenharmony_ci         to_add = to_add->next()) {
36131cb0ef41Sopenharmony_ci      if (!to_add->spilled()) {
36141cb0ef41Sopenharmony_ci        AddToUnhandled(to_add);
36151cb0ef41Sopenharmony_ci      }
36161cb0ef41Sopenharmony_ci    }
36171cb0ef41Sopenharmony_ci  }
36181cb0ef41Sopenharmony_ci
36191cb0ef41Sopenharmony_ci  if (mode() == RegisterKind::kGeneral) {
36201cb0ef41Sopenharmony_ci    for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
36211cb0ef41Sopenharmony_ci      if (current != nullptr) {
36221cb0ef41Sopenharmony_ci        if (current->IsDeferredFixed()) continue;
36231cb0ef41Sopenharmony_ci        AddToInactive(current);
36241cb0ef41Sopenharmony_ci      }
36251cb0ef41Sopenharmony_ci    }
36261cb0ef41Sopenharmony_ci  } else if (mode() == RegisterKind::kDouble) {
36271cb0ef41Sopenharmony_ci    for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
36281cb0ef41Sopenharmony_ci      if (current != nullptr) {
36291cb0ef41Sopenharmony_ci        if (current->IsDeferredFixed()) continue;
36301cb0ef41Sopenharmony_ci        AddToInactive(current);
36311cb0ef41Sopenharmony_ci      }
36321cb0ef41Sopenharmony_ci    }
36331cb0ef41Sopenharmony_ci    if (kFPAliasing == AliasingKind::kCombine && check_fp_aliasing()) {
36341cb0ef41Sopenharmony_ci      for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
36351cb0ef41Sopenharmony_ci        if (current != nullptr) {
36361cb0ef41Sopenharmony_ci          if (current->IsDeferredFixed()) continue;
36371cb0ef41Sopenharmony_ci          AddToInactive(current);
36381cb0ef41Sopenharmony_ci        }
36391cb0ef41Sopenharmony_ci      }
36401cb0ef41Sopenharmony_ci      for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
36411cb0ef41Sopenharmony_ci        if (current != nullptr) {
36421cb0ef41Sopenharmony_ci          if (current->IsDeferredFixed()) continue;
36431cb0ef41Sopenharmony_ci          AddToInactive(current);
36441cb0ef41Sopenharmony_ci        }
36451cb0ef41Sopenharmony_ci      }
36461cb0ef41Sopenharmony_ci    }
36471cb0ef41Sopenharmony_ci  } else {
36481cb0ef41Sopenharmony_ci    DCHECK(mode() == RegisterKind::kSimd128);
36491cb0ef41Sopenharmony_ci    for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
36501cb0ef41Sopenharmony_ci      if (current != nullptr) {
36511cb0ef41Sopenharmony_ci        if (current->IsDeferredFixed()) continue;
36521cb0ef41Sopenharmony_ci        AddToInactive(current);
36531cb0ef41Sopenharmony_ci      }
36541cb0ef41Sopenharmony_ci    }
36551cb0ef41Sopenharmony_ci  }
36561cb0ef41Sopenharmony_ci
36571cb0ef41Sopenharmony_ci  RpoNumber last_block = RpoNumber::FromInt(0);
36581cb0ef41Sopenharmony_ci  RpoNumber max_blocks =
36591cb0ef41Sopenharmony_ci      RpoNumber::FromInt(code()->InstructionBlockCount() - 1);
36601cb0ef41Sopenharmony_ci  LifetimePosition next_block_boundary =
36611cb0ef41Sopenharmony_ci      LifetimePosition::InstructionFromInstructionIndex(
36621cb0ef41Sopenharmony_ci          data()
36631cb0ef41Sopenharmony_ci              ->code()
36641cb0ef41Sopenharmony_ci              ->InstructionBlockAt(last_block)
36651cb0ef41Sopenharmony_ci              ->last_instruction_index())
36661cb0ef41Sopenharmony_ci          .NextFullStart();
36671cb0ef41Sopenharmony_ci  SpillMode spill_mode = SpillMode::kSpillAtDefinition;
36681cb0ef41Sopenharmony_ci
36691cb0ef41Sopenharmony_ci  // Process all ranges. We also need to ensure that we have seen all block
36701cb0ef41Sopenharmony_ci  // boundaries. Linear scan might have assigned and spilled ranges before
36711cb0ef41Sopenharmony_ci  // reaching the last block and hence we would ignore control flow effects for
36721cb0ef41Sopenharmony_ci  // those. Not only does this produce a potentially bad assignment, it also
36731cb0ef41Sopenharmony_ci  // breaks with the invariant that we undo spills that happen in deferred code
36741cb0ef41Sopenharmony_ci  // when crossing a deferred/non-deferred boundary.
36751cb0ef41Sopenharmony_ci  while (!unhandled_live_ranges().empty() || last_block < max_blocks) {
36761cb0ef41Sopenharmony_ci    data()->tick_counter()->TickAndMaybeEnterSafepoint();
36771cb0ef41Sopenharmony_ci    LiveRange* current = unhandled_live_ranges().empty()
36781cb0ef41Sopenharmony_ci                             ? nullptr
36791cb0ef41Sopenharmony_ci                             : *unhandled_live_ranges().begin();
36801cb0ef41Sopenharmony_ci    LifetimePosition position =
36811cb0ef41Sopenharmony_ci        current ? current->Start() : next_block_boundary;
36821cb0ef41Sopenharmony_ci#ifdef DEBUG
36831cb0ef41Sopenharmony_ci    allocation_finger_ = position;
36841cb0ef41Sopenharmony_ci#endif
36851cb0ef41Sopenharmony_ci    // Check whether we just moved across a block boundary. This will trigger
36861cb0ef41Sopenharmony_ci    // for the first range that is past the current boundary.
36871cb0ef41Sopenharmony_ci    if (position >= next_block_boundary) {
36881cb0ef41Sopenharmony_ci      TRACE("Processing boundary at %d leaving %d\n",
36891cb0ef41Sopenharmony_ci            next_block_boundary.value(), last_block.ToInt());
36901cb0ef41Sopenharmony_ci
36911cb0ef41Sopenharmony_ci      // Forward state to before block boundary
36921cb0ef41Sopenharmony_ci      LifetimePosition end_of_block = next_block_boundary.PrevStart().End();
36931cb0ef41Sopenharmony_ci      ForwardStateTo(end_of_block);
36941cb0ef41Sopenharmony_ci
36951cb0ef41Sopenharmony_ci      // Remember this state.
36961cb0ef41Sopenharmony_ci      InstructionBlock* current_block = data()->code()->GetInstructionBlock(
36971cb0ef41Sopenharmony_ci          next_block_boundary.ToInstructionIndex());
36981cb0ef41Sopenharmony_ci
36991cb0ef41Sopenharmony_ci      // Store current spill state (as the state at end of block). For
37001cb0ef41Sopenharmony_ci      // simplicity, we store the active ranges, e.g., the live ranges that
37011cb0ef41Sopenharmony_ci      // are not spilled.
37021cb0ef41Sopenharmony_ci      data()->RememberSpillState(last_block, active_live_ranges());
37031cb0ef41Sopenharmony_ci
37041cb0ef41Sopenharmony_ci      // Only reset the state if this was not a direct fallthrough. Otherwise
37051cb0ef41Sopenharmony_ci      // control flow resolution will get confused (it does not expect changes
37061cb0ef41Sopenharmony_ci      // across fallthrough edges.).
37071cb0ef41Sopenharmony_ci      bool fallthrough =
37081cb0ef41Sopenharmony_ci          (current_block->PredecessorCount() == 1) &&
37091cb0ef41Sopenharmony_ci          current_block->predecessors()[0].IsNext(current_block->rpo_number());
37101cb0ef41Sopenharmony_ci
37111cb0ef41Sopenharmony_ci      // When crossing a deferred/non-deferred boundary, we have to load or
37121cb0ef41Sopenharmony_ci      // remove the deferred fixed ranges from inactive.
37131cb0ef41Sopenharmony_ci      if ((spill_mode == SpillMode::kSpillDeferred) !=
37141cb0ef41Sopenharmony_ci          current_block->IsDeferred()) {
37151cb0ef41Sopenharmony_ci        // Update spill mode.
37161cb0ef41Sopenharmony_ci        spill_mode = current_block->IsDeferred()
37171cb0ef41Sopenharmony_ci                         ? SpillMode::kSpillDeferred
37181cb0ef41Sopenharmony_ci                         : SpillMode::kSpillAtDefinition;
37191cb0ef41Sopenharmony_ci
37201cb0ef41Sopenharmony_ci        ForwardStateTo(next_block_boundary);
37211cb0ef41Sopenharmony_ci
37221cb0ef41Sopenharmony_ci#ifdef DEBUG
37231cb0ef41Sopenharmony_ci        // Allow allocation at current position.
37241cb0ef41Sopenharmony_ci        allocation_finger_ = next_block_boundary;
37251cb0ef41Sopenharmony_ci#endif
37261cb0ef41Sopenharmony_ci        UpdateDeferredFixedRanges(spill_mode, current_block);
37271cb0ef41Sopenharmony_ci      }
37281cb0ef41Sopenharmony_ci
37291cb0ef41Sopenharmony_ci      // Allocation relies on the fact that each non-deferred block has at
37301cb0ef41Sopenharmony_ci      // least one non-deferred predecessor. Check this invariant here.
37311cb0ef41Sopenharmony_ci      DCHECK_IMPLIES(!current_block->IsDeferred(),
37321cb0ef41Sopenharmony_ci                     HasNonDeferredPredecessor(current_block));
37331cb0ef41Sopenharmony_ci
37341cb0ef41Sopenharmony_ci      if (!fallthrough) {
37351cb0ef41Sopenharmony_ci#ifdef DEBUG
37361cb0ef41Sopenharmony_ci        // Allow allocation at current position.
37371cb0ef41Sopenharmony_ci        allocation_finger_ = next_block_boundary;
37381cb0ef41Sopenharmony_ci#endif
37391cb0ef41Sopenharmony_ci
37401cb0ef41Sopenharmony_ci        // We are currently at next_block_boundary - 1. Move the state to the
37411cb0ef41Sopenharmony_ci        // actual block boundary position. In particular, we have to
37421cb0ef41Sopenharmony_ci        // reactivate inactive ranges so that they get rescheduled for
37431cb0ef41Sopenharmony_ci        // allocation if they were not live at the predecessors.
37441cb0ef41Sopenharmony_ci        ForwardStateTo(next_block_boundary);
37451cb0ef41Sopenharmony_ci
37461cb0ef41Sopenharmony_ci        RangeWithRegisterSet to_be_live(data()->allocation_zone());
37471cb0ef41Sopenharmony_ci
37481cb0ef41Sopenharmony_ci        // If we end up deciding to use the state of the immediate
37491cb0ef41Sopenharmony_ci        // predecessor, it is better not to perform a change. It would lead to
37501cb0ef41Sopenharmony_ci        // the same outcome anyway.
37511cb0ef41Sopenharmony_ci        // This may never happen on boundaries between deferred and
37521cb0ef41Sopenharmony_ci        // non-deferred code, as we rely on explicit respill to ensure we
37531cb0ef41Sopenharmony_ci        // spill at definition.
37541cb0ef41Sopenharmony_ci        bool no_change_required = false;
37551cb0ef41Sopenharmony_ci
37561cb0ef41Sopenharmony_ci        auto pick_state_from = [this, current_block](
37571cb0ef41Sopenharmony_ci                                   RpoNumber pred,
37581cb0ef41Sopenharmony_ci                                   RangeWithRegisterSet* to_be_live) -> bool {
37591cb0ef41Sopenharmony_ci          TRACE("Using information from B%d\n", pred.ToInt());
37601cb0ef41Sopenharmony_ci          // If this is a fall-through that is not across a deferred
37611cb0ef41Sopenharmony_ci          // boundary, there is nothing to do.
37621cb0ef41Sopenharmony_ci          bool is_noop = pred.IsNext(current_block->rpo_number());
37631cb0ef41Sopenharmony_ci          if (!is_noop) {
37641cb0ef41Sopenharmony_ci            auto& spill_state = data()->GetSpillState(pred);
37651cb0ef41Sopenharmony_ci            TRACE("Not a fallthrough. Adding %zu elements...\n",
37661cb0ef41Sopenharmony_ci                  spill_state.size());
37671cb0ef41Sopenharmony_ci            LifetimePosition pred_end =
37681cb0ef41Sopenharmony_ci                LifetimePosition::GapFromInstructionIndex(
37691cb0ef41Sopenharmony_ci                    this->code()->InstructionBlockAt(pred)->code_end());
37701cb0ef41Sopenharmony_ci            for (const auto range : spill_state) {
37711cb0ef41Sopenharmony_ci              // Filter out ranges that were split or had their register
37721cb0ef41Sopenharmony_ci              // stolen by backwards working spill heuristics. These have
37731cb0ef41Sopenharmony_ci              // been spilled after the fact, so ignore them.
37741cb0ef41Sopenharmony_ci              if (range->End() < pred_end || !range->HasRegisterAssigned())
37751cb0ef41Sopenharmony_ci                continue;
37761cb0ef41Sopenharmony_ci              to_be_live->emplace(range);
37771cb0ef41Sopenharmony_ci            }
37781cb0ef41Sopenharmony_ci          }
37791cb0ef41Sopenharmony_ci          return is_noop;
37801cb0ef41Sopenharmony_ci        };
37811cb0ef41Sopenharmony_ci
37821cb0ef41Sopenharmony_ci        // Multiple cases here:
37831cb0ef41Sopenharmony_ci        // 1) We have a single predecessor => this is a control flow split, so
37841cb0ef41Sopenharmony_ci        //     just restore the predecessor state.
37851cb0ef41Sopenharmony_ci        // 2) We have two predecessors => this is a conditional, so break ties
37861cb0ef41Sopenharmony_ci        //     based on what to do based on forward uses, trying to benefit
37871cb0ef41Sopenharmony_ci        //     the same branch if in doubt (make one path fast).
37881cb0ef41Sopenharmony_ci        // 3) We have many predecessors => this is a switch. Compute union
37891cb0ef41Sopenharmony_ci        //     based on majority, break ties by looking forward.
37901cb0ef41Sopenharmony_ci        if (current_block->PredecessorCount() == 1) {
37911cb0ef41Sopenharmony_ci          TRACE("Single predecessor for B%d\n",
37921cb0ef41Sopenharmony_ci                current_block->rpo_number().ToInt());
37931cb0ef41Sopenharmony_ci          no_change_required =
37941cb0ef41Sopenharmony_ci              pick_state_from(current_block->predecessors()[0], &to_be_live);
37951cb0ef41Sopenharmony_ci        } else if (current_block->PredecessorCount() == 2) {
37961cb0ef41Sopenharmony_ci          TRACE("Two predecessors for B%d\n",
37971cb0ef41Sopenharmony_ci                current_block->rpo_number().ToInt());
37981cb0ef41Sopenharmony_ci          // If one of the branches does not contribute any information,
37991cb0ef41Sopenharmony_ci          // e.g. because it is deferred or a back edge, we can short cut
38001cb0ef41Sopenharmony_ci          // here right away.
38011cb0ef41Sopenharmony_ci          RpoNumber chosen_predecessor = RpoNumber::Invalid();
38021cb0ef41Sopenharmony_ci          if (!ConsiderBlockForControlFlow(current_block,
38031cb0ef41Sopenharmony_ci                                           current_block->predecessors()[0])) {
38041cb0ef41Sopenharmony_ci            chosen_predecessor = current_block->predecessors()[1];
38051cb0ef41Sopenharmony_ci          } else if (!ConsiderBlockForControlFlow(
38061cb0ef41Sopenharmony_ci                         current_block, current_block->predecessors()[1])) {
38071cb0ef41Sopenharmony_ci            chosen_predecessor = current_block->predecessors()[0];
38081cb0ef41Sopenharmony_ci          } else {
38091cb0ef41Sopenharmony_ci            chosen_predecessor = ChooseOneOfTwoPredecessorStates(
38101cb0ef41Sopenharmony_ci                current_block, next_block_boundary);
38111cb0ef41Sopenharmony_ci          }
38121cb0ef41Sopenharmony_ci          no_change_required = pick_state_from(chosen_predecessor, &to_be_live);
38131cb0ef41Sopenharmony_ci
38141cb0ef41Sopenharmony_ci        } else {
38151cb0ef41Sopenharmony_ci          // Merge at the end of, e.g., a switch.
38161cb0ef41Sopenharmony_ci          ComputeStateFromManyPredecessors(current_block, &to_be_live);
38171cb0ef41Sopenharmony_ci        }
38181cb0ef41Sopenharmony_ci
38191cb0ef41Sopenharmony_ci        if (!no_change_required) {
38201cb0ef41Sopenharmony_ci          SpillNotLiveRanges(&to_be_live, next_block_boundary, spill_mode);
38211cb0ef41Sopenharmony_ci          ReloadLiveRanges(to_be_live, next_block_boundary);
38221cb0ef41Sopenharmony_ci        }
38231cb0ef41Sopenharmony_ci      }
38241cb0ef41Sopenharmony_ci      // Update block information
38251cb0ef41Sopenharmony_ci      last_block = current_block->rpo_number();
38261cb0ef41Sopenharmony_ci      next_block_boundary = LifetimePosition::InstructionFromInstructionIndex(
38271cb0ef41Sopenharmony_ci                                current_block->last_instruction_index())
38281cb0ef41Sopenharmony_ci                                .NextFullStart();
38291cb0ef41Sopenharmony_ci
38301cb0ef41Sopenharmony_ci      // We might have created new unhandled live ranges, so cycle around the
38311cb0ef41Sopenharmony_ci      // loop to make sure we pick the top most range in unhandled for
38321cb0ef41Sopenharmony_ci      // processing.
38331cb0ef41Sopenharmony_ci      continue;
38341cb0ef41Sopenharmony_ci    }
38351cb0ef41Sopenharmony_ci
38361cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(current);
38371cb0ef41Sopenharmony_ci
38381cb0ef41Sopenharmony_ci    TRACE("Processing interval %d:%d start=%d\n", current->TopLevel()->vreg(),
38391cb0ef41Sopenharmony_ci          current->relative_id(), position.value());
38401cb0ef41Sopenharmony_ci
38411cb0ef41Sopenharmony_ci    // Now we can erase current, as we are sure to process it.
38421cb0ef41Sopenharmony_ci    unhandled_live_ranges().erase(unhandled_live_ranges().begin());
38431cb0ef41Sopenharmony_ci
38441cb0ef41Sopenharmony_ci    if (current->IsTopLevel() && TryReuseSpillForPhi(current->TopLevel()))
38451cb0ef41Sopenharmony_ci      continue;
38461cb0ef41Sopenharmony_ci
38471cb0ef41Sopenharmony_ci    ForwardStateTo(position);
38481cb0ef41Sopenharmony_ci
38491cb0ef41Sopenharmony_ci    DCHECK(!current->HasRegisterAssigned() && !current->spilled());
38501cb0ef41Sopenharmony_ci
38511cb0ef41Sopenharmony_ci    ProcessCurrentRange(current, spill_mode);
38521cb0ef41Sopenharmony_ci  }
38531cb0ef41Sopenharmony_ci
38541cb0ef41Sopenharmony_ci  if (data()->is_trace_alloc()) {
38551cb0ef41Sopenharmony_ci    PrintRangeOverview();
38561cb0ef41Sopenharmony_ci  }
38571cb0ef41Sopenharmony_ci}
38581cb0ef41Sopenharmony_ci
38591cb0ef41Sopenharmony_civoid LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
38601cb0ef41Sopenharmony_ci                                                       int reg) {
38611cb0ef41Sopenharmony_ci  data()->MarkAllocated(range->representation(), reg);
38621cb0ef41Sopenharmony_ci  range->set_assigned_register(reg);
38631cb0ef41Sopenharmony_ci  range->SetUseHints(reg);
38641cb0ef41Sopenharmony_ci  range->UpdateBundleRegister(reg);
38651cb0ef41Sopenharmony_ci  if (range->IsTopLevel() && range->TopLevel()->is_phi()) {
38661cb0ef41Sopenharmony_ci    data()->GetPhiMapValueFor(range->TopLevel())->set_assigned_register(reg);
38671cb0ef41Sopenharmony_ci  }
38681cb0ef41Sopenharmony_ci}
38691cb0ef41Sopenharmony_ci
38701cb0ef41Sopenharmony_civoid LinearScanAllocator::AddToActive(LiveRange* range) {
38711cb0ef41Sopenharmony_ci  TRACE("Add live range %d:%d in %s to active\n", range->TopLevel()->vreg(),
38721cb0ef41Sopenharmony_ci        range->relative_id(), RegisterName(range->assigned_register()));
38731cb0ef41Sopenharmony_ci  active_live_ranges().push_back(range);
38741cb0ef41Sopenharmony_ci  next_active_ranges_change_ =
38751cb0ef41Sopenharmony_ci      std::min(next_active_ranges_change_, range->NextEndAfter(range->Start()));
38761cb0ef41Sopenharmony_ci}
38771cb0ef41Sopenharmony_ci
38781cb0ef41Sopenharmony_civoid LinearScanAllocator::AddToInactive(LiveRange* range) {
38791cb0ef41Sopenharmony_ci  TRACE("Add live range %d:%d to inactive\n", range->TopLevel()->vreg(),
38801cb0ef41Sopenharmony_ci        range->relative_id());
38811cb0ef41Sopenharmony_ci  next_inactive_ranges_change_ = std::min(
38821cb0ef41Sopenharmony_ci      next_inactive_ranges_change_, range->NextStartAfter(range->Start()));
38831cb0ef41Sopenharmony_ci  DCHECK(range->HasRegisterAssigned());
38841cb0ef41Sopenharmony_ci  inactive_live_ranges(range->assigned_register()).insert(range);
38851cb0ef41Sopenharmony_ci}
38861cb0ef41Sopenharmony_ci
38871cb0ef41Sopenharmony_civoid LinearScanAllocator::AddToUnhandled(LiveRange* range) {
38881cb0ef41Sopenharmony_ci  if (range == nullptr || range->IsEmpty()) return;
38891cb0ef41Sopenharmony_ci  DCHECK(!range->HasRegisterAssigned() && !range->spilled());
38901cb0ef41Sopenharmony_ci  DCHECK(allocation_finger_ <= range->Start());
38911cb0ef41Sopenharmony_ci
38921cb0ef41Sopenharmony_ci  TRACE("Add live range %d:%d to unhandled\n", range->TopLevel()->vreg(),
38931cb0ef41Sopenharmony_ci        range->relative_id());
38941cb0ef41Sopenharmony_ci  unhandled_live_ranges().insert(range);
38951cb0ef41Sopenharmony_ci}
38961cb0ef41Sopenharmony_ci
38971cb0ef41Sopenharmony_ciZoneVector<LiveRange*>::iterator LinearScanAllocator::ActiveToHandled(
38981cb0ef41Sopenharmony_ci    const ZoneVector<LiveRange*>::iterator it) {
38991cb0ef41Sopenharmony_ci  TRACE("Moving live range %d:%d from active to handled\n",
39001cb0ef41Sopenharmony_ci        (*it)->TopLevel()->vreg(), (*it)->relative_id());
39011cb0ef41Sopenharmony_ci  return active_live_ranges().erase(it);
39021cb0ef41Sopenharmony_ci}
39031cb0ef41Sopenharmony_ci
39041cb0ef41Sopenharmony_ciZoneVector<LiveRange*>::iterator LinearScanAllocator::ActiveToInactive(
39051cb0ef41Sopenharmony_ci    const ZoneVector<LiveRange*>::iterator it, LifetimePosition position) {
39061cb0ef41Sopenharmony_ci  LiveRange* range = *it;
39071cb0ef41Sopenharmony_ci  TRACE("Moving live range %d:%d from active to inactive\n",
39081cb0ef41Sopenharmony_ci        (range)->TopLevel()->vreg(), range->relative_id());
39091cb0ef41Sopenharmony_ci  LifetimePosition next_active = range->NextStartAfter(position);
39101cb0ef41Sopenharmony_ci  next_inactive_ranges_change_ =
39111cb0ef41Sopenharmony_ci      std::min(next_inactive_ranges_change_, next_active);
39121cb0ef41Sopenharmony_ci  DCHECK(range->HasRegisterAssigned());
39131cb0ef41Sopenharmony_ci  inactive_live_ranges(range->assigned_register()).insert(range);
39141cb0ef41Sopenharmony_ci  return active_live_ranges().erase(it);
39151cb0ef41Sopenharmony_ci}
39161cb0ef41Sopenharmony_ci
39171cb0ef41Sopenharmony_ciLinearScanAllocator::InactiveLiveRangeQueue::iterator
39181cb0ef41Sopenharmony_ciLinearScanAllocator::InactiveToHandled(InactiveLiveRangeQueue::iterator it) {
39191cb0ef41Sopenharmony_ci  LiveRange* range = *it;
39201cb0ef41Sopenharmony_ci  TRACE("Moving live range %d:%d from inactive to handled\n",
39211cb0ef41Sopenharmony_ci        range->TopLevel()->vreg(), range->relative_id());
39221cb0ef41Sopenharmony_ci  int reg = range->assigned_register();
39231cb0ef41Sopenharmony_ci  return inactive_live_ranges(reg).erase(it);
39241cb0ef41Sopenharmony_ci}
39251cb0ef41Sopenharmony_ci
39261cb0ef41Sopenharmony_ciLinearScanAllocator::InactiveLiveRangeQueue::iterator
39271cb0ef41Sopenharmony_ciLinearScanAllocator::InactiveToActive(InactiveLiveRangeQueue::iterator it,
39281cb0ef41Sopenharmony_ci                                      LifetimePosition position) {
39291cb0ef41Sopenharmony_ci  LiveRange* range = *it;
39301cb0ef41Sopenharmony_ci  active_live_ranges().push_back(range);
39311cb0ef41Sopenharmony_ci  TRACE("Moving live range %d:%d from inactive to active\n",
39321cb0ef41Sopenharmony_ci        range->TopLevel()->vreg(), range->relative_id());
39331cb0ef41Sopenharmony_ci  next_active_ranges_change_ =
39341cb0ef41Sopenharmony_ci      std::min(next_active_ranges_change_, range->NextEndAfter(position));
39351cb0ef41Sopenharmony_ci  int reg = range->assigned_register();
39361cb0ef41Sopenharmony_ci  return inactive_live_ranges(reg).erase(it);
39371cb0ef41Sopenharmony_ci}
39381cb0ef41Sopenharmony_ci
39391cb0ef41Sopenharmony_civoid LinearScanAllocator::ForwardStateTo(LifetimePosition position) {
39401cb0ef41Sopenharmony_ci  if (position >= next_active_ranges_change_) {
39411cb0ef41Sopenharmony_ci    next_active_ranges_change_ = LifetimePosition::MaxPosition();
39421cb0ef41Sopenharmony_ci    for (auto it = active_live_ranges().begin();
39431cb0ef41Sopenharmony_ci         it != active_live_ranges().end();) {
39441cb0ef41Sopenharmony_ci      LiveRange* cur_active = *it;
39451cb0ef41Sopenharmony_ci      if (cur_active->End() <= position) {
39461cb0ef41Sopenharmony_ci        it = ActiveToHandled(it);
39471cb0ef41Sopenharmony_ci      } else if (!cur_active->Covers(position)) {
39481cb0ef41Sopenharmony_ci        it = ActiveToInactive(it, position);
39491cb0ef41Sopenharmony_ci      } else {
39501cb0ef41Sopenharmony_ci        next_active_ranges_change_ = std::min(
39511cb0ef41Sopenharmony_ci            next_active_ranges_change_, cur_active->NextEndAfter(position));
39521cb0ef41Sopenharmony_ci        ++it;
39531cb0ef41Sopenharmony_ci      }
39541cb0ef41Sopenharmony_ci    }
39551cb0ef41Sopenharmony_ci  }
39561cb0ef41Sopenharmony_ci
39571cb0ef41Sopenharmony_ci  if (position >= next_inactive_ranges_change_) {
39581cb0ef41Sopenharmony_ci    next_inactive_ranges_change_ = LifetimePosition::MaxPosition();
39591cb0ef41Sopenharmony_ci    for (int reg = 0; reg < num_registers(); ++reg) {
39601cb0ef41Sopenharmony_ci      ZoneVector<LiveRange*> reorder(data()->allocation_zone());
39611cb0ef41Sopenharmony_ci      for (auto it = inactive_live_ranges(reg).begin();
39621cb0ef41Sopenharmony_ci           it != inactive_live_ranges(reg).end();) {
39631cb0ef41Sopenharmony_ci        LiveRange* cur_inactive = *it;
39641cb0ef41Sopenharmony_ci        if (cur_inactive->End() <= position) {
39651cb0ef41Sopenharmony_ci          it = InactiveToHandled(it);
39661cb0ef41Sopenharmony_ci        } else if (cur_inactive->Covers(position)) {
39671cb0ef41Sopenharmony_ci          it = InactiveToActive(it, position);
39681cb0ef41Sopenharmony_ci        } else {
39691cb0ef41Sopenharmony_ci          next_inactive_ranges_change_ =
39701cb0ef41Sopenharmony_ci              std::min(next_inactive_ranges_change_,
39711cb0ef41Sopenharmony_ci                       cur_inactive->NextStartAfter(position));
39721cb0ef41Sopenharmony_ci          it = inactive_live_ranges(reg).erase(it);
39731cb0ef41Sopenharmony_ci          reorder.push_back(cur_inactive);
39741cb0ef41Sopenharmony_ci        }
39751cb0ef41Sopenharmony_ci      }
39761cb0ef41Sopenharmony_ci      for (LiveRange* range : reorder) {
39771cb0ef41Sopenharmony_ci        inactive_live_ranges(reg).insert(range);
39781cb0ef41Sopenharmony_ci      }
39791cb0ef41Sopenharmony_ci    }
39801cb0ef41Sopenharmony_ci  }
39811cb0ef41Sopenharmony_ci}
39821cb0ef41Sopenharmony_ci
39831cb0ef41Sopenharmony_ciint LinearScanAllocator::LastDeferredInstructionIndex(InstructionBlock* start) {
39841cb0ef41Sopenharmony_ci  DCHECK(start->IsDeferred());
39851cb0ef41Sopenharmony_ci  RpoNumber last_block =
39861cb0ef41Sopenharmony_ci      RpoNumber::FromInt(code()->InstructionBlockCount() - 1);
39871cb0ef41Sopenharmony_ci  while ((start->rpo_number() < last_block)) {
39881cb0ef41Sopenharmony_ci    InstructionBlock* next =
39891cb0ef41Sopenharmony_ci        code()->InstructionBlockAt(start->rpo_number().Next());
39901cb0ef41Sopenharmony_ci    if (!next->IsDeferred()) break;
39911cb0ef41Sopenharmony_ci    start = next;
39921cb0ef41Sopenharmony_ci  }
39931cb0ef41Sopenharmony_ci  return start->last_instruction_index();
39941cb0ef41Sopenharmony_ci}
39951cb0ef41Sopenharmony_ci
39961cb0ef41Sopenharmony_civoid LinearScanAllocator::GetFPRegisterSet(MachineRepresentation rep,
39971cb0ef41Sopenharmony_ci                                           int* num_regs, int* num_codes,
39981cb0ef41Sopenharmony_ci                                           const int** codes) const {
39991cb0ef41Sopenharmony_ci  DCHECK_EQ(kFPAliasing, AliasingKind::kCombine);
40001cb0ef41Sopenharmony_ci  if (rep == MachineRepresentation::kFloat32) {
40011cb0ef41Sopenharmony_ci    *num_regs = data()->config()->num_float_registers();
40021cb0ef41Sopenharmony_ci    *num_codes = data()->config()->num_allocatable_float_registers();
40031cb0ef41Sopenharmony_ci    *codes = data()->config()->allocatable_float_codes();
40041cb0ef41Sopenharmony_ci  } else if (rep == MachineRepresentation::kSimd128) {
40051cb0ef41Sopenharmony_ci    *num_regs = data()->config()->num_simd128_registers();
40061cb0ef41Sopenharmony_ci    *num_codes = data()->config()->num_allocatable_simd128_registers();
40071cb0ef41Sopenharmony_ci    *codes = data()->config()->allocatable_simd128_codes();
40081cb0ef41Sopenharmony_ci  } else {
40091cb0ef41Sopenharmony_ci    UNREACHABLE();
40101cb0ef41Sopenharmony_ci  }
40111cb0ef41Sopenharmony_ci}
40121cb0ef41Sopenharmony_ci
40131cb0ef41Sopenharmony_civoid LinearScanAllocator::GetSIMD128RegisterSet(int* num_regs, int* num_codes,
40141cb0ef41Sopenharmony_ci                                                const int** codes) const {
40151cb0ef41Sopenharmony_ci  DCHECK_EQ(kFPAliasing, AliasingKind::kIndependent);
40161cb0ef41Sopenharmony_ci
40171cb0ef41Sopenharmony_ci  *num_regs = data()->config()->num_simd128_registers();
40181cb0ef41Sopenharmony_ci  *num_codes = data()->config()->num_allocatable_simd128_registers();
40191cb0ef41Sopenharmony_ci  *codes = data()->config()->allocatable_simd128_codes();
40201cb0ef41Sopenharmony_ci}
40211cb0ef41Sopenharmony_ci
40221cb0ef41Sopenharmony_civoid LinearScanAllocator::FindFreeRegistersForRange(
40231cb0ef41Sopenharmony_ci    LiveRange* range, base::Vector<LifetimePosition> positions) {
40241cb0ef41Sopenharmony_ci  int num_regs = num_registers();
40251cb0ef41Sopenharmony_ci  int num_codes = num_allocatable_registers();
40261cb0ef41Sopenharmony_ci  const int* codes = allocatable_register_codes();
40271cb0ef41Sopenharmony_ci  MachineRepresentation rep = range->representation();
40281cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kCombine &&
40291cb0ef41Sopenharmony_ci      (rep == MachineRepresentation::kFloat32 ||
40301cb0ef41Sopenharmony_ci       rep == MachineRepresentation::kSimd128)) {
40311cb0ef41Sopenharmony_ci    GetFPRegisterSet(rep, &num_regs, &num_codes, &codes);
40321cb0ef41Sopenharmony_ci  } else if (kFPAliasing == AliasingKind::kIndependent &&
40331cb0ef41Sopenharmony_ci             (rep == MachineRepresentation::kSimd128)) {
40341cb0ef41Sopenharmony_ci    GetSIMD128RegisterSet(&num_regs, &num_codes, &codes);
40351cb0ef41Sopenharmony_ci  }
40361cb0ef41Sopenharmony_ci  DCHECK_GE(positions.length(), num_regs);
40371cb0ef41Sopenharmony_ci
40381cb0ef41Sopenharmony_ci  for (int i = 0; i < num_regs; ++i) {
40391cb0ef41Sopenharmony_ci    positions[i] = LifetimePosition::MaxPosition();
40401cb0ef41Sopenharmony_ci  }
40411cb0ef41Sopenharmony_ci
40421cb0ef41Sopenharmony_ci  for (LiveRange* cur_active : active_live_ranges()) {
40431cb0ef41Sopenharmony_ci    int cur_reg = cur_active->assigned_register();
40441cb0ef41Sopenharmony_ci    if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
40451cb0ef41Sopenharmony_ci      positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0);
40461cb0ef41Sopenharmony_ci      TRACE("Register %s is free until pos %d (1) due to %d\n",
40471cb0ef41Sopenharmony_ci            RegisterName(cur_reg),
40481cb0ef41Sopenharmony_ci            LifetimePosition::GapFromInstructionIndex(0).value(),
40491cb0ef41Sopenharmony_ci            cur_active->TopLevel()->vreg());
40501cb0ef41Sopenharmony_ci    } else {
40511cb0ef41Sopenharmony_ci      int alias_base_index = -1;
40521cb0ef41Sopenharmony_ci      int aliases = data()->config()->GetAliases(
40531cb0ef41Sopenharmony_ci          cur_active->representation(), cur_reg, rep, &alias_base_index);
40541cb0ef41Sopenharmony_ci      DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
40551cb0ef41Sopenharmony_ci      while (aliases--) {
40561cb0ef41Sopenharmony_ci        int aliased_reg = alias_base_index + aliases;
40571cb0ef41Sopenharmony_ci        positions[aliased_reg] = LifetimePosition::GapFromInstructionIndex(0);
40581cb0ef41Sopenharmony_ci      }
40591cb0ef41Sopenharmony_ci    }
40601cb0ef41Sopenharmony_ci  }
40611cb0ef41Sopenharmony_ci
40621cb0ef41Sopenharmony_ci  for (int cur_reg = 0; cur_reg < num_regs; ++cur_reg) {
40631cb0ef41Sopenharmony_ci    for (LiveRange* cur_inactive : inactive_live_ranges(cur_reg)) {
40641cb0ef41Sopenharmony_ci      DCHECK_GT(cur_inactive->End(), range->Start());
40651cb0ef41Sopenharmony_ci      CHECK_EQ(cur_inactive->assigned_register(), cur_reg);
40661cb0ef41Sopenharmony_ci      // No need to carry out intersections, when this register won't be
40671cb0ef41Sopenharmony_ci      // interesting to this range anyway.
40681cb0ef41Sopenharmony_ci      // TODO(mtrofin): extend to aliased ranges, too.
40691cb0ef41Sopenharmony_ci      if ((kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) &&
40701cb0ef41Sopenharmony_ci          (positions[cur_reg] <= cur_inactive->NextStart() ||
40711cb0ef41Sopenharmony_ci           range->End() <= cur_inactive->NextStart())) {
40721cb0ef41Sopenharmony_ci        break;
40731cb0ef41Sopenharmony_ci      }
40741cb0ef41Sopenharmony_ci      LifetimePosition next_intersection =
40751cb0ef41Sopenharmony_ci          cur_inactive->FirstIntersection(range);
40761cb0ef41Sopenharmony_ci      if (!next_intersection.IsValid()) continue;
40771cb0ef41Sopenharmony_ci      if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
40781cb0ef41Sopenharmony_ci        positions[cur_reg] = std::min(positions[cur_reg], next_intersection);
40791cb0ef41Sopenharmony_ci        TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
40801cb0ef41Sopenharmony_ci              positions[cur_reg].value());
40811cb0ef41Sopenharmony_ci      } else {
40821cb0ef41Sopenharmony_ci        int alias_base_index = -1;
40831cb0ef41Sopenharmony_ci        int aliases = data()->config()->GetAliases(
40841cb0ef41Sopenharmony_ci            cur_inactive->representation(), cur_reg, rep, &alias_base_index);
40851cb0ef41Sopenharmony_ci        DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
40861cb0ef41Sopenharmony_ci        while (aliases--) {
40871cb0ef41Sopenharmony_ci          int aliased_reg = alias_base_index + aliases;
40881cb0ef41Sopenharmony_ci          positions[aliased_reg] =
40891cb0ef41Sopenharmony_ci              std::min(positions[aliased_reg], next_intersection);
40901cb0ef41Sopenharmony_ci        }
40911cb0ef41Sopenharmony_ci      }
40921cb0ef41Sopenharmony_ci    }
40931cb0ef41Sopenharmony_ci  }
40941cb0ef41Sopenharmony_ci}
40951cb0ef41Sopenharmony_ci
40961cb0ef41Sopenharmony_ci// High-level register allocation summary:
40971cb0ef41Sopenharmony_ci//
40981cb0ef41Sopenharmony_ci// We attempt to first allocate the preferred (hint) register. If that is not
40991cb0ef41Sopenharmony_ci// possible, we find a register that's free, and allocate that. If that's not
41001cb0ef41Sopenharmony_ci// possible, we search for a register to steal from a range that was allocated.
41011cb0ef41Sopenharmony_ci// The goal is to optimize for throughput by avoiding register-to-memory moves,
41021cb0ef41Sopenharmony_ci// which are expensive.
41031cb0ef41Sopenharmony_civoid LinearScanAllocator::ProcessCurrentRange(LiveRange* current,
41041cb0ef41Sopenharmony_ci                                              SpillMode spill_mode) {
41051cb0ef41Sopenharmony_ci  base::EmbeddedVector<LifetimePosition, RegisterConfiguration::kMaxRegisters>
41061cb0ef41Sopenharmony_ci      free_until_pos;
41071cb0ef41Sopenharmony_ci  FindFreeRegistersForRange(current, free_until_pos);
41081cb0ef41Sopenharmony_ci  if (!TryAllocatePreferredReg(current, free_until_pos)) {
41091cb0ef41Sopenharmony_ci    if (!TryAllocateFreeReg(current, free_until_pos)) {
41101cb0ef41Sopenharmony_ci      AllocateBlockedReg(current, spill_mode);
41111cb0ef41Sopenharmony_ci    }
41121cb0ef41Sopenharmony_ci  }
41131cb0ef41Sopenharmony_ci  if (current->HasRegisterAssigned()) {
41141cb0ef41Sopenharmony_ci    AddToActive(current);
41151cb0ef41Sopenharmony_ci  }
41161cb0ef41Sopenharmony_ci}
41171cb0ef41Sopenharmony_ci
41181cb0ef41Sopenharmony_cibool LinearScanAllocator::TryAllocatePreferredReg(
41191cb0ef41Sopenharmony_ci    LiveRange* current, const base::Vector<LifetimePosition>& free_until_pos) {
41201cb0ef41Sopenharmony_ci  int hint_register;
41211cb0ef41Sopenharmony_ci  if (current->RegisterFromControlFlow(&hint_register) ||
41221cb0ef41Sopenharmony_ci      current->FirstHintPosition(&hint_register) != nullptr ||
41231cb0ef41Sopenharmony_ci      current->RegisterFromBundle(&hint_register)) {
41241cb0ef41Sopenharmony_ci    TRACE(
41251cb0ef41Sopenharmony_ci        "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n",
41261cb0ef41Sopenharmony_ci        RegisterName(hint_register), free_until_pos[hint_register].value(),
41271cb0ef41Sopenharmony_ci        current->TopLevel()->vreg(), current->relative_id(),
41281cb0ef41Sopenharmony_ci        current->End().value());
41291cb0ef41Sopenharmony_ci
41301cb0ef41Sopenharmony_ci    // The desired register is free until the end of the current live range.
41311cb0ef41Sopenharmony_ci    if (free_until_pos[hint_register] >= current->End()) {
41321cb0ef41Sopenharmony_ci      TRACE("Assigning preferred reg %s to live range %d:%d\n",
41331cb0ef41Sopenharmony_ci            RegisterName(hint_register), current->TopLevel()->vreg(),
41341cb0ef41Sopenharmony_ci            current->relative_id());
41351cb0ef41Sopenharmony_ci      SetLiveRangeAssignedRegister(current, hint_register);
41361cb0ef41Sopenharmony_ci      return true;
41371cb0ef41Sopenharmony_ci    }
41381cb0ef41Sopenharmony_ci  }
41391cb0ef41Sopenharmony_ci  return false;
41401cb0ef41Sopenharmony_ci}
41411cb0ef41Sopenharmony_ci
41421cb0ef41Sopenharmony_ciint LinearScanAllocator::PickRegisterThatIsAvailableLongest(
41431cb0ef41Sopenharmony_ci    LiveRange* current, int hint_reg,
41441cb0ef41Sopenharmony_ci    const base::Vector<LifetimePosition>& free_until_pos) {
41451cb0ef41Sopenharmony_ci  int num_regs = 0;  // used only for the call to GetFPRegisterSet.
41461cb0ef41Sopenharmony_ci  int num_codes = num_allocatable_registers();
41471cb0ef41Sopenharmony_ci  const int* codes = allocatable_register_codes();
41481cb0ef41Sopenharmony_ci  MachineRepresentation rep = current->representation();
41491cb0ef41Sopenharmony_ci  if (kFPAliasing == AliasingKind::kCombine &&
41501cb0ef41Sopenharmony_ci      (rep == MachineRepresentation::kFloat32 ||
41511cb0ef41Sopenharmony_ci       rep == MachineRepresentation::kSimd128)) {
41521cb0ef41Sopenharmony_ci    GetFPRegisterSet(rep, &num_regs, &num_codes, &codes);
41531cb0ef41Sopenharmony_ci  } else if (kFPAliasing == AliasingKind::kIndependent &&
41541cb0ef41Sopenharmony_ci             (rep == MachineRepresentation::kSimd128)) {
41551cb0ef41Sopenharmony_ci    GetSIMD128RegisterSet(&num_regs, &num_codes, &codes);
41561cb0ef41Sopenharmony_ci  }
41571cb0ef41Sopenharmony_ci
41581cb0ef41Sopenharmony_ci  DCHECK_GE(free_until_pos.length(), num_codes);
41591cb0ef41Sopenharmony_ci
41601cb0ef41Sopenharmony_ci  // Find the register which stays free for the longest time. Check for
41611cb0ef41Sopenharmony_ci  // the hinted register first, as we might want to use that one. Only
41621cb0ef41Sopenharmony_ci  // count full instructions for free ranges, as an instruction's internal
41631cb0ef41Sopenharmony_ci  // positions do not help but might shadow a hinted register. This is
41641cb0ef41Sopenharmony_ci  // typically the case for function calls, where all registered are
41651cb0ef41Sopenharmony_ci  // cloberred after the call except for the argument registers, which are
41661cb0ef41Sopenharmony_ci  // set before the call. Hence, the argument registers always get ignored,
41671cb0ef41Sopenharmony_ci  // as their available time is shorter.
41681cb0ef41Sopenharmony_ci  int reg = (hint_reg == kUnassignedRegister) ? codes[0] : hint_reg;
41691cb0ef41Sopenharmony_ci  int current_free = free_until_pos[reg].ToInstructionIndex();
41701cb0ef41Sopenharmony_ci  for (int i = 0; i < num_codes; ++i) {
41711cb0ef41Sopenharmony_ci    int code = codes[i];
41721cb0ef41Sopenharmony_ci    // Prefer registers that have no fixed uses to avoid blocking later hints.
41731cb0ef41Sopenharmony_ci    // We use the first register that has no fixed uses to ensure we use
41741cb0ef41Sopenharmony_ci    // byte addressable registers in ia32 first.
41751cb0ef41Sopenharmony_ci    int candidate_free = free_until_pos[code].ToInstructionIndex();
41761cb0ef41Sopenharmony_ci    TRACE("Register %s in free until %d\n", RegisterName(code), candidate_free);
41771cb0ef41Sopenharmony_ci    if ((candidate_free > current_free) ||
41781cb0ef41Sopenharmony_ci        (candidate_free == current_free && reg != hint_reg &&
41791cb0ef41Sopenharmony_ci         (data()->HasFixedUse(current->representation(), reg) &&
41801cb0ef41Sopenharmony_ci          !data()->HasFixedUse(current->representation(), code)))) {
41811cb0ef41Sopenharmony_ci      reg = code;
41821cb0ef41Sopenharmony_ci      current_free = candidate_free;
41831cb0ef41Sopenharmony_ci    }
41841cb0ef41Sopenharmony_ci  }
41851cb0ef41Sopenharmony_ci
41861cb0ef41Sopenharmony_ci  return reg;
41871cb0ef41Sopenharmony_ci}
41881cb0ef41Sopenharmony_ci
41891cb0ef41Sopenharmony_cibool LinearScanAllocator::TryAllocateFreeReg(
41901cb0ef41Sopenharmony_ci    LiveRange* current, const base::Vector<LifetimePosition>& free_until_pos) {
41911cb0ef41Sopenharmony_ci  // Compute register hint, if such exists.
41921cb0ef41Sopenharmony_ci  int hint_reg = kUnassignedRegister;
41931cb0ef41Sopenharmony_ci  current->RegisterFromControlFlow(&hint_reg) ||
41941cb0ef41Sopenharmony_ci      current->FirstHintPosition(&hint_reg) != nullptr ||
41951cb0ef41Sopenharmony_ci      current->RegisterFromBundle(&hint_reg);
41961cb0ef41Sopenharmony_ci
41971cb0ef41Sopenharmony_ci  int reg =
41981cb0ef41Sopenharmony_ci      PickRegisterThatIsAvailableLongest(current, hint_reg, free_until_pos);
41991cb0ef41Sopenharmony_ci
42001cb0ef41Sopenharmony_ci  LifetimePosition pos = free_until_pos[reg];
42011cb0ef41Sopenharmony_ci
42021cb0ef41Sopenharmony_ci  if (pos <= current->Start()) {
42031cb0ef41Sopenharmony_ci    // All registers are blocked.
42041cb0ef41Sopenharmony_ci    return false;
42051cb0ef41Sopenharmony_ci  }
42061cb0ef41Sopenharmony_ci
42071cb0ef41Sopenharmony_ci  if (pos < current->End()) {
42081cb0ef41Sopenharmony_ci    // Register reg is available at the range start but becomes blocked before
42091cb0ef41Sopenharmony_ci    // the range end. Split current before the position where it becomes
42101cb0ef41Sopenharmony_ci    // blocked. Shift the split position to the last gap position. This is to
42111cb0ef41Sopenharmony_ci    // ensure that if a connecting move is needed, that move coincides with the
42121cb0ef41Sopenharmony_ci    // start of the range that it defines. See crbug.com/1182985.
42131cb0ef41Sopenharmony_ci    LifetimePosition gap_pos =
42141cb0ef41Sopenharmony_ci        pos.IsGapPosition() ? pos : pos.FullStart().End();
42151cb0ef41Sopenharmony_ci    if (gap_pos <= current->Start()) return false;
42161cb0ef41Sopenharmony_ci    LiveRange* tail = SplitRangeAt(current, gap_pos);
42171cb0ef41Sopenharmony_ci    AddToUnhandled(tail);
42181cb0ef41Sopenharmony_ci
42191cb0ef41Sopenharmony_ci    // Try to allocate preferred register once more.
42201cb0ef41Sopenharmony_ci    if (TryAllocatePreferredReg(current, free_until_pos)) return true;
42211cb0ef41Sopenharmony_ci  }
42221cb0ef41Sopenharmony_ci
42231cb0ef41Sopenharmony_ci  // Register reg is available at the range start and is free until the range
42241cb0ef41Sopenharmony_ci  // end.
42251cb0ef41Sopenharmony_ci  DCHECK_GE(pos, current->End());
42261cb0ef41Sopenharmony_ci  TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(reg),
42271cb0ef41Sopenharmony_ci        current->TopLevel()->vreg(), current->relative_id());
42281cb0ef41Sopenharmony_ci  SetLiveRangeAssignedRegister(current, reg);
42291cb0ef41Sopenharmony_ci
42301cb0ef41Sopenharmony_ci  return true;
42311cb0ef41Sopenharmony_ci}
42321cb0ef41Sopenharmony_ci
42331cb0ef41Sopenharmony_civoid LinearScanAllocator::AllocateBlockedReg(LiveRange* current,
42341cb0ef41Sopenharmony_ci                                             SpillMode spill_mode) {
42351cb0ef41Sopenharmony_ci  UsePosition* register_use = current->NextRegisterPosition(current->Start());
42361cb0ef41Sopenharmony_ci  if (register_use == nullptr) {
42371cb0ef41Sopenharmony_ci    // There is no use in the current live range that requires a register.
42381cb0ef41Sopenharmony_ci    // We can just spill it.
42391cb0ef41Sopenharmony_ci    LiveRange* begin_spill = nullptr;
42401cb0ef41Sopenharmony_ci    LifetimePosition spill_pos = FindOptimalSpillingPos(
42411cb0ef41Sopenharmony_ci        current, current->Start(), spill_mode, &begin_spill);
42421cb0ef41Sopenharmony_ci    MaybeSpillPreviousRanges(begin_spill, spill_pos, current);
42431cb0ef41Sopenharmony_ci    Spill(current, spill_mode);
42441cb0ef41Sopenharmony_ci    return;
42451cb0ef41Sopenharmony_ci  }
42461cb0ef41Sopenharmony_ci
42471cb0ef41Sopenharmony_ci  MachineRepresentation rep = current->representation();
42481cb0ef41Sopenharmony_ci
42491cb0ef41Sopenharmony_ci  // use_pos keeps track of positions a register/alias is used at.
42501cb0ef41Sopenharmony_ci  // block_pos keeps track of positions where a register/alias is blocked
42511cb0ef41Sopenharmony_ci  // from.
42521cb0ef41Sopenharmony_ci  base::EmbeddedVector<LifetimePosition, RegisterConfiguration::kMaxRegisters>
42531cb0ef41Sopenharmony_ci      use_pos(LifetimePosition::MaxPosition());
42541cb0ef41Sopenharmony_ci  base::EmbeddedVector<LifetimePosition, RegisterConfiguration::kMaxRegisters>
42551cb0ef41Sopenharmony_ci      block_pos(LifetimePosition::MaxPosition());
42561cb0ef41Sopenharmony_ci
42571cb0ef41Sopenharmony_ci  for (LiveRange* range : active_live_ranges()) {
42581cb0ef41Sopenharmony_ci    int cur_reg = range->assigned_register();
42591cb0ef41Sopenharmony_ci    bool is_fixed_or_cant_spill =
42601cb0ef41Sopenharmony_ci        range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start());
42611cb0ef41Sopenharmony_ci    if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
42621cb0ef41Sopenharmony_ci      if (is_fixed_or_cant_spill) {
42631cb0ef41Sopenharmony_ci        block_pos[cur_reg] = use_pos[cur_reg] =
42641cb0ef41Sopenharmony_ci            LifetimePosition::GapFromInstructionIndex(0);
42651cb0ef41Sopenharmony_ci      } else {
42661cb0ef41Sopenharmony_ci        DCHECK_NE(LifetimePosition::GapFromInstructionIndex(0),
42671cb0ef41Sopenharmony_ci                  block_pos[cur_reg]);
42681cb0ef41Sopenharmony_ci        use_pos[cur_reg] =
42691cb0ef41Sopenharmony_ci            range->NextLifetimePositionRegisterIsBeneficial(current->Start());
42701cb0ef41Sopenharmony_ci      }
42711cb0ef41Sopenharmony_ci    } else {
42721cb0ef41Sopenharmony_ci      int alias_base_index = -1;
42731cb0ef41Sopenharmony_ci      int aliases = data()->config()->GetAliases(
42741cb0ef41Sopenharmony_ci          range->representation(), cur_reg, rep, &alias_base_index);
42751cb0ef41Sopenharmony_ci      DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
42761cb0ef41Sopenharmony_ci      while (aliases--) {
42771cb0ef41Sopenharmony_ci        int aliased_reg = alias_base_index + aliases;
42781cb0ef41Sopenharmony_ci        if (is_fixed_or_cant_spill) {
42791cb0ef41Sopenharmony_ci          block_pos[aliased_reg] = use_pos[aliased_reg] =
42801cb0ef41Sopenharmony_ci              LifetimePosition::GapFromInstructionIndex(0);
42811cb0ef41Sopenharmony_ci        } else {
42821cb0ef41Sopenharmony_ci          use_pos[aliased_reg] =
42831cb0ef41Sopenharmony_ci              std::min(block_pos[aliased_reg],
42841cb0ef41Sopenharmony_ci                       range->NextLifetimePositionRegisterIsBeneficial(
42851cb0ef41Sopenharmony_ci                           current->Start()));
42861cb0ef41Sopenharmony_ci        }
42871cb0ef41Sopenharmony_ci      }
42881cb0ef41Sopenharmony_ci    }
42891cb0ef41Sopenharmony_ci  }
42901cb0ef41Sopenharmony_ci
42911cb0ef41Sopenharmony_ci  for (int cur_reg = 0; cur_reg < num_registers(); ++cur_reg) {
42921cb0ef41Sopenharmony_ci    for (LiveRange* range : inactive_live_ranges(cur_reg)) {
42931cb0ef41Sopenharmony_ci      DCHECK(range->End() > current->Start());
42941cb0ef41Sopenharmony_ci      DCHECK_EQ(range->assigned_register(), cur_reg);
42951cb0ef41Sopenharmony_ci      bool is_fixed = range->TopLevel()->IsFixed();
42961cb0ef41Sopenharmony_ci
42971cb0ef41Sopenharmony_ci      // Don't perform costly intersections if they are guaranteed to not update
42981cb0ef41Sopenharmony_ci      // block_pos or use_pos.
42991cb0ef41Sopenharmony_ci      // TODO(mtrofin): extend to aliased ranges, too.
43001cb0ef41Sopenharmony_ci      if ((kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing())) {
43011cb0ef41Sopenharmony_ci        DCHECK_LE(use_pos[cur_reg], block_pos[cur_reg]);
43021cb0ef41Sopenharmony_ci        if (block_pos[cur_reg] <= range->NextStart()) break;
43031cb0ef41Sopenharmony_ci        if (!is_fixed && use_pos[cur_reg] <= range->NextStart()) continue;
43041cb0ef41Sopenharmony_ci      }
43051cb0ef41Sopenharmony_ci
43061cb0ef41Sopenharmony_ci      LifetimePosition next_intersection = range->FirstIntersection(current);
43071cb0ef41Sopenharmony_ci      if (!next_intersection.IsValid()) continue;
43081cb0ef41Sopenharmony_ci
43091cb0ef41Sopenharmony_ci      if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
43101cb0ef41Sopenharmony_ci        if (is_fixed) {
43111cb0ef41Sopenharmony_ci          block_pos[cur_reg] = std::min(block_pos[cur_reg], next_intersection);
43121cb0ef41Sopenharmony_ci          use_pos[cur_reg] = std::min(block_pos[cur_reg], use_pos[cur_reg]);
43131cb0ef41Sopenharmony_ci        } else {
43141cb0ef41Sopenharmony_ci          use_pos[cur_reg] = std::min(use_pos[cur_reg], next_intersection);
43151cb0ef41Sopenharmony_ci        }
43161cb0ef41Sopenharmony_ci      } else {
43171cb0ef41Sopenharmony_ci        int alias_base_index = -1;
43181cb0ef41Sopenharmony_ci        int aliases = data()->config()->GetAliases(
43191cb0ef41Sopenharmony_ci            range->representation(), cur_reg, rep, &alias_base_index);
43201cb0ef41Sopenharmony_ci        DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
43211cb0ef41Sopenharmony_ci        while (aliases--) {
43221cb0ef41Sopenharmony_ci          int aliased_reg = alias_base_index + aliases;
43231cb0ef41Sopenharmony_ci          if (is_fixed) {
43241cb0ef41Sopenharmony_ci            block_pos[aliased_reg] =
43251cb0ef41Sopenharmony_ci                std::min(block_pos[aliased_reg], next_intersection);
43261cb0ef41Sopenharmony_ci            use_pos[aliased_reg] =
43271cb0ef41Sopenharmony_ci                std::min(block_pos[aliased_reg], use_pos[aliased_reg]);
43281cb0ef41Sopenharmony_ci          } else {
43291cb0ef41Sopenharmony_ci            use_pos[aliased_reg] =
43301cb0ef41Sopenharmony_ci                std::min(use_pos[aliased_reg], next_intersection);
43311cb0ef41Sopenharmony_ci          }
43321cb0ef41Sopenharmony_ci        }
43331cb0ef41Sopenharmony_ci      }
43341cb0ef41Sopenharmony_ci    }
43351cb0ef41Sopenharmony_ci  }
43361cb0ef41Sopenharmony_ci
43371cb0ef41Sopenharmony_ci  // Compute register hint if it exists.
43381cb0ef41Sopenharmony_ci  int hint_reg = kUnassignedRegister;
43391cb0ef41Sopenharmony_ci  current->RegisterFromControlFlow(&hint_reg) ||
43401cb0ef41Sopenharmony_ci      register_use->HintRegister(&hint_reg) ||
43411cb0ef41Sopenharmony_ci      current->RegisterFromBundle(&hint_reg);
43421cb0ef41Sopenharmony_ci  int reg = PickRegisterThatIsAvailableLongest(current, hint_reg, use_pos);
43431cb0ef41Sopenharmony_ci
43441cb0ef41Sopenharmony_ci  if (use_pos[reg] < register_use->pos()) {
43451cb0ef41Sopenharmony_ci    // If there is a gap position before the next register use, we can
43461cb0ef41Sopenharmony_ci    // spill until there. The gap position will then fit the fill move.
43471cb0ef41Sopenharmony_ci    if (LifetimePosition::ExistsGapPositionBetween(current->Start(),
43481cb0ef41Sopenharmony_ci                                                   register_use->pos())) {
43491cb0ef41Sopenharmony_ci      SpillBetween(current, current->Start(), register_use->pos(), spill_mode);
43501cb0ef41Sopenharmony_ci      return;
43511cb0ef41Sopenharmony_ci    }
43521cb0ef41Sopenharmony_ci  }
43531cb0ef41Sopenharmony_ci
43541cb0ef41Sopenharmony_ci  // When in deferred spilling mode avoid stealing registers beyond the current
43551cb0ef41Sopenharmony_ci  // deferred region. This is required as we otherwise might spill an inactive
43561cb0ef41Sopenharmony_ci  // range with a start outside of deferred code and that would not be reloaded.
43571cb0ef41Sopenharmony_ci  LifetimePosition new_end = current->End();
43581cb0ef41Sopenharmony_ci  if (spill_mode == SpillMode::kSpillDeferred) {
43591cb0ef41Sopenharmony_ci    InstructionBlock* deferred_block =
43601cb0ef41Sopenharmony_ci        code()->GetInstructionBlock(current->Start().ToInstructionIndex());
43611cb0ef41Sopenharmony_ci    new_end =
43621cb0ef41Sopenharmony_ci        std::min(new_end, LifetimePosition::GapFromInstructionIndex(
43631cb0ef41Sopenharmony_ci                              LastDeferredInstructionIndex(deferred_block)));
43641cb0ef41Sopenharmony_ci  }
43651cb0ef41Sopenharmony_ci
43661cb0ef41Sopenharmony_ci  // We couldn't spill until the next register use. Split before the register
43671cb0ef41Sopenharmony_ci  // is blocked, if applicable.
43681cb0ef41Sopenharmony_ci  if (block_pos[reg] < new_end) {
43691cb0ef41Sopenharmony_ci    // Register becomes blocked before the current range end. Split before that
43701cb0ef41Sopenharmony_ci    // position.
43711cb0ef41Sopenharmony_ci    new_end = block_pos[reg].Start();
43721cb0ef41Sopenharmony_ci  }
43731cb0ef41Sopenharmony_ci
43741cb0ef41Sopenharmony_ci  // If there is no register available at all, we can only spill this range.
43751cb0ef41Sopenharmony_ci  // Happens for instance on entry to deferred code where registers might
43761cb0ef41Sopenharmony_ci  // become blocked yet we aim to reload ranges.
43771cb0ef41Sopenharmony_ci  if (new_end == current->Start()) {
43781cb0ef41Sopenharmony_ci    SpillBetween(current, new_end, register_use->pos(), spill_mode);
43791cb0ef41Sopenharmony_ci    return;
43801cb0ef41Sopenharmony_ci  }
43811cb0ef41Sopenharmony_ci
43821cb0ef41Sopenharmony_ci  // Split at the new end if we found one.
43831cb0ef41Sopenharmony_ci  if (new_end != current->End()) {
43841cb0ef41Sopenharmony_ci    LiveRange* tail = SplitBetween(current, current->Start(), new_end);
43851cb0ef41Sopenharmony_ci    AddToUnhandled(tail);
43861cb0ef41Sopenharmony_ci  }
43871cb0ef41Sopenharmony_ci
43881cb0ef41Sopenharmony_ci  // Register reg is not blocked for the whole range.
43891cb0ef41Sopenharmony_ci  DCHECK(block_pos[reg] >= current->End());
43901cb0ef41Sopenharmony_ci  TRACE("Assigning blocked reg %s to live range %d:%d\n", RegisterName(reg),
43911cb0ef41Sopenharmony_ci        current->TopLevel()->vreg(), current->relative_id());
43921cb0ef41Sopenharmony_ci  SetLiveRangeAssignedRegister(current, reg);
43931cb0ef41Sopenharmony_ci
43941cb0ef41Sopenharmony_ci  // This register was not free. Thus we need to find and spill
43951cb0ef41Sopenharmony_ci  // parts of active and inactive live regions that use the same register
43961cb0ef41Sopenharmony_ci  // at the same lifetime positions as current.
43971cb0ef41Sopenharmony_ci  SplitAndSpillIntersecting(current, spill_mode);
43981cb0ef41Sopenharmony_ci}
43991cb0ef41Sopenharmony_ci
44001cb0ef41Sopenharmony_civoid LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current,
44011cb0ef41Sopenharmony_ci                                                    SpillMode spill_mode) {
44021cb0ef41Sopenharmony_ci  DCHECK(current->HasRegisterAssigned());
44031cb0ef41Sopenharmony_ci  int reg = current->assigned_register();
44041cb0ef41Sopenharmony_ci  LifetimePosition split_pos = current->Start();
44051cb0ef41Sopenharmony_ci  for (auto it = active_live_ranges().begin();
44061cb0ef41Sopenharmony_ci       it != active_live_ranges().end();) {
44071cb0ef41Sopenharmony_ci    LiveRange* range = *it;
44081cb0ef41Sopenharmony_ci    if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
44091cb0ef41Sopenharmony_ci      if (range->assigned_register() != reg) {
44101cb0ef41Sopenharmony_ci        ++it;
44111cb0ef41Sopenharmony_ci        continue;
44121cb0ef41Sopenharmony_ci      }
44131cb0ef41Sopenharmony_ci    } else {
44141cb0ef41Sopenharmony_ci      if (!data()->config()->AreAliases(current->representation(), reg,
44151cb0ef41Sopenharmony_ci                                        range->representation(),
44161cb0ef41Sopenharmony_ci                                        range->assigned_register())) {
44171cb0ef41Sopenharmony_ci        ++it;
44181cb0ef41Sopenharmony_ci        continue;
44191cb0ef41Sopenharmony_ci      }
44201cb0ef41Sopenharmony_ci    }
44211cb0ef41Sopenharmony_ci
44221cb0ef41Sopenharmony_ci    UsePosition* next_pos = range->NextRegisterPosition(current->Start());
44231cb0ef41Sopenharmony_ci    LiveRange* begin_spill = nullptr;
44241cb0ef41Sopenharmony_ci    LifetimePosition spill_pos =
44251cb0ef41Sopenharmony_ci        FindOptimalSpillingPos(range, split_pos, spill_mode, &begin_spill);
44261cb0ef41Sopenharmony_ci    MaybeSpillPreviousRanges(begin_spill, spill_pos, range);
44271cb0ef41Sopenharmony_ci    if (next_pos == nullptr) {
44281cb0ef41Sopenharmony_ci      SpillAfter(range, spill_pos, spill_mode);
44291cb0ef41Sopenharmony_ci    } else {
44301cb0ef41Sopenharmony_ci      // When spilling between spill_pos and next_pos ensure that the range
44311cb0ef41Sopenharmony_ci      // remains spilled at least until the start of the current live range.
44321cb0ef41Sopenharmony_ci      // This guarantees that we will not introduce new unhandled ranges that
44331cb0ef41Sopenharmony_ci      // start before the current range as this violates allocation invariants
44341cb0ef41Sopenharmony_ci      // and will lead to an inconsistent state of active and inactive
44351cb0ef41Sopenharmony_ci      // live-ranges: ranges are allocated in order of their start positions,
44361cb0ef41Sopenharmony_ci      // ranges are retired from active/inactive when the start of the
44371cb0ef41Sopenharmony_ci      // current live-range is larger than their end.
44381cb0ef41Sopenharmony_ci      DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(),
44391cb0ef41Sopenharmony_ci                                                        next_pos->pos()));
44401cb0ef41Sopenharmony_ci      SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos(),
44411cb0ef41Sopenharmony_ci                        spill_mode);
44421cb0ef41Sopenharmony_ci    }
44431cb0ef41Sopenharmony_ci    it = ActiveToHandled(it);
44441cb0ef41Sopenharmony_ci  }
44451cb0ef41Sopenharmony_ci
44461cb0ef41Sopenharmony_ci  for (int cur_reg = 0; cur_reg < num_registers(); ++cur_reg) {
44471cb0ef41Sopenharmony_ci    if (kFPAliasing != AliasingKind::kCombine || !check_fp_aliasing()) {
44481cb0ef41Sopenharmony_ci      if (cur_reg != reg) continue;
44491cb0ef41Sopenharmony_ci    }
44501cb0ef41Sopenharmony_ci    for (auto it = inactive_live_ranges(cur_reg).begin();
44511cb0ef41Sopenharmony_ci         it != inactive_live_ranges(cur_reg).end();) {
44521cb0ef41Sopenharmony_ci      LiveRange* range = *it;
44531cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kCombine && check_fp_aliasing() &&
44541cb0ef41Sopenharmony_ci          !data()->config()->AreAliases(current->representation(), reg,
44551cb0ef41Sopenharmony_ci                                        range->representation(), cur_reg)) {
44561cb0ef41Sopenharmony_ci        ++it;
44571cb0ef41Sopenharmony_ci        continue;
44581cb0ef41Sopenharmony_ci      }
44591cb0ef41Sopenharmony_ci      DCHECK(range->End() > current->Start());
44601cb0ef41Sopenharmony_ci      if (range->TopLevel()->IsFixed()) {
44611cb0ef41Sopenharmony_ci        ++it;
44621cb0ef41Sopenharmony_ci        continue;
44631cb0ef41Sopenharmony_ci      }
44641cb0ef41Sopenharmony_ci
44651cb0ef41Sopenharmony_ci      LifetimePosition next_intersection = range->FirstIntersection(current);
44661cb0ef41Sopenharmony_ci      if (next_intersection.IsValid()) {
44671cb0ef41Sopenharmony_ci        UsePosition* next_pos = range->NextRegisterPosition(current->Start());
44681cb0ef41Sopenharmony_ci        if (next_pos == nullptr) {
44691cb0ef41Sopenharmony_ci          SpillAfter(range, split_pos, spill_mode);
44701cb0ef41Sopenharmony_ci        } else {
44711cb0ef41Sopenharmony_ci          next_intersection = std::min(next_intersection, next_pos->pos());
44721cb0ef41Sopenharmony_ci          SpillBetween(range, split_pos, next_intersection, spill_mode);
44731cb0ef41Sopenharmony_ci        }
44741cb0ef41Sopenharmony_ci        it = InactiveToHandled(it);
44751cb0ef41Sopenharmony_ci      } else {
44761cb0ef41Sopenharmony_ci        ++it;
44771cb0ef41Sopenharmony_ci      }
44781cb0ef41Sopenharmony_ci    }
44791cb0ef41Sopenharmony_ci  }
44801cb0ef41Sopenharmony_ci}
44811cb0ef41Sopenharmony_ci
44821cb0ef41Sopenharmony_cibool LinearScanAllocator::TryReuseSpillForPhi(TopLevelLiveRange* range) {
44831cb0ef41Sopenharmony_ci  if (!range->is_phi()) return false;
44841cb0ef41Sopenharmony_ci
44851cb0ef41Sopenharmony_ci  DCHECK(!range->HasSpillOperand());
44861cb0ef41Sopenharmony_ci  // Check how many operands belong to the same bundle as the output.
44871cb0ef41Sopenharmony_ci  LiveRangeBundle* out_bundle = range->get_bundle();
44881cb0ef41Sopenharmony_ci  TopTierRegisterAllocationData::PhiMapValue* phi_map_value =
44891cb0ef41Sopenharmony_ci      data()->GetPhiMapValueFor(range);
44901cb0ef41Sopenharmony_ci  const PhiInstruction* phi = phi_map_value->phi();
44911cb0ef41Sopenharmony_ci  const InstructionBlock* block = phi_map_value->block();
44921cb0ef41Sopenharmony_ci  // Count the number of spilled operands.
44931cb0ef41Sopenharmony_ci  size_t spilled_count = 0;
44941cb0ef41Sopenharmony_ci  for (size_t i = 0; i < phi->operands().size(); i++) {
44951cb0ef41Sopenharmony_ci    int op = phi->operands()[i];
44961cb0ef41Sopenharmony_ci    LiveRange* op_range = data()->GetOrCreateLiveRangeFor(op);
44971cb0ef41Sopenharmony_ci    if (!op_range->TopLevel()->HasSpillRange()) continue;
44981cb0ef41Sopenharmony_ci    const InstructionBlock* pred =
44991cb0ef41Sopenharmony_ci        code()->InstructionBlockAt(block->predecessors()[i]);
45001cb0ef41Sopenharmony_ci    LifetimePosition pred_end =
45011cb0ef41Sopenharmony_ci        LifetimePosition::InstructionFromInstructionIndex(
45021cb0ef41Sopenharmony_ci            pred->last_instruction_index());
45031cb0ef41Sopenharmony_ci    while (op_range != nullptr && !op_range->CanCover(pred_end)) {
45041cb0ef41Sopenharmony_ci      op_range = op_range->next();
45051cb0ef41Sopenharmony_ci    }
45061cb0ef41Sopenharmony_ci    if (op_range != nullptr && op_range->spilled() &&
45071cb0ef41Sopenharmony_ci        op_range->get_bundle() == out_bundle) {
45081cb0ef41Sopenharmony_ci      spilled_count++;
45091cb0ef41Sopenharmony_ci    }
45101cb0ef41Sopenharmony_ci  }
45111cb0ef41Sopenharmony_ci
45121cb0ef41Sopenharmony_ci  // Only continue if more than half of the operands are spilled to the same
45131cb0ef41Sopenharmony_ci  // slot (because part of same bundle).
45141cb0ef41Sopenharmony_ci  if (spilled_count * 2 <= phi->operands().size()) {
45151cb0ef41Sopenharmony_ci    return false;
45161cb0ef41Sopenharmony_ci  }
45171cb0ef41Sopenharmony_ci
45181cb0ef41Sopenharmony_ci  // If the range does not need register soon, spill it to the merged
45191cb0ef41Sopenharmony_ci  // spill range.
45201cb0ef41Sopenharmony_ci  LifetimePosition next_pos = range->Start();
45211cb0ef41Sopenharmony_ci  if (next_pos.IsGapPosition()) next_pos = next_pos.NextStart();
45221cb0ef41Sopenharmony_ci  UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
45231cb0ef41Sopenharmony_ci  if (pos == nullptr) {
45241cb0ef41Sopenharmony_ci    Spill(range, SpillMode::kSpillAtDefinition);
45251cb0ef41Sopenharmony_ci    return true;
45261cb0ef41Sopenharmony_ci  } else if (pos->pos() > range->Start().NextStart()) {
45271cb0ef41Sopenharmony_ci    SpillBetween(range, range->Start(), pos->pos(),
45281cb0ef41Sopenharmony_ci                 SpillMode::kSpillAtDefinition);
45291cb0ef41Sopenharmony_ci    return true;
45301cb0ef41Sopenharmony_ci  }
45311cb0ef41Sopenharmony_ci  return false;
45321cb0ef41Sopenharmony_ci}
45331cb0ef41Sopenharmony_ci
45341cb0ef41Sopenharmony_civoid LinearScanAllocator::SpillAfter(LiveRange* range, LifetimePosition pos,
45351cb0ef41Sopenharmony_ci                                     SpillMode spill_mode) {
45361cb0ef41Sopenharmony_ci  LiveRange* second_part = SplitRangeAt(range, pos);
45371cb0ef41Sopenharmony_ci  Spill(second_part, spill_mode);
45381cb0ef41Sopenharmony_ci}
45391cb0ef41Sopenharmony_ci
45401cb0ef41Sopenharmony_civoid LinearScanAllocator::SpillBetween(LiveRange* range, LifetimePosition start,
45411cb0ef41Sopenharmony_ci                                       LifetimePosition end,
45421cb0ef41Sopenharmony_ci                                       SpillMode spill_mode) {
45431cb0ef41Sopenharmony_ci  SpillBetweenUntil(range, start, start, end, spill_mode);
45441cb0ef41Sopenharmony_ci}
45451cb0ef41Sopenharmony_ci
45461cb0ef41Sopenharmony_civoid LinearScanAllocator::SpillBetweenUntil(LiveRange* range,
45471cb0ef41Sopenharmony_ci                                            LifetimePosition start,
45481cb0ef41Sopenharmony_ci                                            LifetimePosition until,
45491cb0ef41Sopenharmony_ci                                            LifetimePosition end,
45501cb0ef41Sopenharmony_ci                                            SpillMode spill_mode) {
45511cb0ef41Sopenharmony_ci  CHECK(start < end);
45521cb0ef41Sopenharmony_ci  LiveRange* second_part = SplitRangeAt(range, start);
45531cb0ef41Sopenharmony_ci
45541cb0ef41Sopenharmony_ci  if (second_part->Start() < end) {
45551cb0ef41Sopenharmony_ci    // The split result intersects with [start, end[.
45561cb0ef41Sopenharmony_ci    // Split it at position between ]start+1, end[, spill the middle part
45571cb0ef41Sopenharmony_ci    // and put the rest to unhandled.
45581cb0ef41Sopenharmony_ci
45591cb0ef41Sopenharmony_ci    // Make sure that the third part always starts after the start of the
45601cb0ef41Sopenharmony_ci    // second part, as that likely is the current position of the register
45611cb0ef41Sopenharmony_ci    // allocator and we cannot add ranges to unhandled that start before
45621cb0ef41Sopenharmony_ci    // the current position.
45631cb0ef41Sopenharmony_ci    LifetimePosition split_start = std::max(second_part->Start().End(), until);
45641cb0ef41Sopenharmony_ci
45651cb0ef41Sopenharmony_ci    // If end is an actual use (which it typically is) we have to split
45661cb0ef41Sopenharmony_ci    // so that there is a gap before so that we have space for moving the
45671cb0ef41Sopenharmony_ci    // value into its position.
45681cb0ef41Sopenharmony_ci    // However, if we have no choice, split right where asked.
45691cb0ef41Sopenharmony_ci    LifetimePosition third_part_end =
45701cb0ef41Sopenharmony_ci        std::max(split_start, end.PrevStart().End());
45711cb0ef41Sopenharmony_ci    // Instead of spliting right after or even before the block boundary,
45721cb0ef41Sopenharmony_ci    // split on the boumndary to avoid extra moves.
45731cb0ef41Sopenharmony_ci    if (data()->IsBlockBoundary(end.Start())) {
45741cb0ef41Sopenharmony_ci      third_part_end = std::max(split_start, end.Start());
45751cb0ef41Sopenharmony_ci    }
45761cb0ef41Sopenharmony_ci
45771cb0ef41Sopenharmony_ci    LiveRange* third_part =
45781cb0ef41Sopenharmony_ci        SplitBetween(second_part, split_start, third_part_end);
45791cb0ef41Sopenharmony_ci    if (GetInstructionBlock(data()->code(), second_part->Start())
45801cb0ef41Sopenharmony_ci            ->IsDeferred()) {
45811cb0ef41Sopenharmony_ci      // Try to use the same register as before.
45821cb0ef41Sopenharmony_ci      TRACE("Setting control flow hint for %d:%d to %s\n",
45831cb0ef41Sopenharmony_ci            third_part->TopLevel()->vreg(), third_part->relative_id(),
45841cb0ef41Sopenharmony_ci            RegisterName(range->controlflow_hint()));
45851cb0ef41Sopenharmony_ci      third_part->set_controlflow_hint(range->controlflow_hint());
45861cb0ef41Sopenharmony_ci    }
45871cb0ef41Sopenharmony_ci
45881cb0ef41Sopenharmony_ci    AddToUnhandled(third_part);
45891cb0ef41Sopenharmony_ci    // This can happen, even if we checked for start < end above, as we fiddle
45901cb0ef41Sopenharmony_ci    // with the end location. However, we are guaranteed to be after or at
45911cb0ef41Sopenharmony_ci    // until, so this is fine.
45921cb0ef41Sopenharmony_ci    if (third_part != second_part) {
45931cb0ef41Sopenharmony_ci      Spill(second_part, spill_mode);
45941cb0ef41Sopenharmony_ci    }
45951cb0ef41Sopenharmony_ci  } else {
45961cb0ef41Sopenharmony_ci    // The split result does not intersect with [start, end[.
45971cb0ef41Sopenharmony_ci    // Nothing to spill. Just put it to unhandled as whole.
45981cb0ef41Sopenharmony_ci    AddToUnhandled(second_part);
45991cb0ef41Sopenharmony_ci  }
46001cb0ef41Sopenharmony_ci}
46011cb0ef41Sopenharmony_ci
46021cb0ef41Sopenharmony_ciOperandAssigner::OperandAssigner(TopTierRegisterAllocationData* data)
46031cb0ef41Sopenharmony_ci    : data_(data) {}
46041cb0ef41Sopenharmony_ci
46051cb0ef41Sopenharmony_civoid OperandAssigner::DecideSpillingMode() {
46061cb0ef41Sopenharmony_ci  for (auto range : data()->live_ranges()) {
46071cb0ef41Sopenharmony_ci    data()->tick_counter()->TickAndMaybeEnterSafepoint();
46081cb0ef41Sopenharmony_ci    int max_blocks = data()->code()->InstructionBlockCount();
46091cb0ef41Sopenharmony_ci    if (range != nullptr && range->IsSpilledOnlyInDeferredBlocks(data())) {
46101cb0ef41Sopenharmony_ci      // If the range is spilled only in deferred blocks and starts in
46111cb0ef41Sopenharmony_ci      // a non-deferred block, we transition its representation here so
46121cb0ef41Sopenharmony_ci      // that the LiveRangeConnector processes them correctly. If,
46131cb0ef41Sopenharmony_ci      // however, they start in a deferred block, we uograde them to
46141cb0ef41Sopenharmony_ci      // spill at definition, as that definition is in a deferred block
46151cb0ef41Sopenharmony_ci      // anyway. While this is an optimization, the code in LiveRangeConnector
46161cb0ef41Sopenharmony_ci      // relies on it!
46171cb0ef41Sopenharmony_ci      if (GetInstructionBlock(data()->code(), range->Start())->IsDeferred()) {
46181cb0ef41Sopenharmony_ci        TRACE("Live range %d is spilled and alive in deferred code only\n",
46191cb0ef41Sopenharmony_ci              range->vreg());
46201cb0ef41Sopenharmony_ci        range->TransitionRangeToSpillAtDefinition();
46211cb0ef41Sopenharmony_ci      } else {
46221cb0ef41Sopenharmony_ci        TRACE("Live range %d is spilled deferred code only but alive outside\n",
46231cb0ef41Sopenharmony_ci              range->vreg());
46241cb0ef41Sopenharmony_ci        range->TransitionRangeToDeferredSpill(data()->allocation_zone(),
46251cb0ef41Sopenharmony_ci                                              max_blocks);
46261cb0ef41Sopenharmony_ci      }
46271cb0ef41Sopenharmony_ci    }
46281cb0ef41Sopenharmony_ci  }
46291cb0ef41Sopenharmony_ci}
46301cb0ef41Sopenharmony_ci
46311cb0ef41Sopenharmony_civoid OperandAssigner::AssignSpillSlots() {
46321cb0ef41Sopenharmony_ci  for (auto range : data()->live_ranges()) {
46331cb0ef41Sopenharmony_ci    data()->tick_counter()->TickAndMaybeEnterSafepoint();
46341cb0ef41Sopenharmony_ci    if (range != nullptr && range->get_bundle() != nullptr) {
46351cb0ef41Sopenharmony_ci      range->get_bundle()->MergeSpillRangesAndClear();
46361cb0ef41Sopenharmony_ci    }
46371cb0ef41Sopenharmony_ci  }
46381cb0ef41Sopenharmony_ci  ZoneVector<SpillRange*>& spill_ranges = data()->spill_ranges();
46391cb0ef41Sopenharmony_ci  // Merge disjoint spill ranges
46401cb0ef41Sopenharmony_ci  for (size_t i = 0; i < spill_ranges.size(); ++i) {
46411cb0ef41Sopenharmony_ci    data()->tick_counter()->TickAndMaybeEnterSafepoint();
46421cb0ef41Sopenharmony_ci    SpillRange* range = spill_ranges[i];
46431cb0ef41Sopenharmony_ci    if (range == nullptr) continue;
46441cb0ef41Sopenharmony_ci    if (range->IsEmpty()) continue;
46451cb0ef41Sopenharmony_ci    for (size_t j = i + 1; j < spill_ranges.size(); ++j) {
46461cb0ef41Sopenharmony_ci      SpillRange* other = spill_ranges[j];
46471cb0ef41Sopenharmony_ci      if (other != nullptr && !other->IsEmpty()) {
46481cb0ef41Sopenharmony_ci        range->TryMerge(other);
46491cb0ef41Sopenharmony_ci      }
46501cb0ef41Sopenharmony_ci    }
46511cb0ef41Sopenharmony_ci  }
46521cb0ef41Sopenharmony_ci  // Allocate slots for the merged spill ranges.
46531cb0ef41Sopenharmony_ci  for (SpillRange* range : spill_ranges) {
46541cb0ef41Sopenharmony_ci    data()->tick_counter()->TickAndMaybeEnterSafepoint();
46551cb0ef41Sopenharmony_ci    if (range == nullptr || range->IsEmpty()) continue;
46561cb0ef41Sopenharmony_ci    if (!range->HasSlot()) {
46571cb0ef41Sopenharmony_ci      // Allocate a new operand referring to the spill slot, aligned to the
46581cb0ef41Sopenharmony_ci      // operand size.
46591cb0ef41Sopenharmony_ci      int width = range->byte_width();
46601cb0ef41Sopenharmony_ci      int index = data()->frame()->AllocateSpillSlot(width, width);
46611cb0ef41Sopenharmony_ci      range->set_assigned_slot(index);
46621cb0ef41Sopenharmony_ci    }
46631cb0ef41Sopenharmony_ci  }
46641cb0ef41Sopenharmony_ci}
46651cb0ef41Sopenharmony_ci
46661cb0ef41Sopenharmony_civoid OperandAssigner::CommitAssignment() {
46671cb0ef41Sopenharmony_ci  const size_t live_ranges_size = data()->live_ranges().size();
46681cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* top_range : data()->live_ranges()) {
46691cb0ef41Sopenharmony_ci    data()->tick_counter()->TickAndMaybeEnterSafepoint();
46701cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
46711cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
46721cb0ef41Sopenharmony_ci    if (top_range == nullptr || top_range->IsEmpty()) continue;
46731cb0ef41Sopenharmony_ci    InstructionOperand spill_operand;
46741cb0ef41Sopenharmony_ci    if (top_range->HasSpillOperand()) {
46751cb0ef41Sopenharmony_ci      auto it = data()->slot_for_const_range().find(top_range);
46761cb0ef41Sopenharmony_ci      if (it != data()->slot_for_const_range().end()) {
46771cb0ef41Sopenharmony_ci        spill_operand = *it->second;
46781cb0ef41Sopenharmony_ci      } else {
46791cb0ef41Sopenharmony_ci        spill_operand = *top_range->GetSpillOperand();
46801cb0ef41Sopenharmony_ci      }
46811cb0ef41Sopenharmony_ci    } else if (top_range->HasSpillRange()) {
46821cb0ef41Sopenharmony_ci      spill_operand = top_range->GetSpillRangeOperand();
46831cb0ef41Sopenharmony_ci    }
46841cb0ef41Sopenharmony_ci    if (top_range->is_phi()) {
46851cb0ef41Sopenharmony_ci      data()->GetPhiMapValueFor(top_range)->CommitAssignment(
46861cb0ef41Sopenharmony_ci          top_range->GetAssignedOperand());
46871cb0ef41Sopenharmony_ci    }
46881cb0ef41Sopenharmony_ci    for (LiveRange* range = top_range; range != nullptr;
46891cb0ef41Sopenharmony_ci         range = range->next()) {
46901cb0ef41Sopenharmony_ci      InstructionOperand assigned = range->GetAssignedOperand();
46911cb0ef41Sopenharmony_ci      DCHECK(!assigned.IsUnallocated());
46921cb0ef41Sopenharmony_ci      range->ConvertUsesToOperand(assigned, spill_operand);
46931cb0ef41Sopenharmony_ci    }
46941cb0ef41Sopenharmony_ci
46951cb0ef41Sopenharmony_ci    if (!spill_operand.IsInvalid()) {
46961cb0ef41Sopenharmony_ci      // If this top level range has a child spilled in a deferred block, we use
46971cb0ef41Sopenharmony_ci      // the range and control flow connection mechanism instead of spilling at
46981cb0ef41Sopenharmony_ci      // definition. Refer to the ConnectLiveRanges and ResolveControlFlow
46991cb0ef41Sopenharmony_ci      // phases. Normally, when we spill at definition, we do not insert a
47001cb0ef41Sopenharmony_ci      // connecting move when a successor child range is spilled - because the
47011cb0ef41Sopenharmony_ci      // spilled range picks up its value from the slot which was assigned at
47021cb0ef41Sopenharmony_ci      // definition. For ranges that are determined to spill only in deferred
47031cb0ef41Sopenharmony_ci      // blocks, we let ConnectLiveRanges and ResolveControlFlow find the blocks
47041cb0ef41Sopenharmony_ci      // where a spill operand is expected, and then finalize by inserting the
47051cb0ef41Sopenharmony_ci      // spills in the deferred blocks dominators.
47061cb0ef41Sopenharmony_ci      if (!top_range->IsSpilledOnlyInDeferredBlocks(data()) &&
47071cb0ef41Sopenharmony_ci          !top_range->HasGeneralSpillRange()) {
47081cb0ef41Sopenharmony_ci        // Spill at definition if the range isn't spilled in a way that will be
47091cb0ef41Sopenharmony_ci        // handled later.
47101cb0ef41Sopenharmony_ci        top_range->FilterSpillMoves(data(), spill_operand);
47111cb0ef41Sopenharmony_ci        top_range->CommitSpillMoves(data(), spill_operand);
47121cb0ef41Sopenharmony_ci      }
47131cb0ef41Sopenharmony_ci    }
47141cb0ef41Sopenharmony_ci  }
47151cb0ef41Sopenharmony_ci}
47161cb0ef41Sopenharmony_ci
47171cb0ef41Sopenharmony_ciReferenceMapPopulator::ReferenceMapPopulator(
47181cb0ef41Sopenharmony_ci    TopTierRegisterAllocationData* data)
47191cb0ef41Sopenharmony_ci    : data_(data) {}
47201cb0ef41Sopenharmony_ci
47211cb0ef41Sopenharmony_cibool ReferenceMapPopulator::SafePointsAreInOrder() const {
47221cb0ef41Sopenharmony_ci  int safe_point = 0;
47231cb0ef41Sopenharmony_ci  for (ReferenceMap* map : *data()->code()->reference_maps()) {
47241cb0ef41Sopenharmony_ci    if (safe_point > map->instruction_position()) return false;
47251cb0ef41Sopenharmony_ci    safe_point = map->instruction_position();
47261cb0ef41Sopenharmony_ci  }
47271cb0ef41Sopenharmony_ci  return true;
47281cb0ef41Sopenharmony_ci}
47291cb0ef41Sopenharmony_ci
47301cb0ef41Sopenharmony_civoid ReferenceMapPopulator::PopulateReferenceMaps() {
47311cb0ef41Sopenharmony_ci  DCHECK(SafePointsAreInOrder());
47321cb0ef41Sopenharmony_ci  // Map all delayed references.
47331cb0ef41Sopenharmony_ci  for (TopTierRegisterAllocationData::DelayedReference& delayed_reference :
47341cb0ef41Sopenharmony_ci       data()->delayed_references()) {
47351cb0ef41Sopenharmony_ci    delayed_reference.map->RecordReference(
47361cb0ef41Sopenharmony_ci        AllocatedOperand::cast(*delayed_reference.operand));
47371cb0ef41Sopenharmony_ci  }
47381cb0ef41Sopenharmony_ci  // Iterate over all safe point positions and record a pointer
47391cb0ef41Sopenharmony_ci  // for all spilled live ranges at this point.
47401cb0ef41Sopenharmony_ci  int last_range_start = 0;
47411cb0ef41Sopenharmony_ci  const ReferenceMapDeque* reference_maps = data()->code()->reference_maps();
47421cb0ef41Sopenharmony_ci  ReferenceMapDeque::const_iterator first_it = reference_maps->begin();
47431cb0ef41Sopenharmony_ci  const size_t live_ranges_size = data()->live_ranges().size();
47441cb0ef41Sopenharmony_ci  // We break the invariant that live ranges are indexed by their vregs here.
47451cb0ef41Sopenharmony_ci  // This is ok because we don't use that invariant here, and this is the last
47461cb0ef41Sopenharmony_ci  // phase.
47471cb0ef41Sopenharmony_ci  std::sort(data()->live_ranges().begin(), data()->live_ranges().end(),
47481cb0ef41Sopenharmony_ci            [](TopLevelLiveRange* a, TopLevelLiveRange* b) {
47491cb0ef41Sopenharmony_ci              if (!a || a->IsEmpty()) return false;
47501cb0ef41Sopenharmony_ci              if (!b || b->IsEmpty()) return true;
47511cb0ef41Sopenharmony_ci              return a->Start() < b->Start();
47521cb0ef41Sopenharmony_ci            });
47531cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* range : data()->live_ranges()) {
47541cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
47551cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
47561cb0ef41Sopenharmony_ci    if (range == nullptr) continue;
47571cb0ef41Sopenharmony_ci    // Skip non-reference values.
47581cb0ef41Sopenharmony_ci    if (!data()->code()->IsReference(range->vreg())) continue;
47591cb0ef41Sopenharmony_ci    // Skip empty live ranges.
47601cb0ef41Sopenharmony_ci    if (range->IsEmpty()) continue;
47611cb0ef41Sopenharmony_ci    if (range->has_preassigned_slot()) continue;
47621cb0ef41Sopenharmony_ci
47631cb0ef41Sopenharmony_ci    // Find the extent of the range and its children.
47641cb0ef41Sopenharmony_ci    int start = range->Start().ToInstructionIndex();
47651cb0ef41Sopenharmony_ci    int end = 0;
47661cb0ef41Sopenharmony_ci    for (LiveRange* cur = range; cur != nullptr; cur = cur->next()) {
47671cb0ef41Sopenharmony_ci      LifetimePosition this_end = cur->End();
47681cb0ef41Sopenharmony_ci      if (this_end.ToInstructionIndex() > end)
47691cb0ef41Sopenharmony_ci        end = this_end.ToInstructionIndex();
47701cb0ef41Sopenharmony_ci      DCHECK(cur->Start().ToInstructionIndex() >= start);
47711cb0ef41Sopenharmony_ci    }
47721cb0ef41Sopenharmony_ci
47731cb0ef41Sopenharmony_ci    // Ranges should be sorted, so that the first reference map in the current
47741cb0ef41Sopenharmony_ci    // live range has to be after {first_it}.
47751cb0ef41Sopenharmony_ci    DCHECK_LE(last_range_start, start);
47761cb0ef41Sopenharmony_ci    last_range_start = start;
47771cb0ef41Sopenharmony_ci    USE(last_range_start);
47781cb0ef41Sopenharmony_ci
47791cb0ef41Sopenharmony_ci    // Step across all the safe points that are before the start of this range,
47801cb0ef41Sopenharmony_ci    // recording how far we step in order to save doing this for the next range.
47811cb0ef41Sopenharmony_ci    for (; first_it != reference_maps->end(); ++first_it) {
47821cb0ef41Sopenharmony_ci      ReferenceMap* map = *first_it;
47831cb0ef41Sopenharmony_ci      if (map->instruction_position() >= start) break;
47841cb0ef41Sopenharmony_ci    }
47851cb0ef41Sopenharmony_ci
47861cb0ef41Sopenharmony_ci    InstructionOperand spill_operand;
47871cb0ef41Sopenharmony_ci    if (((range->HasSpillOperand() &&
47881cb0ef41Sopenharmony_ci          !range->GetSpillOperand()->IsConstant()) ||
47891cb0ef41Sopenharmony_ci         range->HasSpillRange())) {
47901cb0ef41Sopenharmony_ci      if (range->HasSpillOperand()) {
47911cb0ef41Sopenharmony_ci        spill_operand = *range->GetSpillOperand();
47921cb0ef41Sopenharmony_ci      } else {
47931cb0ef41Sopenharmony_ci        spill_operand = range->GetSpillRangeOperand();
47941cb0ef41Sopenharmony_ci      }
47951cb0ef41Sopenharmony_ci      DCHECK(spill_operand.IsStackSlot());
47961cb0ef41Sopenharmony_ci      DCHECK(CanBeTaggedOrCompressedPointer(
47971cb0ef41Sopenharmony_ci          AllocatedOperand::cast(spill_operand).representation()));
47981cb0ef41Sopenharmony_ci    }
47991cb0ef41Sopenharmony_ci
48001cb0ef41Sopenharmony_ci    LiveRange* cur = range;
48011cb0ef41Sopenharmony_ci    // Step through the safe points to see whether they are in the range.
48021cb0ef41Sopenharmony_ci    for (auto it = first_it; it != reference_maps->end(); ++it) {
48031cb0ef41Sopenharmony_ci      ReferenceMap* map = *it;
48041cb0ef41Sopenharmony_ci      int safe_point = map->instruction_position();
48051cb0ef41Sopenharmony_ci
48061cb0ef41Sopenharmony_ci      // The safe points are sorted so we can stop searching here.
48071cb0ef41Sopenharmony_ci      if (safe_point - 1 > end) break;
48081cb0ef41Sopenharmony_ci
48091cb0ef41Sopenharmony_ci      // Advance to the next active range that covers the current
48101cb0ef41Sopenharmony_ci      // safe point position.
48111cb0ef41Sopenharmony_ci      LifetimePosition safe_point_pos =
48121cb0ef41Sopenharmony_ci          LifetimePosition::InstructionFromInstructionIndex(safe_point);
48131cb0ef41Sopenharmony_ci
48141cb0ef41Sopenharmony_ci      // Search for the child range (cur) that covers safe_point_pos. If we
48151cb0ef41Sopenharmony_ci      // don't find it before the children pass safe_point_pos, keep cur at
48161cb0ef41Sopenharmony_ci      // the last child, because the next safe_point_pos may be covered by cur.
48171cb0ef41Sopenharmony_ci      // This may happen if cur has more than one interval, and the current
48181cb0ef41Sopenharmony_ci      // safe_point_pos is in between intervals.
48191cb0ef41Sopenharmony_ci      // For that reason, cur may be at most the last child.
48201cb0ef41Sopenharmony_ci      DCHECK_NOT_NULL(cur);
48211cb0ef41Sopenharmony_ci      DCHECK(safe_point_pos >= cur->Start() || range == cur);
48221cb0ef41Sopenharmony_ci      bool found = false;
48231cb0ef41Sopenharmony_ci      while (!found) {
48241cb0ef41Sopenharmony_ci        if (cur->Covers(safe_point_pos)) {
48251cb0ef41Sopenharmony_ci          found = true;
48261cb0ef41Sopenharmony_ci        } else {
48271cb0ef41Sopenharmony_ci          LiveRange* next = cur->next();
48281cb0ef41Sopenharmony_ci          if (next == nullptr || next->Start() > safe_point_pos) {
48291cb0ef41Sopenharmony_ci            break;
48301cb0ef41Sopenharmony_ci          }
48311cb0ef41Sopenharmony_ci          cur = next;
48321cb0ef41Sopenharmony_ci        }
48331cb0ef41Sopenharmony_ci      }
48341cb0ef41Sopenharmony_ci
48351cb0ef41Sopenharmony_ci      if (!found) {
48361cb0ef41Sopenharmony_ci        continue;
48371cb0ef41Sopenharmony_ci      }
48381cb0ef41Sopenharmony_ci
48391cb0ef41Sopenharmony_ci      // Check if the live range is spilled and the safe point is after
48401cb0ef41Sopenharmony_ci      // the spill position.
48411cb0ef41Sopenharmony_ci      int spill_index = range->IsSpilledOnlyInDeferredBlocks(data()) ||
48421cb0ef41Sopenharmony_ci                                range->LateSpillingSelected()
48431cb0ef41Sopenharmony_ci                            ? cur->Start().ToInstructionIndex()
48441cb0ef41Sopenharmony_ci                            : range->spill_start_index();
48451cb0ef41Sopenharmony_ci
48461cb0ef41Sopenharmony_ci      if (!spill_operand.IsInvalid() && safe_point >= spill_index) {
48471cb0ef41Sopenharmony_ci        TRACE("Pointer for range %d (spilled at %d) at safe point %d\n",
48481cb0ef41Sopenharmony_ci              range->vreg(), spill_index, safe_point);
48491cb0ef41Sopenharmony_ci        map->RecordReference(AllocatedOperand::cast(spill_operand));
48501cb0ef41Sopenharmony_ci      }
48511cb0ef41Sopenharmony_ci
48521cb0ef41Sopenharmony_ci      if (!cur->spilled()) {
48531cb0ef41Sopenharmony_ci        TRACE(
48541cb0ef41Sopenharmony_ci            "Pointer in register for range %d:%d (start at %d) "
48551cb0ef41Sopenharmony_ci            "at safe point %d\n",
48561cb0ef41Sopenharmony_ci            range->vreg(), cur->relative_id(), cur->Start().value(),
48571cb0ef41Sopenharmony_ci            safe_point);
48581cb0ef41Sopenharmony_ci        InstructionOperand operand = cur->GetAssignedOperand();
48591cb0ef41Sopenharmony_ci        DCHECK(!operand.IsStackSlot());
48601cb0ef41Sopenharmony_ci        DCHECK(CanBeTaggedOrCompressedPointer(
48611cb0ef41Sopenharmony_ci            AllocatedOperand::cast(operand).representation()));
48621cb0ef41Sopenharmony_ci        map->RecordReference(AllocatedOperand::cast(operand));
48631cb0ef41Sopenharmony_ci      }
48641cb0ef41Sopenharmony_ci    }
48651cb0ef41Sopenharmony_ci  }
48661cb0ef41Sopenharmony_ci}
48671cb0ef41Sopenharmony_ci
48681cb0ef41Sopenharmony_ciLiveRangeConnector::LiveRangeConnector(TopTierRegisterAllocationData* data)
48691cb0ef41Sopenharmony_ci    : data_(data) {}
48701cb0ef41Sopenharmony_ci
48711cb0ef41Sopenharmony_cibool LiveRangeConnector::CanEagerlyResolveControlFlow(
48721cb0ef41Sopenharmony_ci    const InstructionBlock* block) const {
48731cb0ef41Sopenharmony_ci  if (block->PredecessorCount() != 1) return false;
48741cb0ef41Sopenharmony_ci  return block->predecessors()[0].IsNext(block->rpo_number());
48751cb0ef41Sopenharmony_ci}
48761cb0ef41Sopenharmony_ci
48771cb0ef41Sopenharmony_civoid LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
48781cb0ef41Sopenharmony_ci  // Lazily linearize live ranges in memory for fast lookup.
48791cb0ef41Sopenharmony_ci  LiveRangeFinder finder(data(), local_zone);
48801cb0ef41Sopenharmony_ci  ZoneVector<BitVector*>& live_in_sets = data()->live_in_sets();
48811cb0ef41Sopenharmony_ci  for (const InstructionBlock* block : code()->instruction_blocks()) {
48821cb0ef41Sopenharmony_ci    if (CanEagerlyResolveControlFlow(block)) continue;
48831cb0ef41Sopenharmony_ci    BitVector* live = live_in_sets[block->rpo_number().ToInt()];
48841cb0ef41Sopenharmony_ci    auto it = live->begin();
48851cb0ef41Sopenharmony_ci    auto end = live->end();
48861cb0ef41Sopenharmony_ci    while (it != end) {
48871cb0ef41Sopenharmony_ci      data()->tick_counter()->TickAndMaybeEnterSafepoint();
48881cb0ef41Sopenharmony_ci      int vreg = *it;
48891cb0ef41Sopenharmony_ci      LiveRangeBoundArray* array = finder.ArrayFor(vreg);
48901cb0ef41Sopenharmony_ci      for (const RpoNumber& pred : block->predecessors()) {
48911cb0ef41Sopenharmony_ci        FindResult result;
48921cb0ef41Sopenharmony_ci        const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
48931cb0ef41Sopenharmony_ci        if (!array->FindConnectableSubranges(block, pred_block, &result)) {
48941cb0ef41Sopenharmony_ci          continue;
48951cb0ef41Sopenharmony_ci        }
48961cb0ef41Sopenharmony_ci        InstructionOperand pred_op = result.pred_cover_->GetAssignedOperand();
48971cb0ef41Sopenharmony_ci        InstructionOperand cur_op = result.cur_cover_->GetAssignedOperand();
48981cb0ef41Sopenharmony_ci        if (pred_op.Equals(cur_op)) continue;
48991cb0ef41Sopenharmony_ci        if (!pred_op.IsAnyRegister() && cur_op.IsAnyRegister()) {
49001cb0ef41Sopenharmony_ci          // We're doing a reload.
49011cb0ef41Sopenharmony_ci          // We don't need to, if:
49021cb0ef41Sopenharmony_ci          // 1) there's no register use in this block, and
49031cb0ef41Sopenharmony_ci          // 2) the range ends before the block does, and
49041cb0ef41Sopenharmony_ci          // 3) we don't have a successor, or the successor is spilled.
49051cb0ef41Sopenharmony_ci          LifetimePosition block_start =
49061cb0ef41Sopenharmony_ci              LifetimePosition::GapFromInstructionIndex(block->code_start());
49071cb0ef41Sopenharmony_ci          LifetimePosition block_end =
49081cb0ef41Sopenharmony_ci              LifetimePosition::GapFromInstructionIndex(block->code_end());
49091cb0ef41Sopenharmony_ci          const LiveRange* current = result.cur_cover_;
49101cb0ef41Sopenharmony_ci          // Note that this is not the successor if we have control flow!
49111cb0ef41Sopenharmony_ci          // However, in the following condition, we only refer to it if it
49121cb0ef41Sopenharmony_ci          // begins in the current block, in which case we can safely declare it
49131cb0ef41Sopenharmony_ci          // to be the successor.
49141cb0ef41Sopenharmony_ci          const LiveRange* successor = current->next();
49151cb0ef41Sopenharmony_ci          if (current->End() < block_end &&
49161cb0ef41Sopenharmony_ci              (successor == nullptr || successor->spilled())) {
49171cb0ef41Sopenharmony_ci            // verify point 1: no register use. We can go to the end of the
49181cb0ef41Sopenharmony_ci            // range, since it's all within the block.
49191cb0ef41Sopenharmony_ci
49201cb0ef41Sopenharmony_ci            bool uses_reg = false;
49211cb0ef41Sopenharmony_ci            for (const UsePosition* use = current->NextUsePosition(block_start);
49221cb0ef41Sopenharmony_ci                 use != nullptr; use = use->next()) {
49231cb0ef41Sopenharmony_ci              if (use->operand()->IsAnyRegister()) {
49241cb0ef41Sopenharmony_ci                uses_reg = true;
49251cb0ef41Sopenharmony_ci                break;
49261cb0ef41Sopenharmony_ci              }
49271cb0ef41Sopenharmony_ci            }
49281cb0ef41Sopenharmony_ci            if (!uses_reg) continue;
49291cb0ef41Sopenharmony_ci          }
49301cb0ef41Sopenharmony_ci          if (current->TopLevel()->IsSpilledOnlyInDeferredBlocks(data()) &&
49311cb0ef41Sopenharmony_ci              pred_block->IsDeferred()) {
49321cb0ef41Sopenharmony_ci            // The spill location should be defined in pred_block, so add
49331cb0ef41Sopenharmony_ci            // pred_block to the list of blocks requiring a spill operand.
49341cb0ef41Sopenharmony_ci            TRACE("Adding B%d to list of spill blocks for %d\n",
49351cb0ef41Sopenharmony_ci                  pred_block->rpo_number().ToInt(),
49361cb0ef41Sopenharmony_ci                  current->TopLevel()->vreg());
49371cb0ef41Sopenharmony_ci            current->TopLevel()
49381cb0ef41Sopenharmony_ci                ->GetListOfBlocksRequiringSpillOperands(data())
49391cb0ef41Sopenharmony_ci                ->Add(pred_block->rpo_number().ToInt());
49401cb0ef41Sopenharmony_ci          }
49411cb0ef41Sopenharmony_ci        }
49421cb0ef41Sopenharmony_ci        int move_loc = ResolveControlFlow(block, cur_op, pred_block, pred_op);
49431cb0ef41Sopenharmony_ci        USE(move_loc);
49441cb0ef41Sopenharmony_ci        DCHECK_IMPLIES(
49451cb0ef41Sopenharmony_ci            result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks(
49461cb0ef41Sopenharmony_ci                data()) &&
49471cb0ef41Sopenharmony_ci                !(pred_op.IsAnyRegister() && cur_op.IsAnyRegister()) &&
49481cb0ef41Sopenharmony_ci                move_loc != -1,
49491cb0ef41Sopenharmony_ci            code()->GetInstructionBlock(move_loc)->IsDeferred());
49501cb0ef41Sopenharmony_ci      }
49511cb0ef41Sopenharmony_ci      ++it;
49521cb0ef41Sopenharmony_ci    }
49531cb0ef41Sopenharmony_ci  }
49541cb0ef41Sopenharmony_ci
49551cb0ef41Sopenharmony_ci  // At this stage, we collected blocks needing a spill operand due to reloads
49561cb0ef41Sopenharmony_ci  // from ConnectRanges and from ResolveControlFlow. Time to commit the spills
49571cb0ef41Sopenharmony_ci  // for deferred blocks. This is a convenient time to commit spills for general
49581cb0ef41Sopenharmony_ci  // spill ranges also, because they need to use the LiveRangeFinder.
49591cb0ef41Sopenharmony_ci  const size_t live_ranges_size = data()->live_ranges().size();
49601cb0ef41Sopenharmony_ci  SpillPlacer spill_placer(&finder, data(), local_zone);
49611cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* top : data()->live_ranges()) {
49621cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
49631cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
49641cb0ef41Sopenharmony_ci    if (top == nullptr || top->IsEmpty()) continue;
49651cb0ef41Sopenharmony_ci    if (top->IsSpilledOnlyInDeferredBlocks(data())) {
49661cb0ef41Sopenharmony_ci      CommitSpillsInDeferredBlocks(top, finder.ArrayFor(top->vreg()),
49671cb0ef41Sopenharmony_ci                                   local_zone);
49681cb0ef41Sopenharmony_ci    } else if (top->HasGeneralSpillRange()) {
49691cb0ef41Sopenharmony_ci      spill_placer.Add(top);
49701cb0ef41Sopenharmony_ci    }
49711cb0ef41Sopenharmony_ci  }
49721cb0ef41Sopenharmony_ci}
49731cb0ef41Sopenharmony_ci
49741cb0ef41Sopenharmony_ciint LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
49751cb0ef41Sopenharmony_ci                                           const InstructionOperand& cur_op,
49761cb0ef41Sopenharmony_ci                                           const InstructionBlock* pred,
49771cb0ef41Sopenharmony_ci                                           const InstructionOperand& pred_op) {
49781cb0ef41Sopenharmony_ci  DCHECK(!pred_op.Equals(cur_op));
49791cb0ef41Sopenharmony_ci  int gap_index;
49801cb0ef41Sopenharmony_ci  Instruction::GapPosition position;
49811cb0ef41Sopenharmony_ci  if (block->PredecessorCount() == 1) {
49821cb0ef41Sopenharmony_ci    gap_index = block->first_instruction_index();
49831cb0ef41Sopenharmony_ci    position = Instruction::START;
49841cb0ef41Sopenharmony_ci  } else {
49851cb0ef41Sopenharmony_ci    Instruction* last = code()->InstructionAt(pred->last_instruction_index());
49861cb0ef41Sopenharmony_ci    // The connecting move might invalidate uses of the destination operand in
49871cb0ef41Sopenharmony_ci    // the deoptimization call. See crbug.com/v8/12218. Omitting the move is
49881cb0ef41Sopenharmony_ci    // safe since the deopt call exits the current code.
49891cb0ef41Sopenharmony_ci    if (last->IsDeoptimizeCall()) {
49901cb0ef41Sopenharmony_ci      return -1;
49911cb0ef41Sopenharmony_ci    }
49921cb0ef41Sopenharmony_ci    // In every other case the last instruction should not participate in
49931cb0ef41Sopenharmony_ci    // register allocation, or it could interfere with the connecting move.
49941cb0ef41Sopenharmony_ci    for (size_t i = 0; i < last->InputCount(); ++i) {
49951cb0ef41Sopenharmony_ci      DCHECK(last->InputAt(i)->IsImmediate());
49961cb0ef41Sopenharmony_ci    }
49971cb0ef41Sopenharmony_ci    DCHECK_EQ(1, pred->SuccessorCount());
49981cb0ef41Sopenharmony_ci    DCHECK(!code()
49991cb0ef41Sopenharmony_ci                ->InstructionAt(pred->last_instruction_index())
50001cb0ef41Sopenharmony_ci                ->HasReferenceMap());
50011cb0ef41Sopenharmony_ci    gap_index = pred->last_instruction_index();
50021cb0ef41Sopenharmony_ci    position = Instruction::END;
50031cb0ef41Sopenharmony_ci  }
50041cb0ef41Sopenharmony_ci  data()->AddGapMove(gap_index, position, pred_op, cur_op);
50051cb0ef41Sopenharmony_ci  return gap_index;
50061cb0ef41Sopenharmony_ci}
50071cb0ef41Sopenharmony_ci
50081cb0ef41Sopenharmony_civoid LiveRangeConnector::ConnectRanges(Zone* local_zone) {
50091cb0ef41Sopenharmony_ci  DelayedInsertionMap delayed_insertion_map(local_zone);
50101cb0ef41Sopenharmony_ci  const size_t live_ranges_size = data()->live_ranges().size();
50111cb0ef41Sopenharmony_ci  for (TopLevelLiveRange* top_range : data()->live_ranges()) {
50121cb0ef41Sopenharmony_ci    CHECK_EQ(live_ranges_size,
50131cb0ef41Sopenharmony_ci             data()->live_ranges().size());  // TODO(neis): crbug.com/831822
50141cb0ef41Sopenharmony_ci    if (top_range == nullptr) continue;
50151cb0ef41Sopenharmony_ci    bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks(data());
50161cb0ef41Sopenharmony_ci    LiveRange* first_range = top_range;
50171cb0ef41Sopenharmony_ci    for (LiveRange *second_range = first_range->next(); second_range != nullptr;
50181cb0ef41Sopenharmony_ci         first_range = second_range, second_range = second_range->next()) {
50191cb0ef41Sopenharmony_ci      LifetimePosition pos = second_range->Start();
50201cb0ef41Sopenharmony_ci      // Add gap move if the two live ranges touch and there is no block
50211cb0ef41Sopenharmony_ci      // boundary.
50221cb0ef41Sopenharmony_ci      if (second_range->spilled()) continue;
50231cb0ef41Sopenharmony_ci      if (first_range->End() != pos) continue;
50241cb0ef41Sopenharmony_ci      if (data()->IsBlockBoundary(pos) &&
50251cb0ef41Sopenharmony_ci          !CanEagerlyResolveControlFlow(GetInstructionBlock(code(), pos))) {
50261cb0ef41Sopenharmony_ci        continue;
50271cb0ef41Sopenharmony_ci      }
50281cb0ef41Sopenharmony_ci      InstructionOperand prev_operand = first_range->GetAssignedOperand();
50291cb0ef41Sopenharmony_ci      InstructionOperand cur_operand = second_range->GetAssignedOperand();
50301cb0ef41Sopenharmony_ci      if (prev_operand.Equals(cur_operand)) continue;
50311cb0ef41Sopenharmony_ci      bool delay_insertion = false;
50321cb0ef41Sopenharmony_ci      Instruction::GapPosition gap_pos;
50331cb0ef41Sopenharmony_ci      int gap_index = pos.ToInstructionIndex();
50341cb0ef41Sopenharmony_ci      if (connect_spilled && !prev_operand.IsAnyRegister() &&
50351cb0ef41Sopenharmony_ci          cur_operand.IsAnyRegister()) {
50361cb0ef41Sopenharmony_ci        const InstructionBlock* block = code()->GetInstructionBlock(gap_index);
50371cb0ef41Sopenharmony_ci        DCHECK(block->IsDeferred());
50381cb0ef41Sopenharmony_ci        // Performing a reload in this block, meaning the spill operand must
50391cb0ef41Sopenharmony_ci        // be defined here.
50401cb0ef41Sopenharmony_ci        top_range->GetListOfBlocksRequiringSpillOperands(data())->Add(
50411cb0ef41Sopenharmony_ci            block->rpo_number().ToInt());
50421cb0ef41Sopenharmony_ci      }
50431cb0ef41Sopenharmony_ci
50441cb0ef41Sopenharmony_ci      if (pos.IsGapPosition()) {
50451cb0ef41Sopenharmony_ci        gap_pos = pos.IsStart() ? Instruction::START : Instruction::END;
50461cb0ef41Sopenharmony_ci      } else {
50471cb0ef41Sopenharmony_ci        if (pos.IsStart()) {
50481cb0ef41Sopenharmony_ci          delay_insertion = true;
50491cb0ef41Sopenharmony_ci        } else {
50501cb0ef41Sopenharmony_ci          gap_index++;
50511cb0ef41Sopenharmony_ci        }
50521cb0ef41Sopenharmony_ci        gap_pos = delay_insertion ? Instruction::END : Instruction::START;
50531cb0ef41Sopenharmony_ci      }
50541cb0ef41Sopenharmony_ci      // Reloads or spills for spilled in deferred blocks ranges must happen
50551cb0ef41Sopenharmony_ci      // only in deferred blocks.
50561cb0ef41Sopenharmony_ci      DCHECK_IMPLIES(connect_spilled && !(prev_operand.IsAnyRegister() &&
50571cb0ef41Sopenharmony_ci                                          cur_operand.IsAnyRegister()),
50581cb0ef41Sopenharmony_ci                     code()->GetInstructionBlock(gap_index)->IsDeferred());
50591cb0ef41Sopenharmony_ci
50601cb0ef41Sopenharmony_ci      ParallelMove* move =
50611cb0ef41Sopenharmony_ci          code()->InstructionAt(gap_index)->GetOrCreateParallelMove(
50621cb0ef41Sopenharmony_ci              gap_pos, code_zone());
50631cb0ef41Sopenharmony_ci      if (!delay_insertion) {
50641cb0ef41Sopenharmony_ci        move->AddMove(prev_operand, cur_operand);
50651cb0ef41Sopenharmony_ci      } else {
50661cb0ef41Sopenharmony_ci        delayed_insertion_map.insert(
50671cb0ef41Sopenharmony_ci            std::make_pair(std::make_pair(move, prev_operand), cur_operand));
50681cb0ef41Sopenharmony_ci      }
50691cb0ef41Sopenharmony_ci    }
50701cb0ef41Sopenharmony_ci  }
50711cb0ef41Sopenharmony_ci  if (delayed_insertion_map.empty()) return;
50721cb0ef41Sopenharmony_ci  // Insert all the moves which should occur after the stored move.
50731cb0ef41Sopenharmony_ci  ZoneVector<MoveOperands*> to_insert(local_zone);
50741cb0ef41Sopenharmony_ci  ZoneVector<MoveOperands*> to_eliminate(local_zone);
50751cb0ef41Sopenharmony_ci  to_insert.reserve(4);
50761cb0ef41Sopenharmony_ci  to_eliminate.reserve(4);
50771cb0ef41Sopenharmony_ci  ParallelMove* moves = delayed_insertion_map.begin()->first.first;
50781cb0ef41Sopenharmony_ci  for (auto it = delayed_insertion_map.begin();; ++it) {
50791cb0ef41Sopenharmony_ci    bool done = it == delayed_insertion_map.end();
50801cb0ef41Sopenharmony_ci    if (done || it->first.first != moves) {
50811cb0ef41Sopenharmony_ci      // Commit the MoveOperands for current ParallelMove.
50821cb0ef41Sopenharmony_ci      for (MoveOperands* move : to_eliminate) {
50831cb0ef41Sopenharmony_ci        move->Eliminate();
50841cb0ef41Sopenharmony_ci      }
50851cb0ef41Sopenharmony_ci      for (MoveOperands* move : to_insert) {
50861cb0ef41Sopenharmony_ci        moves->push_back(move);
50871cb0ef41Sopenharmony_ci      }
50881cb0ef41Sopenharmony_ci      if (done) break;
50891cb0ef41Sopenharmony_ci      // Reset state.
50901cb0ef41Sopenharmony_ci      to_eliminate.clear();
50911cb0ef41Sopenharmony_ci      to_insert.clear();
50921cb0ef41Sopenharmony_ci      moves = it->first.first;
50931cb0ef41Sopenharmony_ci    }
50941cb0ef41Sopenharmony_ci    // Gather all MoveOperands for a single ParallelMove.
50951cb0ef41Sopenharmony_ci    MoveOperands* move =
50961cb0ef41Sopenharmony_ci        code_zone()->New<MoveOperands>(it->first.second, it->second);
50971cb0ef41Sopenharmony_ci    moves->PrepareInsertAfter(move, &to_eliminate);
50981cb0ef41Sopenharmony_ci    to_insert.push_back(move);
50991cb0ef41Sopenharmony_ci  }
51001cb0ef41Sopenharmony_ci}
51011cb0ef41Sopenharmony_ci
51021cb0ef41Sopenharmony_civoid LiveRangeConnector::CommitSpillsInDeferredBlocks(
51031cb0ef41Sopenharmony_ci    TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) {
51041cb0ef41Sopenharmony_ci  DCHECK(range->IsSpilledOnlyInDeferredBlocks(data()));
51051cb0ef41Sopenharmony_ci  DCHECK(!range->spilled());
51061cb0ef41Sopenharmony_ci
51071cb0ef41Sopenharmony_ci  InstructionSequence* code = data()->code();
51081cb0ef41Sopenharmony_ci  InstructionOperand spill_operand = range->GetSpillRangeOperand();
51091cb0ef41Sopenharmony_ci
51101cb0ef41Sopenharmony_ci  TRACE("Live Range %d will be spilled only in deferred blocks.\n",
51111cb0ef41Sopenharmony_ci        range->vreg());
51121cb0ef41Sopenharmony_ci  // If we have ranges that aren't spilled but require the operand on the stack,
51131cb0ef41Sopenharmony_ci  // make sure we insert the spill.
51141cb0ef41Sopenharmony_ci  for (const LiveRange* child = range; child != nullptr;
51151cb0ef41Sopenharmony_ci       child = child->next()) {
51161cb0ef41Sopenharmony_ci    for (const UsePosition* pos = child->first_pos(); pos != nullptr;
51171cb0ef41Sopenharmony_ci         pos = pos->next()) {
51181cb0ef41Sopenharmony_ci      if (pos->type() != UsePositionType::kRequiresSlot && !child->spilled())
51191cb0ef41Sopenharmony_ci        continue;
51201cb0ef41Sopenharmony_ci      range->AddBlockRequiringSpillOperand(
51211cb0ef41Sopenharmony_ci          code->GetInstructionBlock(pos->pos().ToInstructionIndex())
51221cb0ef41Sopenharmony_ci              ->rpo_number(),
51231cb0ef41Sopenharmony_ci          data());
51241cb0ef41Sopenharmony_ci    }
51251cb0ef41Sopenharmony_ci  }
51261cb0ef41Sopenharmony_ci
51271cb0ef41Sopenharmony_ci  ZoneQueue<int> worklist(temp_zone);
51281cb0ef41Sopenharmony_ci
51291cb0ef41Sopenharmony_ci  for (int block_id : *range->GetListOfBlocksRequiringSpillOperands(data())) {
51301cb0ef41Sopenharmony_ci    worklist.push(block_id);
51311cb0ef41Sopenharmony_ci  }
51321cb0ef41Sopenharmony_ci
51331cb0ef41Sopenharmony_ci  ZoneSet<std::pair<RpoNumber, int>> done_moves(temp_zone);
51341cb0ef41Sopenharmony_ci  // Seek the deferred blocks that dominate locations requiring spill operands,
51351cb0ef41Sopenharmony_ci  // and spill there. We only need to spill at the start of such blocks.
51361cb0ef41Sopenharmony_ci  BitVector done_blocks(
51371cb0ef41Sopenharmony_ci      range->GetListOfBlocksRequiringSpillOperands(data())->length(),
51381cb0ef41Sopenharmony_ci      temp_zone);
51391cb0ef41Sopenharmony_ci  while (!worklist.empty()) {
51401cb0ef41Sopenharmony_ci    int block_id = worklist.front();
51411cb0ef41Sopenharmony_ci    worklist.pop();
51421cb0ef41Sopenharmony_ci    if (done_blocks.Contains(block_id)) continue;
51431cb0ef41Sopenharmony_ci    done_blocks.Add(block_id);
51441cb0ef41Sopenharmony_ci    InstructionBlock* spill_block =
51451cb0ef41Sopenharmony_ci        code->InstructionBlockAt(RpoNumber::FromInt(block_id));
51461cb0ef41Sopenharmony_ci
51471cb0ef41Sopenharmony_ci    for (const RpoNumber& pred : spill_block->predecessors()) {
51481cb0ef41Sopenharmony_ci      const InstructionBlock* pred_block = code->InstructionBlockAt(pred);
51491cb0ef41Sopenharmony_ci
51501cb0ef41Sopenharmony_ci      if (pred_block->IsDeferred()) {
51511cb0ef41Sopenharmony_ci        worklist.push(pred_block->rpo_number().ToInt());
51521cb0ef41Sopenharmony_ci      } else {
51531cb0ef41Sopenharmony_ci        LifetimePosition pred_end =
51541cb0ef41Sopenharmony_ci            LifetimePosition::InstructionFromInstructionIndex(
51551cb0ef41Sopenharmony_ci                pred_block->last_instruction_index());
51561cb0ef41Sopenharmony_ci
51571cb0ef41Sopenharmony_ci        LiveRangeBound* bound = array->Find(pred_end);
51581cb0ef41Sopenharmony_ci
51591cb0ef41Sopenharmony_ci        InstructionOperand pred_op = bound->range_->GetAssignedOperand();
51601cb0ef41Sopenharmony_ci
51611cb0ef41Sopenharmony_ci        RpoNumber spill_block_number = spill_block->rpo_number();
51621cb0ef41Sopenharmony_ci        if (done_moves.find(std::make_pair(
51631cb0ef41Sopenharmony_ci                spill_block_number, range->vreg())) == done_moves.end()) {
51641cb0ef41Sopenharmony_ci          TRACE("Spilling deferred spill for range %d at B%d\n", range->vreg(),
51651cb0ef41Sopenharmony_ci                spill_block_number.ToInt());
51661cb0ef41Sopenharmony_ci          data()->AddGapMove(spill_block->first_instruction_index(),
51671cb0ef41Sopenharmony_ci                             Instruction::GapPosition::START, pred_op,
51681cb0ef41Sopenharmony_ci                             spill_operand);
51691cb0ef41Sopenharmony_ci          done_moves.insert(std::make_pair(spill_block_number, range->vreg()));
51701cb0ef41Sopenharmony_ci          spill_block->mark_needs_frame();
51711cb0ef41Sopenharmony_ci        }
51721cb0ef41Sopenharmony_ci      }
51731cb0ef41Sopenharmony_ci    }
51741cb0ef41Sopenharmony_ci  }
51751cb0ef41Sopenharmony_ci}
51761cb0ef41Sopenharmony_ci
51771cb0ef41Sopenharmony_ci#undef TRACE
51781cb0ef41Sopenharmony_ci#undef TRACE_COND
51791cb0ef41Sopenharmony_ci
51801cb0ef41Sopenharmony_ci}  // namespace compiler
51811cb0ef41Sopenharmony_ci}  // namespace internal
51821cb0ef41Sopenharmony_ci}  // namespace v8
5183