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#ifndef V8_COMPILER_BACKEND_REGISTER_ALLOCATOR_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_REGISTER_ALLOCATOR_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/bits.h" 91cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/register-configuration.h" 111cb0ef41Sopenharmony_ci#include "src/common/globals.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/backend/register-allocation.h" 141cb0ef41Sopenharmony_ci#include "src/flags/flags.h" 151cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h" 161cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ciclass TickCounter; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace compiler { 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cistatic const int32_t kUnassignedRegister = RegisterConfiguration::kMaxRegisters; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci// This class represents a single point of a InstructionOperand's lifetime. For 281cb0ef41Sopenharmony_ci// each instruction there are four lifetime positions: 291cb0ef41Sopenharmony_ci// 301cb0ef41Sopenharmony_ci// [[START, END], [START, END]] 311cb0ef41Sopenharmony_ci// 321cb0ef41Sopenharmony_ci// Where the first half position corresponds to 331cb0ef41Sopenharmony_ci// 341cb0ef41Sopenharmony_ci// [GapPosition::START, GapPosition::END] 351cb0ef41Sopenharmony_ci// 361cb0ef41Sopenharmony_ci// and the second half position corresponds to 371cb0ef41Sopenharmony_ci// 381cb0ef41Sopenharmony_ci// [Lifetime::USED_AT_START, Lifetime::USED_AT_END] 391cb0ef41Sopenharmony_ci// 401cb0ef41Sopenharmony_ciclass LifetimePosition final { 411cb0ef41Sopenharmony_ci public: 421cb0ef41Sopenharmony_ci // Return the lifetime position that corresponds to the beginning of 431cb0ef41Sopenharmony_ci // the gap with the given index. 441cb0ef41Sopenharmony_ci static LifetimePosition GapFromInstructionIndex(int index) { 451cb0ef41Sopenharmony_ci return LifetimePosition(index * kStep); 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci // Return the lifetime position that corresponds to the beginning of 481cb0ef41Sopenharmony_ci // the instruction with the given index. 491cb0ef41Sopenharmony_ci static LifetimePosition InstructionFromInstructionIndex(int index) { 501cb0ef41Sopenharmony_ci return LifetimePosition(index * kStep + kHalfStep); 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci static bool ExistsGapPositionBetween(LifetimePosition pos1, 541cb0ef41Sopenharmony_ci LifetimePosition pos2) { 551cb0ef41Sopenharmony_ci if (pos1 > pos2) std::swap(pos1, pos2); 561cb0ef41Sopenharmony_ci LifetimePosition next(pos1.value_ + 1); 571cb0ef41Sopenharmony_ci if (next.IsGapPosition()) return next < pos2; 581cb0ef41Sopenharmony_ci return next.NextFullStart() < pos2; 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // Returns a numeric representation of this lifetime position. 621cb0ef41Sopenharmony_ci int value() const { return value_; } 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // Returns the index of the instruction to which this lifetime position 651cb0ef41Sopenharmony_ci // corresponds. 661cb0ef41Sopenharmony_ci int ToInstructionIndex() const { 671cb0ef41Sopenharmony_ci DCHECK(IsValid()); 681cb0ef41Sopenharmony_ci return value_ / kStep; 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci // Returns true if this lifetime position corresponds to a START value 721cb0ef41Sopenharmony_ci bool IsStart() const { return (value_ & (kHalfStep - 1)) == 0; } 731cb0ef41Sopenharmony_ci // Returns true if this lifetime position corresponds to an END value 741cb0ef41Sopenharmony_ci bool IsEnd() const { return (value_ & (kHalfStep - 1)) == 1; } 751cb0ef41Sopenharmony_ci // Returns true if this lifetime position corresponds to a gap START value 761cb0ef41Sopenharmony_ci bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; } 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci bool IsGapPosition() const { return (value_ & 0x2) == 0; } 791cb0ef41Sopenharmony_ci bool IsInstructionPosition() const { return !IsGapPosition(); } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci // Returns the lifetime position for the current START. 821cb0ef41Sopenharmony_ci LifetimePosition Start() const { 831cb0ef41Sopenharmony_ci DCHECK(IsValid()); 841cb0ef41Sopenharmony_ci return LifetimePosition(value_ & ~(kHalfStep - 1)); 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci // Returns the lifetime position for the current gap START. 881cb0ef41Sopenharmony_ci LifetimePosition FullStart() const { 891cb0ef41Sopenharmony_ci DCHECK(IsValid()); 901cb0ef41Sopenharmony_ci return LifetimePosition(value_ & ~(kStep - 1)); 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Returns the lifetime position for the current END. 941cb0ef41Sopenharmony_ci LifetimePosition End() const { 951cb0ef41Sopenharmony_ci DCHECK(IsValid()); 961cb0ef41Sopenharmony_ci return LifetimePosition(Start().value_ + kHalfStep / 2); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci // Returns the lifetime position for the beginning of the next START. 1001cb0ef41Sopenharmony_ci LifetimePosition NextStart() const { 1011cb0ef41Sopenharmony_ci DCHECK(IsValid()); 1021cb0ef41Sopenharmony_ci return LifetimePosition(Start().value_ + kHalfStep); 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci // Returns the lifetime position for the beginning of the next gap START. 1061cb0ef41Sopenharmony_ci LifetimePosition NextFullStart() const { 1071cb0ef41Sopenharmony_ci DCHECK(IsValid()); 1081cb0ef41Sopenharmony_ci return LifetimePosition(FullStart().value_ + kStep); 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci // Returns the lifetime position for the beginning of the previous START. 1121cb0ef41Sopenharmony_ci LifetimePosition PrevStart() const { 1131cb0ef41Sopenharmony_ci DCHECK(IsValid()); 1141cb0ef41Sopenharmony_ci DCHECK_LE(kHalfStep, value_); 1151cb0ef41Sopenharmony_ci return LifetimePosition(Start().value_ - kHalfStep); 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci // Constructs the lifetime position which does not correspond to any 1191cb0ef41Sopenharmony_ci // instruction. 1201cb0ef41Sopenharmony_ci LifetimePosition() : value_(-1) {} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci // Returns true if this lifetime positions corrensponds to some 1231cb0ef41Sopenharmony_ci // instruction. 1241cb0ef41Sopenharmony_ci bool IsValid() const { return value_ != -1; } 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci bool operator<(const LifetimePosition& that) const { 1271cb0ef41Sopenharmony_ci return this->value_ < that.value_; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci bool operator<=(const LifetimePosition& that) const { 1311cb0ef41Sopenharmony_ci return this->value_ <= that.value_; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci bool operator==(const LifetimePosition& that) const { 1351cb0ef41Sopenharmony_ci return this->value_ == that.value_; 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci bool operator!=(const LifetimePosition& that) const { 1391cb0ef41Sopenharmony_ci return this->value_ != that.value_; 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci bool operator>(const LifetimePosition& that) const { 1431cb0ef41Sopenharmony_ci return this->value_ > that.value_; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci bool operator>=(const LifetimePosition& that) const { 1471cb0ef41Sopenharmony_ci return this->value_ >= that.value_; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci void Print() const; 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci static inline LifetimePosition Invalid() { return LifetimePosition(); } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci static inline LifetimePosition MaxPosition() { 1551cb0ef41Sopenharmony_ci // We have to use this kind of getter instead of static member due to 1561cb0ef41Sopenharmony_ci // crash bug in GDB. 1571cb0ef41Sopenharmony_ci return LifetimePosition(kMaxInt); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci static inline LifetimePosition FromInt(int value) { 1611cb0ef41Sopenharmony_ci return LifetimePosition(value); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci private: 1651cb0ef41Sopenharmony_ci static const int kHalfStep = 2; 1661cb0ef41Sopenharmony_ci static const int kStep = 2 * kHalfStep; 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci static_assert(base::bits::IsPowerOfTwo(kHalfStep), 1691cb0ef41Sopenharmony_ci "Code relies on kStep and kHalfStep being a power of two"); 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci explicit LifetimePosition(int value) : value_(value) {} 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci int value_; 1741cb0ef41Sopenharmony_ci}; 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const LifetimePosition pos); 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_cienum class RegisterAllocationFlag : unsigned { kTraceAllocation = 1 << 0 }; 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ciusing RegisterAllocationFlags = base::Flags<RegisterAllocationFlag>; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ciclass SpillRange; 1831cb0ef41Sopenharmony_ciclass LiveRange; 1841cb0ef41Sopenharmony_ciclass TopLevelLiveRange; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ciclass TopTierRegisterAllocationData final : public RegisterAllocationData { 1871cb0ef41Sopenharmony_ci public: 1881cb0ef41Sopenharmony_ci TopTierRegisterAllocationData(const TopTierRegisterAllocationData&) = delete; 1891cb0ef41Sopenharmony_ci TopTierRegisterAllocationData& operator=( 1901cb0ef41Sopenharmony_ci const TopTierRegisterAllocationData&) = delete; 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci static const TopTierRegisterAllocationData* cast( 1931cb0ef41Sopenharmony_ci const RegisterAllocationData* data) { 1941cb0ef41Sopenharmony_ci DCHECK_EQ(data->type(), Type::kTopTier); 1951cb0ef41Sopenharmony_ci return static_cast<const TopTierRegisterAllocationData*>(data); 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci static TopTierRegisterAllocationData* cast(RegisterAllocationData* data) { 1991cb0ef41Sopenharmony_ci DCHECK_EQ(data->type(), Type::kTopTier); 2001cb0ef41Sopenharmony_ci return static_cast<TopTierRegisterAllocationData*>(data); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci static const TopTierRegisterAllocationData& cast( 2041cb0ef41Sopenharmony_ci const RegisterAllocationData& data) { 2051cb0ef41Sopenharmony_ci DCHECK_EQ(data.type(), Type::kTopTier); 2061cb0ef41Sopenharmony_ci return static_cast<const TopTierRegisterAllocationData&>(data); 2071cb0ef41Sopenharmony_ci } 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci // Encodes whether a spill happens in deferred code (kSpillDeferred) or 2101cb0ef41Sopenharmony_ci // regular code (kSpillAtDefinition). 2111cb0ef41Sopenharmony_ci enum SpillMode { kSpillAtDefinition, kSpillDeferred }; 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci bool is_trace_alloc() { 2141cb0ef41Sopenharmony_ci return flags_ & RegisterAllocationFlag::kTraceAllocation; 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci static constexpr int kNumberOfFixedRangesPerRegister = 2; 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci class PhiMapValue : public ZoneObject { 2201cb0ef41Sopenharmony_ci public: 2211cb0ef41Sopenharmony_ci PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone); 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci const PhiInstruction* phi() const { return phi_; } 2241cb0ef41Sopenharmony_ci const InstructionBlock* block() const { return block_; } 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci // For hinting. 2271cb0ef41Sopenharmony_ci int assigned_register() const { return assigned_register_; } 2281cb0ef41Sopenharmony_ci void set_assigned_register(int register_code) { 2291cb0ef41Sopenharmony_ci DCHECK_EQ(assigned_register_, kUnassignedRegister); 2301cb0ef41Sopenharmony_ci assigned_register_ = register_code; 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci void UnsetAssignedRegister() { assigned_register_ = kUnassignedRegister; } 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci void AddOperand(InstructionOperand* operand); 2351cb0ef41Sopenharmony_ci void CommitAssignment(const InstructionOperand& operand); 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci private: 2381cb0ef41Sopenharmony_ci PhiInstruction* const phi_; 2391cb0ef41Sopenharmony_ci const InstructionBlock* const block_; 2401cb0ef41Sopenharmony_ci ZoneVector<InstructionOperand*> incoming_operands_; 2411cb0ef41Sopenharmony_ci int assigned_register_; 2421cb0ef41Sopenharmony_ci }; 2431cb0ef41Sopenharmony_ci using PhiMap = ZoneMap<int, PhiMapValue*>; 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci struct DelayedReference { 2461cb0ef41Sopenharmony_ci ReferenceMap* map; 2471cb0ef41Sopenharmony_ci InstructionOperand* operand; 2481cb0ef41Sopenharmony_ci }; 2491cb0ef41Sopenharmony_ci using DelayedReferences = ZoneVector<DelayedReference>; 2501cb0ef41Sopenharmony_ci using RangesWithPreassignedSlots = 2511cb0ef41Sopenharmony_ci ZoneVector<std::pair<TopLevelLiveRange*, int>>; 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci TopTierRegisterAllocationData(const RegisterConfiguration* config, 2541cb0ef41Sopenharmony_ci Zone* allocation_zone, Frame* frame, 2551cb0ef41Sopenharmony_ci InstructionSequence* code, 2561cb0ef41Sopenharmony_ci RegisterAllocationFlags flags, 2571cb0ef41Sopenharmony_ci TickCounter* tick_counter, 2581cb0ef41Sopenharmony_ci const char* debug_name = nullptr); 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& live_ranges() const { 2611cb0ef41Sopenharmony_ci return live_ranges_; 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; } 2641cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() const { 2651cb0ef41Sopenharmony_ci return fixed_live_ranges_; 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() { 2681cb0ef41Sopenharmony_ci return fixed_live_ranges_; 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() { 2711cb0ef41Sopenharmony_ci return fixed_float_live_ranges_; 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() const { 2741cb0ef41Sopenharmony_ci return fixed_float_live_ranges_; 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() { 2771cb0ef41Sopenharmony_ci return fixed_double_live_ranges_; 2781cb0ef41Sopenharmony_ci } 2791cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() const { 2801cb0ef41Sopenharmony_ci return fixed_double_live_ranges_; 2811cb0ef41Sopenharmony_ci } 2821cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() { 2831cb0ef41Sopenharmony_ci return fixed_simd128_live_ranges_; 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const { 2861cb0ef41Sopenharmony_ci return fixed_simd128_live_ranges_; 2871cb0ef41Sopenharmony_ci } 2881cb0ef41Sopenharmony_ci ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; } 2891cb0ef41Sopenharmony_ci ZoneVector<BitVector*>& live_out_sets() { return live_out_sets_; } 2901cb0ef41Sopenharmony_ci ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } 2911cb0ef41Sopenharmony_ci DelayedReferences& delayed_references() { return delayed_references_; } 2921cb0ef41Sopenharmony_ci InstructionSequence* code() const { return code_; } 2931cb0ef41Sopenharmony_ci // This zone is for data structures only needed during register allocation 2941cb0ef41Sopenharmony_ci // phases. 2951cb0ef41Sopenharmony_ci Zone* allocation_zone() const { return allocation_zone_; } 2961cb0ef41Sopenharmony_ci // This zone is for InstructionOperands and moves that live beyond register 2971cb0ef41Sopenharmony_ci // allocation. 2981cb0ef41Sopenharmony_ci Zone* code_zone() const { return code()->zone(); } 2991cb0ef41Sopenharmony_ci Frame* frame() const { return frame_; } 3001cb0ef41Sopenharmony_ci const char* debug_name() const { return debug_name_; } 3011cb0ef41Sopenharmony_ci const RegisterConfiguration* config() const { return config_; } 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ci MachineRepresentation RepresentationFor(int virtual_register); 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci TopLevelLiveRange* GetOrCreateLiveRangeFor(int index); 3061cb0ef41Sopenharmony_ci // Creates a new live range. 3071cb0ef41Sopenharmony_ci TopLevelLiveRange* NewLiveRange(int index, MachineRepresentation rep); 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci SpillRange* AssignSpillRangeToLiveRange(TopLevelLiveRange* range, 3101cb0ef41Sopenharmony_ci SpillMode spill_mode); 3111cb0ef41Sopenharmony_ci SpillRange* CreateSpillRangeForLiveRange(TopLevelLiveRange* range); 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci MoveOperands* AddGapMove(int index, Instruction::GapPosition position, 3141cb0ef41Sopenharmony_ci const InstructionOperand& from, 3151cb0ef41Sopenharmony_ci const InstructionOperand& to); 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci bool ExistsUseWithoutDefinition(); 3181cb0ef41Sopenharmony_ci bool RangesDefinedInDeferredStayInDeferred(); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci void MarkFixedUse(MachineRepresentation rep, int index); 3211cb0ef41Sopenharmony_ci bool HasFixedUse(MachineRepresentation rep, int index); 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci void MarkAllocated(MachineRepresentation rep, int index); 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci PhiMapValue* InitializePhiMap(const InstructionBlock* block, 3261cb0ef41Sopenharmony_ci PhiInstruction* phi); 3271cb0ef41Sopenharmony_ci PhiMapValue* GetPhiMapValueFor(TopLevelLiveRange* top_range); 3281cb0ef41Sopenharmony_ci PhiMapValue* GetPhiMapValueFor(int virtual_register); 3291cb0ef41Sopenharmony_ci bool IsBlockBoundary(LifetimePosition pos) const; 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci RangesWithPreassignedSlots& preassigned_slot_ranges() { 3321cb0ef41Sopenharmony_ci return preassigned_slot_ranges_; 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ci void RememberSpillState(RpoNumber block, 3361cb0ef41Sopenharmony_ci const ZoneVector<LiveRange*>& state) { 3371cb0ef41Sopenharmony_ci spill_state_[block.ToSize()] = state; 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci ZoneVector<LiveRange*>& GetSpillState(RpoNumber block) { 3411cb0ef41Sopenharmony_ci auto& result = spill_state_[block.ToSize()]; 3421cb0ef41Sopenharmony_ci return result; 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci void ResetSpillState() { 3461cb0ef41Sopenharmony_ci for (auto& state : spill_state_) { 3471cb0ef41Sopenharmony_ci state.clear(); 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci TickCounter* tick_counter() { return tick_counter_; } 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci ZoneMap<TopLevelLiveRange*, AllocatedOperand*>& slot_for_const_range() { 3541cb0ef41Sopenharmony_ci return slot_for_const_range_; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci private: 3581cb0ef41Sopenharmony_ci Zone* const allocation_zone_; 3591cb0ef41Sopenharmony_ci Frame* const frame_; 3601cb0ef41Sopenharmony_ci InstructionSequence* const code_; 3611cb0ef41Sopenharmony_ci const char* const debug_name_; 3621cb0ef41Sopenharmony_ci const RegisterConfiguration* const config_; 3631cb0ef41Sopenharmony_ci PhiMap phi_map_; 3641cb0ef41Sopenharmony_ci ZoneVector<BitVector*> live_in_sets_; 3651cb0ef41Sopenharmony_ci ZoneVector<BitVector*> live_out_sets_; 3661cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*> live_ranges_; 3671cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*> fixed_live_ranges_; 3681cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_; 3691cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_; 3701cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*> fixed_simd128_live_ranges_; 3711cb0ef41Sopenharmony_ci ZoneVector<SpillRange*> spill_ranges_; 3721cb0ef41Sopenharmony_ci DelayedReferences delayed_references_; 3731cb0ef41Sopenharmony_ci BitVector* assigned_registers_; 3741cb0ef41Sopenharmony_ci BitVector* assigned_double_registers_; 3751cb0ef41Sopenharmony_ci BitVector* assigned_simd128_registers_; 3761cb0ef41Sopenharmony_ci BitVector* fixed_register_use_; 3771cb0ef41Sopenharmony_ci BitVector* fixed_fp_register_use_; 3781cb0ef41Sopenharmony_ci BitVector* fixed_simd128_register_use_; 3791cb0ef41Sopenharmony_ci int virtual_register_count_; 3801cb0ef41Sopenharmony_ci RangesWithPreassignedSlots preassigned_slot_ranges_; 3811cb0ef41Sopenharmony_ci ZoneVector<ZoneVector<LiveRange*>> spill_state_; 3821cb0ef41Sopenharmony_ci RegisterAllocationFlags flags_; 3831cb0ef41Sopenharmony_ci TickCounter* const tick_counter_; 3841cb0ef41Sopenharmony_ci ZoneMap<TopLevelLiveRange*, AllocatedOperand*> slot_for_const_range_; 3851cb0ef41Sopenharmony_ci}; 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci// Representation of the non-empty interval [start,end[. 3881cb0ef41Sopenharmony_ciclass UseInterval final : public ZoneObject { 3891cb0ef41Sopenharmony_ci public: 3901cb0ef41Sopenharmony_ci UseInterval(LifetimePosition start, LifetimePosition end) 3911cb0ef41Sopenharmony_ci : start_(start), end_(end), next_(nullptr) { 3921cb0ef41Sopenharmony_ci DCHECK(start < end); 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci UseInterval(const UseInterval&) = delete; 3951cb0ef41Sopenharmony_ci UseInterval& operator=(const UseInterval&) = delete; 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci LifetimePosition start() const { return start_; } 3981cb0ef41Sopenharmony_ci void set_start(LifetimePosition start) { start_ = start; } 3991cb0ef41Sopenharmony_ci LifetimePosition end() const { return end_; } 4001cb0ef41Sopenharmony_ci void set_end(LifetimePosition end) { end_ = end; } 4011cb0ef41Sopenharmony_ci UseInterval* next() const { return next_; } 4021cb0ef41Sopenharmony_ci void set_next(UseInterval* next) { next_ = next; } 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci // Split this interval at the given position without effecting the 4051cb0ef41Sopenharmony_ci // live range that owns it. The interval must contain the position. 4061cb0ef41Sopenharmony_ci UseInterval* SplitAt(LifetimePosition pos, Zone* zone); 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci // If this interval intersects with other return smallest position 4091cb0ef41Sopenharmony_ci // that belongs to both of them. 4101cb0ef41Sopenharmony_ci LifetimePosition Intersect(const UseInterval* other) const { 4111cb0ef41Sopenharmony_ci if (other->start() < start_) return other->Intersect(this); 4121cb0ef41Sopenharmony_ci if (other->start() < end_) return other->start(); 4131cb0ef41Sopenharmony_ci return LifetimePosition::Invalid(); 4141cb0ef41Sopenharmony_ci } 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_ci bool Contains(LifetimePosition point) const { 4171cb0ef41Sopenharmony_ci return start_ <= point && point < end_; 4181cb0ef41Sopenharmony_ci } 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci // Returns the index of the first gap covered by this interval. 4211cb0ef41Sopenharmony_ci int FirstGapIndex() const { 4221cb0ef41Sopenharmony_ci int ret = start_.ToInstructionIndex(); 4231cb0ef41Sopenharmony_ci if (start_.IsInstructionPosition()) { 4241cb0ef41Sopenharmony_ci ++ret; 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci return ret; 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci // Returns the index of the last gap covered by this interval. 4301cb0ef41Sopenharmony_ci int LastGapIndex() const { 4311cb0ef41Sopenharmony_ci int ret = end_.ToInstructionIndex(); 4321cb0ef41Sopenharmony_ci if (end_.IsGapPosition() && end_.IsStart()) { 4331cb0ef41Sopenharmony_ci --ret; 4341cb0ef41Sopenharmony_ci } 4351cb0ef41Sopenharmony_ci return ret; 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci private: 4391cb0ef41Sopenharmony_ci LifetimePosition start_; 4401cb0ef41Sopenharmony_ci LifetimePosition end_; 4411cb0ef41Sopenharmony_ci UseInterval* next_; 4421cb0ef41Sopenharmony_ci}; 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_cienum class UsePositionType : uint8_t { 4451cb0ef41Sopenharmony_ci kRegisterOrSlot, 4461cb0ef41Sopenharmony_ci kRegisterOrSlotOrConstant, 4471cb0ef41Sopenharmony_ci kRequiresRegister, 4481cb0ef41Sopenharmony_ci kRequiresSlot 4491cb0ef41Sopenharmony_ci}; 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_cienum class UsePositionHintType : uint8_t { 4521cb0ef41Sopenharmony_ci kNone, 4531cb0ef41Sopenharmony_ci kOperand, 4541cb0ef41Sopenharmony_ci kUsePos, 4551cb0ef41Sopenharmony_ci kPhi, 4561cb0ef41Sopenharmony_ci kUnresolved 4571cb0ef41Sopenharmony_ci}; 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci// Representation of a use position. 4601cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE UsePosition final 4611cb0ef41Sopenharmony_ci : public NON_EXPORTED_BASE(ZoneObject) { 4621cb0ef41Sopenharmony_ci public: 4631cb0ef41Sopenharmony_ci UsePosition(LifetimePosition pos, InstructionOperand* operand, void* hint, 4641cb0ef41Sopenharmony_ci UsePositionHintType hint_type); 4651cb0ef41Sopenharmony_ci UsePosition(const UsePosition&) = delete; 4661cb0ef41Sopenharmony_ci UsePosition& operator=(const UsePosition&) = delete; 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci InstructionOperand* operand() const { return operand_; } 4691cb0ef41Sopenharmony_ci bool HasOperand() const { return operand_ != nullptr; } 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci bool RegisterIsBeneficial() const { 4721cb0ef41Sopenharmony_ci return RegisterBeneficialField::decode(flags_); 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci bool SpillDetrimental() const { 4751cb0ef41Sopenharmony_ci return SpillDetrimentalField::decode(flags_); 4761cb0ef41Sopenharmony_ci } 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci UsePositionType type() const { return TypeField::decode(flags_); } 4791cb0ef41Sopenharmony_ci void set_type(UsePositionType type, bool register_beneficial); 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ci LifetimePosition pos() const { return pos_; } 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci UsePosition* next() const { return next_; } 4841cb0ef41Sopenharmony_ci void set_next(UsePosition* next) { next_ = next; } 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci // For hinting only. 4871cb0ef41Sopenharmony_ci void set_assigned_register(int register_code) { 4881cb0ef41Sopenharmony_ci flags_ = AssignedRegisterField::update(flags_, register_code); 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci void set_spill_detrimental() { 4911cb0ef41Sopenharmony_ci flags_ = SpillDetrimentalField::update(flags_, true); 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci UsePositionHintType hint_type() const { 4951cb0ef41Sopenharmony_ci return HintTypeField::decode(flags_); 4961cb0ef41Sopenharmony_ci } 4971cb0ef41Sopenharmony_ci bool HasHint() const; 4981cb0ef41Sopenharmony_ci bool HintRegister(int* register_code) const; 4991cb0ef41Sopenharmony_ci void SetHint(UsePosition* use_pos); 5001cb0ef41Sopenharmony_ci void ResolveHint(UsePosition* use_pos); 5011cb0ef41Sopenharmony_ci bool IsResolved() const { 5021cb0ef41Sopenharmony_ci return hint_type() != UsePositionHintType::kUnresolved; 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci static UsePositionHintType HintTypeForOperand(const InstructionOperand& op); 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci private: 5071cb0ef41Sopenharmony_ci using TypeField = base::BitField<UsePositionType, 0, 2>; 5081cb0ef41Sopenharmony_ci using HintTypeField = base::BitField<UsePositionHintType, 2, 3>; 5091cb0ef41Sopenharmony_ci using RegisterBeneficialField = base::BitField<bool, 5, 1>; 5101cb0ef41Sopenharmony_ci using AssignedRegisterField = base::BitField<int32_t, 6, 6>; 5111cb0ef41Sopenharmony_ci using SpillDetrimentalField = base::BitField<int32_t, 12, 1>; 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci InstructionOperand* const operand_; 5141cb0ef41Sopenharmony_ci void* hint_; 5151cb0ef41Sopenharmony_ci UsePosition* next_; 5161cb0ef41Sopenharmony_ci LifetimePosition const pos_; 5171cb0ef41Sopenharmony_ci uint32_t flags_; 5181cb0ef41Sopenharmony_ci}; 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ciclass SpillRange; 5211cb0ef41Sopenharmony_ciclass TopTierRegisterAllocationData; 5221cb0ef41Sopenharmony_ciclass TopLevelLiveRange; 5231cb0ef41Sopenharmony_ciclass LiveRangeBundle; 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci// Representation of SSA values' live ranges as a collection of (continuous) 5261cb0ef41Sopenharmony_ci// intervals over the instruction ordering. 5271cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) { 5281cb0ef41Sopenharmony_ci public: 5291cb0ef41Sopenharmony_ci LiveRange(const LiveRange&) = delete; 5301cb0ef41Sopenharmony_ci LiveRange& operator=(const LiveRange&) = delete; 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ci UseInterval* first_interval() const { return first_interval_; } 5331cb0ef41Sopenharmony_ci UsePosition* first_pos() const { return first_pos_; } 5341cb0ef41Sopenharmony_ci TopLevelLiveRange* TopLevel() { return top_level_; } 5351cb0ef41Sopenharmony_ci const TopLevelLiveRange* TopLevel() const { return top_level_; } 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_ci bool IsTopLevel() const; 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci LiveRange* next() const { return next_; } 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci int relative_id() const { return relative_id_; } 5421cb0ef41Sopenharmony_ci 5431cb0ef41Sopenharmony_ci bool IsEmpty() const { return first_interval() == nullptr; } 5441cb0ef41Sopenharmony_ci 5451cb0ef41Sopenharmony_ci InstructionOperand GetAssignedOperand() const; 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci MachineRepresentation representation() const { 5481cb0ef41Sopenharmony_ci return RepresentationField::decode(bits_); 5491cb0ef41Sopenharmony_ci } 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci int assigned_register() const { return AssignedRegisterField::decode(bits_); } 5521cb0ef41Sopenharmony_ci bool HasRegisterAssigned() const { 5531cb0ef41Sopenharmony_ci return assigned_register() != kUnassignedRegister; 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci void set_assigned_register(int reg); 5561cb0ef41Sopenharmony_ci void UnsetAssignedRegister(); 5571cb0ef41Sopenharmony_ci 5581cb0ef41Sopenharmony_ci bool ShouldRecombine() const { return RecombineField::decode(bits_); } 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ci void SetRecombine() { bits_ = RecombineField::update(bits_, true); } 5611cb0ef41Sopenharmony_ci void set_controlflow_hint(int reg) { 5621cb0ef41Sopenharmony_ci bits_ = ControlFlowRegisterHint::update(bits_, reg); 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci int controlflow_hint() const { 5651cb0ef41Sopenharmony_ci return ControlFlowRegisterHint::decode(bits_); 5661cb0ef41Sopenharmony_ci } 5671cb0ef41Sopenharmony_ci bool RegisterFromControlFlow(int* reg) { 5681cb0ef41Sopenharmony_ci int hint = controlflow_hint(); 5691cb0ef41Sopenharmony_ci if (hint != kUnassignedRegister) { 5701cb0ef41Sopenharmony_ci *reg = hint; 5711cb0ef41Sopenharmony_ci return true; 5721cb0ef41Sopenharmony_ci } 5731cb0ef41Sopenharmony_ci return false; 5741cb0ef41Sopenharmony_ci } 5751cb0ef41Sopenharmony_ci bool spilled() const { return SpilledField::decode(bits_); } 5761cb0ef41Sopenharmony_ci void AttachToNext(); 5771cb0ef41Sopenharmony_ci void Unspill(); 5781cb0ef41Sopenharmony_ci void Spill(); 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ci RegisterKind kind() const; 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci // Returns use position in this live range that follows both start 5831cb0ef41Sopenharmony_ci // and last processed use position. 5841cb0ef41Sopenharmony_ci UsePosition* NextUsePosition(LifetimePosition start) const; 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci // Returns use position for which register is required in this live 5871cb0ef41Sopenharmony_ci // range and which follows both start and last processed use position 5881cb0ef41Sopenharmony_ci UsePosition* NextRegisterPosition(LifetimePosition start) const; 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci // Returns the first use position requiring stack slot, or nullptr. 5911cb0ef41Sopenharmony_ci UsePosition* NextSlotPosition(LifetimePosition start) const; 5921cb0ef41Sopenharmony_ci 5931cb0ef41Sopenharmony_ci // Returns use position for which register is beneficial in this live 5941cb0ef41Sopenharmony_ci // range and which follows both start and last processed use position 5951cb0ef41Sopenharmony_ci UsePosition* NextUsePositionRegisterIsBeneficial( 5961cb0ef41Sopenharmony_ci LifetimePosition start) const; 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci // Returns lifetime position for which register is beneficial in this live 5991cb0ef41Sopenharmony_ci // range and which follows both start and last processed use position. 6001cb0ef41Sopenharmony_ci LifetimePosition NextLifetimePositionRegisterIsBeneficial( 6011cb0ef41Sopenharmony_ci const LifetimePosition& start) const; 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci // Returns use position for which register is beneficial in this live 6041cb0ef41Sopenharmony_ci // range and which precedes start. 6051cb0ef41Sopenharmony_ci UsePosition* PreviousUsePositionRegisterIsBeneficial( 6061cb0ef41Sopenharmony_ci LifetimePosition start) const; 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci // Returns use position for which spilling is detrimental in this live 6091cb0ef41Sopenharmony_ci // range and which follows both start and last processed use position 6101cb0ef41Sopenharmony_ci UsePosition* NextUsePositionSpillDetrimental(LifetimePosition start) const; 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci // Can this live range be spilled at this position. 6131cb0ef41Sopenharmony_ci bool CanBeSpilled(LifetimePosition pos) const; 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci // Splitting primitive used by splitting members. 6161cb0ef41Sopenharmony_ci // Performs the split, but does not link the resulting ranges. 6171cb0ef41Sopenharmony_ci // The given position must follow the start of the range. 6181cb0ef41Sopenharmony_ci // All uses following the given position will be moved from this 6191cb0ef41Sopenharmony_ci // live range to the result live range. 6201cb0ef41Sopenharmony_ci // The current range will terminate at position, while result will start from 6211cb0ef41Sopenharmony_ci // position. 6221cb0ef41Sopenharmony_ci enum HintConnectionOption : bool { 6231cb0ef41Sopenharmony_ci DoNotConnectHints = false, 6241cb0ef41Sopenharmony_ci ConnectHints = true 6251cb0ef41Sopenharmony_ci }; 6261cb0ef41Sopenharmony_ci UsePosition* DetachAt(LifetimePosition position, LiveRange* result, 6271cb0ef41Sopenharmony_ci Zone* zone, HintConnectionOption connect_hints); 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ci // Detaches at position, and then links the resulting ranges. Returns the 6301cb0ef41Sopenharmony_ci // child, which starts at position. 6311cb0ef41Sopenharmony_ci LiveRange* SplitAt(LifetimePosition position, Zone* zone); 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci // Returns nullptr when no register is hinted, otherwise sets register_index. 6341cb0ef41Sopenharmony_ci // Uses {current_hint_position_} as a cache, and tries to update it. 6351cb0ef41Sopenharmony_ci UsePosition* FirstHintPosition(int* register_index); 6361cb0ef41Sopenharmony_ci UsePosition* FirstHintPosition() { 6371cb0ef41Sopenharmony_ci int register_index; 6381cb0ef41Sopenharmony_ci return FirstHintPosition(®ister_index); 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci 6411cb0ef41Sopenharmony_ci UsePosition* current_hint_position() const { 6421cb0ef41Sopenharmony_ci return current_hint_position_; 6431cb0ef41Sopenharmony_ci } 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_ci LifetimePosition Start() const { 6461cb0ef41Sopenharmony_ci DCHECK(!IsEmpty()); 6471cb0ef41Sopenharmony_ci return first_interval()->start(); 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_ci LifetimePosition End() const { 6511cb0ef41Sopenharmony_ci DCHECK(!IsEmpty()); 6521cb0ef41Sopenharmony_ci return last_interval_->end(); 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_ci bool ShouldBeAllocatedBefore(const LiveRange* other) const; 6561cb0ef41Sopenharmony_ci bool CanCover(LifetimePosition position) const; 6571cb0ef41Sopenharmony_ci bool Covers(LifetimePosition position) const; 6581cb0ef41Sopenharmony_ci LifetimePosition NextStartAfter(LifetimePosition position); 6591cb0ef41Sopenharmony_ci LifetimePosition NextEndAfter(LifetimePosition position) const; 6601cb0ef41Sopenharmony_ci LifetimePosition FirstIntersection(LiveRange* other) const; 6611cb0ef41Sopenharmony_ci LifetimePosition NextStart() const { return next_start_; } 6621cb0ef41Sopenharmony_ci 6631cb0ef41Sopenharmony_ci void VerifyChildStructure() const { 6641cb0ef41Sopenharmony_ci VerifyIntervals(); 6651cb0ef41Sopenharmony_ci VerifyPositions(); 6661cb0ef41Sopenharmony_ci } 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_ci void ConvertUsesToOperand(const InstructionOperand& op, 6691cb0ef41Sopenharmony_ci const InstructionOperand& spill_op); 6701cb0ef41Sopenharmony_ci void SetUseHints(int register_index); 6711cb0ef41Sopenharmony_ci void UnsetUseHints() { SetUseHints(kUnassignedRegister); } 6721cb0ef41Sopenharmony_ci void ResetCurrentHintPosition() { current_hint_position_ = first_pos_; } 6731cb0ef41Sopenharmony_ci 6741cb0ef41Sopenharmony_ci void Print(const RegisterConfiguration* config, bool with_children) const; 6751cb0ef41Sopenharmony_ci void Print(bool with_children) const; 6761cb0ef41Sopenharmony_ci 6771cb0ef41Sopenharmony_ci void set_bundle(LiveRangeBundle* bundle) { bundle_ = bundle; } 6781cb0ef41Sopenharmony_ci LiveRangeBundle* get_bundle() const { return bundle_; } 6791cb0ef41Sopenharmony_ci bool RegisterFromBundle(int* hint) const; 6801cb0ef41Sopenharmony_ci void UpdateBundleRegister(int reg) const; 6811cb0ef41Sopenharmony_ci 6821cb0ef41Sopenharmony_ci private: 6831cb0ef41Sopenharmony_ci friend class TopLevelLiveRange; 6841cb0ef41Sopenharmony_ci friend Zone; 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ci explicit LiveRange(int relative_id, MachineRepresentation rep, 6871cb0ef41Sopenharmony_ci TopLevelLiveRange* top_level); 6881cb0ef41Sopenharmony_ci 6891cb0ef41Sopenharmony_ci void UpdateParentForAllChildren(TopLevelLiveRange* new_top_level); 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_ci void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); } 6921cb0ef41Sopenharmony_ci 6931cb0ef41Sopenharmony_ci UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 6941cb0ef41Sopenharmony_ci void AdvanceLastProcessedMarker(UseInterval* to_start_of, 6951cb0ef41Sopenharmony_ci LifetimePosition but_not_past) const; 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci void VerifyPositions() const; 6981cb0ef41Sopenharmony_ci void VerifyIntervals() const; 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci using SpilledField = base::BitField<bool, 0, 1>; 7011cb0ef41Sopenharmony_ci // Bits (1,7[ are used by TopLevelLiveRange. 7021cb0ef41Sopenharmony_ci using AssignedRegisterField = base::BitField<int32_t, 7, 6>; 7031cb0ef41Sopenharmony_ci using RepresentationField = base::BitField<MachineRepresentation, 13, 8>; 7041cb0ef41Sopenharmony_ci using RecombineField = base::BitField<bool, 21, 1>; 7051cb0ef41Sopenharmony_ci using ControlFlowRegisterHint = base::BitField<uint8_t, 22, 6>; 7061cb0ef41Sopenharmony_ci // Bits 28-31 are used by TopLevelLiveRange. 7071cb0ef41Sopenharmony_ci 7081cb0ef41Sopenharmony_ci // Unique among children of the same virtual register. 7091cb0ef41Sopenharmony_ci int relative_id_; 7101cb0ef41Sopenharmony_ci uint32_t bits_; 7111cb0ef41Sopenharmony_ci UseInterval* last_interval_; 7121cb0ef41Sopenharmony_ci UseInterval* first_interval_; 7131cb0ef41Sopenharmony_ci UsePosition* first_pos_; 7141cb0ef41Sopenharmony_ci TopLevelLiveRange* top_level_; 7151cb0ef41Sopenharmony_ci LiveRange* next_; 7161cb0ef41Sopenharmony_ci // This is used as a cache, it doesn't affect correctness. 7171cb0ef41Sopenharmony_ci mutable UseInterval* current_interval_; 7181cb0ef41Sopenharmony_ci // This is used as a cache, it doesn't affect correctness. 7191cb0ef41Sopenharmony_ci mutable UsePosition* last_processed_use_; 7201cb0ef41Sopenharmony_ci // This is used as a cache in BuildLiveRanges and during register allocation. 7211cb0ef41Sopenharmony_ci UsePosition* current_hint_position_; 7221cb0ef41Sopenharmony_ci LiveRangeBundle* bundle_ = nullptr; 7231cb0ef41Sopenharmony_ci // Next interval start, relative to the current linear scan position. 7241cb0ef41Sopenharmony_ci LifetimePosition next_start_; 7251cb0ef41Sopenharmony_ci}; 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_cistruct LiveRangeOrdering { 7281cb0ef41Sopenharmony_ci bool operator()(const LiveRange* left, const LiveRange* right) const { 7291cb0ef41Sopenharmony_ci return left->Start() < right->Start(); 7301cb0ef41Sopenharmony_ci } 7311cb0ef41Sopenharmony_ci}; 7321cb0ef41Sopenharmony_ciclass LiveRangeBundle : public ZoneObject { 7331cb0ef41Sopenharmony_ci public: 7341cb0ef41Sopenharmony_ci void MergeSpillRangesAndClear(); 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ci int id() { return id_; } 7371cb0ef41Sopenharmony_ci 7381cb0ef41Sopenharmony_ci int reg() { return reg_; } 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_ci void set_reg(int reg) { 7411cb0ef41Sopenharmony_ci DCHECK_EQ(reg_, kUnassignedRegister); 7421cb0ef41Sopenharmony_ci reg_ = reg; 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci 7451cb0ef41Sopenharmony_ci private: 7461cb0ef41Sopenharmony_ci friend class BundleBuilder; 7471cb0ef41Sopenharmony_ci friend Zone; 7481cb0ef41Sopenharmony_ci 7491cb0ef41Sopenharmony_ci // Representation of the non-empty interval [start,end[. 7501cb0ef41Sopenharmony_ci class Range { 7511cb0ef41Sopenharmony_ci public: 7521cb0ef41Sopenharmony_ci Range(int s, int e) : start(s), end(e) {} 7531cb0ef41Sopenharmony_ci Range(LifetimePosition s, LifetimePosition e) 7541cb0ef41Sopenharmony_ci : start(s.value()), end(e.value()) {} 7551cb0ef41Sopenharmony_ci int start; 7561cb0ef41Sopenharmony_ci int end; 7571cb0ef41Sopenharmony_ci }; 7581cb0ef41Sopenharmony_ci 7591cb0ef41Sopenharmony_ci struct RangeOrdering { 7601cb0ef41Sopenharmony_ci bool operator()(const Range left, const Range right) const { 7611cb0ef41Sopenharmony_ci return left.start < right.start; 7621cb0ef41Sopenharmony_ci } 7631cb0ef41Sopenharmony_ci }; 7641cb0ef41Sopenharmony_ci bool UsesOverlap(UseInterval* interval) { 7651cb0ef41Sopenharmony_ci auto use = uses_.begin(); 7661cb0ef41Sopenharmony_ci while (interval != nullptr && use != uses_.end()) { 7671cb0ef41Sopenharmony_ci if (use->end <= interval->start().value()) { 7681cb0ef41Sopenharmony_ci ++use; 7691cb0ef41Sopenharmony_ci } else if (interval->end().value() <= use->start) { 7701cb0ef41Sopenharmony_ci interval = interval->next(); 7711cb0ef41Sopenharmony_ci } else { 7721cb0ef41Sopenharmony_ci return true; 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci } 7751cb0ef41Sopenharmony_ci return false; 7761cb0ef41Sopenharmony_ci } 7771cb0ef41Sopenharmony_ci void InsertUses(UseInterval* interval) { 7781cb0ef41Sopenharmony_ci while (interval != nullptr) { 7791cb0ef41Sopenharmony_ci auto done = uses_.insert({interval->start(), interval->end()}); 7801cb0ef41Sopenharmony_ci USE(done); 7811cb0ef41Sopenharmony_ci DCHECK_EQ(done.second, 1); 7821cb0ef41Sopenharmony_ci interval = interval->next(); 7831cb0ef41Sopenharmony_ci } 7841cb0ef41Sopenharmony_ci } 7851cb0ef41Sopenharmony_ci explicit LiveRangeBundle(Zone* zone, int id) 7861cb0ef41Sopenharmony_ci : ranges_(zone), uses_(zone), id_(id) {} 7871cb0ef41Sopenharmony_ci 7881cb0ef41Sopenharmony_ci bool TryAddRange(LiveRange* range); 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci // If merging is possible, merge either {lhs} into {rhs} or {rhs} into 7911cb0ef41Sopenharmony_ci // {lhs}, clear the source and return the result. Otherwise return nullptr. 7921cb0ef41Sopenharmony_ci static LiveRangeBundle* TryMerge(LiveRangeBundle* lhs, LiveRangeBundle* rhs, 7931cb0ef41Sopenharmony_ci bool trace_alloc); 7941cb0ef41Sopenharmony_ci 7951cb0ef41Sopenharmony_ci ZoneSet<LiveRange*, LiveRangeOrdering> ranges_; 7961cb0ef41Sopenharmony_ci ZoneSet<Range, RangeOrdering> uses_; 7971cb0ef41Sopenharmony_ci int id_; 7981cb0ef41Sopenharmony_ci int reg_ = kUnassignedRegister; 7991cb0ef41Sopenharmony_ci}; 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { 8021cb0ef41Sopenharmony_ci public: 8031cb0ef41Sopenharmony_ci explicit TopLevelLiveRange(int vreg, MachineRepresentation rep); 8041cb0ef41Sopenharmony_ci TopLevelLiveRange(const TopLevelLiveRange&) = delete; 8051cb0ef41Sopenharmony_ci TopLevelLiveRange& operator=(const TopLevelLiveRange&) = delete; 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci int spill_start_index() const { return spill_start_index_; } 8081cb0ef41Sopenharmony_ci 8091cb0ef41Sopenharmony_ci bool IsFixed() const { return vreg_ < 0; } 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_ci bool IsDeferredFixed() const { return DeferredFixedField::decode(bits_); } 8121cb0ef41Sopenharmony_ci void set_deferred_fixed() { bits_ = DeferredFixedField::update(bits_, true); } 8131cb0ef41Sopenharmony_ci bool is_phi() const { return IsPhiField::decode(bits_); } 8141cb0ef41Sopenharmony_ci void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); } 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ci bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); } 8171cb0ef41Sopenharmony_ci bool is_loop_phi() const { return is_phi() && !is_non_loop_phi(); } 8181cb0ef41Sopenharmony_ci void set_is_non_loop_phi(bool value) { 8191cb0ef41Sopenharmony_ci bits_ = IsNonLoopPhiField::update(bits_, value); 8201cb0ef41Sopenharmony_ci } 8211cb0ef41Sopenharmony_ci bool SpillAtLoopHeaderNotBeneficial() const { 8221cb0ef41Sopenharmony_ci return SpillAtLoopHeaderNotBeneficialField::decode(bits_); 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci void set_spilling_at_loop_header_not_beneficial() { 8251cb0ef41Sopenharmony_ci bits_ = SpillAtLoopHeaderNotBeneficialField::update(bits_, true); 8261cb0ef41Sopenharmony_ci } 8271cb0ef41Sopenharmony_ci 8281cb0ef41Sopenharmony_ci enum SlotUseKind { kNoSlotUse, kDeferredSlotUse, kGeneralSlotUse }; 8291cb0ef41Sopenharmony_ci 8301cb0ef41Sopenharmony_ci bool has_slot_use() const { 8311cb0ef41Sopenharmony_ci return slot_use_kind() > SlotUseKind::kNoSlotUse; 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci bool has_non_deferred_slot_use() const { 8351cb0ef41Sopenharmony_ci return slot_use_kind() == SlotUseKind::kGeneralSlotUse; 8361cb0ef41Sopenharmony_ci } 8371cb0ef41Sopenharmony_ci 8381cb0ef41Sopenharmony_ci void reset_slot_use() { 8391cb0ef41Sopenharmony_ci bits_ = HasSlotUseField::update(bits_, SlotUseKind::kNoSlotUse); 8401cb0ef41Sopenharmony_ci } 8411cb0ef41Sopenharmony_ci void register_slot_use(SlotUseKind value) { 8421cb0ef41Sopenharmony_ci bits_ = HasSlotUseField::update(bits_, std::max(slot_use_kind(), value)); 8431cb0ef41Sopenharmony_ci } 8441cb0ef41Sopenharmony_ci SlotUseKind slot_use_kind() const { return HasSlotUseField::decode(bits_); } 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_ci // Add a new interval or a new use position to this live range. 8471cb0ef41Sopenharmony_ci void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone, 8481cb0ef41Sopenharmony_ci bool trace_alloc); 8491cb0ef41Sopenharmony_ci void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone, 8501cb0ef41Sopenharmony_ci bool trace_alloc); 8511cb0ef41Sopenharmony_ci void AddUsePosition(UsePosition* pos, bool trace_alloc); 8521cb0ef41Sopenharmony_ci 8531cb0ef41Sopenharmony_ci // Shorten the most recently added interval by setting a new start. 8541cb0ef41Sopenharmony_ci void ShortenTo(LifetimePosition start, bool trace_alloc); 8551cb0ef41Sopenharmony_ci 8561cb0ef41Sopenharmony_ci // Spill range management. 8571cb0ef41Sopenharmony_ci void SetSpillRange(SpillRange* spill_range); 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ci // Encodes whether a range is also available from a memory location: 8601cb0ef41Sopenharmony_ci // kNoSpillType: not availble in memory location. 8611cb0ef41Sopenharmony_ci // kSpillOperand: computed in a memory location at range start. 8621cb0ef41Sopenharmony_ci // kSpillRange: copied (spilled) to memory location at the definition, 8631cb0ef41Sopenharmony_ci // or at the beginning of some later blocks if 8641cb0ef41Sopenharmony_ci // LateSpillingSelected() is true. 8651cb0ef41Sopenharmony_ci // kDeferredSpillRange: copied (spilled) to memory location at entry 8661cb0ef41Sopenharmony_ci // to deferred blocks that have a use from memory. 8671cb0ef41Sopenharmony_ci // 8681cb0ef41Sopenharmony_ci // Ranges either start out at kSpillOperand, which is also their final 8691cb0ef41Sopenharmony_ci // state, or kNoSpillType. When spilled only in deferred code, a range 8701cb0ef41Sopenharmony_ci // ends up with kDeferredSpillRange, while when spilled in regular code, 8711cb0ef41Sopenharmony_ci // a range will be tagged as kSpillRange. 8721cb0ef41Sopenharmony_ci enum class SpillType { 8731cb0ef41Sopenharmony_ci kNoSpillType, 8741cb0ef41Sopenharmony_ci kSpillOperand, 8751cb0ef41Sopenharmony_ci kSpillRange, 8761cb0ef41Sopenharmony_ci kDeferredSpillRange 8771cb0ef41Sopenharmony_ci }; 8781cb0ef41Sopenharmony_ci void set_spill_type(SpillType value) { 8791cb0ef41Sopenharmony_ci bits_ = SpillTypeField::update(bits_, value); 8801cb0ef41Sopenharmony_ci } 8811cb0ef41Sopenharmony_ci SpillType spill_type() const { return SpillTypeField::decode(bits_); } 8821cb0ef41Sopenharmony_ci InstructionOperand* GetSpillOperand() const { 8831cb0ef41Sopenharmony_ci DCHECK_EQ(SpillType::kSpillOperand, spill_type()); 8841cb0ef41Sopenharmony_ci return spill_operand_; 8851cb0ef41Sopenharmony_ci } 8861cb0ef41Sopenharmony_ci 8871cb0ef41Sopenharmony_ci SpillRange* GetAllocatedSpillRange() const { 8881cb0ef41Sopenharmony_ci DCHECK_NE(SpillType::kSpillOperand, spill_type()); 8891cb0ef41Sopenharmony_ci return spill_range_; 8901cb0ef41Sopenharmony_ci } 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ci SpillRange* GetSpillRange() const { 8931cb0ef41Sopenharmony_ci DCHECK_GE(spill_type(), SpillType::kSpillRange); 8941cb0ef41Sopenharmony_ci return spill_range_; 8951cb0ef41Sopenharmony_ci } 8961cb0ef41Sopenharmony_ci bool HasNoSpillType() const { 8971cb0ef41Sopenharmony_ci return spill_type() == SpillType::kNoSpillType; 8981cb0ef41Sopenharmony_ci } 8991cb0ef41Sopenharmony_ci bool HasSpillOperand() const { 9001cb0ef41Sopenharmony_ci return spill_type() == SpillType::kSpillOperand; 9011cb0ef41Sopenharmony_ci } 9021cb0ef41Sopenharmony_ci bool HasSpillRange() const { return spill_type() >= SpillType::kSpillRange; } 9031cb0ef41Sopenharmony_ci bool HasGeneralSpillRange() const { 9041cb0ef41Sopenharmony_ci return spill_type() == SpillType::kSpillRange; 9051cb0ef41Sopenharmony_ci } 9061cb0ef41Sopenharmony_ci AllocatedOperand GetSpillRangeOperand() const; 9071cb0ef41Sopenharmony_ci 9081cb0ef41Sopenharmony_ci void RecordSpillLocation(Zone* zone, int gap_index, 9091cb0ef41Sopenharmony_ci InstructionOperand* operand); 9101cb0ef41Sopenharmony_ci void SetSpillOperand(InstructionOperand* operand); 9111cb0ef41Sopenharmony_ci void SetSpillStartIndex(int start) { 9121cb0ef41Sopenharmony_ci spill_start_index_ = std::min(start, spill_start_index_); 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_ci // Omits any moves from spill_move_insertion_locations_ that can be skipped. 9161cb0ef41Sopenharmony_ci void FilterSpillMoves(TopTierRegisterAllocationData* data, 9171cb0ef41Sopenharmony_ci const InstructionOperand& operand); 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_ci // Writes all moves from spill_move_insertion_locations_ to the schedule. 9201cb0ef41Sopenharmony_ci void CommitSpillMoves(TopTierRegisterAllocationData* data, 9211cb0ef41Sopenharmony_ci const InstructionOperand& operand); 9221cb0ef41Sopenharmony_ci 9231cb0ef41Sopenharmony_ci // If all the children of this range are spilled in deferred blocks, and if 9241cb0ef41Sopenharmony_ci // for any non-spilled child with a use position requiring a slot, that range 9251cb0ef41Sopenharmony_ci // is contained in a deferred block, mark the range as 9261cb0ef41Sopenharmony_ci // IsSpilledOnlyInDeferredBlocks, so that we avoid spilling at definition, 9271cb0ef41Sopenharmony_ci // and instead let the LiveRangeConnector perform the spills within the 9281cb0ef41Sopenharmony_ci // deferred blocks. If so, we insert here spills for non-spilled ranges 9291cb0ef41Sopenharmony_ci // with slot use positions. 9301cb0ef41Sopenharmony_ci void TreatAsSpilledInDeferredBlock(Zone* zone, int total_block_count) { 9311cb0ef41Sopenharmony_ci spill_start_index_ = -1; 9321cb0ef41Sopenharmony_ci spilled_in_deferred_blocks_ = true; 9331cb0ef41Sopenharmony_ci spill_move_insertion_locations_ = nullptr; 9341cb0ef41Sopenharmony_ci list_of_blocks_requiring_spill_operands_ = 9351cb0ef41Sopenharmony_ci zone->New<BitVector>(total_block_count, zone); 9361cb0ef41Sopenharmony_ci } 9371cb0ef41Sopenharmony_ci 9381cb0ef41Sopenharmony_ci // Updates internal data structures to reflect that this range is not 9391cb0ef41Sopenharmony_ci // spilled at definition but instead spilled in some blocks only. 9401cb0ef41Sopenharmony_ci void TransitionRangeToDeferredSpill(Zone* zone, int total_block_count) { 9411cb0ef41Sopenharmony_ci spill_start_index_ = -1; 9421cb0ef41Sopenharmony_ci spill_move_insertion_locations_ = nullptr; 9431cb0ef41Sopenharmony_ci list_of_blocks_requiring_spill_operands_ = 9441cb0ef41Sopenharmony_ci zone->New<BitVector>(total_block_count, zone); 9451cb0ef41Sopenharmony_ci } 9461cb0ef41Sopenharmony_ci 9471cb0ef41Sopenharmony_ci // Promotes this range to spill at definition if it was marked for spilling 9481cb0ef41Sopenharmony_ci // in deferred blocks before. 9491cb0ef41Sopenharmony_ci void TransitionRangeToSpillAtDefinition() { 9501cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(spill_move_insertion_locations_); 9511cb0ef41Sopenharmony_ci if (spill_type() == SpillType::kDeferredSpillRange) { 9521cb0ef41Sopenharmony_ci set_spill_type(SpillType::kSpillRange); 9531cb0ef41Sopenharmony_ci } 9541cb0ef41Sopenharmony_ci } 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_ci bool MayRequireSpillRange() const { 9571cb0ef41Sopenharmony_ci return !HasSpillOperand() && spill_range_ == nullptr; 9581cb0ef41Sopenharmony_ci } 9591cb0ef41Sopenharmony_ci void UpdateSpillRangePostMerge(TopLevelLiveRange* merged); 9601cb0ef41Sopenharmony_ci int vreg() const { return vreg_; } 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_ci void Verify() const; 9631cb0ef41Sopenharmony_ci void VerifyChildrenInOrder() const; 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_ci // Returns the LiveRange covering the given position, or nullptr if no such 9661cb0ef41Sopenharmony_ci // range exists. Uses a linear search through child ranges. The range at the 9671cb0ef41Sopenharmony_ci // previously requested position is cached, so this function will be very fast 9681cb0ef41Sopenharmony_ci // if you call it with a non-decreasing sequence of positions. 9691cb0ef41Sopenharmony_ci LiveRange* GetChildCovers(LifetimePosition pos); 9701cb0ef41Sopenharmony_ci 9711cb0ef41Sopenharmony_ci int GetNextChildId() { return ++last_child_id_; } 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci int GetMaxChildCount() const { return last_child_id_ + 1; } 9741cb0ef41Sopenharmony_ci 9751cb0ef41Sopenharmony_ci bool IsSpilledOnlyInDeferredBlocks( 9761cb0ef41Sopenharmony_ci const TopTierRegisterAllocationData* data) const { 9771cb0ef41Sopenharmony_ci return spill_type() == SpillType::kDeferredSpillRange; 9781cb0ef41Sopenharmony_ci } 9791cb0ef41Sopenharmony_ci 9801cb0ef41Sopenharmony_ci struct SpillMoveInsertionList; 9811cb0ef41Sopenharmony_ci 9821cb0ef41Sopenharmony_ci SpillMoveInsertionList* GetSpillMoveInsertionLocations( 9831cb0ef41Sopenharmony_ci const TopTierRegisterAllocationData* data) const { 9841cb0ef41Sopenharmony_ci DCHECK(!IsSpilledOnlyInDeferredBlocks(data)); 9851cb0ef41Sopenharmony_ci return spill_move_insertion_locations_; 9861cb0ef41Sopenharmony_ci } 9871cb0ef41Sopenharmony_ci 9881cb0ef41Sopenharmony_ci void MarkHasPreassignedSlot() { has_preassigned_slot_ = true; } 9891cb0ef41Sopenharmony_ci bool has_preassigned_slot() const { return has_preassigned_slot_; } 9901cb0ef41Sopenharmony_ci 9911cb0ef41Sopenharmony_ci // Late spilling refers to spilling at places after the definition. These 9921cb0ef41Sopenharmony_ci // spills are guaranteed to cover at least all of the sub-ranges where the 9931cb0ef41Sopenharmony_ci // register allocator chose to evict the value from a register. 9941cb0ef41Sopenharmony_ci void SetLateSpillingSelected(bool late_spilling_selected) { 9951cb0ef41Sopenharmony_ci DCHECK(spill_type() == SpillType::kSpillRange); 9961cb0ef41Sopenharmony_ci SpillRangeMode new_mode = late_spilling_selected 9971cb0ef41Sopenharmony_ci ? SpillRangeMode::kSpillLater 9981cb0ef41Sopenharmony_ci : SpillRangeMode::kSpillAtDefinition; 9991cb0ef41Sopenharmony_ci // A single TopLevelLiveRange should never be used in both modes. 10001cb0ef41Sopenharmony_ci DCHECK(SpillRangeModeField::decode(bits_) == SpillRangeMode::kNotSet || 10011cb0ef41Sopenharmony_ci SpillRangeModeField::decode(bits_) == new_mode); 10021cb0ef41Sopenharmony_ci bits_ = SpillRangeModeField::update(bits_, new_mode); 10031cb0ef41Sopenharmony_ci } 10041cb0ef41Sopenharmony_ci bool LateSpillingSelected() const { 10051cb0ef41Sopenharmony_ci // Nobody should be reading this value until it's been decided. 10061cb0ef41Sopenharmony_ci DCHECK_IMPLIES(HasGeneralSpillRange(), SpillRangeModeField::decode(bits_) != 10071cb0ef41Sopenharmony_ci SpillRangeMode::kNotSet); 10081cb0ef41Sopenharmony_ci return SpillRangeModeField::decode(bits_) == SpillRangeMode::kSpillLater; 10091cb0ef41Sopenharmony_ci } 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_ci void AddBlockRequiringSpillOperand( 10121cb0ef41Sopenharmony_ci RpoNumber block_id, const TopTierRegisterAllocationData* data) { 10131cb0ef41Sopenharmony_ci DCHECK(IsSpilledOnlyInDeferredBlocks(data)); 10141cb0ef41Sopenharmony_ci GetListOfBlocksRequiringSpillOperands(data)->Add(block_id.ToInt()); 10151cb0ef41Sopenharmony_ci } 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci BitVector* GetListOfBlocksRequiringSpillOperands( 10181cb0ef41Sopenharmony_ci const TopTierRegisterAllocationData* data) const { 10191cb0ef41Sopenharmony_ci DCHECK(IsSpilledOnlyInDeferredBlocks(data)); 10201cb0ef41Sopenharmony_ci return list_of_blocks_requiring_spill_operands_; 10211cb0ef41Sopenharmony_ci } 10221cb0ef41Sopenharmony_ci 10231cb0ef41Sopenharmony_ci private: 10241cb0ef41Sopenharmony_ci friend class LiveRange; 10251cb0ef41Sopenharmony_ci 10261cb0ef41Sopenharmony_ci // If spill type is kSpillRange, then this value indicates whether we've 10271cb0ef41Sopenharmony_ci // chosen to spill at the definition or at some later points. 10281cb0ef41Sopenharmony_ci enum class SpillRangeMode : uint8_t { 10291cb0ef41Sopenharmony_ci kNotSet, 10301cb0ef41Sopenharmony_ci kSpillAtDefinition, 10311cb0ef41Sopenharmony_ci kSpillLater, 10321cb0ef41Sopenharmony_ci }; 10331cb0ef41Sopenharmony_ci 10341cb0ef41Sopenharmony_ci using HasSlotUseField = base::BitField<SlotUseKind, 1, 2>; 10351cb0ef41Sopenharmony_ci using IsPhiField = base::BitField<bool, 3, 1>; 10361cb0ef41Sopenharmony_ci using IsNonLoopPhiField = base::BitField<bool, 4, 1>; 10371cb0ef41Sopenharmony_ci using SpillTypeField = base::BitField<SpillType, 5, 2>; 10381cb0ef41Sopenharmony_ci using DeferredFixedField = base::BitField<bool, 28, 1>; 10391cb0ef41Sopenharmony_ci using SpillAtLoopHeaderNotBeneficialField = base::BitField<bool, 29, 1>; 10401cb0ef41Sopenharmony_ci using SpillRangeModeField = base::BitField<SpillRangeMode, 30, 2>; 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_ci int vreg_; 10431cb0ef41Sopenharmony_ci int last_child_id_; 10441cb0ef41Sopenharmony_ci union { 10451cb0ef41Sopenharmony_ci // Correct value determined by spill_type() 10461cb0ef41Sopenharmony_ci InstructionOperand* spill_operand_; 10471cb0ef41Sopenharmony_ci SpillRange* spill_range_; 10481cb0ef41Sopenharmony_ci }; 10491cb0ef41Sopenharmony_ci 10501cb0ef41Sopenharmony_ci union { 10511cb0ef41Sopenharmony_ci SpillMoveInsertionList* spill_move_insertion_locations_; 10521cb0ef41Sopenharmony_ci BitVector* list_of_blocks_requiring_spill_operands_; 10531cb0ef41Sopenharmony_ci }; 10541cb0ef41Sopenharmony_ci 10551cb0ef41Sopenharmony_ci // TODO(mtrofin): generalize spilling after definition, currently specialized 10561cb0ef41Sopenharmony_ci // just for spill in a single deferred block. 10571cb0ef41Sopenharmony_ci bool spilled_in_deferred_blocks_; 10581cb0ef41Sopenharmony_ci bool has_preassigned_slot_; 10591cb0ef41Sopenharmony_ci 10601cb0ef41Sopenharmony_ci int spill_start_index_; 10611cb0ef41Sopenharmony_ci UsePosition* last_pos_; 10621cb0ef41Sopenharmony_ci LiveRange* last_child_covers_; 10631cb0ef41Sopenharmony_ci}; 10641cb0ef41Sopenharmony_ci 10651cb0ef41Sopenharmony_cistruct PrintableLiveRange { 10661cb0ef41Sopenharmony_ci const RegisterConfiguration* register_configuration_; 10671cb0ef41Sopenharmony_ci const LiveRange* range_; 10681cb0ef41Sopenharmony_ci}; 10691cb0ef41Sopenharmony_ci 10701cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, 10711cb0ef41Sopenharmony_ci const PrintableLiveRange& printable_range); 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ciclass SpillRange final : public ZoneObject { 10741cb0ef41Sopenharmony_ci public: 10751cb0ef41Sopenharmony_ci static const int kUnassignedSlot = -1; 10761cb0ef41Sopenharmony_ci SpillRange(TopLevelLiveRange* range, Zone* zone); 10771cb0ef41Sopenharmony_ci SpillRange(const SpillRange&) = delete; 10781cb0ef41Sopenharmony_ci SpillRange& operator=(const SpillRange&) = delete; 10791cb0ef41Sopenharmony_ci 10801cb0ef41Sopenharmony_ci UseInterval* interval() const { return use_interval_; } 10811cb0ef41Sopenharmony_ci 10821cb0ef41Sopenharmony_ci bool IsEmpty() const { return live_ranges_.empty(); } 10831cb0ef41Sopenharmony_ci bool TryMerge(SpillRange* other); 10841cb0ef41Sopenharmony_ci bool HasSlot() const { return assigned_slot_ != kUnassignedSlot; } 10851cb0ef41Sopenharmony_ci 10861cb0ef41Sopenharmony_ci void set_assigned_slot(int index) { 10871cb0ef41Sopenharmony_ci DCHECK_EQ(kUnassignedSlot, assigned_slot_); 10881cb0ef41Sopenharmony_ci assigned_slot_ = index; 10891cb0ef41Sopenharmony_ci } 10901cb0ef41Sopenharmony_ci int assigned_slot() { 10911cb0ef41Sopenharmony_ci DCHECK_NE(kUnassignedSlot, assigned_slot_); 10921cb0ef41Sopenharmony_ci return assigned_slot_; 10931cb0ef41Sopenharmony_ci } 10941cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& live_ranges() const { 10951cb0ef41Sopenharmony_ci return live_ranges_; 10961cb0ef41Sopenharmony_ci } 10971cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; } 10981cb0ef41Sopenharmony_ci // Spill slots can be 4, 8, or 16 bytes wide. 10991cb0ef41Sopenharmony_ci int byte_width() const { return byte_width_; } 11001cb0ef41Sopenharmony_ci void Print() const; 11011cb0ef41Sopenharmony_ci 11021cb0ef41Sopenharmony_ci private: 11031cb0ef41Sopenharmony_ci LifetimePosition End() const { return end_position_; } 11041cb0ef41Sopenharmony_ci bool IsIntersectingWith(SpillRange* other) const; 11051cb0ef41Sopenharmony_ci // Merge intervals, making sure the use intervals are sorted 11061cb0ef41Sopenharmony_ci void MergeDisjointIntervals(UseInterval* other); 11071cb0ef41Sopenharmony_ci 11081cb0ef41Sopenharmony_ci ZoneVector<TopLevelLiveRange*> live_ranges_; 11091cb0ef41Sopenharmony_ci UseInterval* use_interval_; 11101cb0ef41Sopenharmony_ci LifetimePosition end_position_; 11111cb0ef41Sopenharmony_ci int assigned_slot_; 11121cb0ef41Sopenharmony_ci int byte_width_; 11131cb0ef41Sopenharmony_ci}; 11141cb0ef41Sopenharmony_ci 11151cb0ef41Sopenharmony_ciclass LiveRangeBound { 11161cb0ef41Sopenharmony_ci public: 11171cb0ef41Sopenharmony_ci explicit LiveRangeBound(LiveRange* range, bool skip) 11181cb0ef41Sopenharmony_ci : range_(range), start_(range->Start()), end_(range->End()), skip_(skip) { 11191cb0ef41Sopenharmony_ci DCHECK(!range->IsEmpty()); 11201cb0ef41Sopenharmony_ci } 11211cb0ef41Sopenharmony_ci LiveRangeBound(const LiveRangeBound&) = delete; 11221cb0ef41Sopenharmony_ci LiveRangeBound& operator=(const LiveRangeBound&) = delete; 11231cb0ef41Sopenharmony_ci 11241cb0ef41Sopenharmony_ci bool CanCover(LifetimePosition position) { 11251cb0ef41Sopenharmony_ci return start_ <= position && position < end_; 11261cb0ef41Sopenharmony_ci } 11271cb0ef41Sopenharmony_ci 11281cb0ef41Sopenharmony_ci LiveRange* const range_; 11291cb0ef41Sopenharmony_ci const LifetimePosition start_; 11301cb0ef41Sopenharmony_ci const LifetimePosition end_; 11311cb0ef41Sopenharmony_ci const bool skip_; 11321cb0ef41Sopenharmony_ci}; 11331cb0ef41Sopenharmony_ci 11341cb0ef41Sopenharmony_cistruct FindResult { 11351cb0ef41Sopenharmony_ci LiveRange* cur_cover_; 11361cb0ef41Sopenharmony_ci LiveRange* pred_cover_; 11371cb0ef41Sopenharmony_ci}; 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_ciclass LiveRangeBoundArray { 11401cb0ef41Sopenharmony_ci public: 11411cb0ef41Sopenharmony_ci LiveRangeBoundArray() : length_(0), start_(nullptr) {} 11421cb0ef41Sopenharmony_ci LiveRangeBoundArray(const LiveRangeBoundArray&) = delete; 11431cb0ef41Sopenharmony_ci LiveRangeBoundArray& operator=(const LiveRangeBoundArray&) = delete; 11441cb0ef41Sopenharmony_ci 11451cb0ef41Sopenharmony_ci bool ShouldInitialize() { return start_ == nullptr; } 11461cb0ef41Sopenharmony_ci void Initialize(Zone* zone, TopLevelLiveRange* range); 11471cb0ef41Sopenharmony_ci LiveRangeBound* Find(const LifetimePosition position) const; 11481cb0ef41Sopenharmony_ci LiveRangeBound* FindPred(const InstructionBlock* pred); 11491cb0ef41Sopenharmony_ci LiveRangeBound* FindSucc(const InstructionBlock* succ); 11501cb0ef41Sopenharmony_ci bool FindConnectableSubranges(const InstructionBlock* block, 11511cb0ef41Sopenharmony_ci const InstructionBlock* pred, 11521cb0ef41Sopenharmony_ci FindResult* result) const; 11531cb0ef41Sopenharmony_ci 11541cb0ef41Sopenharmony_ci private: 11551cb0ef41Sopenharmony_ci size_t length_; 11561cb0ef41Sopenharmony_ci LiveRangeBound* start_; 11571cb0ef41Sopenharmony_ci}; 11581cb0ef41Sopenharmony_ci 11591cb0ef41Sopenharmony_ciclass LiveRangeFinder { 11601cb0ef41Sopenharmony_ci public: 11611cb0ef41Sopenharmony_ci explicit LiveRangeFinder(const TopTierRegisterAllocationData* data, 11621cb0ef41Sopenharmony_ci Zone* zone); 11631cb0ef41Sopenharmony_ci LiveRangeFinder(const LiveRangeFinder&) = delete; 11641cb0ef41Sopenharmony_ci LiveRangeFinder& operator=(const LiveRangeFinder&) = delete; 11651cb0ef41Sopenharmony_ci 11661cb0ef41Sopenharmony_ci LiveRangeBoundArray* ArrayFor(int operand_index); 11671cb0ef41Sopenharmony_ci 11681cb0ef41Sopenharmony_ci private: 11691cb0ef41Sopenharmony_ci const TopTierRegisterAllocationData* const data_; 11701cb0ef41Sopenharmony_ci const int bounds_length_; 11711cb0ef41Sopenharmony_ci LiveRangeBoundArray* const bounds_; 11721cb0ef41Sopenharmony_ci Zone* const zone_; 11731cb0ef41Sopenharmony_ci}; 11741cb0ef41Sopenharmony_ci 11751cb0ef41Sopenharmony_ciclass ConstraintBuilder final : public ZoneObject { 11761cb0ef41Sopenharmony_ci public: 11771cb0ef41Sopenharmony_ci explicit ConstraintBuilder(TopTierRegisterAllocationData* data); 11781cb0ef41Sopenharmony_ci ConstraintBuilder(const ConstraintBuilder&) = delete; 11791cb0ef41Sopenharmony_ci ConstraintBuilder& operator=(const ConstraintBuilder&) = delete; 11801cb0ef41Sopenharmony_ci 11811cb0ef41Sopenharmony_ci // Phase 1 : insert moves to account for fixed register operands. 11821cb0ef41Sopenharmony_ci void MeetRegisterConstraints(); 11831cb0ef41Sopenharmony_ci 11841cb0ef41Sopenharmony_ci // Phase 2: deconstruct SSA by inserting moves in successors and the headers 11851cb0ef41Sopenharmony_ci // of blocks containing phis. 11861cb0ef41Sopenharmony_ci void ResolvePhis(); 11871cb0ef41Sopenharmony_ci 11881cb0ef41Sopenharmony_ci private: 11891cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 11901cb0ef41Sopenharmony_ci InstructionSequence* code() const { return data()->code(); } 11911cb0ef41Sopenharmony_ci Zone* allocation_zone() const { return data()->allocation_zone(); } 11921cb0ef41Sopenharmony_ci 11931cb0ef41Sopenharmony_ci InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, 11941cb0ef41Sopenharmony_ci bool is_tagged, bool is_input); 11951cb0ef41Sopenharmony_ci void MeetRegisterConstraints(const InstructionBlock* block); 11961cb0ef41Sopenharmony_ci void MeetConstraintsBefore(int index); 11971cb0ef41Sopenharmony_ci void MeetConstraintsAfter(int index); 11981cb0ef41Sopenharmony_ci void MeetRegisterConstraintsForLastInstructionInBlock( 11991cb0ef41Sopenharmony_ci const InstructionBlock* block); 12001cb0ef41Sopenharmony_ci void ResolvePhis(const InstructionBlock* block); 12011cb0ef41Sopenharmony_ci 12021cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* const data_; 12031cb0ef41Sopenharmony_ci}; 12041cb0ef41Sopenharmony_ci 12051cb0ef41Sopenharmony_ciclass LiveRangeBuilder final : public ZoneObject { 12061cb0ef41Sopenharmony_ci public: 12071cb0ef41Sopenharmony_ci explicit LiveRangeBuilder(TopTierRegisterAllocationData* data, 12081cb0ef41Sopenharmony_ci Zone* local_zone); 12091cb0ef41Sopenharmony_ci LiveRangeBuilder(const LiveRangeBuilder&) = delete; 12101cb0ef41Sopenharmony_ci LiveRangeBuilder& operator=(const LiveRangeBuilder&) = delete; 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_ci // Phase 3: compute liveness of all virtual register. 12131cb0ef41Sopenharmony_ci void BuildLiveRanges(); 12141cb0ef41Sopenharmony_ci static BitVector* ComputeLiveOut(const InstructionBlock* block, 12151cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data); 12161cb0ef41Sopenharmony_ci 12171cb0ef41Sopenharmony_ci private: 12181cb0ef41Sopenharmony_ci using SpillMode = TopTierRegisterAllocationData::SpillMode; 12191cb0ef41Sopenharmony_ci static constexpr int kNumberOfFixedRangesPerRegister = 12201cb0ef41Sopenharmony_ci TopTierRegisterAllocationData::kNumberOfFixedRangesPerRegister; 12211cb0ef41Sopenharmony_ci 12221cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 12231cb0ef41Sopenharmony_ci InstructionSequence* code() const { return data()->code(); } 12241cb0ef41Sopenharmony_ci Zone* allocation_zone() const { return data()->allocation_zone(); } 12251cb0ef41Sopenharmony_ci Zone* code_zone() const { return code()->zone(); } 12261cb0ef41Sopenharmony_ci const RegisterConfiguration* config() const { return data()->config(); } 12271cb0ef41Sopenharmony_ci ZoneVector<BitVector*>& live_in_sets() const { 12281cb0ef41Sopenharmony_ci return data()->live_in_sets(); 12291cb0ef41Sopenharmony_ci } 12301cb0ef41Sopenharmony_ci 12311cb0ef41Sopenharmony_ci // Verification. 12321cb0ef41Sopenharmony_ci void Verify() const; 12331cb0ef41Sopenharmony_ci bool IntervalStartsAtBlockBoundary(const UseInterval* interval) const; 12341cb0ef41Sopenharmony_ci bool IntervalPredecessorsCoveredByRange(const UseInterval* interval, 12351cb0ef41Sopenharmony_ci const TopLevelLiveRange* range) const; 12361cb0ef41Sopenharmony_ci bool NextIntervalStartsInDifferentBlocks(const UseInterval* interval) const; 12371cb0ef41Sopenharmony_ci 12381cb0ef41Sopenharmony_ci // Liveness analysis support. 12391cb0ef41Sopenharmony_ci void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); 12401cb0ef41Sopenharmony_ci void ProcessInstructions(const InstructionBlock* block, BitVector* live); 12411cb0ef41Sopenharmony_ci void ProcessPhis(const InstructionBlock* block, BitVector* live); 12421cb0ef41Sopenharmony_ci void ProcessLoopHeader(const InstructionBlock* block, BitVector* live); 12431cb0ef41Sopenharmony_ci 12441cb0ef41Sopenharmony_ci static int FixedLiveRangeID(int index) { return -index - 1; } 12451cb0ef41Sopenharmony_ci int FixedFPLiveRangeID(int index, MachineRepresentation rep); 12461cb0ef41Sopenharmony_ci TopLevelLiveRange* FixedLiveRangeFor(int index, SpillMode spill_mode); 12471cb0ef41Sopenharmony_ci TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep, 12481cb0ef41Sopenharmony_ci SpillMode spill_mode); 12491cb0ef41Sopenharmony_ci TopLevelLiveRange* FixedSIMD128LiveRangeFor(int index, SpillMode spill_mode); 12501cb0ef41Sopenharmony_ci 12511cb0ef41Sopenharmony_ci void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos); 12521cb0ef41Sopenharmony_ci void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos); 12531cb0ef41Sopenharmony_ci 12541cb0ef41Sopenharmony_ci UsePosition* NewUsePosition(LifetimePosition pos, InstructionOperand* operand, 12551cb0ef41Sopenharmony_ci void* hint, UsePositionHintType hint_type); 12561cb0ef41Sopenharmony_ci UsePosition* NewUsePosition(LifetimePosition pos) { 12571cb0ef41Sopenharmony_ci return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone); 12581cb0ef41Sopenharmony_ci } 12591cb0ef41Sopenharmony_ci TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand, 12601cb0ef41Sopenharmony_ci SpillMode spill_mode); 12611cb0ef41Sopenharmony_ci // Helper methods for building intervals. 12621cb0ef41Sopenharmony_ci UsePosition* Define(LifetimePosition position, InstructionOperand* operand, 12631cb0ef41Sopenharmony_ci void* hint, UsePositionHintType hint_type, 12641cb0ef41Sopenharmony_ci SpillMode spill_mode); 12651cb0ef41Sopenharmony_ci void Define(LifetimePosition position, InstructionOperand* operand, 12661cb0ef41Sopenharmony_ci SpillMode spill_mode) { 12671cb0ef41Sopenharmony_ci Define(position, operand, nullptr, UsePositionHintType::kNone, spill_mode); 12681cb0ef41Sopenharmony_ci } 12691cb0ef41Sopenharmony_ci UsePosition* Use(LifetimePosition block_start, LifetimePosition position, 12701cb0ef41Sopenharmony_ci InstructionOperand* operand, void* hint, 12711cb0ef41Sopenharmony_ci UsePositionHintType hint_type, SpillMode spill_mode); 12721cb0ef41Sopenharmony_ci void Use(LifetimePosition block_start, LifetimePosition position, 12731cb0ef41Sopenharmony_ci InstructionOperand* operand, SpillMode spill_mode) { 12741cb0ef41Sopenharmony_ci Use(block_start, position, operand, nullptr, UsePositionHintType::kNone, 12751cb0ef41Sopenharmony_ci spill_mode); 12761cb0ef41Sopenharmony_ci } 12771cb0ef41Sopenharmony_ci SpillMode SpillModeForBlock(const InstructionBlock* block) const { 12781cb0ef41Sopenharmony_ci return block->IsDeferred() ? SpillMode::kSpillDeferred 12791cb0ef41Sopenharmony_ci : SpillMode::kSpillAtDefinition; 12801cb0ef41Sopenharmony_ci } 12811cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* const data_; 12821cb0ef41Sopenharmony_ci ZoneMap<InstructionOperand*, UsePosition*> phi_hints_; 12831cb0ef41Sopenharmony_ci}; 12841cb0ef41Sopenharmony_ci 12851cb0ef41Sopenharmony_ciclass BundleBuilder final : public ZoneObject { 12861cb0ef41Sopenharmony_ci public: 12871cb0ef41Sopenharmony_ci explicit BundleBuilder(TopTierRegisterAllocationData* data) : data_(data) {} 12881cb0ef41Sopenharmony_ci 12891cb0ef41Sopenharmony_ci void BuildBundles(); 12901cb0ef41Sopenharmony_ci 12911cb0ef41Sopenharmony_ci private: 12921cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 12931cb0ef41Sopenharmony_ci InstructionSequence* code() const { return data_->code(); } 12941cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data_; 12951cb0ef41Sopenharmony_ci int next_bundle_id_ = 0; 12961cb0ef41Sopenharmony_ci}; 12971cb0ef41Sopenharmony_ci 12981cb0ef41Sopenharmony_ciclass RegisterAllocator : public ZoneObject { 12991cb0ef41Sopenharmony_ci public: 13001cb0ef41Sopenharmony_ci RegisterAllocator(TopTierRegisterAllocationData* data, RegisterKind kind); 13011cb0ef41Sopenharmony_ci RegisterAllocator(const RegisterAllocator&) = delete; 13021cb0ef41Sopenharmony_ci RegisterAllocator& operator=(const RegisterAllocator&) = delete; 13031cb0ef41Sopenharmony_ci 13041cb0ef41Sopenharmony_ci protected: 13051cb0ef41Sopenharmony_ci using SpillMode = TopTierRegisterAllocationData::SpillMode; 13061cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 13071cb0ef41Sopenharmony_ci InstructionSequence* code() const { return data()->code(); } 13081cb0ef41Sopenharmony_ci RegisterKind mode() const { return mode_; } 13091cb0ef41Sopenharmony_ci int num_registers() const { return num_registers_; } 13101cb0ef41Sopenharmony_ci int num_allocatable_registers() const { return num_allocatable_registers_; } 13111cb0ef41Sopenharmony_ci const int* allocatable_register_codes() const { 13121cb0ef41Sopenharmony_ci return allocatable_register_codes_; 13131cb0ef41Sopenharmony_ci } 13141cb0ef41Sopenharmony_ci // Returns true iff. we must check float register aliasing. 13151cb0ef41Sopenharmony_ci bool check_fp_aliasing() const { return check_fp_aliasing_; } 13161cb0ef41Sopenharmony_ci 13171cb0ef41Sopenharmony_ci // TODO(mtrofin): explain why splitting in gap START is always OK. 13181cb0ef41Sopenharmony_ci LifetimePosition GetSplitPositionForInstruction(const LiveRange* range, 13191cb0ef41Sopenharmony_ci int instruction_index); 13201cb0ef41Sopenharmony_ci 13211cb0ef41Sopenharmony_ci Zone* allocation_zone() const { return data()->allocation_zone(); } 13221cb0ef41Sopenharmony_ci 13231cb0ef41Sopenharmony_ci // Find the optimal split for ranges defined by a memory operand, e.g. 13241cb0ef41Sopenharmony_ci // constants or function parameters passed on the stack. 13251cb0ef41Sopenharmony_ci void SplitAndSpillRangesDefinedByMemoryOperand(); 13261cb0ef41Sopenharmony_ci 13271cb0ef41Sopenharmony_ci // Split the given range at the given position. 13281cb0ef41Sopenharmony_ci // If range starts at or after the given position then the 13291cb0ef41Sopenharmony_ci // original range is returned. 13301cb0ef41Sopenharmony_ci // Otherwise returns the live range that starts at pos and contains 13311cb0ef41Sopenharmony_ci // all uses from the original range that follow pos. Uses at pos will 13321cb0ef41Sopenharmony_ci // still be owned by the original range after splitting. 13331cb0ef41Sopenharmony_ci LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); 13341cb0ef41Sopenharmony_ci 13351cb0ef41Sopenharmony_ci bool CanProcessRange(LiveRange* range) const { 13361cb0ef41Sopenharmony_ci return range != nullptr && !range->IsEmpty() && range->kind() == mode(); 13371cb0ef41Sopenharmony_ci } 13381cb0ef41Sopenharmony_ci 13391cb0ef41Sopenharmony_ci // Split the given range in a position from the interval [start, end]. 13401cb0ef41Sopenharmony_ci LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, 13411cb0ef41Sopenharmony_ci LifetimePosition end); 13421cb0ef41Sopenharmony_ci 13431cb0ef41Sopenharmony_ci // Find a lifetime position in the interval [start, end] which 13441cb0ef41Sopenharmony_ci // is optimal for splitting: it is either header of the outermost 13451cb0ef41Sopenharmony_ci // loop covered by this interval or the latest possible position. 13461cb0ef41Sopenharmony_ci LifetimePosition FindOptimalSplitPos(LifetimePosition start, 13471cb0ef41Sopenharmony_ci LifetimePosition end); 13481cb0ef41Sopenharmony_ci 13491cb0ef41Sopenharmony_ci void Spill(LiveRange* range, SpillMode spill_mode); 13501cb0ef41Sopenharmony_ci 13511cb0ef41Sopenharmony_ci // If we are trying to spill a range inside the loop try to 13521cb0ef41Sopenharmony_ci // hoist spill position out to the point just before the loop. 13531cb0ef41Sopenharmony_ci LifetimePosition FindOptimalSpillingPos(LiveRange* range, 13541cb0ef41Sopenharmony_ci LifetimePosition pos, 13551cb0ef41Sopenharmony_ci SpillMode spill_mode, 13561cb0ef41Sopenharmony_ci LiveRange** begin_spill_out); 13571cb0ef41Sopenharmony_ci 13581cb0ef41Sopenharmony_ci const ZoneVector<TopLevelLiveRange*>& GetFixedRegisters() const; 13591cb0ef41Sopenharmony_ci const char* RegisterName(int allocation_index) const; 13601cb0ef41Sopenharmony_ci 13611cb0ef41Sopenharmony_ci private: 13621cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* const data_; 13631cb0ef41Sopenharmony_ci const RegisterKind mode_; 13641cb0ef41Sopenharmony_ci const int num_registers_; 13651cb0ef41Sopenharmony_ci int num_allocatable_registers_; 13661cb0ef41Sopenharmony_ci const int* allocatable_register_codes_; 13671cb0ef41Sopenharmony_ci bool check_fp_aliasing_; 13681cb0ef41Sopenharmony_ci 13691cb0ef41Sopenharmony_ci private: 13701cb0ef41Sopenharmony_ci bool no_combining_; 13711cb0ef41Sopenharmony_ci}; 13721cb0ef41Sopenharmony_ci 13731cb0ef41Sopenharmony_ciclass LinearScanAllocator final : public RegisterAllocator { 13741cb0ef41Sopenharmony_ci public: 13751cb0ef41Sopenharmony_ci LinearScanAllocator(TopTierRegisterAllocationData* data, RegisterKind kind, 13761cb0ef41Sopenharmony_ci Zone* local_zone); 13771cb0ef41Sopenharmony_ci LinearScanAllocator(const LinearScanAllocator&) = delete; 13781cb0ef41Sopenharmony_ci LinearScanAllocator& operator=(const LinearScanAllocator&) = delete; 13791cb0ef41Sopenharmony_ci 13801cb0ef41Sopenharmony_ci // Phase 4: compute register assignments. 13811cb0ef41Sopenharmony_ci void AllocateRegisters(); 13821cb0ef41Sopenharmony_ci 13831cb0ef41Sopenharmony_ci private: 13841cb0ef41Sopenharmony_ci struct RangeWithRegister { 13851cb0ef41Sopenharmony_ci TopLevelLiveRange* range; 13861cb0ef41Sopenharmony_ci int expected_register; 13871cb0ef41Sopenharmony_ci struct Hash { 13881cb0ef41Sopenharmony_ci size_t operator()(const RangeWithRegister item) const { 13891cb0ef41Sopenharmony_ci return item.range->vreg(); 13901cb0ef41Sopenharmony_ci } 13911cb0ef41Sopenharmony_ci }; 13921cb0ef41Sopenharmony_ci struct Equals { 13931cb0ef41Sopenharmony_ci bool operator()(const RangeWithRegister one, 13941cb0ef41Sopenharmony_ci const RangeWithRegister two) const { 13951cb0ef41Sopenharmony_ci return one.range == two.range; 13961cb0ef41Sopenharmony_ci } 13971cb0ef41Sopenharmony_ci }; 13981cb0ef41Sopenharmony_ci 13991cb0ef41Sopenharmony_ci explicit RangeWithRegister(LiveRange* a_range) 14001cb0ef41Sopenharmony_ci : range(a_range->TopLevel()), 14011cb0ef41Sopenharmony_ci expected_register(a_range->assigned_register()) {} 14021cb0ef41Sopenharmony_ci RangeWithRegister(TopLevelLiveRange* toplevel, int reg) 14031cb0ef41Sopenharmony_ci : range(toplevel), expected_register(reg) {} 14041cb0ef41Sopenharmony_ci }; 14051cb0ef41Sopenharmony_ci 14061cb0ef41Sopenharmony_ci using RangeWithRegisterSet = 14071cb0ef41Sopenharmony_ci ZoneUnorderedSet<RangeWithRegister, RangeWithRegister::Hash, 14081cb0ef41Sopenharmony_ci RangeWithRegister::Equals>; 14091cb0ef41Sopenharmony_ci 14101cb0ef41Sopenharmony_ci void MaybeSpillPreviousRanges(LiveRange* begin_range, 14111cb0ef41Sopenharmony_ci LifetimePosition begin_pos, 14121cb0ef41Sopenharmony_ci LiveRange* end_range); 14131cb0ef41Sopenharmony_ci void MaybeUndoPreviousSplit(LiveRange* range); 14141cb0ef41Sopenharmony_ci void SpillNotLiveRanges(RangeWithRegisterSet* to_be_live, 14151cb0ef41Sopenharmony_ci LifetimePosition position, SpillMode spill_mode); 14161cb0ef41Sopenharmony_ci LiveRange* AssignRegisterOnReload(LiveRange* range, int reg); 14171cb0ef41Sopenharmony_ci void ReloadLiveRanges(RangeWithRegisterSet const& to_be_live, 14181cb0ef41Sopenharmony_ci LifetimePosition position); 14191cb0ef41Sopenharmony_ci 14201cb0ef41Sopenharmony_ci void UpdateDeferredFixedRanges(SpillMode spill_mode, InstructionBlock* block); 14211cb0ef41Sopenharmony_ci bool BlockIsDeferredOrImmediatePredecessorIsNotDeferred( 14221cb0ef41Sopenharmony_ci const InstructionBlock* block); 14231cb0ef41Sopenharmony_ci bool HasNonDeferredPredecessor(InstructionBlock* block); 14241cb0ef41Sopenharmony_ci 14251cb0ef41Sopenharmony_ci struct UnhandledLiveRangeOrdering { 14261cb0ef41Sopenharmony_ci bool operator()(const LiveRange* a, const LiveRange* b) const { 14271cb0ef41Sopenharmony_ci return a->ShouldBeAllocatedBefore(b); 14281cb0ef41Sopenharmony_ci } 14291cb0ef41Sopenharmony_ci }; 14301cb0ef41Sopenharmony_ci 14311cb0ef41Sopenharmony_ci struct InactiveLiveRangeOrdering { 14321cb0ef41Sopenharmony_ci bool operator()(const LiveRange* a, const LiveRange* b) const { 14331cb0ef41Sopenharmony_ci return a->NextStart() < b->NextStart(); 14341cb0ef41Sopenharmony_ci } 14351cb0ef41Sopenharmony_ci }; 14361cb0ef41Sopenharmony_ci 14371cb0ef41Sopenharmony_ci using UnhandledLiveRangeQueue = 14381cb0ef41Sopenharmony_ci ZoneMultiset<LiveRange*, UnhandledLiveRangeOrdering>; 14391cb0ef41Sopenharmony_ci using InactiveLiveRangeQueue = 14401cb0ef41Sopenharmony_ci ZoneMultiset<LiveRange*, InactiveLiveRangeOrdering>; 14411cb0ef41Sopenharmony_ci UnhandledLiveRangeQueue& unhandled_live_ranges() { 14421cb0ef41Sopenharmony_ci return unhandled_live_ranges_; 14431cb0ef41Sopenharmony_ci } 14441cb0ef41Sopenharmony_ci ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } 14451cb0ef41Sopenharmony_ci InactiveLiveRangeQueue& inactive_live_ranges(int reg) { 14461cb0ef41Sopenharmony_ci return inactive_live_ranges_[reg]; 14471cb0ef41Sopenharmony_ci } 14481cb0ef41Sopenharmony_ci 14491cb0ef41Sopenharmony_ci void SetLiveRangeAssignedRegister(LiveRange* range, int reg); 14501cb0ef41Sopenharmony_ci 14511cb0ef41Sopenharmony_ci // Helper methods for updating the life range lists. 14521cb0ef41Sopenharmony_ci void AddToActive(LiveRange* range); 14531cb0ef41Sopenharmony_ci void AddToInactive(LiveRange* range); 14541cb0ef41Sopenharmony_ci void AddToUnhandled(LiveRange* range); 14551cb0ef41Sopenharmony_ci ZoneVector<LiveRange*>::iterator ActiveToHandled( 14561cb0ef41Sopenharmony_ci ZoneVector<LiveRange*>::iterator it); 14571cb0ef41Sopenharmony_ci ZoneVector<LiveRange*>::iterator ActiveToInactive( 14581cb0ef41Sopenharmony_ci ZoneVector<LiveRange*>::iterator it, LifetimePosition position); 14591cb0ef41Sopenharmony_ci InactiveLiveRangeQueue::iterator InactiveToHandled( 14601cb0ef41Sopenharmony_ci InactiveLiveRangeQueue::iterator it); 14611cb0ef41Sopenharmony_ci InactiveLiveRangeQueue::iterator InactiveToActive( 14621cb0ef41Sopenharmony_ci InactiveLiveRangeQueue::iterator it, LifetimePosition position); 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_ci void ForwardStateTo(LifetimePosition position); 14651cb0ef41Sopenharmony_ci 14661cb0ef41Sopenharmony_ci int LastDeferredInstructionIndex(InstructionBlock* start); 14671cb0ef41Sopenharmony_ci 14681cb0ef41Sopenharmony_ci // Helper methods for choosing state after control flow events. 14691cb0ef41Sopenharmony_ci 14701cb0ef41Sopenharmony_ci bool ConsiderBlockForControlFlow(InstructionBlock* current_block, 14711cb0ef41Sopenharmony_ci RpoNumber predecessor); 14721cb0ef41Sopenharmony_ci RpoNumber ChooseOneOfTwoPredecessorStates(InstructionBlock* current_block, 14731cb0ef41Sopenharmony_ci LifetimePosition boundary); 14741cb0ef41Sopenharmony_ci bool CheckConflict(MachineRepresentation rep, int reg, 14751cb0ef41Sopenharmony_ci RangeWithRegisterSet* to_be_live); 14761cb0ef41Sopenharmony_ci void ComputeStateFromManyPredecessors(InstructionBlock* current_block, 14771cb0ef41Sopenharmony_ci RangeWithRegisterSet* to_be_live); 14781cb0ef41Sopenharmony_ci 14791cb0ef41Sopenharmony_ci // Helper methods for allocating registers. 14801cb0ef41Sopenharmony_ci bool TryReuseSpillForPhi(TopLevelLiveRange* range); 14811cb0ef41Sopenharmony_ci int PickRegisterThatIsAvailableLongest( 14821cb0ef41Sopenharmony_ci LiveRange* current, int hint_reg, 14831cb0ef41Sopenharmony_ci const base::Vector<LifetimePosition>& free_until_pos); 14841cb0ef41Sopenharmony_ci bool TryAllocateFreeReg(LiveRange* range, 14851cb0ef41Sopenharmony_ci const base::Vector<LifetimePosition>& free_until_pos); 14861cb0ef41Sopenharmony_ci bool TryAllocatePreferredReg( 14871cb0ef41Sopenharmony_ci LiveRange* range, const base::Vector<LifetimePosition>& free_until_pos); 14881cb0ef41Sopenharmony_ci void GetFPRegisterSet(MachineRepresentation rep, int* num_regs, 14891cb0ef41Sopenharmony_ci int* num_codes, const int** codes) const; 14901cb0ef41Sopenharmony_ci void GetSIMD128RegisterSet(int* num_regs, int* num_codes, 14911cb0ef41Sopenharmony_ci const int** codes) const; 14921cb0ef41Sopenharmony_ci void FindFreeRegistersForRange(LiveRange* range, 14931cb0ef41Sopenharmony_ci base::Vector<LifetimePosition> free_until_pos); 14941cb0ef41Sopenharmony_ci void ProcessCurrentRange(LiveRange* current, SpillMode spill_mode); 14951cb0ef41Sopenharmony_ci void AllocateBlockedReg(LiveRange* range, SpillMode spill_mode); 14961cb0ef41Sopenharmony_ci 14971cb0ef41Sopenharmony_ci // Spill the given life range after position pos. 14981cb0ef41Sopenharmony_ci void SpillAfter(LiveRange* range, LifetimePosition pos, SpillMode spill_mode); 14991cb0ef41Sopenharmony_ci 15001cb0ef41Sopenharmony_ci // Spill the given life range after position [start] and up to position [end]. 15011cb0ef41Sopenharmony_ci void SpillBetween(LiveRange* range, LifetimePosition start, 15021cb0ef41Sopenharmony_ci LifetimePosition end, SpillMode spill_mode); 15031cb0ef41Sopenharmony_ci 15041cb0ef41Sopenharmony_ci // Spill the given life range after position [start] and up to position [end]. 15051cb0ef41Sopenharmony_ci // Range is guaranteed to be spilled at least until position [until]. 15061cb0ef41Sopenharmony_ci void SpillBetweenUntil(LiveRange* range, LifetimePosition start, 15071cb0ef41Sopenharmony_ci LifetimePosition until, LifetimePosition end, 15081cb0ef41Sopenharmony_ci SpillMode spill_mode); 15091cb0ef41Sopenharmony_ci void SplitAndSpillIntersecting(LiveRange* range, SpillMode spill_mode); 15101cb0ef41Sopenharmony_ci 15111cb0ef41Sopenharmony_ci void PrintRangeRow(std::ostream& os, const TopLevelLiveRange* toplevel); 15121cb0ef41Sopenharmony_ci 15131cb0ef41Sopenharmony_ci void PrintRangeOverview(); 15141cb0ef41Sopenharmony_ci 15151cb0ef41Sopenharmony_ci UnhandledLiveRangeQueue unhandled_live_ranges_; 15161cb0ef41Sopenharmony_ci ZoneVector<LiveRange*> active_live_ranges_; 15171cb0ef41Sopenharmony_ci ZoneVector<InactiveLiveRangeQueue> inactive_live_ranges_; 15181cb0ef41Sopenharmony_ci 15191cb0ef41Sopenharmony_ci // Approximate at what position the set of ranges will change next. 15201cb0ef41Sopenharmony_ci // Used to avoid scanning for updates even if none are present. 15211cb0ef41Sopenharmony_ci LifetimePosition next_active_ranges_change_; 15221cb0ef41Sopenharmony_ci LifetimePosition next_inactive_ranges_change_; 15231cb0ef41Sopenharmony_ci 15241cb0ef41Sopenharmony_ci#ifdef DEBUG 15251cb0ef41Sopenharmony_ci LifetimePosition allocation_finger_; 15261cb0ef41Sopenharmony_ci#endif 15271cb0ef41Sopenharmony_ci}; 15281cb0ef41Sopenharmony_ci 15291cb0ef41Sopenharmony_ciclass OperandAssigner final : public ZoneObject { 15301cb0ef41Sopenharmony_ci public: 15311cb0ef41Sopenharmony_ci explicit OperandAssigner(TopTierRegisterAllocationData* data); 15321cb0ef41Sopenharmony_ci OperandAssigner(const OperandAssigner&) = delete; 15331cb0ef41Sopenharmony_ci OperandAssigner& operator=(const OperandAssigner&) = delete; 15341cb0ef41Sopenharmony_ci 15351cb0ef41Sopenharmony_ci // Phase 5: final decision on spilling mode. 15361cb0ef41Sopenharmony_ci void DecideSpillingMode(); 15371cb0ef41Sopenharmony_ci 15381cb0ef41Sopenharmony_ci // Phase 6: assign spill splots. 15391cb0ef41Sopenharmony_ci void AssignSpillSlots(); 15401cb0ef41Sopenharmony_ci 15411cb0ef41Sopenharmony_ci // Phase 7: commit assignment. 15421cb0ef41Sopenharmony_ci void CommitAssignment(); 15431cb0ef41Sopenharmony_ci 15441cb0ef41Sopenharmony_ci private: 15451cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 15461cb0ef41Sopenharmony_ci 15471cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* const data_; 15481cb0ef41Sopenharmony_ci}; 15491cb0ef41Sopenharmony_ci 15501cb0ef41Sopenharmony_ciclass ReferenceMapPopulator final : public ZoneObject { 15511cb0ef41Sopenharmony_ci public: 15521cb0ef41Sopenharmony_ci explicit ReferenceMapPopulator(TopTierRegisterAllocationData* data); 15531cb0ef41Sopenharmony_ci ReferenceMapPopulator(const ReferenceMapPopulator&) = delete; 15541cb0ef41Sopenharmony_ci ReferenceMapPopulator& operator=(const ReferenceMapPopulator&) = delete; 15551cb0ef41Sopenharmony_ci 15561cb0ef41Sopenharmony_ci // Phase 10: compute values for pointer maps. 15571cb0ef41Sopenharmony_ci void PopulateReferenceMaps(); 15581cb0ef41Sopenharmony_ci 15591cb0ef41Sopenharmony_ci private: 15601cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 15611cb0ef41Sopenharmony_ci 15621cb0ef41Sopenharmony_ci bool SafePointsAreInOrder() const; 15631cb0ef41Sopenharmony_ci 15641cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* const data_; 15651cb0ef41Sopenharmony_ci}; 15661cb0ef41Sopenharmony_ci 15671cb0ef41Sopenharmony_ciclass LiveRangeBoundArray; 15681cb0ef41Sopenharmony_ci// Insert moves of the form 15691cb0ef41Sopenharmony_ci// 15701cb0ef41Sopenharmony_ci// Operand(child_(k+1)) = Operand(child_k) 15711cb0ef41Sopenharmony_ci// 15721cb0ef41Sopenharmony_ci// where child_k and child_(k+1) are consecutive children of a range (so 15731cb0ef41Sopenharmony_ci// child_k->next() == child_(k+1)), and Operand(...) refers to the 15741cb0ef41Sopenharmony_ci// assigned operand, be it a register or a slot. 15751cb0ef41Sopenharmony_ciclass LiveRangeConnector final : public ZoneObject { 15761cb0ef41Sopenharmony_ci public: 15771cb0ef41Sopenharmony_ci explicit LiveRangeConnector(TopTierRegisterAllocationData* data); 15781cb0ef41Sopenharmony_ci LiveRangeConnector(const LiveRangeConnector&) = delete; 15791cb0ef41Sopenharmony_ci LiveRangeConnector& operator=(const LiveRangeConnector&) = delete; 15801cb0ef41Sopenharmony_ci 15811cb0ef41Sopenharmony_ci // Phase 8: reconnect split ranges with moves, when the control flow 15821cb0ef41Sopenharmony_ci // between the ranges is trivial (no branches). 15831cb0ef41Sopenharmony_ci void ConnectRanges(Zone* local_zone); 15841cb0ef41Sopenharmony_ci 15851cb0ef41Sopenharmony_ci // Phase 9: insert moves to connect ranges across basic blocks, when the 15861cb0ef41Sopenharmony_ci // control flow between them cannot be trivially resolved, such as joining 15871cb0ef41Sopenharmony_ci // branches. Also determines whether to spill at the definition or later, and 15881cb0ef41Sopenharmony_ci // adds spill moves to the gaps in the schedule. 15891cb0ef41Sopenharmony_ci void ResolveControlFlow(Zone* local_zone); 15901cb0ef41Sopenharmony_ci 15911cb0ef41Sopenharmony_ci private: 15921cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* data() const { return data_; } 15931cb0ef41Sopenharmony_ci InstructionSequence* code() const { return data()->code(); } 15941cb0ef41Sopenharmony_ci Zone* code_zone() const { return code()->zone(); } 15951cb0ef41Sopenharmony_ci 15961cb0ef41Sopenharmony_ci bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; 15971cb0ef41Sopenharmony_ci 15981cb0ef41Sopenharmony_ci int ResolveControlFlow(const InstructionBlock* block, 15991cb0ef41Sopenharmony_ci const InstructionOperand& cur_op, 16001cb0ef41Sopenharmony_ci const InstructionBlock* pred, 16011cb0ef41Sopenharmony_ci const InstructionOperand& pred_op); 16021cb0ef41Sopenharmony_ci 16031cb0ef41Sopenharmony_ci void CommitSpillsInDeferredBlocks(TopLevelLiveRange* range, 16041cb0ef41Sopenharmony_ci LiveRangeBoundArray* array, 16051cb0ef41Sopenharmony_ci Zone* temp_zone); 16061cb0ef41Sopenharmony_ci 16071cb0ef41Sopenharmony_ci TopTierRegisterAllocationData* const data_; 16081cb0ef41Sopenharmony_ci}; 16091cb0ef41Sopenharmony_ci 16101cb0ef41Sopenharmony_ci} // namespace compiler 16111cb0ef41Sopenharmony_ci} // namespace internal 16121cb0ef41Sopenharmony_ci} // namespace v8 16131cb0ef41Sopenharmony_ci 16141cb0ef41Sopenharmony_ci#endif // V8_COMPILER_BACKEND_REGISTER_ALLOCATOR_H_ 1615