11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction-scheduler.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/base/iterator.h"
81cb0ef41Sopenharmony_ci#include "src/base/optional.h"
91cb0ef41Sopenharmony_ci#include "src/base/utils/random-number-generator.h"
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cinamespace v8 {
121cb0ef41Sopenharmony_cinamespace internal {
131cb0ef41Sopenharmony_cinamespace compiler {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_civoid InstructionScheduler::SchedulingQueueBase::AddNode(
161cb0ef41Sopenharmony_ci    ScheduleGraphNode* node) {
171cb0ef41Sopenharmony_ci  // We keep the ready list sorted by total latency so that we can quickly find
181cb0ef41Sopenharmony_ci  // the next best candidate to schedule.
191cb0ef41Sopenharmony_ci  auto it = nodes_.begin();
201cb0ef41Sopenharmony_ci  while ((it != nodes_.end()) &&
211cb0ef41Sopenharmony_ci         ((*it)->total_latency() >= node->total_latency())) {
221cb0ef41Sopenharmony_ci    ++it;
231cb0ef41Sopenharmony_ci  }
241cb0ef41Sopenharmony_ci  nodes_.insert(it, node);
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciInstructionScheduler::ScheduleGraphNode*
281cb0ef41Sopenharmony_ciInstructionScheduler::CriticalPathFirstQueue::PopBestCandidate(int cycle) {
291cb0ef41Sopenharmony_ci  DCHECK(!IsEmpty());
301cb0ef41Sopenharmony_ci  auto candidate = nodes_.end();
311cb0ef41Sopenharmony_ci  for (auto iterator = nodes_.begin(); iterator != nodes_.end(); ++iterator) {
321cb0ef41Sopenharmony_ci    // We only consider instructions that have all their operands ready.
331cb0ef41Sopenharmony_ci    if (cycle >= (*iterator)->start_cycle()) {
341cb0ef41Sopenharmony_ci      candidate = iterator;
351cb0ef41Sopenharmony_ci      break;
361cb0ef41Sopenharmony_ci    }
371cb0ef41Sopenharmony_ci  }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  if (candidate != nodes_.end()) {
401cb0ef41Sopenharmony_ci    ScheduleGraphNode* result = *candidate;
411cb0ef41Sopenharmony_ci    nodes_.erase(candidate);
421cb0ef41Sopenharmony_ci    return result;
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  return nullptr;
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciInstructionScheduler::ScheduleGraphNode*
491cb0ef41Sopenharmony_ciInstructionScheduler::StressSchedulerQueue::PopBestCandidate(int cycle) {
501cb0ef41Sopenharmony_ci  DCHECK(!IsEmpty());
511cb0ef41Sopenharmony_ci  // Choose a random element from the ready list.
521cb0ef41Sopenharmony_ci  auto candidate = nodes_.begin();
531cb0ef41Sopenharmony_ci  std::advance(candidate, random_number_generator()->NextInt(
541cb0ef41Sopenharmony_ci                              static_cast<int>(nodes_.size())));
551cb0ef41Sopenharmony_ci  ScheduleGraphNode* result = *candidate;
561cb0ef41Sopenharmony_ci  nodes_.erase(candidate);
571cb0ef41Sopenharmony_ci  return result;
581cb0ef41Sopenharmony_ci}
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciInstructionScheduler::ScheduleGraphNode::ScheduleGraphNode(Zone* zone,
611cb0ef41Sopenharmony_ci                                                           Instruction* instr)
621cb0ef41Sopenharmony_ci    : instr_(instr),
631cb0ef41Sopenharmony_ci      successors_(zone),
641cb0ef41Sopenharmony_ci      unscheduled_predecessors_count_(0),
651cb0ef41Sopenharmony_ci      latency_(GetInstructionLatency(instr)),
661cb0ef41Sopenharmony_ci      total_latency_(-1),
671cb0ef41Sopenharmony_ci      start_cycle_(-1) {}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_civoid InstructionScheduler::ScheduleGraphNode::AddSuccessor(
701cb0ef41Sopenharmony_ci    ScheduleGraphNode* node) {
711cb0ef41Sopenharmony_ci  successors_.push_back(node);
721cb0ef41Sopenharmony_ci  node->unscheduled_predecessors_count_++;
731cb0ef41Sopenharmony_ci}
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ciInstructionScheduler::InstructionScheduler(Zone* zone,
761cb0ef41Sopenharmony_ci                                           InstructionSequence* sequence)
771cb0ef41Sopenharmony_ci    : zone_(zone),
781cb0ef41Sopenharmony_ci      sequence_(sequence),
791cb0ef41Sopenharmony_ci      graph_(zone),
801cb0ef41Sopenharmony_ci      last_side_effect_instr_(nullptr),
811cb0ef41Sopenharmony_ci      pending_loads_(zone),
821cb0ef41Sopenharmony_ci      last_live_in_reg_marker_(nullptr),
831cb0ef41Sopenharmony_ci      last_deopt_or_trap_(nullptr),
841cb0ef41Sopenharmony_ci      operands_map_(zone) {
851cb0ef41Sopenharmony_ci  if (FLAG_turbo_stress_instruction_scheduling) {
861cb0ef41Sopenharmony_ci    random_number_generator_ =
871cb0ef41Sopenharmony_ci        base::Optional<base::RandomNumberGenerator>(FLAG_random_seed);
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_civoid InstructionScheduler::StartBlock(RpoNumber rpo) {
921cb0ef41Sopenharmony_ci  DCHECK(graph_.empty());
931cb0ef41Sopenharmony_ci  DCHECK_NULL(last_side_effect_instr_);
941cb0ef41Sopenharmony_ci  DCHECK(pending_loads_.empty());
951cb0ef41Sopenharmony_ci  DCHECK_NULL(last_live_in_reg_marker_);
961cb0ef41Sopenharmony_ci  DCHECK_NULL(last_deopt_or_trap_);
971cb0ef41Sopenharmony_ci  DCHECK(operands_map_.empty());
981cb0ef41Sopenharmony_ci  sequence()->StartBlock(rpo);
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_civoid InstructionScheduler::EndBlock(RpoNumber rpo) {
1021cb0ef41Sopenharmony_ci  if (FLAG_turbo_stress_instruction_scheduling) {
1031cb0ef41Sopenharmony_ci    Schedule<StressSchedulerQueue>();
1041cb0ef41Sopenharmony_ci  } else {
1051cb0ef41Sopenharmony_ci    Schedule<CriticalPathFirstQueue>();
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci  sequence()->EndBlock(rpo);
1081cb0ef41Sopenharmony_ci}
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_civoid InstructionScheduler::AddTerminator(Instruction* instr) {
1111cb0ef41Sopenharmony_ci  ScheduleGraphNode* new_node = zone()->New<ScheduleGraphNode>(zone(), instr);
1121cb0ef41Sopenharmony_ci  // Make sure that basic block terminators are not moved by adding them
1131cb0ef41Sopenharmony_ci  // as successor of every instruction.
1141cb0ef41Sopenharmony_ci  for (ScheduleGraphNode* node : graph_) {
1151cb0ef41Sopenharmony_ci    node->AddSuccessor(new_node);
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci  graph_.push_back(new_node);
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_civoid InstructionScheduler::AddInstruction(Instruction* instr) {
1211cb0ef41Sopenharmony_ci  if (IsBarrier(instr)) {
1221cb0ef41Sopenharmony_ci    if (FLAG_turbo_stress_instruction_scheduling) {
1231cb0ef41Sopenharmony_ci      Schedule<StressSchedulerQueue>();
1241cb0ef41Sopenharmony_ci    } else {
1251cb0ef41Sopenharmony_ci      Schedule<CriticalPathFirstQueue>();
1261cb0ef41Sopenharmony_ci    }
1271cb0ef41Sopenharmony_ci    sequence()->AddInstruction(instr);
1281cb0ef41Sopenharmony_ci    return;
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  ScheduleGraphNode* new_node = zone()->New<ScheduleGraphNode>(zone(), instr);
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  // We should not have branches in the middle of a block.
1341cb0ef41Sopenharmony_ci  DCHECK_NE(instr->flags_mode(), kFlags_branch);
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  if (IsFixedRegisterParameter(instr)) {
1371cb0ef41Sopenharmony_ci    if (last_live_in_reg_marker_ != nullptr) {
1381cb0ef41Sopenharmony_ci      last_live_in_reg_marker_->AddSuccessor(new_node);
1391cb0ef41Sopenharmony_ci    }
1401cb0ef41Sopenharmony_ci    last_live_in_reg_marker_ = new_node;
1411cb0ef41Sopenharmony_ci  } else {
1421cb0ef41Sopenharmony_ci    if (last_live_in_reg_marker_ != nullptr) {
1431cb0ef41Sopenharmony_ci      last_live_in_reg_marker_->AddSuccessor(new_node);
1441cb0ef41Sopenharmony_ci    }
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci    // Make sure that instructions are not scheduled before the last
1471cb0ef41Sopenharmony_ci    // deoptimization or trap point when they depend on it.
1481cb0ef41Sopenharmony_ci    if ((last_deopt_or_trap_ != nullptr) && DependsOnDeoptOrTrap(instr)) {
1491cb0ef41Sopenharmony_ci      last_deopt_or_trap_->AddSuccessor(new_node);
1501cb0ef41Sopenharmony_ci    }
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci    // Instructions with side effects and memory operations can't be
1531cb0ef41Sopenharmony_ci    // reordered with respect to each other.
1541cb0ef41Sopenharmony_ci    if (HasSideEffect(instr)) {
1551cb0ef41Sopenharmony_ci      if (last_side_effect_instr_ != nullptr) {
1561cb0ef41Sopenharmony_ci        last_side_effect_instr_->AddSuccessor(new_node);
1571cb0ef41Sopenharmony_ci      }
1581cb0ef41Sopenharmony_ci      for (ScheduleGraphNode* load : pending_loads_) {
1591cb0ef41Sopenharmony_ci        load->AddSuccessor(new_node);
1601cb0ef41Sopenharmony_ci      }
1611cb0ef41Sopenharmony_ci      pending_loads_.clear();
1621cb0ef41Sopenharmony_ci      last_side_effect_instr_ = new_node;
1631cb0ef41Sopenharmony_ci    } else if (IsLoadOperation(instr)) {
1641cb0ef41Sopenharmony_ci      // Load operations can't be reordered with side effects instructions but
1651cb0ef41Sopenharmony_ci      // independent loads can be reordered with respect to each other.
1661cb0ef41Sopenharmony_ci      if (last_side_effect_instr_ != nullptr) {
1671cb0ef41Sopenharmony_ci        last_side_effect_instr_->AddSuccessor(new_node);
1681cb0ef41Sopenharmony_ci      }
1691cb0ef41Sopenharmony_ci      pending_loads_.push_back(new_node);
1701cb0ef41Sopenharmony_ci    } else if (instr->IsDeoptimizeCall() || CanTrap(instr)) {
1711cb0ef41Sopenharmony_ci      // Ensure that deopts or traps are not reordered with respect to
1721cb0ef41Sopenharmony_ci      // side-effect instructions.
1731cb0ef41Sopenharmony_ci      if (last_side_effect_instr_ != nullptr) {
1741cb0ef41Sopenharmony_ci        last_side_effect_instr_->AddSuccessor(new_node);
1751cb0ef41Sopenharmony_ci      }
1761cb0ef41Sopenharmony_ci    }
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci    // Update last deoptimization or trap point.
1791cb0ef41Sopenharmony_ci    if (instr->IsDeoptimizeCall() || CanTrap(instr)) {
1801cb0ef41Sopenharmony_ci      last_deopt_or_trap_ = new_node;
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci    // Look for operand dependencies.
1841cb0ef41Sopenharmony_ci    for (size_t i = 0; i < instr->InputCount(); ++i) {
1851cb0ef41Sopenharmony_ci      const InstructionOperand* input = instr->InputAt(i);
1861cb0ef41Sopenharmony_ci      if (input->IsUnallocated()) {
1871cb0ef41Sopenharmony_ci        int32_t vreg = UnallocatedOperand::cast(input)->virtual_register();
1881cb0ef41Sopenharmony_ci        auto it = operands_map_.find(vreg);
1891cb0ef41Sopenharmony_ci        if (it != operands_map_.end()) {
1901cb0ef41Sopenharmony_ci          it->second->AddSuccessor(new_node);
1911cb0ef41Sopenharmony_ci        }
1921cb0ef41Sopenharmony_ci      }
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci    // Record the virtual registers defined by this instruction.
1961cb0ef41Sopenharmony_ci    for (size_t i = 0; i < instr->OutputCount(); ++i) {
1971cb0ef41Sopenharmony_ci      const InstructionOperand* output = instr->OutputAt(i);
1981cb0ef41Sopenharmony_ci      if (output->IsUnallocated()) {
1991cb0ef41Sopenharmony_ci        operands_map_[UnallocatedOperand::cast(output)->virtual_register()] =
2001cb0ef41Sopenharmony_ci            new_node;
2011cb0ef41Sopenharmony_ci      } else if (output->IsConstant()) {
2021cb0ef41Sopenharmony_ci        operands_map_[ConstantOperand::cast(output)->virtual_register()] =
2031cb0ef41Sopenharmony_ci            new_node;
2041cb0ef41Sopenharmony_ci      }
2051cb0ef41Sopenharmony_ci    }
2061cb0ef41Sopenharmony_ci  }
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  graph_.push_back(new_node);
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_citemplate <typename QueueType>
2121cb0ef41Sopenharmony_civoid InstructionScheduler::Schedule() {
2131cb0ef41Sopenharmony_ci  QueueType ready_list(this);
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  // Compute total latencies so that we can schedule the critical path first.
2161cb0ef41Sopenharmony_ci  ComputeTotalLatencies();
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  // Add nodes which don't have dependencies to the ready list.
2191cb0ef41Sopenharmony_ci  for (ScheduleGraphNode* node : graph_) {
2201cb0ef41Sopenharmony_ci    if (!node->HasUnscheduledPredecessor()) {
2211cb0ef41Sopenharmony_ci      ready_list.AddNode(node);
2221cb0ef41Sopenharmony_ci    }
2231cb0ef41Sopenharmony_ci  }
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  // Go through the ready list and schedule the instructions.
2261cb0ef41Sopenharmony_ci  int cycle = 0;
2271cb0ef41Sopenharmony_ci  while (!ready_list.IsEmpty()) {
2281cb0ef41Sopenharmony_ci    ScheduleGraphNode* candidate = ready_list.PopBestCandidate(cycle);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci    if (candidate != nullptr) {
2311cb0ef41Sopenharmony_ci      sequence()->AddInstruction(candidate->instruction());
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci      for (ScheduleGraphNode* successor : candidate->successors()) {
2341cb0ef41Sopenharmony_ci        successor->DropUnscheduledPredecessor();
2351cb0ef41Sopenharmony_ci        successor->set_start_cycle(
2361cb0ef41Sopenharmony_ci            std::max(successor->start_cycle(), cycle + candidate->latency()));
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci        if (!successor->HasUnscheduledPredecessor()) {
2391cb0ef41Sopenharmony_ci          ready_list.AddNode(successor);
2401cb0ef41Sopenharmony_ci        }
2411cb0ef41Sopenharmony_ci      }
2421cb0ef41Sopenharmony_ci    }
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci    cycle++;
2451cb0ef41Sopenharmony_ci  }
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  // Reset own state.
2481cb0ef41Sopenharmony_ci  graph_.clear();
2491cb0ef41Sopenharmony_ci  operands_map_.clear();
2501cb0ef41Sopenharmony_ci  pending_loads_.clear();
2511cb0ef41Sopenharmony_ci  last_deopt_or_trap_ = nullptr;
2521cb0ef41Sopenharmony_ci  last_live_in_reg_marker_ = nullptr;
2531cb0ef41Sopenharmony_ci  last_side_effect_instr_ = nullptr;
2541cb0ef41Sopenharmony_ci}
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ciint InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
2571cb0ef41Sopenharmony_ci  switch (instr->arch_opcode()) {
2581cb0ef41Sopenharmony_ci    case kArchNop:
2591cb0ef41Sopenharmony_ci    case kArchStackCheckOffset:
2601cb0ef41Sopenharmony_ci    case kArchFramePointer:
2611cb0ef41Sopenharmony_ci    case kArchParentFramePointer:
2621cb0ef41Sopenharmony_ci    case kArchStackSlot:  // Despite its name this opcode will produce a
2631cb0ef41Sopenharmony_ci                          // reference to a frame slot, so it is not affected
2641cb0ef41Sopenharmony_ci                          // by the arm64 dual stack issues mentioned below.
2651cb0ef41Sopenharmony_ci    case kArchComment:
2661cb0ef41Sopenharmony_ci    case kArchDeoptimize:
2671cb0ef41Sopenharmony_ci    case kArchJmp:
2681cb0ef41Sopenharmony_ci    case kArchBinarySearchSwitch:
2691cb0ef41Sopenharmony_ci    case kArchRet:
2701cb0ef41Sopenharmony_ci    case kArchTableSwitch:
2711cb0ef41Sopenharmony_ci    case kArchThrowTerminator:
2721cb0ef41Sopenharmony_ci      return kNoOpcodeFlags;
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci    case kArchTruncateDoubleToI:
2751cb0ef41Sopenharmony_ci    case kIeee754Float64Acos:
2761cb0ef41Sopenharmony_ci    case kIeee754Float64Acosh:
2771cb0ef41Sopenharmony_ci    case kIeee754Float64Asin:
2781cb0ef41Sopenharmony_ci    case kIeee754Float64Asinh:
2791cb0ef41Sopenharmony_ci    case kIeee754Float64Atan:
2801cb0ef41Sopenharmony_ci    case kIeee754Float64Atanh:
2811cb0ef41Sopenharmony_ci    case kIeee754Float64Atan2:
2821cb0ef41Sopenharmony_ci    case kIeee754Float64Cbrt:
2831cb0ef41Sopenharmony_ci    case kIeee754Float64Cos:
2841cb0ef41Sopenharmony_ci    case kIeee754Float64Cosh:
2851cb0ef41Sopenharmony_ci    case kIeee754Float64Exp:
2861cb0ef41Sopenharmony_ci    case kIeee754Float64Expm1:
2871cb0ef41Sopenharmony_ci    case kIeee754Float64Log:
2881cb0ef41Sopenharmony_ci    case kIeee754Float64Log1p:
2891cb0ef41Sopenharmony_ci    case kIeee754Float64Log10:
2901cb0ef41Sopenharmony_ci    case kIeee754Float64Log2:
2911cb0ef41Sopenharmony_ci    case kIeee754Float64Pow:
2921cb0ef41Sopenharmony_ci    case kIeee754Float64Sin:
2931cb0ef41Sopenharmony_ci    case kIeee754Float64Sinh:
2941cb0ef41Sopenharmony_ci    case kIeee754Float64Tan:
2951cb0ef41Sopenharmony_ci    case kIeee754Float64Tanh:
2961cb0ef41Sopenharmony_ci      return kNoOpcodeFlags;
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci    case kArchStackPointerGreaterThan:
2991cb0ef41Sopenharmony_ci      // The ArchStackPointerGreaterThan instruction loads the current stack
3001cb0ef41Sopenharmony_ci      // pointer value and must not be reordered with instructions with side
3011cb0ef41Sopenharmony_ci      // effects.
3021cb0ef41Sopenharmony_ci      return kIsLoadOperation;
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci    case kArchPrepareCallCFunction:
3051cb0ef41Sopenharmony_ci    case kArchPrepareTailCall:
3061cb0ef41Sopenharmony_ci    case kArchTailCallCodeObject:
3071cb0ef41Sopenharmony_ci    case kArchTailCallAddress:
3081cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
3091cb0ef41Sopenharmony_ci    case kArchTailCallWasm:
3101cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
3111cb0ef41Sopenharmony_ci    case kArchAbortCSADcheck:
3121cb0ef41Sopenharmony_ci      return kHasSideEffect;
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci    case kArchDebugBreak:
3151cb0ef41Sopenharmony_ci      return kIsBarrier;
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    case kArchSaveCallerRegisters:
3181cb0ef41Sopenharmony_ci    case kArchRestoreCallerRegisters:
3191cb0ef41Sopenharmony_ci      return kIsBarrier;
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci    case kArchCallCFunction:
3221cb0ef41Sopenharmony_ci    case kArchCallCodeObject:
3231cb0ef41Sopenharmony_ci    case kArchCallJSFunction:
3241cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
3251cb0ef41Sopenharmony_ci    case kArchCallWasmFunction:
3261cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
3271cb0ef41Sopenharmony_ci    case kArchCallBuiltinPointer:
3281cb0ef41Sopenharmony_ci      // Calls can cause GC and GC may relocate objects. If a pure instruction
3291cb0ef41Sopenharmony_ci      // operates on a tagged pointer that was cast to a word then it may be
3301cb0ef41Sopenharmony_ci      // incorrect to move the instruction across the call. Hence we mark all
3311cb0ef41Sopenharmony_ci      // (non-tail-)calls as barriers.
3321cb0ef41Sopenharmony_ci      return kIsBarrier;
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci    case kArchStoreWithWriteBarrier:
3351cb0ef41Sopenharmony_ci    case kArchAtomicStoreWithWriteBarrier:
3361cb0ef41Sopenharmony_ci      return kHasSideEffect;
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci    case kAtomicLoadInt8:
3391cb0ef41Sopenharmony_ci    case kAtomicLoadUint8:
3401cb0ef41Sopenharmony_ci    case kAtomicLoadInt16:
3411cb0ef41Sopenharmony_ci    case kAtomicLoadUint16:
3421cb0ef41Sopenharmony_ci    case kAtomicLoadWord32:
3431cb0ef41Sopenharmony_ci      return kIsLoadOperation;
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci    case kAtomicStoreWord8:
3461cb0ef41Sopenharmony_ci    case kAtomicStoreWord16:
3471cb0ef41Sopenharmony_ci    case kAtomicStoreWord32:
3481cb0ef41Sopenharmony_ci      return kHasSideEffect;
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci    case kAtomicExchangeInt8:
3511cb0ef41Sopenharmony_ci    case kAtomicExchangeUint8:
3521cb0ef41Sopenharmony_ci    case kAtomicExchangeInt16:
3531cb0ef41Sopenharmony_ci    case kAtomicExchangeUint16:
3541cb0ef41Sopenharmony_ci    case kAtomicExchangeWord32:
3551cb0ef41Sopenharmony_ci    case kAtomicCompareExchangeInt8:
3561cb0ef41Sopenharmony_ci    case kAtomicCompareExchangeUint8:
3571cb0ef41Sopenharmony_ci    case kAtomicCompareExchangeInt16:
3581cb0ef41Sopenharmony_ci    case kAtomicCompareExchangeUint16:
3591cb0ef41Sopenharmony_ci    case kAtomicCompareExchangeWord32:
3601cb0ef41Sopenharmony_ci    case kAtomicAddInt8:
3611cb0ef41Sopenharmony_ci    case kAtomicAddUint8:
3621cb0ef41Sopenharmony_ci    case kAtomicAddInt16:
3631cb0ef41Sopenharmony_ci    case kAtomicAddUint16:
3641cb0ef41Sopenharmony_ci    case kAtomicAddWord32:
3651cb0ef41Sopenharmony_ci    case kAtomicSubInt8:
3661cb0ef41Sopenharmony_ci    case kAtomicSubUint8:
3671cb0ef41Sopenharmony_ci    case kAtomicSubInt16:
3681cb0ef41Sopenharmony_ci    case kAtomicSubUint16:
3691cb0ef41Sopenharmony_ci    case kAtomicSubWord32:
3701cb0ef41Sopenharmony_ci    case kAtomicAndInt8:
3711cb0ef41Sopenharmony_ci    case kAtomicAndUint8:
3721cb0ef41Sopenharmony_ci    case kAtomicAndInt16:
3731cb0ef41Sopenharmony_ci    case kAtomicAndUint16:
3741cb0ef41Sopenharmony_ci    case kAtomicAndWord32:
3751cb0ef41Sopenharmony_ci    case kAtomicOrInt8:
3761cb0ef41Sopenharmony_ci    case kAtomicOrUint8:
3771cb0ef41Sopenharmony_ci    case kAtomicOrInt16:
3781cb0ef41Sopenharmony_ci    case kAtomicOrUint16:
3791cb0ef41Sopenharmony_ci    case kAtomicOrWord32:
3801cb0ef41Sopenharmony_ci    case kAtomicXorInt8:
3811cb0ef41Sopenharmony_ci    case kAtomicXorUint8:
3821cb0ef41Sopenharmony_ci    case kAtomicXorInt16:
3831cb0ef41Sopenharmony_ci    case kAtomicXorUint16:
3841cb0ef41Sopenharmony_ci    case kAtomicXorWord32:
3851cb0ef41Sopenharmony_ci      return kHasSideEffect;
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci#define CASE(Name) case k##Name:
3881cb0ef41Sopenharmony_ci      TARGET_ARCH_OPCODE_LIST(CASE)
3891cb0ef41Sopenharmony_ci#undef CASE
3901cb0ef41Sopenharmony_ci      return GetTargetInstructionFlags(instr);
3911cb0ef41Sopenharmony_ci  }
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci  UNREACHABLE();
3941cb0ef41Sopenharmony_ci}
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_civoid InstructionScheduler::ComputeTotalLatencies() {
3971cb0ef41Sopenharmony_ci  for (ScheduleGraphNode* node : base::Reversed(graph_)) {
3981cb0ef41Sopenharmony_ci    int max_latency = 0;
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci    for (ScheduleGraphNode* successor : node->successors()) {
4011cb0ef41Sopenharmony_ci      DCHECK_NE(-1, successor->total_latency());
4021cb0ef41Sopenharmony_ci      if (successor->total_latency() > max_latency) {
4031cb0ef41Sopenharmony_ci        max_latency = successor->total_latency();
4041cb0ef41Sopenharmony_ci      }
4051cb0ef41Sopenharmony_ci    }
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci    node->set_total_latency(max_latency + node->latency());
4081cb0ef41Sopenharmony_ci  }
4091cb0ef41Sopenharmony_ci}
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci}  // namespace compiler
4121cb0ef41Sopenharmony_ci}  // namespace internal
4131cb0ef41Sopenharmony_ci}  // namespace v8
414