| 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 #ifndef V8_COMPILER_INSTRUCTION_SCHEDULER_H_ | 5 #ifndef V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |
| 6 #define V8_COMPILER_INSTRUCTION_SCHEDULER_H_ | 6 #define V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |
| 7 | 7 |
| 8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
| 9 #include "src/zone/zone-containers.h" | 9 #include "src/zone/zone-containers.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace compiler { | 13 namespace compiler { |
| 14 | 14 |
| 15 // A set of flags describing properties of the instructions so that the | 15 // A set of flags describing properties of the instructions so that the |
| 16 // scheduler is aware of dependencies between instructions. | 16 // scheduler is aware of dependencies between instructions. |
| 17 enum ArchOpcodeFlags { | 17 enum ArchOpcodeFlags { |
| 18 kNoOpcodeFlags = 0, | 18 kNoOpcodeFlags = 0, |
| 19 kIsBlockTerminator = 1, // The instruction marks the end of a basic block | 19 kIsBlockTerminator = 1, // The instruction marks the end of a basic block |
| 20 // e.g.: jump and return instructions. | 20 // e.g.: jump and return instructions. |
| 21 kHasSideEffect = 2, // The instruction has some side effects (memory | 21 kHasSideEffect = 2, // The instruction has some side effects (memory |
| 22 // store, function call...) | 22 // store, function call...) |
| 23 kIsLoadOperation = 4, // The instruction is a memory load. | 23 kIsLoadOperation = 4, // The instruction is a memory load. |
| 24 kMayNeedDeoptCheck = 8, // The instruction might be associated with a deopt | 24 kMayNeedDeoptOrTrapCheck = 8, // The instruction may be associated with a |
| 25 // check. This is the case of instruction which can | 25 // deopt or trap check which must be run before |
| 26 // blow up with particular inputs (e.g.: division by | 26 // instruction e.g. div on Intel platform which |
| 27 // zero on Intel platforms). | 27 // will raise an exception when the divisor is |
| 28 // zero. |
| 28 }; | 29 }; |
| 29 | 30 |
| 30 class InstructionScheduler final : public ZoneObject { | 31 class InstructionScheduler final : public ZoneObject { |
| 31 public: | 32 public: |
| 32 InstructionScheduler(Zone* zone, InstructionSequence* sequence); | 33 InstructionScheduler(Zone* zone, InstructionSequence* sequence); |
| 33 | 34 |
| 34 void StartBlock(RpoNumber rpo); | 35 void StartBlock(RpoNumber rpo); |
| 35 void EndBlock(RpoNumber rpo); | 36 void EndBlock(RpoNumber rpo); |
| 36 | 37 |
| 37 void AddInstruction(Instruction* instr); | 38 void AddInstruction(Instruction* instr); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 // memory store). | 160 // memory store). |
| 160 bool HasSideEffect(const Instruction* instr) const { | 161 bool HasSideEffect(const Instruction* instr) const { |
| 161 return (GetInstructionFlags(instr) & kHasSideEffect) != 0; | 162 return (GetInstructionFlags(instr) & kHasSideEffect) != 0; |
| 162 } | 163 } |
| 163 | 164 |
| 164 // Return true if the instruction is a memory load. | 165 // Return true if the instruction is a memory load. |
| 165 bool IsLoadOperation(const Instruction* instr) const { | 166 bool IsLoadOperation(const Instruction* instr) const { |
| 166 return (GetInstructionFlags(instr) & kIsLoadOperation) != 0; | 167 return (GetInstructionFlags(instr) & kIsLoadOperation) != 0; |
| 167 } | 168 } |
| 168 | 169 |
| 169 // Return true if this instruction is usually associated with a deopt check | 170 // The scheduler will not move the following instructions before the last |
| 170 // to validate its input. | 171 // deopt/trap check: |
| 171 bool MayNeedDeoptCheck(const Instruction* instr) const { | 172 // * loads (this is conservative) |
| 172 return (GetInstructionFlags(instr) & kMayNeedDeoptCheck) != 0; | 173 // * instructions with side effect |
| 174 // * other deopts/traps |
| 175 // Any other instruction can be moved, apart from those that raise exceptions |
| 176 // on specific inputs - these are filtered out by the deopt/trap check. |
| 177 bool MayNeedDeoptOrTrapCheck(const Instruction* instr) const { |
| 178 return (GetInstructionFlags(instr) & kMayNeedDeoptOrTrapCheck) != 0; |
| 173 } | 179 } |
| 174 | 180 |
| 175 // Return true if the instruction cannot be moved before the last deopt | 181 // Return true if the instruction cannot be moved before the last deopt or |
| 176 // point we encountered. | 182 // trap point we encountered. |
| 177 bool DependsOnDeoptimization(const Instruction* instr) const { | 183 bool DependsOnDeoptOrTrap(const Instruction* instr) const { |
| 178 return MayNeedDeoptCheck(instr) || instr->IsDeoptimizeCall() || | 184 return MayNeedDeoptOrTrapCheck(instr) || instr->IsDeoptimizeCall() || |
| 179 HasSideEffect(instr) || IsLoadOperation(instr); | 185 instr->IsTrap() || HasSideEffect(instr) || IsLoadOperation(instr); |
| 180 } | 186 } |
| 181 | 187 |
| 182 // Identify nops used as a definition point for live-in registers at | 188 // Identify nops used as a definition point for live-in registers at |
| 183 // function entry. | 189 // function entry. |
| 184 bool IsFixedRegisterParameter(const Instruction* instr) const { | 190 bool IsFixedRegisterParameter(const Instruction* instr) const { |
| 185 return (instr->arch_opcode() == kArchNop) && (instr->OutputCount() == 1) && | 191 return (instr->arch_opcode() == kArchNop) && (instr->OutputCount() == 1) && |
| 186 (instr->OutputAt(0)->IsUnallocated()) && | 192 (instr->OutputAt(0)->IsUnallocated()) && |
| 187 (UnallocatedOperand::cast(instr->OutputAt(0)) | 193 (UnallocatedOperand::cast(instr->OutputAt(0)) |
| 188 ->HasFixedRegisterPolicy() || | 194 ->HasFixedRegisterPolicy() || |
| 189 UnallocatedOperand::cast(instr->OutputAt(0)) | 195 UnallocatedOperand::cast(instr->OutputAt(0)) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 210 // effects. | 216 // effects. |
| 211 ZoneVector<ScheduleGraphNode*> pending_loads_; | 217 ZoneVector<ScheduleGraphNode*> pending_loads_; |
| 212 | 218 |
| 213 // Live-in register markers are nop instructions which are emitted at the | 219 // Live-in register markers are nop instructions which are emitted at the |
| 214 // beginning of a basic block so that the register allocator will find a | 220 // beginning of a basic block so that the register allocator will find a |
| 215 // defining instruction for live-in values. They must not be moved. | 221 // defining instruction for live-in values. They must not be moved. |
| 216 // All these nops are chained together and added as a predecessor of every | 222 // All these nops are chained together and added as a predecessor of every |
| 217 // other instructions in the basic block. | 223 // other instructions in the basic block. |
| 218 ScheduleGraphNode* last_live_in_reg_marker_; | 224 ScheduleGraphNode* last_live_in_reg_marker_; |
| 219 | 225 |
| 220 // Last deoptimization instruction encountered while building the graph. | 226 // Last deoptimization or trap instruction encountered while building the |
| 221 ScheduleGraphNode* last_deopt_; | 227 // graph. |
| 228 ScheduleGraphNode* last_deopt_or_trap_; |
| 222 | 229 |
| 223 // Keep track of definition points for virtual registers. This is used to | 230 // Keep track of definition points for virtual registers. This is used to |
| 224 // record operand dependencies in the scheduling graph. | 231 // record operand dependencies in the scheduling graph. |
| 225 ZoneMap<int32_t, ScheduleGraphNode*> operands_map_; | 232 ZoneMap<int32_t, ScheduleGraphNode*> operands_map_; |
| 226 }; | 233 }; |
| 227 | 234 |
| 228 } // namespace compiler | 235 } // namespace compiler |
| 229 } // namespace internal | 236 } // namespace internal |
| 230 } // namespace v8 | 237 } // namespace v8 |
| 231 | 238 |
| 232 #endif // V8_COMPILER_INSTRUCTION_SCHEDULER_H_ | 239 #endif // V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |
| OLD | NEW |