11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <cstddef> 81cb0ef41Sopenharmony_ci#include <iomanip> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/codegen/aligned-slot-allocator.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/register-configuration.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/source-position.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/graph.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h" 191cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h" 201cb0ef41Sopenharmony_ci#include "src/execution/frames.h" 211cb0ef41Sopenharmony_ci#include "src/execution/isolate-utils-inl.h" 221cb0ef41Sopenharmony_ci#include "src/objects/instance-type-inl.h" 231cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h" 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 261cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h" 271cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_cinamespace v8 { 301cb0ef41Sopenharmony_cinamespace internal { 311cb0ef41Sopenharmony_cinamespace compiler { 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ciconst RegisterConfiguration* (*GetRegConfig)() = RegisterConfiguration::Default; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciFlagsCondition CommuteFlagsCondition(FlagsCondition condition) { 361cb0ef41Sopenharmony_ci switch (condition) { 371cb0ef41Sopenharmony_ci case kSignedLessThan: 381cb0ef41Sopenharmony_ci return kSignedGreaterThan; 391cb0ef41Sopenharmony_ci case kSignedGreaterThanOrEqual: 401cb0ef41Sopenharmony_ci return kSignedLessThanOrEqual; 411cb0ef41Sopenharmony_ci case kSignedLessThanOrEqual: 421cb0ef41Sopenharmony_ci return kSignedGreaterThanOrEqual; 431cb0ef41Sopenharmony_ci case kSignedGreaterThan: 441cb0ef41Sopenharmony_ci return kSignedLessThan; 451cb0ef41Sopenharmony_ci case kUnsignedLessThan: 461cb0ef41Sopenharmony_ci return kUnsignedGreaterThan; 471cb0ef41Sopenharmony_ci case kUnsignedGreaterThanOrEqual: 481cb0ef41Sopenharmony_ci return kUnsignedLessThanOrEqual; 491cb0ef41Sopenharmony_ci case kUnsignedLessThanOrEqual: 501cb0ef41Sopenharmony_ci return kUnsignedGreaterThanOrEqual; 511cb0ef41Sopenharmony_ci case kUnsignedGreaterThan: 521cb0ef41Sopenharmony_ci return kUnsignedLessThan; 531cb0ef41Sopenharmony_ci case kFloatLessThanOrUnordered: 541cb0ef41Sopenharmony_ci return kFloatGreaterThanOrUnordered; 551cb0ef41Sopenharmony_ci case kFloatGreaterThanOrEqual: 561cb0ef41Sopenharmony_ci return kFloatLessThanOrEqual; 571cb0ef41Sopenharmony_ci case kFloatLessThanOrEqual: 581cb0ef41Sopenharmony_ci return kFloatGreaterThanOrEqual; 591cb0ef41Sopenharmony_ci case kFloatGreaterThanOrUnordered: 601cb0ef41Sopenharmony_ci return kFloatLessThanOrUnordered; 611cb0ef41Sopenharmony_ci case kFloatLessThan: 621cb0ef41Sopenharmony_ci return kFloatGreaterThan; 631cb0ef41Sopenharmony_ci case kFloatGreaterThanOrEqualOrUnordered: 641cb0ef41Sopenharmony_ci return kFloatLessThanOrEqualOrUnordered; 651cb0ef41Sopenharmony_ci case kFloatLessThanOrEqualOrUnordered: 661cb0ef41Sopenharmony_ci return kFloatGreaterThanOrEqualOrUnordered; 671cb0ef41Sopenharmony_ci case kFloatGreaterThan: 681cb0ef41Sopenharmony_ci return kFloatLessThan; 691cb0ef41Sopenharmony_ci case kPositiveOrZero: 701cb0ef41Sopenharmony_ci case kNegative: 711cb0ef41Sopenharmony_ci UNREACHABLE(); 721cb0ef41Sopenharmony_ci case kEqual: 731cb0ef41Sopenharmony_ci case kNotEqual: 741cb0ef41Sopenharmony_ci case kOverflow: 751cb0ef41Sopenharmony_ci case kNotOverflow: 761cb0ef41Sopenharmony_ci case kUnorderedEqual: 771cb0ef41Sopenharmony_ci case kUnorderedNotEqual: 781cb0ef41Sopenharmony_ci return condition; 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci UNREACHABLE(); 811cb0ef41Sopenharmony_ci} 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_cibool InstructionOperand::InterferesWith(const InstructionOperand& other) const { 841cb0ef41Sopenharmony_ci const bool kCombineFPAliasing = kFPAliasing == AliasingKind::kCombine && 851cb0ef41Sopenharmony_ci this->IsFPLocationOperand() && 861cb0ef41Sopenharmony_ci other.IsFPLocationOperand(); 871cb0ef41Sopenharmony_ci const bool kComplexS128SlotAliasing = 881cb0ef41Sopenharmony_ci (this->IsSimd128StackSlot() && other.IsAnyStackSlot()) || 891cb0ef41Sopenharmony_ci (other.IsSimd128StackSlot() && this->IsAnyStackSlot()); 901cb0ef41Sopenharmony_ci if (!kCombineFPAliasing && !kComplexS128SlotAliasing) { 911cb0ef41Sopenharmony_ci return EqualsCanonicalized(other); 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci const LocationOperand& loc = *LocationOperand::cast(this); 941cb0ef41Sopenharmony_ci const LocationOperand& other_loc = LocationOperand::cast(other); 951cb0ef41Sopenharmony_ci LocationOperand::LocationKind kind = loc.location_kind(); 961cb0ef41Sopenharmony_ci LocationOperand::LocationKind other_kind = other_loc.location_kind(); 971cb0ef41Sopenharmony_ci if (kind != other_kind) return false; 981cb0ef41Sopenharmony_ci MachineRepresentation rep = loc.representation(); 991cb0ef41Sopenharmony_ci MachineRepresentation other_rep = other_loc.representation(); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci if (kCombineFPAliasing && !kComplexS128SlotAliasing) { 1021cb0ef41Sopenharmony_ci if (rep == other_rep) return EqualsCanonicalized(other); 1031cb0ef41Sopenharmony_ci if (kind == LocationOperand::REGISTER) { 1041cb0ef41Sopenharmony_ci // FP register-register interference. 1051cb0ef41Sopenharmony_ci return GetRegConfig()->AreAliases(rep, loc.register_code(), other_rep, 1061cb0ef41Sopenharmony_ci other_loc.register_code()); 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci // Complex multi-slot operand interference: 1111cb0ef41Sopenharmony_ci // - slots of different FP reps can alias because the gap resolver may break a 1121cb0ef41Sopenharmony_ci // move into 2 or 4 equivalent smaller moves, 1131cb0ef41Sopenharmony_ci // - stack layout can be rearranged for tail calls 1141cb0ef41Sopenharmony_ci DCHECK_EQ(LocationOperand::STACK_SLOT, kind); 1151cb0ef41Sopenharmony_ci int index_hi = loc.index(); 1161cb0ef41Sopenharmony_ci int index_lo = 1171cb0ef41Sopenharmony_ci index_hi - 1181cb0ef41Sopenharmony_ci AlignedSlotAllocator::NumSlotsForWidth(ElementSizeInBytes(rep)) + 1; 1191cb0ef41Sopenharmony_ci int other_index_hi = other_loc.index(); 1201cb0ef41Sopenharmony_ci int other_index_lo = 1211cb0ef41Sopenharmony_ci other_index_hi - 1221cb0ef41Sopenharmony_ci AlignedSlotAllocator::NumSlotsForWidth(ElementSizeInBytes(other_rep)) + 1; 1231cb0ef41Sopenharmony_ci return other_index_hi >= index_lo && index_hi >= other_index_lo; 1241cb0ef41Sopenharmony_ci} 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_cibool LocationOperand::IsCompatible(LocationOperand* op) { 1271cb0ef41Sopenharmony_ci if (IsRegister() || IsStackSlot()) { 1281cb0ef41Sopenharmony_ci return op->IsRegister() || op->IsStackSlot(); 1291cb0ef41Sopenharmony_ci } else if (kFPAliasing != AliasingKind::kCombine) { 1301cb0ef41Sopenharmony_ci // A backend may choose to generate the same instruction sequence regardless 1311cb0ef41Sopenharmony_ci // of the FP representation. As a result, we can relax the compatibility and 1321cb0ef41Sopenharmony_ci // allow a Double to be moved in a Float for example. However, this is only 1331cb0ef41Sopenharmony_ci // allowed if registers do not overlap. 1341cb0ef41Sopenharmony_ci return (IsFPRegister() || IsFPStackSlot()) && 1351cb0ef41Sopenharmony_ci (op->IsFPRegister() || op->IsFPStackSlot()); 1361cb0ef41Sopenharmony_ci } else if (IsFloatRegister() || IsFloatStackSlot()) { 1371cb0ef41Sopenharmony_ci return op->IsFloatRegister() || op->IsFloatStackSlot(); 1381cb0ef41Sopenharmony_ci } else if (IsDoubleRegister() || IsDoubleStackSlot()) { 1391cb0ef41Sopenharmony_ci return op->IsDoubleRegister() || op->IsDoubleStackSlot(); 1401cb0ef41Sopenharmony_ci } else { 1411cb0ef41Sopenharmony_ci return (IsSimd128Register() || IsSimd128StackSlot()) && 1421cb0ef41Sopenharmony_ci (op->IsSimd128Register() || op->IsSimd128StackSlot()); 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_civoid InstructionOperand::Print() const { StdoutStream{} << *this << std::endl; } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const InstructionOperand& op) { 1491cb0ef41Sopenharmony_ci switch (op.kind()) { 1501cb0ef41Sopenharmony_ci case InstructionOperand::UNALLOCATED: { 1511cb0ef41Sopenharmony_ci const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op); 1521cb0ef41Sopenharmony_ci os << "v" << unalloc->virtual_register(); 1531cb0ef41Sopenharmony_ci if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) { 1541cb0ef41Sopenharmony_ci return os << "(=" << unalloc->fixed_slot_index() << "S)"; 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci switch (unalloc->extended_policy()) { 1571cb0ef41Sopenharmony_ci case UnallocatedOperand::NONE: 1581cb0ef41Sopenharmony_ci return os; 1591cb0ef41Sopenharmony_ci case UnallocatedOperand::FIXED_REGISTER: 1601cb0ef41Sopenharmony_ci return os << "(=" 1611cb0ef41Sopenharmony_ci << Register::from_code(unalloc->fixed_register_index()) 1621cb0ef41Sopenharmony_ci << ")"; 1631cb0ef41Sopenharmony_ci case UnallocatedOperand::FIXED_FP_REGISTER: 1641cb0ef41Sopenharmony_ci return os << "(=" 1651cb0ef41Sopenharmony_ci << (unalloc->IsSimd128Register() 1661cb0ef41Sopenharmony_ci ? i::RegisterName((Simd128Register::from_code( 1671cb0ef41Sopenharmony_ci unalloc->fixed_register_index()))) 1681cb0ef41Sopenharmony_ci : i::RegisterName(DoubleRegister::from_code( 1691cb0ef41Sopenharmony_ci unalloc->fixed_register_index()))) 1701cb0ef41Sopenharmony_ci << ")"; 1711cb0ef41Sopenharmony_ci case UnallocatedOperand::MUST_HAVE_REGISTER: 1721cb0ef41Sopenharmony_ci return os << "(R)"; 1731cb0ef41Sopenharmony_ci case UnallocatedOperand::MUST_HAVE_SLOT: 1741cb0ef41Sopenharmony_ci return os << "(S)"; 1751cb0ef41Sopenharmony_ci case UnallocatedOperand::SAME_AS_INPUT: 1761cb0ef41Sopenharmony_ci return os << "(" << unalloc->input_index() << ")"; 1771cb0ef41Sopenharmony_ci case UnallocatedOperand::REGISTER_OR_SLOT: 1781cb0ef41Sopenharmony_ci return os << "(-)"; 1791cb0ef41Sopenharmony_ci case UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT: 1801cb0ef41Sopenharmony_ci return os << "(*)"; 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci case InstructionOperand::CONSTANT: 1841cb0ef41Sopenharmony_ci return os << "[constant:v" << ConstantOperand::cast(op).virtual_register() 1851cb0ef41Sopenharmony_ci << "]"; 1861cb0ef41Sopenharmony_ci case InstructionOperand::IMMEDIATE: { 1871cb0ef41Sopenharmony_ci ImmediateOperand imm = ImmediateOperand::cast(op); 1881cb0ef41Sopenharmony_ci switch (imm.type()) { 1891cb0ef41Sopenharmony_ci case ImmediateOperand::INLINE_INT32: 1901cb0ef41Sopenharmony_ci return os << "#" << imm.inline_int32_value(); 1911cb0ef41Sopenharmony_ci case ImmediateOperand::INLINE_INT64: 1921cb0ef41Sopenharmony_ci return os << "#" << imm.inline_int64_value(); 1931cb0ef41Sopenharmony_ci case ImmediateOperand::INDEXED_RPO: 1941cb0ef41Sopenharmony_ci return os << "[rpo_immediate:" << imm.indexed_value() << "]"; 1951cb0ef41Sopenharmony_ci case ImmediateOperand::INDEXED_IMM: 1961cb0ef41Sopenharmony_ci return os << "[immediate:" << imm.indexed_value() << "]"; 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci case InstructionOperand::PENDING: 2001cb0ef41Sopenharmony_ci return os << "[pending: " << PendingOperand::cast(op).next() << "]"; 2011cb0ef41Sopenharmony_ci case InstructionOperand::ALLOCATED: { 2021cb0ef41Sopenharmony_ci LocationOperand allocated = LocationOperand::cast(op); 2031cb0ef41Sopenharmony_ci if (op.IsStackSlot()) { 2041cb0ef41Sopenharmony_ci os << "[stack:" << allocated.index(); 2051cb0ef41Sopenharmony_ci } else if (op.IsFPStackSlot()) { 2061cb0ef41Sopenharmony_ci os << "[fp_stack:" << allocated.index(); 2071cb0ef41Sopenharmony_ci } else if (op.IsRegister()) { 2081cb0ef41Sopenharmony_ci const char* name = 2091cb0ef41Sopenharmony_ci allocated.register_code() < Register::kNumRegisters 2101cb0ef41Sopenharmony_ci ? RegisterName(Register::from_code(allocated.register_code())) 2111cb0ef41Sopenharmony_ci : Register::GetSpecialRegisterName(allocated.register_code()); 2121cb0ef41Sopenharmony_ci os << "[" << name << "|R"; 2131cb0ef41Sopenharmony_ci } else if (op.IsDoubleRegister()) { 2141cb0ef41Sopenharmony_ci os << "[" << DoubleRegister::from_code(allocated.register_code()) 2151cb0ef41Sopenharmony_ci << "|R"; 2161cb0ef41Sopenharmony_ci } else if (op.IsFloatRegister()) { 2171cb0ef41Sopenharmony_ci os << "[" << FloatRegister::from_code(allocated.register_code()) 2181cb0ef41Sopenharmony_ci << "|R"; 2191cb0ef41Sopenharmony_ci } else { 2201cb0ef41Sopenharmony_ci DCHECK(op.IsSimd128Register()); 2211cb0ef41Sopenharmony_ci os << "[" << Simd128Register::from_code(allocated.register_code()) 2221cb0ef41Sopenharmony_ci << "|R"; 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci switch (allocated.representation()) { 2251cb0ef41Sopenharmony_ci case MachineRepresentation::kNone: 2261cb0ef41Sopenharmony_ci os << "|-"; 2271cb0ef41Sopenharmony_ci break; 2281cb0ef41Sopenharmony_ci case MachineRepresentation::kBit: 2291cb0ef41Sopenharmony_ci os << "|b"; 2301cb0ef41Sopenharmony_ci break; 2311cb0ef41Sopenharmony_ci case MachineRepresentation::kWord8: 2321cb0ef41Sopenharmony_ci os << "|w8"; 2331cb0ef41Sopenharmony_ci break; 2341cb0ef41Sopenharmony_ci case MachineRepresentation::kWord16: 2351cb0ef41Sopenharmony_ci os << "|w16"; 2361cb0ef41Sopenharmony_ci break; 2371cb0ef41Sopenharmony_ci case MachineRepresentation::kWord32: 2381cb0ef41Sopenharmony_ci os << "|w32"; 2391cb0ef41Sopenharmony_ci break; 2401cb0ef41Sopenharmony_ci case MachineRepresentation::kWord64: 2411cb0ef41Sopenharmony_ci os << "|w64"; 2421cb0ef41Sopenharmony_ci break; 2431cb0ef41Sopenharmony_ci case MachineRepresentation::kFloat32: 2441cb0ef41Sopenharmony_ci os << "|f32"; 2451cb0ef41Sopenharmony_ci break; 2461cb0ef41Sopenharmony_ci case MachineRepresentation::kFloat64: 2471cb0ef41Sopenharmony_ci os << "|f64"; 2481cb0ef41Sopenharmony_ci break; 2491cb0ef41Sopenharmony_ci case MachineRepresentation::kSimd128: 2501cb0ef41Sopenharmony_ci os << "|s128"; 2511cb0ef41Sopenharmony_ci break; 2521cb0ef41Sopenharmony_ci case MachineRepresentation::kTaggedSigned: 2531cb0ef41Sopenharmony_ci os << "|ts"; 2541cb0ef41Sopenharmony_ci break; 2551cb0ef41Sopenharmony_ci case MachineRepresentation::kTaggedPointer: 2561cb0ef41Sopenharmony_ci os << "|tp"; 2571cb0ef41Sopenharmony_ci break; 2581cb0ef41Sopenharmony_ci case MachineRepresentation::kTagged: 2591cb0ef41Sopenharmony_ci os << "|t"; 2601cb0ef41Sopenharmony_ci break; 2611cb0ef41Sopenharmony_ci case MachineRepresentation::kCompressedPointer: 2621cb0ef41Sopenharmony_ci os << "|cp"; 2631cb0ef41Sopenharmony_ci break; 2641cb0ef41Sopenharmony_ci case MachineRepresentation::kCompressed: 2651cb0ef41Sopenharmony_ci os << "|c"; 2661cb0ef41Sopenharmony_ci break; 2671cb0ef41Sopenharmony_ci case MachineRepresentation::kSandboxedPointer: 2681cb0ef41Sopenharmony_ci os << "|sb"; 2691cb0ef41Sopenharmony_ci break; 2701cb0ef41Sopenharmony_ci case MachineRepresentation::kMapWord: 2711cb0ef41Sopenharmony_ci UNREACHABLE(); 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci return os << "]"; 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci case InstructionOperand::INVALID: 2761cb0ef41Sopenharmony_ci return os << "(x)"; 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci UNREACHABLE(); 2791cb0ef41Sopenharmony_ci} 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_civoid MoveOperands::Print() const { 2821cb0ef41Sopenharmony_ci StdoutStream{} << destination() << " = " << source() << std::endl; 2831cb0ef41Sopenharmony_ci} 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const MoveOperands& mo) { 2861cb0ef41Sopenharmony_ci os << mo.destination(); 2871cb0ef41Sopenharmony_ci if (!mo.source().Equals(mo.destination())) { 2881cb0ef41Sopenharmony_ci os << " = " << mo.source(); 2891cb0ef41Sopenharmony_ci } 2901cb0ef41Sopenharmony_ci return os; 2911cb0ef41Sopenharmony_ci} 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_cibool ParallelMove::IsRedundant() const { 2941cb0ef41Sopenharmony_ci for (MoveOperands* move : *this) { 2951cb0ef41Sopenharmony_ci if (!move->IsRedundant()) return false; 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci return true; 2981cb0ef41Sopenharmony_ci} 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_civoid ParallelMove::PrepareInsertAfter( 3011cb0ef41Sopenharmony_ci MoveOperands* move, ZoneVector<MoveOperands*>* to_eliminate) const { 3021cb0ef41Sopenharmony_ci bool no_aliasing = kFPAliasing != AliasingKind::kCombine || 3031cb0ef41Sopenharmony_ci !move->destination().IsFPLocationOperand(); 3041cb0ef41Sopenharmony_ci MoveOperands* replacement = nullptr; 3051cb0ef41Sopenharmony_ci MoveOperands* eliminated = nullptr; 3061cb0ef41Sopenharmony_ci for (MoveOperands* curr : *this) { 3071cb0ef41Sopenharmony_ci if (curr->IsEliminated()) continue; 3081cb0ef41Sopenharmony_ci if (curr->destination().EqualsCanonicalized(move->source())) { 3091cb0ef41Sopenharmony_ci // We must replace move's source with curr's destination in order to 3101cb0ef41Sopenharmony_ci // insert it into this ParallelMove. 3111cb0ef41Sopenharmony_ci DCHECK(!replacement); 3121cb0ef41Sopenharmony_ci replacement = curr; 3131cb0ef41Sopenharmony_ci if (no_aliasing && eliminated != nullptr) break; 3141cb0ef41Sopenharmony_ci } else if (curr->destination().InterferesWith(move->destination())) { 3151cb0ef41Sopenharmony_ci // We can eliminate curr, since move overwrites at least a part of its 3161cb0ef41Sopenharmony_ci // destination, implying its value is no longer live. 3171cb0ef41Sopenharmony_ci eliminated = curr; 3181cb0ef41Sopenharmony_ci to_eliminate->push_back(curr); 3191cb0ef41Sopenharmony_ci if (no_aliasing && replacement != nullptr) break; 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci } 3221cb0ef41Sopenharmony_ci if (replacement != nullptr) move->set_source(replacement->source()); 3231cb0ef41Sopenharmony_ci} 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ciInstruction::Instruction(InstructionCode opcode) 3261cb0ef41Sopenharmony_ci : opcode_(opcode), 3271cb0ef41Sopenharmony_ci bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) | 3281cb0ef41Sopenharmony_ci TempCountField::encode(0) | IsCallField::encode(false)), 3291cb0ef41Sopenharmony_ci reference_map_(nullptr), 3301cb0ef41Sopenharmony_ci block_(nullptr) { 3311cb0ef41Sopenharmony_ci parallel_moves_[0] = nullptr; 3321cb0ef41Sopenharmony_ci parallel_moves_[1] = nullptr; 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci // PendingOperands are required to be 8 byte aligned. 3351cb0ef41Sopenharmony_ci STATIC_ASSERT(offsetof(Instruction, operands_) % 8 == 0); 3361cb0ef41Sopenharmony_ci} 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ciInstruction::Instruction(InstructionCode opcode, size_t output_count, 3391cb0ef41Sopenharmony_ci InstructionOperand* outputs, size_t input_count, 3401cb0ef41Sopenharmony_ci InstructionOperand* inputs, size_t temp_count, 3411cb0ef41Sopenharmony_ci InstructionOperand* temps) 3421cb0ef41Sopenharmony_ci : opcode_(opcode), 3431cb0ef41Sopenharmony_ci bit_field_(OutputCountField::encode(output_count) | 3441cb0ef41Sopenharmony_ci InputCountField::encode(input_count) | 3451cb0ef41Sopenharmony_ci TempCountField::encode(temp_count) | 3461cb0ef41Sopenharmony_ci IsCallField::encode(false)), 3471cb0ef41Sopenharmony_ci reference_map_(nullptr), 3481cb0ef41Sopenharmony_ci block_(nullptr) { 3491cb0ef41Sopenharmony_ci parallel_moves_[0] = nullptr; 3501cb0ef41Sopenharmony_ci parallel_moves_[1] = nullptr; 3511cb0ef41Sopenharmony_ci size_t offset = 0; 3521cb0ef41Sopenharmony_ci for (size_t i = 0; i < output_count; ++i) { 3531cb0ef41Sopenharmony_ci DCHECK(!outputs[i].IsInvalid()); 3541cb0ef41Sopenharmony_ci operands_[offset++] = outputs[i]; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci for (size_t i = 0; i < input_count; ++i) { 3571cb0ef41Sopenharmony_ci DCHECK(!inputs[i].IsInvalid()); 3581cb0ef41Sopenharmony_ci operands_[offset++] = inputs[i]; 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci for (size_t i = 0; i < temp_count; ++i) { 3611cb0ef41Sopenharmony_ci DCHECK(!temps[i].IsInvalid()); 3621cb0ef41Sopenharmony_ci operands_[offset++] = temps[i]; 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci} 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_cibool Instruction::AreMovesRedundant() const { 3671cb0ef41Sopenharmony_ci for (int i = Instruction::FIRST_GAP_POSITION; 3681cb0ef41Sopenharmony_ci i <= Instruction::LAST_GAP_POSITION; i++) { 3691cb0ef41Sopenharmony_ci if (parallel_moves_[i] != nullptr && !parallel_moves_[i]->IsRedundant()) { 3701cb0ef41Sopenharmony_ci return false; 3711cb0ef41Sopenharmony_ci } 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci return true; 3741cb0ef41Sopenharmony_ci} 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_civoid Instruction::Print() const { StdoutStream{} << *this << std::endl; } 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const ParallelMove& pm) { 3791cb0ef41Sopenharmony_ci const char* delimiter = ""; 3801cb0ef41Sopenharmony_ci for (MoveOperands* move : pm) { 3811cb0ef41Sopenharmony_ci if (move->IsEliminated()) continue; 3821cb0ef41Sopenharmony_ci os << delimiter << *move; 3831cb0ef41Sopenharmony_ci delimiter = "; "; 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci return os; 3861cb0ef41Sopenharmony_ci} 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_civoid ReferenceMap::RecordReference(const AllocatedOperand& op) { 3891cb0ef41Sopenharmony_ci // Do not record arguments as pointers. 3901cb0ef41Sopenharmony_ci if (op.IsStackSlot() && LocationOperand::cast(op).index() < 0) return; 3911cb0ef41Sopenharmony_ci DCHECK(!op.IsFPRegister() && !op.IsFPStackSlot()); 3921cb0ef41Sopenharmony_ci reference_operands_.push_back(op); 3931cb0ef41Sopenharmony_ci} 3941cb0ef41Sopenharmony_ci 3951cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) { 3961cb0ef41Sopenharmony_ci os << "{"; 3971cb0ef41Sopenharmony_ci const char* separator = ""; 3981cb0ef41Sopenharmony_ci for (const InstructionOperand& op : pm.reference_operands_) { 3991cb0ef41Sopenharmony_ci os << separator << op; 4001cb0ef41Sopenharmony_ci separator = ";"; 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci return os << "}"; 4031cb0ef41Sopenharmony_ci} 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) { 4061cb0ef41Sopenharmony_ci switch (ao) { 4071cb0ef41Sopenharmony_ci#define CASE(Name) \ 4081cb0ef41Sopenharmony_ci case k##Name: \ 4091cb0ef41Sopenharmony_ci return os << #Name; 4101cb0ef41Sopenharmony_ci ARCH_OPCODE_LIST(CASE) 4111cb0ef41Sopenharmony_ci#undef CASE 4121cb0ef41Sopenharmony_ci } 4131cb0ef41Sopenharmony_ci UNREACHABLE(); 4141cb0ef41Sopenharmony_ci} 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const AddressingMode& am) { 4171cb0ef41Sopenharmony_ci switch (am) { 4181cb0ef41Sopenharmony_ci case kMode_None: 4191cb0ef41Sopenharmony_ci return os; 4201cb0ef41Sopenharmony_ci#define CASE(Name) \ 4211cb0ef41Sopenharmony_ci case kMode_##Name: \ 4221cb0ef41Sopenharmony_ci return os << #Name; 4231cb0ef41Sopenharmony_ci TARGET_ADDRESSING_MODE_LIST(CASE) 4241cb0ef41Sopenharmony_ci#undef CASE 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci UNREACHABLE(); 4271cb0ef41Sopenharmony_ci} 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const FlagsMode& fm) { 4301cb0ef41Sopenharmony_ci switch (fm) { 4311cb0ef41Sopenharmony_ci case kFlags_none: 4321cb0ef41Sopenharmony_ci return os; 4331cb0ef41Sopenharmony_ci case kFlags_branch: 4341cb0ef41Sopenharmony_ci return os << "branch"; 4351cb0ef41Sopenharmony_ci case kFlags_deoptimize: 4361cb0ef41Sopenharmony_ci return os << "deoptimize"; 4371cb0ef41Sopenharmony_ci case kFlags_set: 4381cb0ef41Sopenharmony_ci return os << "set"; 4391cb0ef41Sopenharmony_ci case kFlags_trap: 4401cb0ef41Sopenharmony_ci return os << "trap"; 4411cb0ef41Sopenharmony_ci case kFlags_select: 4421cb0ef41Sopenharmony_ci return os << "select"; 4431cb0ef41Sopenharmony_ci } 4441cb0ef41Sopenharmony_ci UNREACHABLE(); 4451cb0ef41Sopenharmony_ci} 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) { 4481cb0ef41Sopenharmony_ci switch (fc) { 4491cb0ef41Sopenharmony_ci case kEqual: 4501cb0ef41Sopenharmony_ci return os << "equal"; 4511cb0ef41Sopenharmony_ci case kNotEqual: 4521cb0ef41Sopenharmony_ci return os << "not equal"; 4531cb0ef41Sopenharmony_ci case kSignedLessThan: 4541cb0ef41Sopenharmony_ci return os << "signed less than"; 4551cb0ef41Sopenharmony_ci case kSignedGreaterThanOrEqual: 4561cb0ef41Sopenharmony_ci return os << "signed greater than or equal"; 4571cb0ef41Sopenharmony_ci case kSignedLessThanOrEqual: 4581cb0ef41Sopenharmony_ci return os << "signed less than or equal"; 4591cb0ef41Sopenharmony_ci case kSignedGreaterThan: 4601cb0ef41Sopenharmony_ci return os << "signed greater than"; 4611cb0ef41Sopenharmony_ci case kUnsignedLessThan: 4621cb0ef41Sopenharmony_ci return os << "unsigned less than"; 4631cb0ef41Sopenharmony_ci case kUnsignedGreaterThanOrEqual: 4641cb0ef41Sopenharmony_ci return os << "unsigned greater than or equal"; 4651cb0ef41Sopenharmony_ci case kUnsignedLessThanOrEqual: 4661cb0ef41Sopenharmony_ci return os << "unsigned less than or equal"; 4671cb0ef41Sopenharmony_ci case kUnsignedGreaterThan: 4681cb0ef41Sopenharmony_ci return os << "unsigned greater than"; 4691cb0ef41Sopenharmony_ci case kFloatLessThanOrUnordered: 4701cb0ef41Sopenharmony_ci return os << "less than or unordered (FP)"; 4711cb0ef41Sopenharmony_ci case kFloatGreaterThanOrEqual: 4721cb0ef41Sopenharmony_ci return os << "greater than or equal (FP)"; 4731cb0ef41Sopenharmony_ci case kFloatLessThanOrEqual: 4741cb0ef41Sopenharmony_ci return os << "less than or equal (FP)"; 4751cb0ef41Sopenharmony_ci case kFloatGreaterThanOrUnordered: 4761cb0ef41Sopenharmony_ci return os << "greater than or unordered (FP)"; 4771cb0ef41Sopenharmony_ci case kFloatLessThan: 4781cb0ef41Sopenharmony_ci return os << "less than (FP)"; 4791cb0ef41Sopenharmony_ci case kFloatGreaterThanOrEqualOrUnordered: 4801cb0ef41Sopenharmony_ci return os << "greater than, equal or unordered (FP)"; 4811cb0ef41Sopenharmony_ci case kFloatLessThanOrEqualOrUnordered: 4821cb0ef41Sopenharmony_ci return os << "less than, equal or unordered (FP)"; 4831cb0ef41Sopenharmony_ci case kFloatGreaterThan: 4841cb0ef41Sopenharmony_ci return os << "greater than (FP)"; 4851cb0ef41Sopenharmony_ci case kUnorderedEqual: 4861cb0ef41Sopenharmony_ci return os << "unordered equal"; 4871cb0ef41Sopenharmony_ci case kUnorderedNotEqual: 4881cb0ef41Sopenharmony_ci return os << "unordered not equal"; 4891cb0ef41Sopenharmony_ci case kOverflow: 4901cb0ef41Sopenharmony_ci return os << "overflow"; 4911cb0ef41Sopenharmony_ci case kNotOverflow: 4921cb0ef41Sopenharmony_ci return os << "not overflow"; 4931cb0ef41Sopenharmony_ci case kPositiveOrZero: 4941cb0ef41Sopenharmony_ci return os << "positive or zero"; 4951cb0ef41Sopenharmony_ci case kNegative: 4961cb0ef41Sopenharmony_ci return os << "negative"; 4971cb0ef41Sopenharmony_ci } 4981cb0ef41Sopenharmony_ci UNREACHABLE(); 4991cb0ef41Sopenharmony_ci} 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const Instruction& instr) { 5021cb0ef41Sopenharmony_ci os << "gap "; 5031cb0ef41Sopenharmony_ci for (int i = Instruction::FIRST_GAP_POSITION; 5041cb0ef41Sopenharmony_ci i <= Instruction::LAST_GAP_POSITION; i++) { 5051cb0ef41Sopenharmony_ci os << "("; 5061cb0ef41Sopenharmony_ci if (instr.parallel_moves()[i] != nullptr) { 5071cb0ef41Sopenharmony_ci os << *instr.parallel_moves()[i]; 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci os << ") "; 5101cb0ef41Sopenharmony_ci } 5111cb0ef41Sopenharmony_ci os << "\n "; 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci if (instr.OutputCount() == 1) { 5141cb0ef41Sopenharmony_ci os << *instr.OutputAt(0) << " = "; 5151cb0ef41Sopenharmony_ci } else if (instr.OutputCount() > 1) { 5161cb0ef41Sopenharmony_ci os << "(" << *instr.OutputAt(0); 5171cb0ef41Sopenharmony_ci for (size_t i = 1; i < instr.OutputCount(); i++) { 5181cb0ef41Sopenharmony_ci os << ", " << *instr.OutputAt(i); 5191cb0ef41Sopenharmony_ci } 5201cb0ef41Sopenharmony_ci os << ") = "; 5211cb0ef41Sopenharmony_ci } 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci os << ArchOpcodeField::decode(instr.opcode()); 5241cb0ef41Sopenharmony_ci AddressingMode am = AddressingModeField::decode(instr.opcode()); 5251cb0ef41Sopenharmony_ci if (am != kMode_None) { 5261cb0ef41Sopenharmony_ci os << " : " << AddressingModeField::decode(instr.opcode()); 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci FlagsMode fm = FlagsModeField::decode(instr.opcode()); 5291cb0ef41Sopenharmony_ci if (fm != kFlags_none) { 5301cb0ef41Sopenharmony_ci os << " && " << fm << " if " << FlagsConditionField::decode(instr.opcode()); 5311cb0ef41Sopenharmony_ci } 5321cb0ef41Sopenharmony_ci for (size_t i = 0; i < instr.InputCount(); i++) { 5331cb0ef41Sopenharmony_ci os << " " << *instr.InputAt(i); 5341cb0ef41Sopenharmony_ci } 5351cb0ef41Sopenharmony_ci return os; 5361cb0ef41Sopenharmony_ci} 5371cb0ef41Sopenharmony_ci 5381cb0ef41Sopenharmony_ciConstant::Constant(int32_t v) : type_(kInt32), value_(v) {} 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ciConstant::Constant(RelocatablePtrConstantInfo info) { 5411cb0ef41Sopenharmony_ci if (info.type() == RelocatablePtrConstantInfo::kInt32) { 5421cb0ef41Sopenharmony_ci type_ = kInt32; 5431cb0ef41Sopenharmony_ci } else if (info.type() == RelocatablePtrConstantInfo::kInt64) { 5441cb0ef41Sopenharmony_ci type_ = kInt64; 5451cb0ef41Sopenharmony_ci } else { 5461cb0ef41Sopenharmony_ci UNREACHABLE(); 5471cb0ef41Sopenharmony_ci } 5481cb0ef41Sopenharmony_ci value_ = info.value(); 5491cb0ef41Sopenharmony_ci rmode_ = info.rmode(); 5501cb0ef41Sopenharmony_ci} 5511cb0ef41Sopenharmony_ci 5521cb0ef41Sopenharmony_ciHandle<HeapObject> Constant::ToHeapObject() const { 5531cb0ef41Sopenharmony_ci DCHECK(kHeapObject == type() || kCompressedHeapObject == type()); 5541cb0ef41Sopenharmony_ci Handle<HeapObject> value( 5551cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(static_cast<intptr_t>(value_))); 5561cb0ef41Sopenharmony_ci return value; 5571cb0ef41Sopenharmony_ci} 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_ciHandle<CodeT> Constant::ToCode() const { 5601cb0ef41Sopenharmony_ci DCHECK_EQ(kHeapObject, type()); 5611cb0ef41Sopenharmony_ci Handle<CodeT> value( 5621cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(static_cast<intptr_t>(value_))); 5631cb0ef41Sopenharmony_ci DCHECK(value->IsCodeT(GetPtrComprCageBaseSlow(*value))); 5641cb0ef41Sopenharmony_ci return value; 5651cb0ef41Sopenharmony_ci} 5661cb0ef41Sopenharmony_ci 5671cb0ef41Sopenharmony_ciconst StringConstantBase* Constant::ToDelayedStringConstant() const { 5681cb0ef41Sopenharmony_ci DCHECK_EQ(kDelayedStringConstant, type()); 5691cb0ef41Sopenharmony_ci const StringConstantBase* value = 5701cb0ef41Sopenharmony_ci bit_cast<StringConstantBase*>(static_cast<intptr_t>(value_)); 5711cb0ef41Sopenharmony_ci return value; 5721cb0ef41Sopenharmony_ci} 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const Constant& constant) { 5751cb0ef41Sopenharmony_ci switch (constant.type()) { 5761cb0ef41Sopenharmony_ci case Constant::kInt32: 5771cb0ef41Sopenharmony_ci return os << constant.ToInt32(); 5781cb0ef41Sopenharmony_ci case Constant::kInt64: 5791cb0ef41Sopenharmony_ci return os << constant.ToInt64() << "l"; 5801cb0ef41Sopenharmony_ci case Constant::kFloat32: 5811cb0ef41Sopenharmony_ci return os << constant.ToFloat32() << "f"; 5821cb0ef41Sopenharmony_ci case Constant::kFloat64: 5831cb0ef41Sopenharmony_ci return os << constant.ToFloat64().value(); 5841cb0ef41Sopenharmony_ci case Constant::kExternalReference: 5851cb0ef41Sopenharmony_ci return os << constant.ToExternalReference().address(); 5861cb0ef41Sopenharmony_ci case Constant::kHeapObject: // Fall through. 5871cb0ef41Sopenharmony_ci case Constant::kCompressedHeapObject: 5881cb0ef41Sopenharmony_ci return os << Brief(*constant.ToHeapObject()); 5891cb0ef41Sopenharmony_ci case Constant::kRpoNumber: 5901cb0ef41Sopenharmony_ci return os << "RPO" << constant.ToRpoNumber().ToInt(); 5911cb0ef41Sopenharmony_ci case Constant::kDelayedStringConstant: 5921cb0ef41Sopenharmony_ci return os << "DelayedStringConstant: " 5931cb0ef41Sopenharmony_ci << constant.ToDelayedStringConstant(); 5941cb0ef41Sopenharmony_ci } 5951cb0ef41Sopenharmony_ci UNREACHABLE(); 5961cb0ef41Sopenharmony_ci} 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ciPhiInstruction::PhiInstruction(Zone* zone, int virtual_register, 5991cb0ef41Sopenharmony_ci size_t input_count) 6001cb0ef41Sopenharmony_ci : virtual_register_(virtual_register), 6011cb0ef41Sopenharmony_ci output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)), 6021cb0ef41Sopenharmony_ci operands_(input_count, InstructionOperand::kInvalidVirtualRegister, 6031cb0ef41Sopenharmony_ci zone) {} 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_civoid PhiInstruction::SetInput(size_t offset, int virtual_register) { 6061cb0ef41Sopenharmony_ci DCHECK_EQ(InstructionOperand::kInvalidVirtualRegister, operands_[offset]); 6071cb0ef41Sopenharmony_ci operands_[offset] = virtual_register; 6081cb0ef41Sopenharmony_ci} 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_civoid PhiInstruction::RenameInput(size_t offset, int virtual_register) { 6111cb0ef41Sopenharmony_ci DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, operands_[offset]); 6121cb0ef41Sopenharmony_ci operands_[offset] = virtual_register; 6131cb0ef41Sopenharmony_ci} 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ciInstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number, 6161cb0ef41Sopenharmony_ci RpoNumber loop_header, RpoNumber loop_end, 6171cb0ef41Sopenharmony_ci RpoNumber dominator, bool deferred, 6181cb0ef41Sopenharmony_ci bool handler) 6191cb0ef41Sopenharmony_ci : successors_(zone), 6201cb0ef41Sopenharmony_ci predecessors_(zone), 6211cb0ef41Sopenharmony_ci phis_(zone), 6221cb0ef41Sopenharmony_ci ao_number_(RpoNumber::Invalid()), 6231cb0ef41Sopenharmony_ci rpo_number_(rpo_number), 6241cb0ef41Sopenharmony_ci loop_header_(loop_header), 6251cb0ef41Sopenharmony_ci loop_end_(loop_end), 6261cb0ef41Sopenharmony_ci dominator_(dominator), 6271cb0ef41Sopenharmony_ci deferred_(deferred), 6281cb0ef41Sopenharmony_ci handler_(handler), 6291cb0ef41Sopenharmony_ci switch_target_(false), 6301cb0ef41Sopenharmony_ci code_target_alignment_(false), 6311cb0ef41Sopenharmony_ci loop_header_alignment_(false), 6321cb0ef41Sopenharmony_ci needs_frame_(false), 6331cb0ef41Sopenharmony_ci must_construct_frame_(false), 6341cb0ef41Sopenharmony_ci must_deconstruct_frame_(false) {} 6351cb0ef41Sopenharmony_ci 6361cb0ef41Sopenharmony_cisize_t InstructionBlock::PredecessorIndexOf(RpoNumber rpo_number) const { 6371cb0ef41Sopenharmony_ci size_t j = 0; 6381cb0ef41Sopenharmony_ci for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin(); 6391cb0ef41Sopenharmony_ci i != predecessors_.end(); ++i, ++j) { 6401cb0ef41Sopenharmony_ci if (*i == rpo_number) break; 6411cb0ef41Sopenharmony_ci } 6421cb0ef41Sopenharmony_ci return j; 6431cb0ef41Sopenharmony_ci} 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_cistatic RpoNumber GetRpo(const BasicBlock* block) { 6461cb0ef41Sopenharmony_ci if (block == nullptr) return RpoNumber::Invalid(); 6471cb0ef41Sopenharmony_ci return RpoNumber::FromInt(block->rpo_number()); 6481cb0ef41Sopenharmony_ci} 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_cistatic RpoNumber GetLoopEndRpo(const BasicBlock* block) { 6511cb0ef41Sopenharmony_ci if (!block->IsLoopHeader()) return RpoNumber::Invalid(); 6521cb0ef41Sopenharmony_ci return RpoNumber::FromInt(block->loop_end()->rpo_number()); 6531cb0ef41Sopenharmony_ci} 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_cistatic InstructionBlock* InstructionBlockFor(Zone* zone, 6561cb0ef41Sopenharmony_ci const BasicBlock* block) { 6571cb0ef41Sopenharmony_ci bool is_handler = 6581cb0ef41Sopenharmony_ci !block->empty() && block->front()->opcode() == IrOpcode::kIfException; 6591cb0ef41Sopenharmony_ci InstructionBlock* instr_block = zone->New<InstructionBlock>( 6601cb0ef41Sopenharmony_ci zone, GetRpo(block), GetRpo(block->loop_header()), GetLoopEndRpo(block), 6611cb0ef41Sopenharmony_ci GetRpo(block->dominator()), block->deferred(), is_handler); 6621cb0ef41Sopenharmony_ci // Map successors and precessors 6631cb0ef41Sopenharmony_ci instr_block->successors().reserve(block->SuccessorCount()); 6641cb0ef41Sopenharmony_ci for (BasicBlock* successor : block->successors()) { 6651cb0ef41Sopenharmony_ci instr_block->successors().push_back(GetRpo(successor)); 6661cb0ef41Sopenharmony_ci } 6671cb0ef41Sopenharmony_ci instr_block->predecessors().reserve(block->PredecessorCount()); 6681cb0ef41Sopenharmony_ci for (BasicBlock* predecessor : block->predecessors()) { 6691cb0ef41Sopenharmony_ci instr_block->predecessors().push_back(GetRpo(predecessor)); 6701cb0ef41Sopenharmony_ci } 6711cb0ef41Sopenharmony_ci if (block->PredecessorCount() == 1 && 6721cb0ef41Sopenharmony_ci block->predecessors()[0]->control() == BasicBlock::Control::kSwitch) { 6731cb0ef41Sopenharmony_ci instr_block->set_switch_target(true); 6741cb0ef41Sopenharmony_ci } 6751cb0ef41Sopenharmony_ci return instr_block; 6761cb0ef41Sopenharmony_ci} 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, 6791cb0ef41Sopenharmony_ci const PrintableInstructionBlock& printable_block) { 6801cb0ef41Sopenharmony_ci const InstructionBlock* block = printable_block.block_; 6811cb0ef41Sopenharmony_ci const InstructionSequence* code = printable_block.code_; 6821cb0ef41Sopenharmony_ci 6831cb0ef41Sopenharmony_ci os << "B" << block->rpo_number(); 6841cb0ef41Sopenharmony_ci if (block->ao_number().IsValid()) { 6851cb0ef41Sopenharmony_ci os << ": AO#" << block->ao_number(); 6861cb0ef41Sopenharmony_ci } else { 6871cb0ef41Sopenharmony_ci os << ": AO#?"; 6881cb0ef41Sopenharmony_ci } 6891cb0ef41Sopenharmony_ci if (block->IsDeferred()) os << " (deferred)"; 6901cb0ef41Sopenharmony_ci if (!block->needs_frame()) os << " (no frame)"; 6911cb0ef41Sopenharmony_ci if (block->must_construct_frame()) os << " (construct frame)"; 6921cb0ef41Sopenharmony_ci if (block->must_deconstruct_frame()) os << " (deconstruct frame)"; 6931cb0ef41Sopenharmony_ci if (block->IsLoopHeader()) { 6941cb0ef41Sopenharmony_ci os << " loop blocks: [" << block->rpo_number() << ", " << block->loop_end() 6951cb0ef41Sopenharmony_ci << ")"; 6961cb0ef41Sopenharmony_ci } 6971cb0ef41Sopenharmony_ci os << " instructions: [" << block->code_start() << ", " << block->code_end() 6981cb0ef41Sopenharmony_ci << ")" << std::endl 6991cb0ef41Sopenharmony_ci << " predecessors:"; 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_ci for (RpoNumber pred : block->predecessors()) { 7021cb0ef41Sopenharmony_ci os << " B" << pred.ToInt(); 7031cb0ef41Sopenharmony_ci } 7041cb0ef41Sopenharmony_ci os << std::endl; 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_ci for (const PhiInstruction* phi : block->phis()) { 7071cb0ef41Sopenharmony_ci os << " phi: " << phi->output() << " ="; 7081cb0ef41Sopenharmony_ci for (int input : phi->operands()) { 7091cb0ef41Sopenharmony_ci os << " v" << input; 7101cb0ef41Sopenharmony_ci } 7111cb0ef41Sopenharmony_ci os << std::endl; 7121cb0ef41Sopenharmony_ci } 7131cb0ef41Sopenharmony_ci 7141cb0ef41Sopenharmony_ci for (int j = block->first_instruction_index(); 7151cb0ef41Sopenharmony_ci j <= block->last_instruction_index(); j++) { 7161cb0ef41Sopenharmony_ci os << " " << std::setw(5) << j << ": " << *code->InstructionAt(j) 7171cb0ef41Sopenharmony_ci << std::endl; 7181cb0ef41Sopenharmony_ci } 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ci os << " successors:"; 7211cb0ef41Sopenharmony_ci for (RpoNumber succ : block->successors()) { 7221cb0ef41Sopenharmony_ci os << " B" << succ.ToInt(); 7231cb0ef41Sopenharmony_ci } 7241cb0ef41Sopenharmony_ci os << std::endl; 7251cb0ef41Sopenharmony_ci return os; 7261cb0ef41Sopenharmony_ci} 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ciInstructionBlocks* InstructionSequence::InstructionBlocksFor( 7291cb0ef41Sopenharmony_ci Zone* zone, const Schedule* schedule) { 7301cb0ef41Sopenharmony_ci InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1); 7311cb0ef41Sopenharmony_ci new (blocks) InstructionBlocks( 7321cb0ef41Sopenharmony_ci static_cast<int>(schedule->rpo_order()->size()), nullptr, zone); 7331cb0ef41Sopenharmony_ci size_t rpo_number = 0; 7341cb0ef41Sopenharmony_ci for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin(); 7351cb0ef41Sopenharmony_ci it != schedule->rpo_order()->end(); ++it, ++rpo_number) { 7361cb0ef41Sopenharmony_ci DCHECK(!(*blocks)[rpo_number]); 7371cb0ef41Sopenharmony_ci DCHECK(GetRpo(*it).ToSize() == rpo_number); 7381cb0ef41Sopenharmony_ci (*blocks)[rpo_number] = InstructionBlockFor(zone, *it); 7391cb0ef41Sopenharmony_ci } 7401cb0ef41Sopenharmony_ci return blocks; 7411cb0ef41Sopenharmony_ci} 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_civoid InstructionSequence::ValidateEdgeSplitForm() const { 7441cb0ef41Sopenharmony_ci // Validate blocks are in edge-split form: no block with multiple successors 7451cb0ef41Sopenharmony_ci // has an edge to a block (== a successor) with more than one predecessors. 7461cb0ef41Sopenharmony_ci for (const InstructionBlock* block : instruction_blocks()) { 7471cb0ef41Sopenharmony_ci if (block->SuccessorCount() > 1) { 7481cb0ef41Sopenharmony_ci for (const RpoNumber& successor_id : block->successors()) { 7491cb0ef41Sopenharmony_ci const InstructionBlock* successor = InstructionBlockAt(successor_id); 7501cb0ef41Sopenharmony_ci // Expect precisely one predecessor: "block". 7511cb0ef41Sopenharmony_ci CHECK(successor->PredecessorCount() == 1 && 7521cb0ef41Sopenharmony_ci successor->predecessors()[0] == block->rpo_number()); 7531cb0ef41Sopenharmony_ci } 7541cb0ef41Sopenharmony_ci } 7551cb0ef41Sopenharmony_ci } 7561cb0ef41Sopenharmony_ci} 7571cb0ef41Sopenharmony_ci 7581cb0ef41Sopenharmony_civoid InstructionSequence::ValidateDeferredBlockExitPaths() const { 7591cb0ef41Sopenharmony_ci // A deferred block with more than one successor must have all its successors 7601cb0ef41Sopenharmony_ci // deferred. 7611cb0ef41Sopenharmony_ci for (const InstructionBlock* block : instruction_blocks()) { 7621cb0ef41Sopenharmony_ci if (!block->IsDeferred() || block->SuccessorCount() <= 1) continue; 7631cb0ef41Sopenharmony_ci for (RpoNumber successor_id : block->successors()) { 7641cb0ef41Sopenharmony_ci CHECK(InstructionBlockAt(successor_id)->IsDeferred()); 7651cb0ef41Sopenharmony_ci } 7661cb0ef41Sopenharmony_ci } 7671cb0ef41Sopenharmony_ci} 7681cb0ef41Sopenharmony_ci 7691cb0ef41Sopenharmony_civoid InstructionSequence::ValidateDeferredBlockEntryPaths() const { 7701cb0ef41Sopenharmony_ci // If a deferred block has multiple predecessors, they have to 7711cb0ef41Sopenharmony_ci // all be deferred. Otherwise, we can run into a situation where a range 7721cb0ef41Sopenharmony_ci // that spills only in deferred blocks inserts its spill in the block, but 7731cb0ef41Sopenharmony_ci // other ranges need moves inserted by ResolveControlFlow in the predecessors, 7741cb0ef41Sopenharmony_ci // which may clobber the register of this range. 7751cb0ef41Sopenharmony_ci for (const InstructionBlock* block : instruction_blocks()) { 7761cb0ef41Sopenharmony_ci if (!block->IsDeferred() || block->PredecessorCount() <= 1) continue; 7771cb0ef41Sopenharmony_ci for (RpoNumber predecessor_id : block->predecessors()) { 7781cb0ef41Sopenharmony_ci CHECK(InstructionBlockAt(predecessor_id)->IsDeferred()); 7791cb0ef41Sopenharmony_ci } 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci} 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_civoid InstructionSequence::ValidateSSA() const { 7841cb0ef41Sopenharmony_ci // TODO(mtrofin): We could use a local zone here instead. 7851cb0ef41Sopenharmony_ci BitVector definitions(VirtualRegisterCount(), zone()); 7861cb0ef41Sopenharmony_ci for (const Instruction* instruction : *this) { 7871cb0ef41Sopenharmony_ci for (size_t i = 0; i < instruction->OutputCount(); ++i) { 7881cb0ef41Sopenharmony_ci const InstructionOperand* output = instruction->OutputAt(i); 7891cb0ef41Sopenharmony_ci int vreg = (output->IsConstant()) 7901cb0ef41Sopenharmony_ci ? ConstantOperand::cast(output)->virtual_register() 7911cb0ef41Sopenharmony_ci : UnallocatedOperand::cast(output)->virtual_register(); 7921cb0ef41Sopenharmony_ci CHECK(!definitions.Contains(vreg)); 7931cb0ef41Sopenharmony_ci definitions.Add(vreg); 7941cb0ef41Sopenharmony_ci } 7951cb0ef41Sopenharmony_ci } 7961cb0ef41Sopenharmony_ci} 7971cb0ef41Sopenharmony_ci 7981cb0ef41Sopenharmony_civoid InstructionSequence::ComputeAssemblyOrder() { 7991cb0ef41Sopenharmony_ci int ao = 0; 8001cb0ef41Sopenharmony_ci RpoNumber invalid = RpoNumber::Invalid(); 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci ao_blocks_ = zone()->NewArray<InstructionBlocks>(1); 8031cb0ef41Sopenharmony_ci new (ao_blocks_) InstructionBlocks(zone()); 8041cb0ef41Sopenharmony_ci ao_blocks_->reserve(instruction_blocks_->size()); 8051cb0ef41Sopenharmony_ci 8061cb0ef41Sopenharmony_ci // Place non-deferred blocks. 8071cb0ef41Sopenharmony_ci for (InstructionBlock* const block : *instruction_blocks_) { 8081cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(block); 8091cb0ef41Sopenharmony_ci if (block->IsDeferred()) continue; // skip deferred blocks. 8101cb0ef41Sopenharmony_ci if (block->ao_number() != invalid) continue; // loop rotated. 8111cb0ef41Sopenharmony_ci if (block->IsLoopHeader()) { 8121cb0ef41Sopenharmony_ci bool header_align = true; 8131cb0ef41Sopenharmony_ci if (FLAG_turbo_loop_rotation) { 8141cb0ef41Sopenharmony_ci // Perform loop rotation for non-deferred loops. 8151cb0ef41Sopenharmony_ci InstructionBlock* loop_end = 8161cb0ef41Sopenharmony_ci instruction_blocks_->at(block->loop_end().ToSize() - 1); 8171cb0ef41Sopenharmony_ci if (loop_end->SuccessorCount() == 1 && /* ends with goto */ 8181cb0ef41Sopenharmony_ci loop_end != block /* not a degenerate infinite loop */) { 8191cb0ef41Sopenharmony_ci // If the last block has an unconditional jump back to the header, 8201cb0ef41Sopenharmony_ci // then move it to be in front of the header in the assembly order. 8211cb0ef41Sopenharmony_ci DCHECK_EQ(block->rpo_number(), loop_end->successors()[0]); 8221cb0ef41Sopenharmony_ci loop_end->set_ao_number(RpoNumber::FromInt(ao++)); 8231cb0ef41Sopenharmony_ci ao_blocks_->push_back(loop_end); 8241cb0ef41Sopenharmony_ci // This block will be the new machine-level loop header, so align 8251cb0ef41Sopenharmony_ci // this block instead of the loop header block. 8261cb0ef41Sopenharmony_ci loop_end->set_loop_header_alignment(true); 8271cb0ef41Sopenharmony_ci header_align = false; 8281cb0ef41Sopenharmony_ci } 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci block->set_loop_header_alignment(header_align); 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci if (block->loop_header().IsValid() && block->IsSwitchTarget()) { 8331cb0ef41Sopenharmony_ci block->set_code_target_alignment(true); 8341cb0ef41Sopenharmony_ci } 8351cb0ef41Sopenharmony_ci block->set_ao_number(RpoNumber::FromInt(ao++)); 8361cb0ef41Sopenharmony_ci ao_blocks_->push_back(block); 8371cb0ef41Sopenharmony_ci } 8381cb0ef41Sopenharmony_ci // Add all leftover (deferred) blocks. 8391cb0ef41Sopenharmony_ci for (InstructionBlock* const block : *instruction_blocks_) { 8401cb0ef41Sopenharmony_ci if (block->ao_number() == invalid) { 8411cb0ef41Sopenharmony_ci block->set_ao_number(RpoNumber::FromInt(ao++)); 8421cb0ef41Sopenharmony_ci ao_blocks_->push_back(block); 8431cb0ef41Sopenharmony_ci } 8441cb0ef41Sopenharmony_ci } 8451cb0ef41Sopenharmony_ci DCHECK_EQ(instruction_blocks_->size(), ao); 8461cb0ef41Sopenharmony_ci} 8471cb0ef41Sopenharmony_ci 8481cb0ef41Sopenharmony_civoid InstructionSequence::RecomputeAssemblyOrderForTesting() { 8491cb0ef41Sopenharmony_ci RpoNumber invalid = RpoNumber::Invalid(); 8501cb0ef41Sopenharmony_ci for (InstructionBlock* block : *instruction_blocks_) { 8511cb0ef41Sopenharmony_ci block->set_ao_number(invalid); 8521cb0ef41Sopenharmony_ci } 8531cb0ef41Sopenharmony_ci ComputeAssemblyOrder(); 8541cb0ef41Sopenharmony_ci} 8551cb0ef41Sopenharmony_ci 8561cb0ef41Sopenharmony_ciInstructionSequence::InstructionSequence(Isolate* isolate, 8571cb0ef41Sopenharmony_ci Zone* instruction_zone, 8581cb0ef41Sopenharmony_ci InstructionBlocks* instruction_blocks) 8591cb0ef41Sopenharmony_ci : isolate_(isolate), 8601cb0ef41Sopenharmony_ci zone_(instruction_zone), 8611cb0ef41Sopenharmony_ci instruction_blocks_(instruction_blocks), 8621cb0ef41Sopenharmony_ci ao_blocks_(nullptr), 8631cb0ef41Sopenharmony_ci source_positions_(zone()), 8641cb0ef41Sopenharmony_ci constants_(ConstantMap::key_compare(), 8651cb0ef41Sopenharmony_ci ConstantMap::allocator_type(zone())), 8661cb0ef41Sopenharmony_ci immediates_(zone()), 8671cb0ef41Sopenharmony_ci rpo_immediates_(instruction_blocks->size(), zone()), 8681cb0ef41Sopenharmony_ci instructions_(zone()), 8691cb0ef41Sopenharmony_ci next_virtual_register_(0), 8701cb0ef41Sopenharmony_ci reference_maps_(zone()), 8711cb0ef41Sopenharmony_ci representations_(zone()), 8721cb0ef41Sopenharmony_ci representation_mask_(0), 8731cb0ef41Sopenharmony_ci deoptimization_entries_(zone()), 8741cb0ef41Sopenharmony_ci current_block_(nullptr) { 8751cb0ef41Sopenharmony_ci ComputeAssemblyOrder(); 8761cb0ef41Sopenharmony_ci} 8771cb0ef41Sopenharmony_ci 8781cb0ef41Sopenharmony_ciint InstructionSequence::NextVirtualRegister() { 8791cb0ef41Sopenharmony_ci int virtual_register = next_virtual_register_++; 8801cb0ef41Sopenharmony_ci CHECK_NE(virtual_register, InstructionOperand::kInvalidVirtualRegister); 8811cb0ef41Sopenharmony_ci return virtual_register; 8821cb0ef41Sopenharmony_ci} 8831cb0ef41Sopenharmony_ci 8841cb0ef41Sopenharmony_ciInstruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const { 8851cb0ef41Sopenharmony_ci const InstructionBlock* block = InstructionBlockAt(rpo); 8861cb0ef41Sopenharmony_ci return InstructionAt(block->code_start()); 8871cb0ef41Sopenharmony_ci} 8881cb0ef41Sopenharmony_ci 8891cb0ef41Sopenharmony_civoid InstructionSequence::StartBlock(RpoNumber rpo) { 8901cb0ef41Sopenharmony_ci DCHECK_NULL(current_block_); 8911cb0ef41Sopenharmony_ci current_block_ = InstructionBlockAt(rpo); 8921cb0ef41Sopenharmony_ci int code_start = static_cast<int>(instructions_.size()); 8931cb0ef41Sopenharmony_ci current_block_->set_code_start(code_start); 8941cb0ef41Sopenharmony_ci} 8951cb0ef41Sopenharmony_ci 8961cb0ef41Sopenharmony_civoid InstructionSequence::EndBlock(RpoNumber rpo) { 8971cb0ef41Sopenharmony_ci int end = static_cast<int>(instructions_.size()); 8981cb0ef41Sopenharmony_ci DCHECK_EQ(current_block_->rpo_number(), rpo); 8991cb0ef41Sopenharmony_ci CHECK(current_block_->code_start() >= 0 && 9001cb0ef41Sopenharmony_ci current_block_->code_start() < end); 9011cb0ef41Sopenharmony_ci current_block_->set_code_end(end); 9021cb0ef41Sopenharmony_ci current_block_ = nullptr; 9031cb0ef41Sopenharmony_ci} 9041cb0ef41Sopenharmony_ci 9051cb0ef41Sopenharmony_ciint InstructionSequence::AddInstruction(Instruction* instr) { 9061cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(current_block_); 9071cb0ef41Sopenharmony_ci int index = static_cast<int>(instructions_.size()); 9081cb0ef41Sopenharmony_ci instr->set_block(current_block_); 9091cb0ef41Sopenharmony_ci instructions_.push_back(instr); 9101cb0ef41Sopenharmony_ci if (instr->NeedsReferenceMap()) { 9111cb0ef41Sopenharmony_ci DCHECK_NULL(instr->reference_map()); 9121cb0ef41Sopenharmony_ci ReferenceMap* reference_map = zone()->New<ReferenceMap>(zone()); 9131cb0ef41Sopenharmony_ci reference_map->set_instruction_position(index); 9141cb0ef41Sopenharmony_ci instr->set_reference_map(reference_map); 9151cb0ef41Sopenharmony_ci reference_maps_.push_back(reference_map); 9161cb0ef41Sopenharmony_ci } 9171cb0ef41Sopenharmony_ci return index; 9181cb0ef41Sopenharmony_ci} 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_ciInstructionBlock* InstructionSequence::GetInstructionBlock( 9211cb0ef41Sopenharmony_ci int instruction_index) const { 9221cb0ef41Sopenharmony_ci return instructions()[instruction_index]->block(); 9231cb0ef41Sopenharmony_ci} 9241cb0ef41Sopenharmony_ci 9251cb0ef41Sopenharmony_cistatic MachineRepresentation FilterRepresentation(MachineRepresentation rep) { 9261cb0ef41Sopenharmony_ci switch (rep) { 9271cb0ef41Sopenharmony_ci case MachineRepresentation::kBit: 9281cb0ef41Sopenharmony_ci case MachineRepresentation::kWord8: 9291cb0ef41Sopenharmony_ci case MachineRepresentation::kWord16: 9301cb0ef41Sopenharmony_ci return InstructionSequence::DefaultRepresentation(); 9311cb0ef41Sopenharmony_ci case MachineRepresentation::kWord32: 9321cb0ef41Sopenharmony_ci case MachineRepresentation::kWord64: 9331cb0ef41Sopenharmony_ci case MachineRepresentation::kTaggedSigned: 9341cb0ef41Sopenharmony_ci case MachineRepresentation::kTaggedPointer: 9351cb0ef41Sopenharmony_ci case MachineRepresentation::kTagged: 9361cb0ef41Sopenharmony_ci case MachineRepresentation::kFloat32: 9371cb0ef41Sopenharmony_ci case MachineRepresentation::kFloat64: 9381cb0ef41Sopenharmony_ci case MachineRepresentation::kSimd128: 9391cb0ef41Sopenharmony_ci case MachineRepresentation::kCompressedPointer: 9401cb0ef41Sopenharmony_ci case MachineRepresentation::kCompressed: 9411cb0ef41Sopenharmony_ci case MachineRepresentation::kSandboxedPointer: 9421cb0ef41Sopenharmony_ci return rep; 9431cb0ef41Sopenharmony_ci case MachineRepresentation::kNone: 9441cb0ef41Sopenharmony_ci case MachineRepresentation::kMapWord: 9451cb0ef41Sopenharmony_ci break; 9461cb0ef41Sopenharmony_ci } 9471cb0ef41Sopenharmony_ci 9481cb0ef41Sopenharmony_ci UNREACHABLE(); 9491cb0ef41Sopenharmony_ci} 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ciMachineRepresentation InstructionSequence::GetRepresentation( 9521cb0ef41Sopenharmony_ci int virtual_register) const { 9531cb0ef41Sopenharmony_ci DCHECK_LE(0, virtual_register); 9541cb0ef41Sopenharmony_ci DCHECK_LT(virtual_register, VirtualRegisterCount()); 9551cb0ef41Sopenharmony_ci if (virtual_register >= static_cast<int>(representations_.size())) { 9561cb0ef41Sopenharmony_ci return DefaultRepresentation(); 9571cb0ef41Sopenharmony_ci } 9581cb0ef41Sopenharmony_ci return representations_[virtual_register]; 9591cb0ef41Sopenharmony_ci} 9601cb0ef41Sopenharmony_ci 9611cb0ef41Sopenharmony_civoid InstructionSequence::MarkAsRepresentation(MachineRepresentation rep, 9621cb0ef41Sopenharmony_ci int virtual_register) { 9631cb0ef41Sopenharmony_ci DCHECK_LE(0, virtual_register); 9641cb0ef41Sopenharmony_ci DCHECK_LT(virtual_register, VirtualRegisterCount()); 9651cb0ef41Sopenharmony_ci if (virtual_register >= static_cast<int>(representations_.size())) { 9661cb0ef41Sopenharmony_ci representations_.resize(VirtualRegisterCount(), DefaultRepresentation()); 9671cb0ef41Sopenharmony_ci } 9681cb0ef41Sopenharmony_ci rep = FilterRepresentation(rep); 9691cb0ef41Sopenharmony_ci DCHECK_IMPLIES(representations_[virtual_register] != rep, 9701cb0ef41Sopenharmony_ci representations_[virtual_register] == DefaultRepresentation()); 9711cb0ef41Sopenharmony_ci representations_[virtual_register] = rep; 9721cb0ef41Sopenharmony_ci representation_mask_ |= RepresentationBit(rep); 9731cb0ef41Sopenharmony_ci} 9741cb0ef41Sopenharmony_ci 9751cb0ef41Sopenharmony_ciint InstructionSequence::AddDeoptimizationEntry( 9761cb0ef41Sopenharmony_ci FrameStateDescriptor* descriptor, DeoptimizeKind kind, 9771cb0ef41Sopenharmony_ci DeoptimizeReason reason, NodeId node_id, FeedbackSource const& feedback) { 9781cb0ef41Sopenharmony_ci int deoptimization_id = static_cast<int>(deoptimization_entries_.size()); 9791cb0ef41Sopenharmony_ci deoptimization_entries_.push_back( 9801cb0ef41Sopenharmony_ci DeoptimizationEntry(descriptor, kind, reason, node_id, feedback)); 9811cb0ef41Sopenharmony_ci return deoptimization_id; 9821cb0ef41Sopenharmony_ci} 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_ciDeoptimizationEntry const& InstructionSequence::GetDeoptimizationEntry( 9851cb0ef41Sopenharmony_ci int state_id) { 9861cb0ef41Sopenharmony_ci return deoptimization_entries_[state_id]; 9871cb0ef41Sopenharmony_ci} 9881cb0ef41Sopenharmony_ci 9891cb0ef41Sopenharmony_ciRpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) { 9901cb0ef41Sopenharmony_ci InstructionOperand* operand = instr->InputAt(index); 9911cb0ef41Sopenharmony_ci Constant constant = 9921cb0ef41Sopenharmony_ci operand->IsImmediate() 9931cb0ef41Sopenharmony_ci ? GetImmediate(ImmediateOperand::cast(operand)) 9941cb0ef41Sopenharmony_ci : GetConstant(ConstantOperand::cast(operand)->virtual_register()); 9951cb0ef41Sopenharmony_ci return constant.ToRpoNumber(); 9961cb0ef41Sopenharmony_ci} 9971cb0ef41Sopenharmony_ci 9981cb0ef41Sopenharmony_cibool InstructionSequence::GetSourcePosition(const Instruction* instr, 9991cb0ef41Sopenharmony_ci SourcePosition* result) const { 10001cb0ef41Sopenharmony_ci auto it = source_positions_.find(instr); 10011cb0ef41Sopenharmony_ci if (it == source_positions_.end()) return false; 10021cb0ef41Sopenharmony_ci *result = it->second; 10031cb0ef41Sopenharmony_ci return true; 10041cb0ef41Sopenharmony_ci} 10051cb0ef41Sopenharmony_ci 10061cb0ef41Sopenharmony_civoid InstructionSequence::SetSourcePosition(const Instruction* instr, 10071cb0ef41Sopenharmony_ci SourcePosition value) { 10081cb0ef41Sopenharmony_ci source_positions_.insert(std::make_pair(instr, value)); 10091cb0ef41Sopenharmony_ci} 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_civoid InstructionSequence::Print() const { 10121cb0ef41Sopenharmony_ci StdoutStream{} << *this << std::endl; 10131cb0ef41Sopenharmony_ci} 10141cb0ef41Sopenharmony_ci 10151cb0ef41Sopenharmony_civoid InstructionSequence::PrintBlock(int block_id) const { 10161cb0ef41Sopenharmony_ci RpoNumber rpo = RpoNumber::FromInt(block_id); 10171cb0ef41Sopenharmony_ci const InstructionBlock* block = InstructionBlockAt(rpo); 10181cb0ef41Sopenharmony_ci CHECK(block->rpo_number() == rpo); 10191cb0ef41Sopenharmony_ci StdoutStream{} << PrintableInstructionBlock{block, this} << std::endl; 10201cb0ef41Sopenharmony_ci} 10211cb0ef41Sopenharmony_ci 10221cb0ef41Sopenharmony_ciconst RegisterConfiguration* 10231cb0ef41Sopenharmony_ci InstructionSequence::registerConfigurationForTesting_ = nullptr; 10241cb0ef41Sopenharmony_ci 10251cb0ef41Sopenharmony_ciconst RegisterConfiguration* 10261cb0ef41Sopenharmony_ciInstructionSequence::RegisterConfigurationForTesting() { 10271cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(registerConfigurationForTesting_); 10281cb0ef41Sopenharmony_ci return registerConfigurationForTesting_; 10291cb0ef41Sopenharmony_ci} 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_civoid InstructionSequence::SetRegisterConfigurationForTesting( 10321cb0ef41Sopenharmony_ci const RegisterConfiguration* regConfig) { 10331cb0ef41Sopenharmony_ci registerConfigurationForTesting_ = regConfig; 10341cb0ef41Sopenharmony_ci GetRegConfig = InstructionSequence::RegisterConfigurationForTesting; 10351cb0ef41Sopenharmony_ci} 10361cb0ef41Sopenharmony_ci 10371cb0ef41Sopenharmony_cinamespace { 10381cb0ef41Sopenharmony_ci 10391cb0ef41Sopenharmony_cisize_t GetConservativeFrameSizeInBytes(FrameStateType type, 10401cb0ef41Sopenharmony_ci size_t parameters_count, 10411cb0ef41Sopenharmony_ci size_t locals_count, 10421cb0ef41Sopenharmony_ci BytecodeOffset bailout_id) { 10431cb0ef41Sopenharmony_ci switch (type) { 10441cb0ef41Sopenharmony_ci case FrameStateType::kUnoptimizedFunction: { 10451cb0ef41Sopenharmony_ci auto info = UnoptimizedFrameInfo::Conservative( 10461cb0ef41Sopenharmony_ci static_cast<int>(parameters_count), static_cast<int>(locals_count)); 10471cb0ef41Sopenharmony_ci return info.frame_size_in_bytes(); 10481cb0ef41Sopenharmony_ci } 10491cb0ef41Sopenharmony_ci case FrameStateType::kArgumentsAdaptor: 10501cb0ef41Sopenharmony_ci // The arguments adaptor frame state is only used in the deoptimizer and 10511cb0ef41Sopenharmony_ci // does not occupy any extra space in the stack. Check out the design doc: 10521cb0ef41Sopenharmony_ci // https://docs.google.com/document/d/150wGaUREaZI6YWqOQFD5l2mWQXaPbbZjcAIJLOFrzMs/edit 10531cb0ef41Sopenharmony_ci // We just need to account for the additional parameters we might push 10541cb0ef41Sopenharmony_ci // here. 10551cb0ef41Sopenharmony_ci return UnoptimizedFrameInfo::GetStackSizeForAdditionalArguments( 10561cb0ef41Sopenharmony_ci static_cast<int>(parameters_count)); 10571cb0ef41Sopenharmony_ci case FrameStateType::kConstructStub: { 10581cb0ef41Sopenharmony_ci auto info = ConstructStubFrameInfo::Conservative( 10591cb0ef41Sopenharmony_ci static_cast<int>(parameters_count)); 10601cb0ef41Sopenharmony_ci return info.frame_size_in_bytes(); 10611cb0ef41Sopenharmony_ci } 10621cb0ef41Sopenharmony_ci case FrameStateType::kBuiltinContinuation: 10631cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 10641cb0ef41Sopenharmony_ci case FrameStateType::kJSToWasmBuiltinContinuation: 10651cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 10661cb0ef41Sopenharmony_ci case FrameStateType::kJavaScriptBuiltinContinuation: 10671cb0ef41Sopenharmony_ci case FrameStateType::kJavaScriptBuiltinContinuationWithCatch: { 10681cb0ef41Sopenharmony_ci const RegisterConfiguration* config = RegisterConfiguration::Default(); 10691cb0ef41Sopenharmony_ci auto info = BuiltinContinuationFrameInfo::Conservative( 10701cb0ef41Sopenharmony_ci static_cast<int>(parameters_count), 10711cb0ef41Sopenharmony_ci Builtins::CallInterfaceDescriptorFor( 10721cb0ef41Sopenharmony_ci Builtins::GetBuiltinFromBytecodeOffset(bailout_id)), 10731cb0ef41Sopenharmony_ci config); 10741cb0ef41Sopenharmony_ci return info.frame_size_in_bytes(); 10751cb0ef41Sopenharmony_ci } 10761cb0ef41Sopenharmony_ci } 10771cb0ef41Sopenharmony_ci UNREACHABLE(); 10781cb0ef41Sopenharmony_ci} 10791cb0ef41Sopenharmony_ci 10801cb0ef41Sopenharmony_cisize_t GetTotalConservativeFrameSizeInBytes(FrameStateType type, 10811cb0ef41Sopenharmony_ci size_t parameters_count, 10821cb0ef41Sopenharmony_ci size_t locals_count, 10831cb0ef41Sopenharmony_ci BytecodeOffset bailout_id, 10841cb0ef41Sopenharmony_ci FrameStateDescriptor* outer_state) { 10851cb0ef41Sopenharmony_ci size_t outer_total_conservative_frame_size_in_bytes = 10861cb0ef41Sopenharmony_ci (outer_state == nullptr) 10871cb0ef41Sopenharmony_ci ? 0 10881cb0ef41Sopenharmony_ci : outer_state->total_conservative_frame_size_in_bytes(); 10891cb0ef41Sopenharmony_ci return GetConservativeFrameSizeInBytes(type, parameters_count, locals_count, 10901cb0ef41Sopenharmony_ci bailout_id) + 10911cb0ef41Sopenharmony_ci outer_total_conservative_frame_size_in_bytes; 10921cb0ef41Sopenharmony_ci} 10931cb0ef41Sopenharmony_ci 10941cb0ef41Sopenharmony_ci} // namespace 10951cb0ef41Sopenharmony_ci 10961cb0ef41Sopenharmony_ciFrameStateDescriptor::FrameStateDescriptor( 10971cb0ef41Sopenharmony_ci Zone* zone, FrameStateType type, BytecodeOffset bailout_id, 10981cb0ef41Sopenharmony_ci OutputFrameStateCombine state_combine, size_t parameters_count, 10991cb0ef41Sopenharmony_ci size_t locals_count, size_t stack_count, 11001cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> shared_info, 11011cb0ef41Sopenharmony_ci FrameStateDescriptor* outer_state) 11021cb0ef41Sopenharmony_ci : type_(type), 11031cb0ef41Sopenharmony_ci bailout_id_(bailout_id), 11041cb0ef41Sopenharmony_ci frame_state_combine_(state_combine), 11051cb0ef41Sopenharmony_ci parameters_count_(parameters_count), 11061cb0ef41Sopenharmony_ci locals_count_(locals_count), 11071cb0ef41Sopenharmony_ci stack_count_(stack_count), 11081cb0ef41Sopenharmony_ci total_conservative_frame_size_in_bytes_( 11091cb0ef41Sopenharmony_ci GetTotalConservativeFrameSizeInBytes( 11101cb0ef41Sopenharmony_ci type, parameters_count, locals_count, bailout_id, outer_state)), 11111cb0ef41Sopenharmony_ci values_(zone), 11121cb0ef41Sopenharmony_ci shared_info_(shared_info), 11131cb0ef41Sopenharmony_ci outer_state_(outer_state) {} 11141cb0ef41Sopenharmony_ci 11151cb0ef41Sopenharmony_cisize_t FrameStateDescriptor::GetHeight() const { 11161cb0ef41Sopenharmony_ci switch (type()) { 11171cb0ef41Sopenharmony_ci case FrameStateType::kUnoptimizedFunction: 11181cb0ef41Sopenharmony_ci return locals_count(); // The accumulator is *not* included. 11191cb0ef41Sopenharmony_ci case FrameStateType::kBuiltinContinuation: 11201cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 11211cb0ef41Sopenharmony_ci case FrameStateType::kJSToWasmBuiltinContinuation: 11221cb0ef41Sopenharmony_ci#endif 11231cb0ef41Sopenharmony_ci // Custom, non-JS calling convention (that does not have a notion of 11241cb0ef41Sopenharmony_ci // a receiver or context). 11251cb0ef41Sopenharmony_ci return parameters_count(); 11261cb0ef41Sopenharmony_ci case FrameStateType::kArgumentsAdaptor: 11271cb0ef41Sopenharmony_ci case FrameStateType::kConstructStub: 11281cb0ef41Sopenharmony_ci case FrameStateType::kJavaScriptBuiltinContinuation: 11291cb0ef41Sopenharmony_ci case FrameStateType::kJavaScriptBuiltinContinuationWithCatch: 11301cb0ef41Sopenharmony_ci // JS linkage. The parameters count 11311cb0ef41Sopenharmony_ci // - includes the receiver (input 1 in CreateArtificialFrameState, and 11321cb0ef41Sopenharmony_ci // passed as part of stack parameters to 11331cb0ef41Sopenharmony_ci // CreateJavaScriptBuiltinContinuationFrameState), and 11341cb0ef41Sopenharmony_ci // - does *not* include the context. 11351cb0ef41Sopenharmony_ci return parameters_count(); 11361cb0ef41Sopenharmony_ci } 11371cb0ef41Sopenharmony_ci UNREACHABLE(); 11381cb0ef41Sopenharmony_ci} 11391cb0ef41Sopenharmony_ci 11401cb0ef41Sopenharmony_cisize_t FrameStateDescriptor::GetSize() const { 11411cb0ef41Sopenharmony_ci return 1 + parameters_count() + locals_count() + stack_count() + 11421cb0ef41Sopenharmony_ci (HasContext() ? 1 : 0); 11431cb0ef41Sopenharmony_ci} 11441cb0ef41Sopenharmony_ci 11451cb0ef41Sopenharmony_cisize_t FrameStateDescriptor::GetTotalSize() const { 11461cb0ef41Sopenharmony_ci size_t total_size = 0; 11471cb0ef41Sopenharmony_ci for (const FrameStateDescriptor* iter = this; iter != nullptr; 11481cb0ef41Sopenharmony_ci iter = iter->outer_state_) { 11491cb0ef41Sopenharmony_ci total_size += iter->GetSize(); 11501cb0ef41Sopenharmony_ci } 11511cb0ef41Sopenharmony_ci return total_size; 11521cb0ef41Sopenharmony_ci} 11531cb0ef41Sopenharmony_ci 11541cb0ef41Sopenharmony_cisize_t FrameStateDescriptor::GetFrameCount() const { 11551cb0ef41Sopenharmony_ci size_t count = 0; 11561cb0ef41Sopenharmony_ci for (const FrameStateDescriptor* iter = this; iter != nullptr; 11571cb0ef41Sopenharmony_ci iter = iter->outer_state_) { 11581cb0ef41Sopenharmony_ci ++count; 11591cb0ef41Sopenharmony_ci } 11601cb0ef41Sopenharmony_ci return count; 11611cb0ef41Sopenharmony_ci} 11621cb0ef41Sopenharmony_ci 11631cb0ef41Sopenharmony_cisize_t FrameStateDescriptor::GetJSFrameCount() const { 11641cb0ef41Sopenharmony_ci size_t count = 0; 11651cb0ef41Sopenharmony_ci for (const FrameStateDescriptor* iter = this; iter != nullptr; 11661cb0ef41Sopenharmony_ci iter = iter->outer_state_) { 11671cb0ef41Sopenharmony_ci if (FrameStateFunctionInfo::IsJSFunctionType(iter->type_)) { 11681cb0ef41Sopenharmony_ci ++count; 11691cb0ef41Sopenharmony_ci } 11701cb0ef41Sopenharmony_ci } 11711cb0ef41Sopenharmony_ci return count; 11721cb0ef41Sopenharmony_ci} 11731cb0ef41Sopenharmony_ci 11741cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 11751cb0ef41Sopenharmony_ciJSToWasmFrameStateDescriptor::JSToWasmFrameStateDescriptor( 11761cb0ef41Sopenharmony_ci Zone* zone, FrameStateType type, BytecodeOffset bailout_id, 11771cb0ef41Sopenharmony_ci OutputFrameStateCombine state_combine, size_t parameters_count, 11781cb0ef41Sopenharmony_ci size_t locals_count, size_t stack_count, 11791cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> shared_info, 11801cb0ef41Sopenharmony_ci FrameStateDescriptor* outer_state, const wasm::FunctionSig* wasm_signature) 11811cb0ef41Sopenharmony_ci : FrameStateDescriptor(zone, type, bailout_id, state_combine, 11821cb0ef41Sopenharmony_ci parameters_count, locals_count, stack_count, 11831cb0ef41Sopenharmony_ci shared_info, outer_state), 11841cb0ef41Sopenharmony_ci return_kind_(wasm::WasmReturnTypeFromSignature(wasm_signature)) {} 11851cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 11861cb0ef41Sopenharmony_ci 11871cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const RpoNumber& rpo) { 11881cb0ef41Sopenharmony_ci return os << rpo.ToSize(); 11891cb0ef41Sopenharmony_ci} 11901cb0ef41Sopenharmony_ci 11911cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const InstructionSequence& code) { 11921cb0ef41Sopenharmony_ci for (size_t i = 0; i < code.immediates_.size(); ++i) { 11931cb0ef41Sopenharmony_ci Constant constant = code.immediates_[i]; 11941cb0ef41Sopenharmony_ci os << "IMM#" << i << ": " << constant << "\n"; 11951cb0ef41Sopenharmony_ci } 11961cb0ef41Sopenharmony_ci int n = 0; 11971cb0ef41Sopenharmony_ci for (ConstantMap::const_iterator it = code.constants_.begin(); 11981cb0ef41Sopenharmony_ci it != code.constants_.end(); ++n, ++it) { 11991cb0ef41Sopenharmony_ci os << "CST#" << n << ": v" << it->first << " = " << it->second << "\n"; 12001cb0ef41Sopenharmony_ci } 12011cb0ef41Sopenharmony_ci for (int i = 0; i < code.InstructionBlockCount(); i++) { 12021cb0ef41Sopenharmony_ci auto* block = code.InstructionBlockAt(RpoNumber::FromInt(i)); 12031cb0ef41Sopenharmony_ci os << PrintableInstructionBlock{block, &code}; 12041cb0ef41Sopenharmony_ci } 12051cb0ef41Sopenharmony_ci return os; 12061cb0ef41Sopenharmony_ci} 12071cb0ef41Sopenharmony_ci 12081cb0ef41Sopenharmony_ci} // namespace compiler 12091cb0ef41Sopenharmony_ci} // namespace internal 12101cb0ef41Sopenharmony_ci} // namespace v8 1211