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