| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/instruction-scheduler.h" | 5 #include "src/compiler/instruction-scheduler.h" |
| 6 | 6 |
| 7 #include "src/base/adapters.h" | 7 #include "src/base/adapters.h" |
| 8 #include "src/base/utils/random-number-generator.h" | 8 #include "src/base/utils/random-number-generator.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 start_cycle_(-1) { | 70 start_cycle_(-1) { |
| 71 } | 71 } |
| 72 | 72 |
| 73 | 73 |
| 74 void InstructionScheduler::ScheduleGraphNode::AddSuccessor( | 74 void InstructionScheduler::ScheduleGraphNode::AddSuccessor( |
| 75 ScheduleGraphNode* node) { | 75 ScheduleGraphNode* node) { |
| 76 successors_.push_back(node); | 76 successors_.push_back(node); |
| 77 node->unscheduled_predecessors_count_++; | 77 node->unscheduled_predecessors_count_++; |
| 78 } | 78 } |
| 79 | 79 |
| 80 | |
| 81 InstructionScheduler::InstructionScheduler(Zone* zone, | 80 InstructionScheduler::InstructionScheduler(Zone* zone, |
| 82 InstructionSequence* sequence) | 81 InstructionSequence* sequence) |
| 83 : zone_(zone), | 82 : zone_(zone), |
| 84 sequence_(sequence), | 83 sequence_(sequence), |
| 85 graph_(zone), | 84 graph_(zone), |
| 86 last_side_effect_instr_(nullptr), | 85 last_side_effect_instr_(nullptr), |
| 87 pending_loads_(zone), | 86 pending_loads_(zone), |
| 88 last_live_in_reg_marker_(nullptr), | 87 last_live_in_reg_marker_(nullptr), |
| 89 last_deopt_(nullptr), | 88 last_deopt_or_trap_(nullptr), |
| 90 operands_map_(zone) {} | 89 operands_map_(zone) {} |
| 91 | 90 |
| 92 | |
| 93 void InstructionScheduler::StartBlock(RpoNumber rpo) { | 91 void InstructionScheduler::StartBlock(RpoNumber rpo) { |
| 94 DCHECK(graph_.empty()); | 92 DCHECK(graph_.empty()); |
| 95 DCHECK(last_side_effect_instr_ == nullptr); | 93 DCHECK(last_side_effect_instr_ == nullptr); |
| 96 DCHECK(pending_loads_.empty()); | 94 DCHECK(pending_loads_.empty()); |
| 97 DCHECK(last_live_in_reg_marker_ == nullptr); | 95 DCHECK(last_live_in_reg_marker_ == nullptr); |
| 98 DCHECK(last_deopt_ == nullptr); | 96 DCHECK(last_deopt_or_trap_ == nullptr); |
| 99 DCHECK(operands_map_.empty()); | 97 DCHECK(operands_map_.empty()); |
| 100 sequence()->StartBlock(rpo); | 98 sequence()->StartBlock(rpo); |
| 101 } | 99 } |
| 102 | 100 |
| 103 | 101 |
| 104 void InstructionScheduler::EndBlock(RpoNumber rpo) { | 102 void InstructionScheduler::EndBlock(RpoNumber rpo) { |
| 105 if (FLAG_turbo_stress_instruction_scheduling) { | 103 if (FLAG_turbo_stress_instruction_scheduling) { |
| 106 ScheduleBlock<StressSchedulerQueue>(); | 104 ScheduleBlock<StressSchedulerQueue>(); |
| 107 } else { | 105 } else { |
| 108 ScheduleBlock<CriticalPathFirstQueue>(); | 106 ScheduleBlock<CriticalPathFirstQueue>(); |
| 109 } | 107 } |
| 110 sequence()->EndBlock(rpo); | 108 sequence()->EndBlock(rpo); |
| 111 graph_.clear(); | 109 graph_.clear(); |
| 112 last_side_effect_instr_ = nullptr; | 110 last_side_effect_instr_ = nullptr; |
| 113 pending_loads_.clear(); | 111 pending_loads_.clear(); |
| 114 last_live_in_reg_marker_ = nullptr; | 112 last_live_in_reg_marker_ = nullptr; |
| 115 last_deopt_ = nullptr; | 113 last_deopt_or_trap_ = nullptr; |
| 116 operands_map_.clear(); | 114 operands_map_.clear(); |
| 117 } | 115 } |
| 118 | 116 |
| 119 | 117 |
| 120 void InstructionScheduler::AddInstruction(Instruction* instr) { | 118 void InstructionScheduler::AddInstruction(Instruction* instr) { |
| 121 ScheduleGraphNode* new_node = new (zone()) ScheduleGraphNode(zone(), instr); | 119 ScheduleGraphNode* new_node = new (zone()) ScheduleGraphNode(zone(), instr); |
| 122 | 120 |
| 123 if (IsBlockTerminator(instr)) { | 121 if (IsBlockTerminator(instr)) { |
| 124 // Make sure that basic block terminators are not moved by adding them | 122 // Make sure that basic block terminators are not moved by adding them |
| 125 // as successor of every instruction. | 123 // as successor of every instruction. |
| 126 for (ScheduleGraphNode* node : graph_) { | 124 for (ScheduleGraphNode* node : graph_) { |
| 127 node->AddSuccessor(new_node); | 125 node->AddSuccessor(new_node); |
| 128 } | 126 } |
| 129 } else if (IsFixedRegisterParameter(instr)) { | 127 } else if (IsFixedRegisterParameter(instr)) { |
| 130 if (last_live_in_reg_marker_ != nullptr) { | 128 if (last_live_in_reg_marker_ != nullptr) { |
| 131 last_live_in_reg_marker_->AddSuccessor(new_node); | 129 last_live_in_reg_marker_->AddSuccessor(new_node); |
| 132 } | 130 } |
| 133 last_live_in_reg_marker_ = new_node; | 131 last_live_in_reg_marker_ = new_node; |
| 134 } else { | 132 } else { |
| 135 if (last_live_in_reg_marker_ != nullptr) { | 133 if (last_live_in_reg_marker_ != nullptr) { |
| 136 last_live_in_reg_marker_->AddSuccessor(new_node); | 134 last_live_in_reg_marker_->AddSuccessor(new_node); |
| 137 } | 135 } |
| 138 | 136 |
| 139 // Make sure that instructions are not scheduled before the last | 137 // Make sure that instructions are not scheduled before the last |
| 140 // deoptimization point when they depend on it. | 138 // deoptimization or trap point when they depend on it. |
| 141 if ((last_deopt_ != nullptr) && DependsOnDeoptimization(instr)) { | 139 if ((last_deopt_or_trap_ != nullptr) && DependsOnDeoptOrTrap(instr)) { |
| 142 last_deopt_->AddSuccessor(new_node); | 140 last_deopt_or_trap_->AddSuccessor(new_node); |
| 143 } | 141 } |
| 144 | 142 |
| 145 // Instructions with side effects and memory operations can't be | 143 // Instructions with side effects and memory operations can't be |
| 146 // reordered with respect to each other. | 144 // reordered with respect to each other. |
| 147 if (HasSideEffect(instr)) { | 145 if (HasSideEffect(instr)) { |
| 148 if (last_side_effect_instr_ != nullptr) { | 146 if (last_side_effect_instr_ != nullptr) { |
| 149 last_side_effect_instr_->AddSuccessor(new_node); | 147 last_side_effect_instr_->AddSuccessor(new_node); |
| 150 } | 148 } |
| 151 for (ScheduleGraphNode* load : pending_loads_) { | 149 for (ScheduleGraphNode* load : pending_loads_) { |
| 152 load->AddSuccessor(new_node); | 150 load->AddSuccessor(new_node); |
| 153 } | 151 } |
| 154 pending_loads_.clear(); | 152 pending_loads_.clear(); |
| 155 last_side_effect_instr_ = new_node; | 153 last_side_effect_instr_ = new_node; |
| 156 } else if (IsLoadOperation(instr)) { | 154 } else if (IsLoadOperation(instr)) { |
| 157 // Load operations can't be reordered with side effects instructions but | 155 // Load operations can't be reordered with side effects instructions but |
| 158 // independent loads can be reordered with respect to each other. | 156 // independent loads can be reordered with respect to each other. |
| 159 if (last_side_effect_instr_ != nullptr) { | 157 if (last_side_effect_instr_ != nullptr) { |
| 160 last_side_effect_instr_->AddSuccessor(new_node); | 158 last_side_effect_instr_->AddSuccessor(new_node); |
| 161 } | 159 } |
| 162 pending_loads_.push_back(new_node); | 160 pending_loads_.push_back(new_node); |
| 163 } else if (instr->IsDeoptimizeCall()) { | 161 } else if (instr->IsDeoptimizeCall() || instr->IsTrap()) { |
| 164 // Ensure that deopts are not reordered with respect to side-effect | 162 // Ensure that deopts or traps are not reordered with respect to |
| 165 // instructions. | 163 // side-effect instructions. |
| 166 if (last_side_effect_instr_ != nullptr) { | 164 if (last_side_effect_instr_ != nullptr) { |
| 167 last_side_effect_instr_->AddSuccessor(new_node); | 165 last_side_effect_instr_->AddSuccessor(new_node); |
| 168 } | 166 } |
| 169 last_deopt_ = new_node; | 167 last_deopt_or_trap_ = new_node; |
| 170 } | 168 } |
| 171 | 169 |
| 172 // Look for operand dependencies. | 170 // Look for operand dependencies. |
| 173 for (size_t i = 0; i < instr->InputCount(); ++i) { | 171 for (size_t i = 0; i < instr->InputCount(); ++i) { |
| 174 const InstructionOperand* input = instr->InputAt(i); | 172 const InstructionOperand* input = instr->InputAt(i); |
| 175 if (input->IsUnallocated()) { | 173 if (input->IsUnallocated()) { |
| 176 int32_t vreg = UnallocatedOperand::cast(input)->virtual_register(); | 174 int32_t vreg = UnallocatedOperand::cast(input)->virtual_register(); |
| 177 auto it = operands_map_.find(vreg); | 175 auto it = operands_map_.find(vreg); |
| 178 if (it != operands_map_.end()) { | 176 if (it != operands_map_.end()) { |
| 179 it->second->AddSuccessor(new_node); | 177 it->second->AddSuccessor(new_node); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 } | 388 } |
| 391 } | 389 } |
| 392 | 390 |
| 393 node->set_total_latency(max_latency + node->latency()); | 391 node->set_total_latency(max_latency + node->latency()); |
| 394 } | 392 } |
| 395 } | 393 } |
| 396 | 394 |
| 397 } // namespace compiler | 395 } // namespace compiler |
| 398 } // namespace internal | 396 } // namespace internal |
| 399 } // namespace v8 | 397 } // namespace v8 |
| OLD | NEW |