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 |
| 25 // check. This is the case of instruction which can |
| 26 // blow up with particular inputs (e.g.: division by |
| 27 // zero on Intel platforms). |
24 }; | 28 }; |
25 | 29 |
26 | |
27 class InstructionScheduler final : public ZoneObject { | 30 class InstructionScheduler final : public ZoneObject { |
28 public: | 31 public: |
29 InstructionScheduler(Zone* zone, InstructionSequence* sequence); | 32 InstructionScheduler(Zone* zone, InstructionSequence* sequence); |
30 | 33 |
31 void StartBlock(RpoNumber rpo); | 34 void StartBlock(RpoNumber rpo); |
32 void EndBlock(RpoNumber rpo); | 35 void EndBlock(RpoNumber rpo); |
33 | 36 |
34 void AddInstruction(Instruction* instr); | 37 void AddInstruction(Instruction* instr); |
35 | 38 |
36 static bool SchedulerSupported(); | 39 static bool SchedulerSupported(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 // Return the scheduling properties of the given instruction. | 151 // Return the scheduling properties of the given instruction. |
149 int GetInstructionFlags(const Instruction* instr) const; | 152 int GetInstructionFlags(const Instruction* instr) const; |
150 int GetTargetInstructionFlags(const Instruction* instr) const; | 153 int GetTargetInstructionFlags(const Instruction* instr) const; |
151 | 154 |
152 // Return true if the instruction is a basic block terminator. | 155 // Return true if the instruction is a basic block terminator. |
153 bool IsBlockTerminator(const Instruction* instr) const; | 156 bool IsBlockTerminator(const Instruction* instr) const; |
154 | 157 |
155 // Check whether the given instruction has side effects (e.g. function call, | 158 // Check whether the given instruction has side effects (e.g. function call, |
156 // memory store). | 159 // memory store). |
157 bool HasSideEffect(const Instruction* instr) const { | 160 bool HasSideEffect(const Instruction* instr) const { |
158 return GetInstructionFlags(instr) & kHasSideEffect; | 161 return (GetInstructionFlags(instr) & kHasSideEffect) != 0; |
159 } | 162 } |
160 | 163 |
161 // Return true if the instruction is a memory load. | 164 // Return true if the instruction is a memory load. |
162 bool IsLoadOperation(const Instruction* instr) const { | 165 bool IsLoadOperation(const Instruction* instr) const { |
163 return GetInstructionFlags(instr) & kIsLoadOperation; | 166 return (GetInstructionFlags(instr) & kIsLoadOperation) != 0; |
| 167 } |
| 168 |
| 169 // Return true if this instruction is usually associated with a deopt check |
| 170 // to validate its input. |
| 171 bool MayNeedDeoptCheck(const Instruction* instr) const { |
| 172 return (GetInstructionFlags(instr) & kMayNeedDeoptCheck) != 0; |
| 173 } |
| 174 |
| 175 // Return true if the instruction cannot be moved before the last deopt |
| 176 // point we encountered. |
| 177 bool DependsOnDeoptimization(const Instruction* instr) const { |
| 178 return MayNeedDeoptCheck(instr) || instr->IsDeoptimizeCall() || |
| 179 HasSideEffect(instr) || IsLoadOperation(instr); |
164 } | 180 } |
165 | 181 |
166 // Identify nops used as a definition point for live-in registers at | 182 // Identify nops used as a definition point for live-in registers at |
167 // function entry. | 183 // function entry. |
168 bool IsFixedRegisterParameter(const Instruction* instr) const { | 184 bool IsFixedRegisterParameter(const Instruction* instr) const { |
169 return (instr->arch_opcode() == kArchNop) && (instr->OutputCount() == 1) && | 185 return (instr->arch_opcode() == kArchNop) && (instr->OutputCount() == 1) && |
170 (instr->OutputAt(0)->IsUnallocated()) && | 186 (instr->OutputAt(0)->IsUnallocated()) && |
171 (UnallocatedOperand::cast(instr->OutputAt(0)) | 187 (UnallocatedOperand::cast(instr->OutputAt(0)) |
172 ->HasFixedRegisterPolicy() || | 188 ->HasFixedRegisterPolicy() || |
173 UnallocatedOperand::cast(instr->OutputAt(0)) | 189 UnallocatedOperand::cast(instr->OutputAt(0)) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 // Keep track of definition points for virtual registers. This is used to | 223 // Keep track of definition points for virtual registers. This is used to |
208 // record operand dependencies in the scheduling graph. | 224 // record operand dependencies in the scheduling graph. |
209 ZoneMap<int32_t, ScheduleGraphNode*> operands_map_; | 225 ZoneMap<int32_t, ScheduleGraphNode*> operands_map_; |
210 }; | 226 }; |
211 | 227 |
212 } // namespace compiler | 228 } // namespace compiler |
213 } // namespace internal | 229 } // namespace internal |
214 } // namespace v8 | 230 } // namespace v8 |
215 | 231 |
216 #endif // V8_COMPILER_INSTRUCTION_SCHEDULER_H_ | 232 #endif // V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |
OLD | NEW |