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