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_INSTRUCTION_SELECTOR_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <map> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/codegen/cpu-features.h" 111cb0ef41Sopenharmony_ci#include "src/common/globals.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction-scheduler.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h" 141cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/machine-operator.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 191cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 221cb0ef41Sopenharmony_ci#include "src/wasm/simd-shuffle.h" 231cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cinamespace v8 { 261cb0ef41Sopenharmony_cinamespace internal { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciclass TickCounter; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_cinamespace compiler { 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// Forward declarations. 331cb0ef41Sopenharmony_ciclass BasicBlock; 341cb0ef41Sopenharmony_cistruct CallBuffer; // TODO(bmeurer): Remove this. 351cb0ef41Sopenharmony_ciclass Linkage; 361cb0ef41Sopenharmony_ciclass OperandGenerator; 371cb0ef41Sopenharmony_ciclass SwitchInfo; 381cb0ef41Sopenharmony_ciclass StateObjectDeduplicator; 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci// The flags continuation is a way to combine a branch or a materialization 411cb0ef41Sopenharmony_ci// of a boolean value with an instruction that sets the flags register. 421cb0ef41Sopenharmony_ci// The whole instruction is treated as a unit by the register allocator, and 431cb0ef41Sopenharmony_ci// thus no spills or moves can be introduced between the flags-setting 441cb0ef41Sopenharmony_ci// instruction and the branch or set it should be combined with. 451cb0ef41Sopenharmony_ciclass FlagsContinuation final { 461cb0ef41Sopenharmony_ci public: 471cb0ef41Sopenharmony_ci FlagsContinuation() : mode_(kFlags_none) {} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci // Creates a new flags continuation from the given condition and true/false 501cb0ef41Sopenharmony_ci // blocks. 511cb0ef41Sopenharmony_ci static FlagsContinuation ForBranch(FlagsCondition condition, 521cb0ef41Sopenharmony_ci BasicBlock* true_block, 531cb0ef41Sopenharmony_ci BasicBlock* false_block) { 541cb0ef41Sopenharmony_ci return FlagsContinuation(kFlags_branch, condition, true_block, false_block); 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci // Creates a new flags continuation for an eager deoptimization exit. 581cb0ef41Sopenharmony_ci static FlagsContinuation ForDeoptimize(FlagsCondition condition, 591cb0ef41Sopenharmony_ci DeoptimizeReason reason, 601cb0ef41Sopenharmony_ci NodeId node_id, 611cb0ef41Sopenharmony_ci FeedbackSource const& feedback, 621cb0ef41Sopenharmony_ci FrameState frame_state) { 631cb0ef41Sopenharmony_ci return FlagsContinuation(kFlags_deoptimize, condition, reason, node_id, 641cb0ef41Sopenharmony_ci feedback, frame_state); 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci static FlagsContinuation ForDeoptimizeForTesting( 671cb0ef41Sopenharmony_ci FlagsCondition condition, DeoptimizeReason reason, NodeId node_id, 681cb0ef41Sopenharmony_ci FeedbackSource const& feedback, Node* frame_state) { 691cb0ef41Sopenharmony_ci // test-instruction-scheduler.cc passes a dummy Node* as frame_state. 701cb0ef41Sopenharmony_ci // Contents don't matter as long as it's not nullptr. 711cb0ef41Sopenharmony_ci return FlagsContinuation(kFlags_deoptimize, condition, reason, node_id, 721cb0ef41Sopenharmony_ci feedback, frame_state); 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci // Creates a new flags continuation for a boolean value. 761cb0ef41Sopenharmony_ci static FlagsContinuation ForSet(FlagsCondition condition, Node* result) { 771cb0ef41Sopenharmony_ci return FlagsContinuation(condition, result); 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci // Creates a new flags continuation for a wasm trap. 811cb0ef41Sopenharmony_ci static FlagsContinuation ForTrap(FlagsCondition condition, TrapId trap_id, 821cb0ef41Sopenharmony_ci Node* result) { 831cb0ef41Sopenharmony_ci return FlagsContinuation(condition, trap_id, result); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci static FlagsContinuation ForSelect(FlagsCondition condition, Node* result, 871cb0ef41Sopenharmony_ci Node* true_value, Node* false_value) { 881cb0ef41Sopenharmony_ci return FlagsContinuation(condition, result, true_value, false_value); 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci bool IsNone() const { return mode_ == kFlags_none; } 921cb0ef41Sopenharmony_ci bool IsBranch() const { return mode_ == kFlags_branch; } 931cb0ef41Sopenharmony_ci bool IsDeoptimize() const { return mode_ == kFlags_deoptimize; } 941cb0ef41Sopenharmony_ci bool IsSet() const { return mode_ == kFlags_set; } 951cb0ef41Sopenharmony_ci bool IsTrap() const { return mode_ == kFlags_trap; } 961cb0ef41Sopenharmony_ci bool IsSelect() const { return mode_ == kFlags_select; } 971cb0ef41Sopenharmony_ci FlagsCondition condition() const { 981cb0ef41Sopenharmony_ci DCHECK(!IsNone()); 991cb0ef41Sopenharmony_ci return condition_; 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci DeoptimizeReason reason() const { 1021cb0ef41Sopenharmony_ci DCHECK(IsDeoptimize()); 1031cb0ef41Sopenharmony_ci return reason_; 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci NodeId node_id() const { 1061cb0ef41Sopenharmony_ci DCHECK(IsDeoptimize()); 1071cb0ef41Sopenharmony_ci return node_id_; 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci FeedbackSource const& feedback() const { 1101cb0ef41Sopenharmony_ci DCHECK(IsDeoptimize()); 1111cb0ef41Sopenharmony_ci return feedback_; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci Node* frame_state() const { 1141cb0ef41Sopenharmony_ci DCHECK(IsDeoptimize()); 1151cb0ef41Sopenharmony_ci return frame_state_or_result_; 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci Node* result() const { 1181cb0ef41Sopenharmony_ci DCHECK(IsSet() || IsSelect()); 1191cb0ef41Sopenharmony_ci return frame_state_or_result_; 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci TrapId trap_id() const { 1221cb0ef41Sopenharmony_ci DCHECK(IsTrap()); 1231cb0ef41Sopenharmony_ci return trap_id_; 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci BasicBlock* true_block() const { 1261cb0ef41Sopenharmony_ci DCHECK(IsBranch()); 1271cb0ef41Sopenharmony_ci return true_block_; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci BasicBlock* false_block() const { 1301cb0ef41Sopenharmony_ci DCHECK(IsBranch()); 1311cb0ef41Sopenharmony_ci return false_block_; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci Node* true_value() const { 1341cb0ef41Sopenharmony_ci DCHECK(IsSelect()); 1351cb0ef41Sopenharmony_ci return true_value_; 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci Node* false_value() const { 1381cb0ef41Sopenharmony_ci DCHECK(IsSelect()); 1391cb0ef41Sopenharmony_ci return false_value_; 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci void Negate() { 1431cb0ef41Sopenharmony_ci DCHECK(!IsNone()); 1441cb0ef41Sopenharmony_ci condition_ = NegateFlagsCondition(condition_); 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci void Commute() { 1481cb0ef41Sopenharmony_ci DCHECK(!IsNone()); 1491cb0ef41Sopenharmony_ci condition_ = CommuteFlagsCondition(condition_); 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci void Overwrite(FlagsCondition condition) { condition_ = condition; } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci void OverwriteAndNegateIfEqual(FlagsCondition condition) { 1551cb0ef41Sopenharmony_ci DCHECK(condition_ == kEqual || condition_ == kNotEqual); 1561cb0ef41Sopenharmony_ci bool negate = condition_ == kEqual; 1571cb0ef41Sopenharmony_ci condition_ = condition; 1581cb0ef41Sopenharmony_ci if (negate) Negate(); 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci void OverwriteUnsignedIfSigned() { 1621cb0ef41Sopenharmony_ci switch (condition_) { 1631cb0ef41Sopenharmony_ci case kSignedLessThan: 1641cb0ef41Sopenharmony_ci condition_ = kUnsignedLessThan; 1651cb0ef41Sopenharmony_ci break; 1661cb0ef41Sopenharmony_ci case kSignedLessThanOrEqual: 1671cb0ef41Sopenharmony_ci condition_ = kUnsignedLessThanOrEqual; 1681cb0ef41Sopenharmony_ci break; 1691cb0ef41Sopenharmony_ci case kSignedGreaterThan: 1701cb0ef41Sopenharmony_ci condition_ = kUnsignedGreaterThan; 1711cb0ef41Sopenharmony_ci break; 1721cb0ef41Sopenharmony_ci case kSignedGreaterThanOrEqual: 1731cb0ef41Sopenharmony_ci condition_ = kUnsignedGreaterThanOrEqual; 1741cb0ef41Sopenharmony_ci break; 1751cb0ef41Sopenharmony_ci default: 1761cb0ef41Sopenharmony_ci break; 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci // Encodes this flags continuation into the given opcode. 1811cb0ef41Sopenharmony_ci InstructionCode Encode(InstructionCode opcode) { 1821cb0ef41Sopenharmony_ci opcode |= FlagsModeField::encode(mode_); 1831cb0ef41Sopenharmony_ci if (mode_ != kFlags_none) { 1841cb0ef41Sopenharmony_ci opcode |= FlagsConditionField::encode(condition_); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci return opcode; 1871cb0ef41Sopenharmony_ci } 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci private: 1901cb0ef41Sopenharmony_ci FlagsContinuation(FlagsMode mode, FlagsCondition condition, 1911cb0ef41Sopenharmony_ci BasicBlock* true_block, BasicBlock* false_block) 1921cb0ef41Sopenharmony_ci : mode_(mode), 1931cb0ef41Sopenharmony_ci condition_(condition), 1941cb0ef41Sopenharmony_ci true_block_(true_block), 1951cb0ef41Sopenharmony_ci false_block_(false_block) { 1961cb0ef41Sopenharmony_ci DCHECK(mode == kFlags_branch); 1971cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(true_block); 1981cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(false_block); 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci FlagsContinuation(FlagsMode mode, FlagsCondition condition, 2021cb0ef41Sopenharmony_ci DeoptimizeReason reason, NodeId node_id, 2031cb0ef41Sopenharmony_ci FeedbackSource const& feedback, Node* frame_state) 2041cb0ef41Sopenharmony_ci : mode_(mode), 2051cb0ef41Sopenharmony_ci condition_(condition), 2061cb0ef41Sopenharmony_ci reason_(reason), 2071cb0ef41Sopenharmony_ci node_id_(node_id), 2081cb0ef41Sopenharmony_ci feedback_(feedback), 2091cb0ef41Sopenharmony_ci frame_state_or_result_(frame_state) { 2101cb0ef41Sopenharmony_ci DCHECK(mode == kFlags_deoptimize); 2111cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(frame_state); 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci FlagsContinuation(FlagsCondition condition, Node* result) 2151cb0ef41Sopenharmony_ci : mode_(kFlags_set), 2161cb0ef41Sopenharmony_ci condition_(condition), 2171cb0ef41Sopenharmony_ci frame_state_or_result_(result) { 2181cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(result); 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci FlagsContinuation(FlagsCondition condition, TrapId trap_id, Node* result) 2221cb0ef41Sopenharmony_ci : mode_(kFlags_trap), 2231cb0ef41Sopenharmony_ci condition_(condition), 2241cb0ef41Sopenharmony_ci frame_state_or_result_(result), 2251cb0ef41Sopenharmony_ci trap_id_(trap_id) { 2261cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(result); 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci FlagsContinuation(FlagsCondition condition, Node* result, Node* true_value, 2301cb0ef41Sopenharmony_ci Node* false_value) 2311cb0ef41Sopenharmony_ci : mode_(kFlags_select), 2321cb0ef41Sopenharmony_ci condition_(condition), 2331cb0ef41Sopenharmony_ci frame_state_or_result_(result), 2341cb0ef41Sopenharmony_ci true_value_(true_value), 2351cb0ef41Sopenharmony_ci false_value_(false_value) { 2361cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(result); 2371cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(true_value); 2381cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(false_value); 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci FlagsMode const mode_; 2421cb0ef41Sopenharmony_ci FlagsCondition condition_; 2431cb0ef41Sopenharmony_ci DeoptimizeReason reason_; // Only valid if mode_ == kFlags_deoptimize* 2441cb0ef41Sopenharmony_ci NodeId node_id_; // Only valid if mode_ == kFlags_deoptimize* 2451cb0ef41Sopenharmony_ci FeedbackSource feedback_; // Only valid if mode_ == kFlags_deoptimize* 2461cb0ef41Sopenharmony_ci Node* frame_state_or_result_; // Only valid if mode_ == kFlags_deoptimize* 2471cb0ef41Sopenharmony_ci // or mode_ == kFlags_set. 2481cb0ef41Sopenharmony_ci BasicBlock* true_block_; // Only valid if mode_ == kFlags_branch*. 2491cb0ef41Sopenharmony_ci BasicBlock* false_block_; // Only valid if mode_ == kFlags_branch*. 2501cb0ef41Sopenharmony_ci TrapId trap_id_; // Only valid if mode_ == kFlags_trap. 2511cb0ef41Sopenharmony_ci Node* true_value_; // Only valid if mode_ == kFlags_select. 2521cb0ef41Sopenharmony_ci Node* false_value_; // Only valid if mode_ == kFlags_select. 2531cb0ef41Sopenharmony_ci}; 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci// This struct connects nodes of parameters which are going to be pushed on the 2561cb0ef41Sopenharmony_ci// call stack with their parameter index in the call descriptor of the callee. 2571cb0ef41Sopenharmony_cistruct PushParameter { 2581cb0ef41Sopenharmony_ci PushParameter(Node* n = nullptr, 2591cb0ef41Sopenharmony_ci LinkageLocation l = LinkageLocation::ForAnyRegister()) 2601cb0ef41Sopenharmony_ci : node(n), location(l) {} 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci Node* node; 2631cb0ef41Sopenharmony_ci LinkageLocation location; 2641cb0ef41Sopenharmony_ci}; 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_cienum class FrameStateInputKind { kAny, kStackSlot }; 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci// Instruction selection generates an InstructionSequence for a given Schedule. 2691cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE InstructionSelector final { 2701cb0ef41Sopenharmony_ci public: 2711cb0ef41Sopenharmony_ci // Forward declarations. 2721cb0ef41Sopenharmony_ci class Features; 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci enum SourcePositionMode { kCallSourcePositions, kAllSourcePositions }; 2751cb0ef41Sopenharmony_ci enum EnableScheduling { kDisableScheduling, kEnableScheduling }; 2761cb0ef41Sopenharmony_ci enum EnableRootsRelativeAddressing { 2771cb0ef41Sopenharmony_ci kDisableRootsRelativeAddressing, 2781cb0ef41Sopenharmony_ci kEnableRootsRelativeAddressing 2791cb0ef41Sopenharmony_ci }; 2801cb0ef41Sopenharmony_ci enum EnableSwitchJumpTable { 2811cb0ef41Sopenharmony_ci kDisableSwitchJumpTable, 2821cb0ef41Sopenharmony_ci kEnableSwitchJumpTable 2831cb0ef41Sopenharmony_ci }; 2841cb0ef41Sopenharmony_ci enum EnableTraceTurboJson { kDisableTraceTurboJson, kEnableTraceTurboJson }; 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci InstructionSelector( 2871cb0ef41Sopenharmony_ci Zone* zone, size_t node_count, Linkage* linkage, 2881cb0ef41Sopenharmony_ci InstructionSequence* sequence, Schedule* schedule, 2891cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, Frame* frame, 2901cb0ef41Sopenharmony_ci EnableSwitchJumpTable enable_switch_jump_table, TickCounter* tick_counter, 2911cb0ef41Sopenharmony_ci JSHeapBroker* broker, size_t* max_unoptimized_frame_height, 2921cb0ef41Sopenharmony_ci size_t* max_pushed_argument_count, 2931cb0ef41Sopenharmony_ci SourcePositionMode source_position_mode = kCallSourcePositions, 2941cb0ef41Sopenharmony_ci Features features = SupportedFeatures(), 2951cb0ef41Sopenharmony_ci EnableScheduling enable_scheduling = FLAG_turbo_instruction_scheduling 2961cb0ef41Sopenharmony_ci ? kEnableScheduling 2971cb0ef41Sopenharmony_ci : kDisableScheduling, 2981cb0ef41Sopenharmony_ci EnableRootsRelativeAddressing enable_roots_relative_addressing = 2991cb0ef41Sopenharmony_ci kDisableRootsRelativeAddressing, 3001cb0ef41Sopenharmony_ci EnableTraceTurboJson trace_turbo = kDisableTraceTurboJson); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci // Visit code for the entire graph with the included schedule. 3031cb0ef41Sopenharmony_ci bool SelectInstructions(); 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci void StartBlock(RpoNumber rpo); 3061cb0ef41Sopenharmony_ci void EndBlock(RpoNumber rpo); 3071cb0ef41Sopenharmony_ci void AddInstruction(Instruction* instr); 3081cb0ef41Sopenharmony_ci void AddTerminator(Instruction* instr); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // =========================================================================== 3111cb0ef41Sopenharmony_ci // ============= Architecture-independent code emission methods. ============= 3121cb0ef41Sopenharmony_ci // =========================================================================== 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3151cb0ef41Sopenharmony_ci size_t temp_count = 0, InstructionOperand* temps = nullptr); 3161cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3171cb0ef41Sopenharmony_ci InstructionOperand a, size_t temp_count = 0, 3181cb0ef41Sopenharmony_ci InstructionOperand* temps = nullptr); 3191cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3201cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3211cb0ef41Sopenharmony_ci size_t temp_count = 0, InstructionOperand* temps = nullptr); 3221cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3231cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3241cb0ef41Sopenharmony_ci InstructionOperand c, size_t temp_count = 0, 3251cb0ef41Sopenharmony_ci InstructionOperand* temps = nullptr); 3261cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3271cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3281cb0ef41Sopenharmony_ci InstructionOperand c, InstructionOperand d, 3291cb0ef41Sopenharmony_ci size_t temp_count = 0, InstructionOperand* temps = nullptr); 3301cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3311cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3321cb0ef41Sopenharmony_ci InstructionOperand c, InstructionOperand d, 3331cb0ef41Sopenharmony_ci InstructionOperand e, size_t temp_count = 0, 3341cb0ef41Sopenharmony_ci InstructionOperand* temps = nullptr); 3351cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, InstructionOperand output, 3361cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3371cb0ef41Sopenharmony_ci InstructionOperand c, InstructionOperand d, 3381cb0ef41Sopenharmony_ci InstructionOperand e, InstructionOperand f, 3391cb0ef41Sopenharmony_ci size_t temp_count = 0, InstructionOperand* temps = nullptr); 3401cb0ef41Sopenharmony_ci Instruction* Emit(InstructionCode opcode, size_t output_count, 3411cb0ef41Sopenharmony_ci InstructionOperand* outputs, size_t input_count, 3421cb0ef41Sopenharmony_ci InstructionOperand* inputs, size_t temp_count = 0, 3431cb0ef41Sopenharmony_ci InstructionOperand* temps = nullptr); 3441cb0ef41Sopenharmony_ci Instruction* Emit(Instruction* instr); 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci // [0-3] operand instructions with no output, uses labels for true and false 3471cb0ef41Sopenharmony_ci // blocks of the continuation. 3481cb0ef41Sopenharmony_ci Instruction* EmitWithContinuation(InstructionCode opcode, 3491cb0ef41Sopenharmony_ci FlagsContinuation* cont); 3501cb0ef41Sopenharmony_ci Instruction* EmitWithContinuation(InstructionCode opcode, 3511cb0ef41Sopenharmony_ci InstructionOperand a, 3521cb0ef41Sopenharmony_ci FlagsContinuation* cont); 3531cb0ef41Sopenharmony_ci Instruction* EmitWithContinuation(InstructionCode opcode, 3541cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3551cb0ef41Sopenharmony_ci FlagsContinuation* cont); 3561cb0ef41Sopenharmony_ci Instruction* EmitWithContinuation(InstructionCode opcode, 3571cb0ef41Sopenharmony_ci InstructionOperand a, InstructionOperand b, 3581cb0ef41Sopenharmony_ci InstructionOperand c, 3591cb0ef41Sopenharmony_ci FlagsContinuation* cont); 3601cb0ef41Sopenharmony_ci Instruction* EmitWithContinuation(InstructionCode opcode, size_t output_count, 3611cb0ef41Sopenharmony_ci InstructionOperand* outputs, 3621cb0ef41Sopenharmony_ci size_t input_count, 3631cb0ef41Sopenharmony_ci InstructionOperand* inputs, 3641cb0ef41Sopenharmony_ci FlagsContinuation* cont); 3651cb0ef41Sopenharmony_ci Instruction* EmitWithContinuation( 3661cb0ef41Sopenharmony_ci InstructionCode opcode, size_t output_count, InstructionOperand* outputs, 3671cb0ef41Sopenharmony_ci size_t input_count, InstructionOperand* inputs, size_t temp_count, 3681cb0ef41Sopenharmony_ci InstructionOperand* temps, FlagsContinuation* cont); 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci void EmitIdentity(Node* node); 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci // =========================================================================== 3731cb0ef41Sopenharmony_ci // ============== Architecture-independent CPU feature methods. ============== 3741cb0ef41Sopenharmony_ci // =========================================================================== 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci class Features final { 3771cb0ef41Sopenharmony_ci public: 3781cb0ef41Sopenharmony_ci Features() : bits_(0) {} 3791cb0ef41Sopenharmony_ci explicit Features(unsigned bits) : bits_(bits) {} 3801cb0ef41Sopenharmony_ci explicit Features(CpuFeature f) : bits_(1u << f) {} 3811cb0ef41Sopenharmony_ci Features(CpuFeature f1, CpuFeature f2) : bits_((1u << f1) | (1u << f2)) {} 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci bool Contains(CpuFeature f) const { return (bits_ & (1u << f)); } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci private: 3861cb0ef41Sopenharmony_ci unsigned bits_; 3871cb0ef41Sopenharmony_ci }; 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci bool IsSupported(CpuFeature feature) const { 3901cb0ef41Sopenharmony_ci return features_.Contains(feature); 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci // Returns the features supported on the target platform. 3941cb0ef41Sopenharmony_ci static Features SupportedFeatures() { 3951cb0ef41Sopenharmony_ci return Features(CpuFeatures::SupportedFeatures()); 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci // TODO(sigurds) This should take a CpuFeatures argument. 3991cb0ef41Sopenharmony_ci static MachineOperatorBuilder::Flags SupportedMachineOperatorFlags(); 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci static MachineOperatorBuilder::AlignmentRequirements AlignmentRequirements(); 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci // =========================================================================== 4041cb0ef41Sopenharmony_ci // ============ Architecture-independent graph covering methods. ============= 4051cb0ef41Sopenharmony_ci // =========================================================================== 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci // Used in pattern matching during code generation. 4081cb0ef41Sopenharmony_ci // Check if {node} can be covered while generating code for the current 4091cb0ef41Sopenharmony_ci // instruction. A node can be covered if the {user} of the node has the only 4101cb0ef41Sopenharmony_ci // edge, the two are in the same basic block, and there are no side-effects 4111cb0ef41Sopenharmony_ci // in-between. The last check is crucial for soundness. 4121cb0ef41Sopenharmony_ci // For pure nodes, CanCover(a,b) is checked to avoid duplicated execution: 4131cb0ef41Sopenharmony_ci // If this is not the case, code for b must still be generated for other 4141cb0ef41Sopenharmony_ci // users, and fusing is unlikely to improve performance. 4151cb0ef41Sopenharmony_ci bool CanCover(Node* user, Node* node) const; 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci // Used in pattern matching during code generation. 4181cb0ef41Sopenharmony_ci // This function checks that {node} and {user} are in the same basic block, 4191cb0ef41Sopenharmony_ci // and that {user} is the only user of {node} in this basic block. This 4201cb0ef41Sopenharmony_ci // check guarantees that there are no users of {node} scheduled between 4211cb0ef41Sopenharmony_ci // {node} and {user}, and thus we can select a single instruction for both 4221cb0ef41Sopenharmony_ci // nodes, if such an instruction exists. This check can be used for example 4231cb0ef41Sopenharmony_ci // when selecting instructions for: 4241cb0ef41Sopenharmony_ci // n = Int32Add(a, b) 4251cb0ef41Sopenharmony_ci // c = Word32Compare(n, 0, cond) 4261cb0ef41Sopenharmony_ci // Branch(c, true_label, false_label) 4271cb0ef41Sopenharmony_ci // Here we can generate a flag-setting add instruction, even if the add has 4281cb0ef41Sopenharmony_ci // uses in other basic blocks, since the flag-setting add instruction will 4291cb0ef41Sopenharmony_ci // still generate the result of the addition and not just set the flags. 4301cb0ef41Sopenharmony_ci // However, if we had uses of the add in the same basic block, we could have: 4311cb0ef41Sopenharmony_ci // n = Int32Add(a, b) 4321cb0ef41Sopenharmony_ci // o = OtherOp(n, ...) 4331cb0ef41Sopenharmony_ci // c = Word32Compare(n, 0, cond) 4341cb0ef41Sopenharmony_ci // Branch(c, true_label, false_label) 4351cb0ef41Sopenharmony_ci // where we cannot select the add and the compare together. If we were to 4361cb0ef41Sopenharmony_ci // select a flag-setting add instruction for Word32Compare and Int32Add while 4371cb0ef41Sopenharmony_ci // visiting Word32Compare, we would then have to select an instruction for 4381cb0ef41Sopenharmony_ci // OtherOp *afterwards*, which means we would attempt to use the result of 4391cb0ef41Sopenharmony_ci // the add before we have defined it. 4401cb0ef41Sopenharmony_ci bool IsOnlyUserOfNodeInSameBlock(Node* user, Node* node) const; 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci // Checks if {node} was already defined, and therefore code was already 4431cb0ef41Sopenharmony_ci // generated for it. 4441cb0ef41Sopenharmony_ci bool IsDefined(Node* node) const; 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci // Checks if {node} has any uses, and therefore code has to be generated for 4471cb0ef41Sopenharmony_ci // it. 4481cb0ef41Sopenharmony_ci bool IsUsed(Node* node) const; 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci // Checks if {node} is currently live. 4511cb0ef41Sopenharmony_ci bool IsLive(Node* node) const { return !IsDefined(node) && IsUsed(node); } 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_ci // Gets the effect level of {node}. 4541cb0ef41Sopenharmony_ci int GetEffectLevel(Node* node) const; 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci // Gets the effect level of {node}, appropriately adjusted based on 4571cb0ef41Sopenharmony_ci // continuation flags if the node is a branch. 4581cb0ef41Sopenharmony_ci int GetEffectLevel(Node* node, FlagsContinuation* cont) const; 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ci int GetVirtualRegister(const Node* node); 4611cb0ef41Sopenharmony_ci const std::map<NodeId, int> GetVirtualRegistersForTesting() const; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci // Check if we can generate loads and stores of ExternalConstants relative 4641cb0ef41Sopenharmony_ci // to the roots register. 4651cb0ef41Sopenharmony_ci bool CanAddressRelativeToRootsRegister( 4661cb0ef41Sopenharmony_ci const ExternalReference& reference) const; 4671cb0ef41Sopenharmony_ci // Check if we can use the roots register to access GC roots. 4681cb0ef41Sopenharmony_ci bool CanUseRootsRegister() const; 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci Isolate* isolate() const { return sequence()->isolate(); } 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci const ZoneVector<std::pair<int, int>>& instr_origins() const { 4731cb0ef41Sopenharmony_ci return instr_origins_; 4741cb0ef41Sopenharmony_ci } 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci private: 4771cb0ef41Sopenharmony_ci friend class OperandGenerator; 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci bool UseInstructionScheduling() const { 4801cb0ef41Sopenharmony_ci return (enable_scheduling_ == kEnableScheduling) && 4811cb0ef41Sopenharmony_ci InstructionScheduler::SchedulerSupported(); 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci void AppendDeoptimizeArguments(InstructionOperandVector* args, 4851cb0ef41Sopenharmony_ci DeoptimizeReason reason, NodeId node_id, 4861cb0ef41Sopenharmony_ci FeedbackSource const& feedback, 4871cb0ef41Sopenharmony_ci FrameState frame_state); 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci void EmitTableSwitch(const SwitchInfo& sw, 4901cb0ef41Sopenharmony_ci InstructionOperand const& index_operand); 4911cb0ef41Sopenharmony_ci void EmitBinarySearchSwitch(const SwitchInfo& sw, 4921cb0ef41Sopenharmony_ci InstructionOperand const& value_operand); 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci void TryRename(InstructionOperand* op); 4951cb0ef41Sopenharmony_ci int GetRename(int virtual_register); 4961cb0ef41Sopenharmony_ci void SetRename(const Node* node, const Node* rename); 4971cb0ef41Sopenharmony_ci void UpdateRenames(Instruction* instruction); 4981cb0ef41Sopenharmony_ci void UpdateRenamesInPhi(PhiInstruction* phi); 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci // Inform the instruction selection that {node} was just defined. 5011cb0ef41Sopenharmony_ci void MarkAsDefined(Node* node); 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci // Inform the instruction selection that {node} has at least one use and we 5041cb0ef41Sopenharmony_ci // will need to generate code for it. 5051cb0ef41Sopenharmony_ci void MarkAsUsed(Node* node); 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci // Sets the effect level of {node}. 5081cb0ef41Sopenharmony_ci void SetEffectLevel(Node* node, int effect_level); 5091cb0ef41Sopenharmony_ci 5101cb0ef41Sopenharmony_ci // Inform the register allocation of the representation of the value produced 5111cb0ef41Sopenharmony_ci // by {node}. 5121cb0ef41Sopenharmony_ci void MarkAsRepresentation(MachineRepresentation rep, Node* node); 5131cb0ef41Sopenharmony_ci void MarkAsWord32(Node* node) { 5141cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kWord32, node); 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci void MarkAsWord64(Node* node) { 5171cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kWord64, node); 5181cb0ef41Sopenharmony_ci } 5191cb0ef41Sopenharmony_ci void MarkAsFloat32(Node* node) { 5201cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kFloat32, node); 5211cb0ef41Sopenharmony_ci } 5221cb0ef41Sopenharmony_ci void MarkAsFloat64(Node* node) { 5231cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kFloat64, node); 5241cb0ef41Sopenharmony_ci } 5251cb0ef41Sopenharmony_ci void MarkAsSimd128(Node* node) { 5261cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kSimd128, node); 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci void MarkAsTagged(Node* node) { 5291cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kTagged, node); 5301cb0ef41Sopenharmony_ci } 5311cb0ef41Sopenharmony_ci void MarkAsCompressed(Node* node) { 5321cb0ef41Sopenharmony_ci MarkAsRepresentation(MachineRepresentation::kCompressed, node); 5331cb0ef41Sopenharmony_ci } 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci // Inform the register allocation of the representation of the unallocated 5361cb0ef41Sopenharmony_ci // operand {op}. 5371cb0ef41Sopenharmony_ci void MarkAsRepresentation(MachineRepresentation rep, 5381cb0ef41Sopenharmony_ci const InstructionOperand& op); 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ci enum CallBufferFlag { 5411cb0ef41Sopenharmony_ci kCallCodeImmediate = 1u << 0, 5421cb0ef41Sopenharmony_ci kCallAddressImmediate = 1u << 1, 5431cb0ef41Sopenharmony_ci kCallTail = 1u << 2, 5441cb0ef41Sopenharmony_ci kCallFixedTargetRegister = 1u << 3 5451cb0ef41Sopenharmony_ci }; 5461cb0ef41Sopenharmony_ci using CallBufferFlags = base::Flags<CallBufferFlag>; 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci // Initialize the call buffer with the InstructionOperands, nodes, etc, 5491cb0ef41Sopenharmony_ci // corresponding 5501cb0ef41Sopenharmony_ci // to the inputs and outputs of the call. 5511cb0ef41Sopenharmony_ci // {call_code_immediate} to generate immediate operands to calls of code. 5521cb0ef41Sopenharmony_ci // {call_address_immediate} to generate immediate operands to address calls. 5531cb0ef41Sopenharmony_ci void InitializeCallBuffer(Node* call, CallBuffer* buffer, 5541cb0ef41Sopenharmony_ci CallBufferFlags flags, int stack_slot_delta = 0); 5551cb0ef41Sopenharmony_ci bool IsTailCallAddressImmediate(); 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci void UpdateMaxPushedArgumentCount(size_t count); 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_ci FrameStateDescriptor* GetFrameStateDescriptor(FrameState node); 5601cb0ef41Sopenharmony_ci size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor, 5611cb0ef41Sopenharmony_ci FrameState state, OperandGenerator* g, 5621cb0ef41Sopenharmony_ci StateObjectDeduplicator* deduplicator, 5631cb0ef41Sopenharmony_ci InstructionOperandVector* inputs, 5641cb0ef41Sopenharmony_ci FrameStateInputKind kind, Zone* zone); 5651cb0ef41Sopenharmony_ci size_t AddInputsToFrameStateDescriptor(StateValueList* values, 5661cb0ef41Sopenharmony_ci InstructionOperandVector* inputs, 5671cb0ef41Sopenharmony_ci OperandGenerator* g, 5681cb0ef41Sopenharmony_ci StateObjectDeduplicator* deduplicator, 5691cb0ef41Sopenharmony_ci Node* node, FrameStateInputKind kind, 5701cb0ef41Sopenharmony_ci Zone* zone); 5711cb0ef41Sopenharmony_ci size_t AddOperandToStateValueDescriptor(StateValueList* values, 5721cb0ef41Sopenharmony_ci InstructionOperandVector* inputs, 5731cb0ef41Sopenharmony_ci OperandGenerator* g, 5741cb0ef41Sopenharmony_ci StateObjectDeduplicator* deduplicator, 5751cb0ef41Sopenharmony_ci Node* input, MachineType type, 5761cb0ef41Sopenharmony_ci FrameStateInputKind kind, Zone* zone); 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ci // =========================================================================== 5791cb0ef41Sopenharmony_ci // ============= Architecture-specific graph covering methods. =============== 5801cb0ef41Sopenharmony_ci // =========================================================================== 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci // Visit nodes in the given block and generate code. 5831cb0ef41Sopenharmony_ci void VisitBlock(BasicBlock* block); 5841cb0ef41Sopenharmony_ci 5851cb0ef41Sopenharmony_ci // Visit the node for the control flow at the end of the block, generating 5861cb0ef41Sopenharmony_ci // code if necessary. 5871cb0ef41Sopenharmony_ci void VisitControl(BasicBlock* block); 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci // Visit the node and generate code, if any. 5901cb0ef41Sopenharmony_ci void VisitNode(Node* node); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci // Visit the node and generate code for IEEE 754 functions. 5931cb0ef41Sopenharmony_ci void VisitFloat64Ieee754Binop(Node*, InstructionCode code); 5941cb0ef41Sopenharmony_ci void VisitFloat64Ieee754Unop(Node*, InstructionCode code); 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci#define DECLARE_GENERATOR(x) void Visit##x(Node* node); 5971cb0ef41Sopenharmony_ci MACHINE_OP_LIST(DECLARE_GENERATOR) 5981cb0ef41Sopenharmony_ci MACHINE_SIMD_OP_LIST(DECLARE_GENERATOR) 5991cb0ef41Sopenharmony_ci#undef DECLARE_GENERATOR 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_ci // Visit the load node with a value and opcode to replace with. 6021cb0ef41Sopenharmony_ci void VisitLoad(Node* node, Node* value, InstructionCode opcode); 6031cb0ef41Sopenharmony_ci void VisitLoadTransform(Node* node, Node* value, InstructionCode opcode); 6041cb0ef41Sopenharmony_ci void VisitFinishRegion(Node* node); 6051cb0ef41Sopenharmony_ci void VisitParameter(Node* node); 6061cb0ef41Sopenharmony_ci void VisitIfException(Node* node); 6071cb0ef41Sopenharmony_ci void VisitOsrValue(Node* node); 6081cb0ef41Sopenharmony_ci void VisitPhi(Node* node); 6091cb0ef41Sopenharmony_ci void VisitProjection(Node* node); 6101cb0ef41Sopenharmony_ci void VisitConstant(Node* node); 6111cb0ef41Sopenharmony_ci void VisitCall(Node* call, BasicBlock* handler = nullptr); 6121cb0ef41Sopenharmony_ci void VisitDeoptimizeIf(Node* node); 6131cb0ef41Sopenharmony_ci void VisitDeoptimizeUnless(Node* node); 6141cb0ef41Sopenharmony_ci void VisitDynamicCheckMapsWithDeoptUnless(Node* node); 6151cb0ef41Sopenharmony_ci void VisitTrapIf(Node* node, TrapId trap_id); 6161cb0ef41Sopenharmony_ci void VisitTrapUnless(Node* node, TrapId trap_id); 6171cb0ef41Sopenharmony_ci void VisitTailCall(Node* call); 6181cb0ef41Sopenharmony_ci void VisitGoto(BasicBlock* target); 6191cb0ef41Sopenharmony_ci void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch); 6201cb0ef41Sopenharmony_ci void VisitSwitch(Node* node, const SwitchInfo& sw); 6211cb0ef41Sopenharmony_ci void VisitDeoptimize(DeoptimizeReason reason, NodeId node_id, 6221cb0ef41Sopenharmony_ci FeedbackSource const& feedback, FrameState frame_state); 6231cb0ef41Sopenharmony_ci void VisitSelect(Node* node); 6241cb0ef41Sopenharmony_ci void VisitReturn(Node* ret); 6251cb0ef41Sopenharmony_ci void VisitThrow(Node* node); 6261cb0ef41Sopenharmony_ci void VisitRetain(Node* node); 6271cb0ef41Sopenharmony_ci void VisitUnreachable(Node* node); 6281cb0ef41Sopenharmony_ci void VisitStaticAssert(Node* node); 6291cb0ef41Sopenharmony_ci void VisitDeadValue(Node* node); 6301cb0ef41Sopenharmony_ci 6311cb0ef41Sopenharmony_ci void VisitStackPointerGreaterThan(Node* node, FlagsContinuation* cont); 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci void VisitWordCompareZero(Node* user, Node* value, FlagsContinuation* cont); 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments, 6361cb0ef41Sopenharmony_ci const CallDescriptor* call_descriptor, Node* node); 6371cb0ef41Sopenharmony_ci void EmitPrepareResults(ZoneVector<compiler::PushParameter>* results, 6381cb0ef41Sopenharmony_ci const CallDescriptor* call_descriptor, Node* node); 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ci bool CanProduceSignalingNaN(Node* node); 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_ci void AddOutputToSelectContinuation(OperandGenerator* g, int first_input_index, 6431cb0ef41Sopenharmony_ci Node* node); 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_ci // =========================================================================== 6461cb0ef41Sopenharmony_ci // ============= Vector instruction (SIMD) helper fns. ======================= 6471cb0ef41Sopenharmony_ci // =========================================================================== 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 6501cb0ef41Sopenharmony_ci // Canonicalize shuffles to make pattern matching simpler. Returns the shuffle 6511cb0ef41Sopenharmony_ci // indices, and a boolean indicating if the shuffle is a swizzle (one input). 6521cb0ef41Sopenharmony_ci void CanonicalizeShuffle(Node* node, uint8_t* shuffle, bool* is_swizzle); 6531cb0ef41Sopenharmony_ci 6541cb0ef41Sopenharmony_ci // Swaps the two first input operands of the node, to help match shuffles 6551cb0ef41Sopenharmony_ci // to specific architectural instructions. 6561cb0ef41Sopenharmony_ci void SwapShuffleInputs(Node* node); 6571cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci // =========================================================================== 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci Schedule* schedule() const { return schedule_; } 6621cb0ef41Sopenharmony_ci Linkage* linkage() const { return linkage_; } 6631cb0ef41Sopenharmony_ci InstructionSequence* sequence() const { return sequence_; } 6641cb0ef41Sopenharmony_ci Zone* instruction_zone() const { return sequence()->zone(); } 6651cb0ef41Sopenharmony_ci Zone* zone() const { return zone_; } 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci void set_instruction_selection_failed() { 6681cb0ef41Sopenharmony_ci instruction_selection_failed_ = true; 6691cb0ef41Sopenharmony_ci } 6701cb0ef41Sopenharmony_ci bool instruction_selection_failed() { return instruction_selection_failed_; } 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci void MarkPairProjectionsAsWord32(Node* node); 6731cb0ef41Sopenharmony_ci bool IsSourcePositionUsed(Node* node); 6741cb0ef41Sopenharmony_ci void VisitWord32AtomicBinaryOperation(Node* node, ArchOpcode int8_op, 6751cb0ef41Sopenharmony_ci ArchOpcode uint8_op, 6761cb0ef41Sopenharmony_ci ArchOpcode int16_op, 6771cb0ef41Sopenharmony_ci ArchOpcode uint16_op, 6781cb0ef41Sopenharmony_ci ArchOpcode word32_op); 6791cb0ef41Sopenharmony_ci void VisitWord64AtomicBinaryOperation(Node* node, ArchOpcode uint8_op, 6801cb0ef41Sopenharmony_ci ArchOpcode uint16_op, 6811cb0ef41Sopenharmony_ci ArchOpcode uint32_op, 6821cb0ef41Sopenharmony_ci ArchOpcode uint64_op); 6831cb0ef41Sopenharmony_ci void VisitWord64AtomicNarrowBinop(Node* node, ArchOpcode uint8_op, 6841cb0ef41Sopenharmony_ci ArchOpcode uint16_op, ArchOpcode uint32_op); 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_64_BIT 6871cb0ef41Sopenharmony_ci bool ZeroExtendsWord32ToWord64(Node* node, int recursion_depth = 0); 6881cb0ef41Sopenharmony_ci bool ZeroExtendsWord32ToWord64NoPhis(Node* node); 6891cb0ef41Sopenharmony_ci 6901cb0ef41Sopenharmony_ci enum Upper32BitsState : uint8_t { 6911cb0ef41Sopenharmony_ci kNotYetChecked, 6921cb0ef41Sopenharmony_ci kUpperBitsGuaranteedZero, 6931cb0ef41Sopenharmony_ci kNoGuarantee, 6941cb0ef41Sopenharmony_ci }; 6951cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_64_BIT 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci struct FrameStateInput { 6981cb0ef41Sopenharmony_ci FrameStateInput(Node* node_, FrameStateInputKind kind_) 6991cb0ef41Sopenharmony_ci : node(node_), kind(kind_) {} 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_ci Node* node; 7021cb0ef41Sopenharmony_ci FrameStateInputKind kind; 7031cb0ef41Sopenharmony_ci 7041cb0ef41Sopenharmony_ci struct Hash { 7051cb0ef41Sopenharmony_ci size_t operator()(FrameStateInput const& source) const { 7061cb0ef41Sopenharmony_ci return base::hash_combine(source.node, 7071cb0ef41Sopenharmony_ci static_cast<size_t>(source.kind)); 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci }; 7101cb0ef41Sopenharmony_ci 7111cb0ef41Sopenharmony_ci struct Equal { 7121cb0ef41Sopenharmony_ci bool operator()(FrameStateInput const& lhs, 7131cb0ef41Sopenharmony_ci FrameStateInput const& rhs) const { 7141cb0ef41Sopenharmony_ci return lhs.node == rhs.node && lhs.kind == rhs.kind; 7151cb0ef41Sopenharmony_ci } 7161cb0ef41Sopenharmony_ci }; 7171cb0ef41Sopenharmony_ci }; 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci struct CachedStateValues; 7201cb0ef41Sopenharmony_ci class CachedStateValuesBuilder; 7211cb0ef41Sopenharmony_ci 7221cb0ef41Sopenharmony_ci // =========================================================================== 7231cb0ef41Sopenharmony_ci 7241cb0ef41Sopenharmony_ci Zone* const zone_; 7251cb0ef41Sopenharmony_ci Linkage* const linkage_; 7261cb0ef41Sopenharmony_ci InstructionSequence* const sequence_; 7271cb0ef41Sopenharmony_ci SourcePositionTable* const source_positions_; 7281cb0ef41Sopenharmony_ci SourcePositionMode const source_position_mode_; 7291cb0ef41Sopenharmony_ci Features features_; 7301cb0ef41Sopenharmony_ci Schedule* const schedule_; 7311cb0ef41Sopenharmony_ci BasicBlock* current_block_; 7321cb0ef41Sopenharmony_ci ZoneVector<Instruction*> instructions_; 7331cb0ef41Sopenharmony_ci InstructionOperandVector continuation_inputs_; 7341cb0ef41Sopenharmony_ci InstructionOperandVector continuation_outputs_; 7351cb0ef41Sopenharmony_ci InstructionOperandVector continuation_temps_; 7361cb0ef41Sopenharmony_ci BoolVector defined_; 7371cb0ef41Sopenharmony_ci BoolVector used_; 7381cb0ef41Sopenharmony_ci IntVector effect_level_; 7391cb0ef41Sopenharmony_ci int current_effect_level_; 7401cb0ef41Sopenharmony_ci IntVector virtual_registers_; 7411cb0ef41Sopenharmony_ci IntVector virtual_register_rename_; 7421cb0ef41Sopenharmony_ci InstructionScheduler* scheduler_; 7431cb0ef41Sopenharmony_ci EnableScheduling enable_scheduling_; 7441cb0ef41Sopenharmony_ci EnableRootsRelativeAddressing enable_roots_relative_addressing_; 7451cb0ef41Sopenharmony_ci EnableSwitchJumpTable enable_switch_jump_table_; 7461cb0ef41Sopenharmony_ci ZoneUnorderedMap<FrameStateInput, CachedStateValues*, FrameStateInput::Hash, 7471cb0ef41Sopenharmony_ci FrameStateInput::Equal> 7481cb0ef41Sopenharmony_ci state_values_cache_; 7491cb0ef41Sopenharmony_ci 7501cb0ef41Sopenharmony_ci Frame* frame_; 7511cb0ef41Sopenharmony_ci bool instruction_selection_failed_; 7521cb0ef41Sopenharmony_ci ZoneVector<std::pair<int, int>> instr_origins_; 7531cb0ef41Sopenharmony_ci EnableTraceTurboJson trace_turbo_; 7541cb0ef41Sopenharmony_ci TickCounter* const tick_counter_; 7551cb0ef41Sopenharmony_ci // The broker is only used for unparking the LocalHeap for diagnostic printing 7561cb0ef41Sopenharmony_ci // for failed StaticAsserts. 7571cb0ef41Sopenharmony_ci JSHeapBroker* const broker_; 7581cb0ef41Sopenharmony_ci 7591cb0ef41Sopenharmony_ci // Store the maximal unoptimized frame height and an maximal number of pushed 7601cb0ef41Sopenharmony_ci // arguments (for calls). Later used to apply an offset to stack checks. 7611cb0ef41Sopenharmony_ci size_t* max_unoptimized_frame_height_; 7621cb0ef41Sopenharmony_ci size_t* max_pushed_argument_count_; 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_64_BIT 7651cb0ef41Sopenharmony_ci // Holds lazily-computed results for whether phi nodes guarantee their upper 7661cb0ef41Sopenharmony_ci // 32 bits to be zero. Indexed by node ID; nobody reads or writes the values 7671cb0ef41Sopenharmony_ci // for non-phi nodes. 7681cb0ef41Sopenharmony_ci ZoneVector<Upper32BitsState> phi_states_; 7691cb0ef41Sopenharmony_ci#endif 7701cb0ef41Sopenharmony_ci}; 7711cb0ef41Sopenharmony_ci 7721cb0ef41Sopenharmony_ci} // namespace compiler 7731cb0ef41Sopenharmony_ci} // namespace internal 7741cb0ef41Sopenharmony_ci} // namespace v8 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_ci#endif // V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_H_ 777