| 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 } | 75 } |
| 76 | 76 |
| 77 | 77 |
| 78 InstructionScheduler::InstructionScheduler(Zone* zone, | 78 InstructionScheduler::InstructionScheduler(Zone* zone, |
| 79 InstructionSequence* sequence) | 79 InstructionSequence* sequence) |
| 80 : zone_(zone), | 80 : zone_(zone), |
| 81 sequence_(sequence), | 81 sequence_(sequence), |
| 82 graph_(zone), | 82 graph_(zone), |
| 83 last_side_effect_instr_(nullptr), | 83 last_side_effect_instr_(nullptr), |
| 84 pending_loads_(zone), | 84 pending_loads_(zone), |
| 85 last_live_in_reg_marker_(nullptr) { | 85 last_live_in_reg_marker_(nullptr), |
| 86 last_deopt_(nullptr) { |
| 86 } | 87 } |
| 87 | 88 |
| 88 | 89 |
| 89 void InstructionScheduler::StartBlock(RpoNumber rpo) { | 90 void InstructionScheduler::StartBlock(RpoNumber rpo) { |
| 90 DCHECK(graph_.empty()); | 91 DCHECK(graph_.empty()); |
| 91 DCHECK(last_side_effect_instr_ == nullptr); | 92 DCHECK(last_side_effect_instr_ == nullptr); |
| 92 DCHECK(pending_loads_.empty()); | 93 DCHECK(pending_loads_.empty()); |
| 93 DCHECK(last_live_in_reg_marker_ == nullptr); | 94 DCHECK(last_live_in_reg_marker_ == nullptr); |
| 95 DCHECK(last_deopt_ == nullptr); |
| 94 sequence()->StartBlock(rpo); | 96 sequence()->StartBlock(rpo); |
| 95 } | 97 } |
| 96 | 98 |
| 97 | 99 |
| 98 void InstructionScheduler::EndBlock(RpoNumber rpo) { | 100 void InstructionScheduler::EndBlock(RpoNumber rpo) { |
| 99 if (FLAG_turbo_stress_instruction_scheduling) { | 101 if (FLAG_turbo_stress_instruction_scheduling) { |
| 100 ScheduleBlock<StressSchedulerQueue>(); | 102 ScheduleBlock<StressSchedulerQueue>(); |
| 101 } else { | 103 } else { |
| 102 ScheduleBlock<CriticalPathFirstQueue>(); | 104 ScheduleBlock<CriticalPathFirstQueue>(); |
| 103 } | 105 } |
| 104 sequence()->EndBlock(rpo); | 106 sequence()->EndBlock(rpo); |
| 105 graph_.clear(); | 107 graph_.clear(); |
| 106 last_side_effect_instr_ = nullptr; | 108 last_side_effect_instr_ = nullptr; |
| 107 pending_loads_.clear(); | 109 pending_loads_.clear(); |
| 108 last_live_in_reg_marker_ = nullptr; | 110 last_live_in_reg_marker_ = nullptr; |
| 111 last_deopt_ = nullptr; |
| 109 } | 112 } |
| 110 | 113 |
| 111 | 114 |
| 112 void InstructionScheduler::AddInstruction(Instruction* instr) { | 115 void InstructionScheduler::AddInstruction(Instruction* instr) { |
| 113 ScheduleGraphNode* new_node = new (zone()) ScheduleGraphNode(zone(), instr); | 116 ScheduleGraphNode* new_node = new (zone()) ScheduleGraphNode(zone(), instr); |
| 114 | 117 |
| 115 if (IsBlockTerminator(instr)) { | 118 if (IsBlockTerminator(instr)) { |
| 116 // Make sure that basic block terminators are not moved by adding them | 119 // Make sure that basic block terminators are not moved by adding them |
| 117 // as successor of every instruction. | 120 // as successor of every instruction. |
| 118 for (ScheduleGraphNode* node : graph_) { | 121 for (ScheduleGraphNode* node : graph_) { |
| 119 node->AddSuccessor(new_node); | 122 node->AddSuccessor(new_node); |
| 120 } | 123 } |
| 121 } else if (IsFixedRegisterParameter(instr)) { | 124 } else if (IsFixedRegisterParameter(instr)) { |
| 122 if (last_live_in_reg_marker_ != nullptr) { | 125 if (last_live_in_reg_marker_ != nullptr) { |
| 123 last_live_in_reg_marker_->AddSuccessor(new_node); | 126 last_live_in_reg_marker_->AddSuccessor(new_node); |
| 124 } | 127 } |
| 125 last_live_in_reg_marker_ = new_node; | 128 last_live_in_reg_marker_ = new_node; |
| 126 } else { | 129 } else { |
| 127 if (last_live_in_reg_marker_ != nullptr) { | 130 if (last_live_in_reg_marker_ != nullptr) { |
| 128 last_live_in_reg_marker_->AddSuccessor(new_node); | 131 last_live_in_reg_marker_->AddSuccessor(new_node); |
| 129 } | 132 } |
| 130 | 133 |
| 134 // Make sure that new instructions are not scheduled before the last |
| 135 // deoptimization point. |
| 136 if (last_deopt_ != nullptr) { |
| 137 last_deopt_->AddSuccessor(new_node); |
| 138 } |
| 139 |
| 131 // Instructions with side effects and memory operations can't be | 140 // Instructions with side effects and memory operations can't be |
| 132 // reordered with respect to each other. | 141 // reordered with respect to each other. |
| 133 if (HasSideEffect(instr)) { | 142 if (HasSideEffect(instr)) { |
| 134 if (last_side_effect_instr_ != nullptr) { | 143 if (last_side_effect_instr_ != nullptr) { |
| 135 last_side_effect_instr_->AddSuccessor(new_node); | 144 last_side_effect_instr_->AddSuccessor(new_node); |
| 136 } | 145 } |
| 137 for (ScheduleGraphNode* load : pending_loads_) { | 146 for (ScheduleGraphNode* load : pending_loads_) { |
| 138 load->AddSuccessor(new_node); | 147 load->AddSuccessor(new_node); |
| 139 } | 148 } |
| 140 pending_loads_.clear(); | 149 pending_loads_.clear(); |
| 141 last_side_effect_instr_ = new_node; | 150 last_side_effect_instr_ = new_node; |
| 142 } else if (IsLoadOperation(instr)) { | 151 } else if (IsLoadOperation(instr)) { |
| 143 // Load operations can't be reordered with side effects instructions but | 152 // Load operations can't be reordered with side effects instructions but |
| 144 // independent loads can be reordered with respect to each other. | 153 // independent loads can be reordered with respect to each other. |
| 145 if (last_side_effect_instr_ != nullptr) { | 154 if (last_side_effect_instr_ != nullptr) { |
| 146 last_side_effect_instr_->AddSuccessor(new_node); | 155 last_side_effect_instr_->AddSuccessor(new_node); |
| 147 } | 156 } |
| 148 pending_loads_.push_back(new_node); | 157 pending_loads_.push_back(new_node); |
| 158 } else if (instr->IsDeoptimizeCall()) { |
| 159 // Ensure that deopts are not reordered with respect to side-effect |
| 160 // instructions. |
| 161 if (last_side_effect_instr_ != nullptr) { |
| 162 last_side_effect_instr_->AddSuccessor(new_node); |
| 163 } |
| 164 last_deopt_ = new_node; |
| 149 } | 165 } |
| 150 | 166 |
| 151 // Look for operand dependencies. | 167 // Look for operand dependencies. |
| 152 for (ScheduleGraphNode* node : graph_) { | 168 for (ScheduleGraphNode* node : graph_) { |
| 153 if (HasOperandDependency(node->instruction(), instr)) { | 169 if (HasOperandDependency(node->instruction(), instr)) { |
| 154 node->AddSuccessor(new_node); | 170 node->AddSuccessor(new_node); |
| 155 } | 171 } |
| 156 } | 172 } |
| 157 } | 173 } |
| 158 | 174 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 } | 332 } |
| 317 } | 333 } |
| 318 | 334 |
| 319 node->set_total_latency(max_latency + node->latency()); | 335 node->set_total_latency(max_latency + node->latency()); |
| 320 } | 336 } |
| 321 } | 337 } |
| 322 | 338 |
| 323 } // namespace compiler | 339 } // namespace compiler |
| 324 } // namespace internal | 340 } // namespace internal |
| 325 } // namespace v8 | 341 } // namespace v8 |
| OLD | NEW |