| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
| 6 | 6 |
| 7 #include "src/compiler/graph.h" | |
| 8 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
| 9 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 10 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 11 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
| 12 | 11 |
| 13 namespace v8 { | 12 namespace v8 { |
| 14 namespace internal { | 13 namespace internal { |
| 15 namespace compiler { | 14 namespace compiler { |
| 16 | 15 |
| 17 InstructionSelector::InstructionSelector(Zone* local_zone, Graph* graph, | 16 InstructionSelector::InstructionSelector(Zone* zone, size_t node_count, |
| 18 Linkage* linkage, | 17 Linkage* linkage, |
| 19 InstructionSequence* sequence, | 18 InstructionSequence* sequence, |
| 20 Schedule* schedule, | 19 Schedule* schedule, |
| 21 SourcePositionTable* source_positions, | 20 SourcePositionTable* source_positions, |
| 22 Features features) | 21 Features features) |
| 23 : zone_(local_zone), | 22 : zone_(zone), |
| 24 linkage_(linkage), | 23 linkage_(linkage), |
| 25 sequence_(sequence), | 24 sequence_(sequence), |
| 26 source_positions_(source_positions), | 25 source_positions_(source_positions), |
| 27 features_(features), | 26 features_(features), |
| 28 schedule_(schedule), | 27 schedule_(schedule), |
| 29 node_map_(graph->NodeCount(), kNodeUnmapped, zone()), | |
| 30 current_block_(NULL), | 28 current_block_(NULL), |
| 31 instructions_(zone()), | 29 instructions_(zone), |
| 32 defined_(graph->NodeCount(), false, zone()), | 30 defined_(node_count, false, zone), |
| 33 used_(graph->NodeCount(), false, zone()) {} | 31 used_(node_count, false, zone), |
| 32 virtual_registers_(node_count, |
| 33 UnallocatedOperand::kInvalidVirtualRegister, zone) { |
| 34 instructions_.reserve(node_count); |
| 35 } |
| 34 | 36 |
| 35 | 37 |
| 36 void InstructionSelector::SelectInstructions() { | 38 void InstructionSelector::SelectInstructions() { |
| 37 // Mark the inputs of all phis in loop headers as used. | 39 // Mark the inputs of all phis in loop headers as used. |
| 38 BasicBlockVector* blocks = schedule()->rpo_order(); | 40 BasicBlockVector* blocks = schedule()->rpo_order(); |
| 39 for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end(); ++i) { | 41 for (auto const block : *blocks) { |
| 40 BasicBlock* block = *i; | |
| 41 if (!block->IsLoopHeader()) continue; | 42 if (!block->IsLoopHeader()) continue; |
| 42 DCHECK_NE(0, static_cast<int>(block->PredecessorCount())); | 43 DCHECK_LE(2, block->PredecessorCount()); |
| 43 DCHECK_NE(1, static_cast<int>(block->PredecessorCount())); | 44 for (Node* const phi : *block) { |
| 44 for (BasicBlock::const_iterator j = block->begin(); j != block->end(); | |
| 45 ++j) { | |
| 46 Node* phi = *j; | |
| 47 if (phi->opcode() != IrOpcode::kPhi) continue; | 45 if (phi->opcode() != IrOpcode::kPhi) continue; |
| 48 | 46 |
| 49 // Mark all inputs as used. | 47 // Mark all inputs as used. |
| 50 for (Node* const k : phi->inputs()) { | 48 for (Node* const input : phi->inputs()) { |
| 51 MarkAsUsed(k); | 49 MarkAsUsed(input); |
| 52 } | 50 } |
| 53 } | 51 } |
| 54 } | 52 } |
| 55 | 53 |
| 56 // Visit each basic block in post order. | 54 // Visit each basic block in post order. |
| 57 for (BasicBlockVectorRIter i = blocks->rbegin(); i != blocks->rend(); ++i) { | 55 for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) { |
| 58 VisitBlock(*i); | 56 VisitBlock(*i); |
| 59 } | 57 } |
| 60 | 58 |
| 61 // Schedule the selected instructions. | 59 // Schedule the selected instructions. |
| 62 for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end(); ++i) { | 60 for (auto const block : *blocks) { |
| 63 BasicBlock* block = *i; | |
| 64 InstructionBlock* instruction_block = | 61 InstructionBlock* instruction_block = |
| 65 sequence()->InstructionBlockAt(block->GetRpoNumber()); | 62 sequence()->InstructionBlockAt(block->GetRpoNumber()); |
| 66 size_t end = instruction_block->code_end(); | 63 size_t end = instruction_block->code_end(); |
| 67 size_t start = instruction_block->code_start(); | 64 size_t start = instruction_block->code_start(); |
| 65 DCHECK_LE(end, start); |
| 68 sequence()->StartBlock(block->GetRpoNumber()); | 66 sequence()->StartBlock(block->GetRpoNumber()); |
| 69 while (start-- > end) { | 67 while (start-- > end) { |
| 70 sequence()->AddInstruction(instructions_[start]); | 68 sequence()->AddInstruction(instructions_[start]); |
| 71 } | 69 } |
| 72 sequence()->EndBlock(block->GetRpoNumber()); | 70 sequence()->EndBlock(block->GetRpoNumber()); |
| 73 } | 71 } |
| 74 } | 72 } |
| 75 | 73 |
| 76 | 74 |
| 77 Instruction* InstructionSelector::Emit(InstructionCode opcode, | 75 Instruction* InstructionSelector::Emit(InstructionCode opcode, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 } | 171 } |
| 174 | 172 |
| 175 | 173 |
| 176 bool InstructionSelector::CanCover(Node* user, Node* node) const { | 174 bool InstructionSelector::CanCover(Node* user, Node* node) const { |
| 177 return node->OwnedBy(user) && | 175 return node->OwnedBy(user) && |
| 178 schedule()->block(node) == schedule()->block(user); | 176 schedule()->block(node) == schedule()->block(user); |
| 179 } | 177 } |
| 180 | 178 |
| 181 | 179 |
| 182 int InstructionSelector::GetVirtualRegister(const Node* node) { | 180 int InstructionSelector::GetVirtualRegister(const Node* node) { |
| 183 if (node_map_[node->id()] == kNodeUnmapped) { | 181 DCHECK_NOT_NULL(node); |
| 184 node_map_[node->id()] = sequence()->NextVirtualRegister(); | 182 size_t const id = node->id(); |
| 183 DCHECK_LT(id, virtual_registers_.size()); |
| 184 int virtual_register = virtual_registers_[id]; |
| 185 if (virtual_register == UnallocatedOperand::kInvalidVirtualRegister) { |
| 186 virtual_register = sequence()->NextVirtualRegister(); |
| 187 virtual_registers_[id] = virtual_register; |
| 185 } | 188 } |
| 186 return node_map_[node->id()]; | 189 return virtual_register; |
| 187 } | 190 } |
| 188 | 191 |
| 189 | 192 |
| 190 int InstructionSelector::GetMappedVirtualRegister(const Node* node) const { | 193 const std::map<NodeId, int> InstructionSelector::GetVirtualRegistersForTesting() |
| 191 return node_map_[node->id()]; | 194 const { |
| 195 std::map<NodeId, int> virtual_registers; |
| 196 for (size_t n = 0; n < virtual_registers_.size(); ++n) { |
| 197 if (virtual_registers_[n] != UnallocatedOperand::kInvalidVirtualRegister) { |
| 198 NodeId const id = static_cast<NodeId>(n); |
| 199 virtual_registers.insert(std::make_pair(id, virtual_registers_[n])); |
| 200 } |
| 201 } |
| 202 return virtual_registers; |
| 192 } | 203 } |
| 193 | 204 |
| 194 | 205 |
| 195 bool InstructionSelector::IsDefined(Node* node) const { | 206 bool InstructionSelector::IsDefined(Node* node) const { |
| 196 DCHECK_NOT_NULL(node); | 207 DCHECK_NOT_NULL(node); |
| 197 NodeId id = node->id(); | 208 size_t const id = node->id(); |
| 198 DCHECK(id >= 0); | 209 DCHECK_LT(id, defined_.size()); |
| 199 DCHECK(id < static_cast<NodeId>(defined_.size())); | |
| 200 return defined_[id]; | 210 return defined_[id]; |
| 201 } | 211 } |
| 202 | 212 |
| 203 | 213 |
| 204 void InstructionSelector::MarkAsDefined(Node* node) { | 214 void InstructionSelector::MarkAsDefined(Node* node) { |
| 205 DCHECK_NOT_NULL(node); | 215 DCHECK_NOT_NULL(node); |
| 206 NodeId id = node->id(); | 216 size_t const id = node->id(); |
| 207 DCHECK(id >= 0); | 217 DCHECK_LT(id, defined_.size()); |
| 208 DCHECK(id < static_cast<NodeId>(defined_.size())); | |
| 209 defined_[id] = true; | 218 defined_[id] = true; |
| 210 } | 219 } |
| 211 | 220 |
| 212 | 221 |
| 213 bool InstructionSelector::IsUsed(Node* node) const { | 222 bool InstructionSelector::IsUsed(Node* node) const { |
| 223 DCHECK_NOT_NULL(node); |
| 214 if (!node->op()->HasProperty(Operator::kEliminatable)) return true; | 224 if (!node->op()->HasProperty(Operator::kEliminatable)) return true; |
| 215 NodeId id = node->id(); | 225 size_t const id = node->id(); |
| 216 DCHECK(id >= 0); | 226 DCHECK_LT(id, used_.size()); |
| 217 DCHECK(id < static_cast<NodeId>(used_.size())); | |
| 218 return used_[id]; | 227 return used_[id]; |
| 219 } | 228 } |
| 220 | 229 |
| 221 | 230 |
| 222 void InstructionSelector::MarkAsUsed(Node* node) { | 231 void InstructionSelector::MarkAsUsed(Node* node) { |
| 223 DCHECK_NOT_NULL(node); | 232 DCHECK_NOT_NULL(node); |
| 224 NodeId id = node->id(); | 233 size_t const id = node->id(); |
| 225 DCHECK(id >= 0); | 234 DCHECK_LT(id, used_.size()); |
| 226 DCHECK(id < static_cast<NodeId>(used_.size())); | |
| 227 used_[id] = true; | 235 used_[id] = true; |
| 228 } | 236 } |
| 229 | 237 |
| 230 | 238 |
| 231 bool InstructionSelector::IsDouble(const Node* node) const { | 239 bool InstructionSelector::IsDouble(const Node* node) const { |
| 232 DCHECK_NOT_NULL(node); | 240 DCHECK_NOT_NULL(node); |
| 233 int virtual_register = GetMappedVirtualRegister(node); | 241 int const virtual_register = virtual_registers_[node->id()]; |
| 234 if (virtual_register == kNodeUnmapped) return false; | 242 if (virtual_register == UnallocatedOperand::kInvalidVirtualRegister) { |
| 243 return false; |
| 244 } |
| 235 return sequence()->IsDouble(virtual_register); | 245 return sequence()->IsDouble(virtual_register); |
| 236 } | 246 } |
| 237 | 247 |
| 238 | 248 |
| 239 void InstructionSelector::MarkAsDouble(Node* node) { | 249 void InstructionSelector::MarkAsDouble(Node* node) { |
| 240 DCHECK_NOT_NULL(node); | 250 DCHECK_NOT_NULL(node); |
| 241 DCHECK(!IsReference(node)); | 251 DCHECK(!IsReference(node)); |
| 242 sequence()->MarkAsDouble(GetVirtualRegister(node)); | 252 sequence()->MarkAsDouble(GetVirtualRegister(node)); |
| 243 } | 253 } |
| 244 | 254 |
| 245 | 255 |
| 246 bool InstructionSelector::IsReference(const Node* node) const { | 256 bool InstructionSelector::IsReference(const Node* node) const { |
| 247 DCHECK_NOT_NULL(node); | 257 DCHECK_NOT_NULL(node); |
| 248 int virtual_register = GetMappedVirtualRegister(node); | 258 int const virtual_register = virtual_registers_[node->id()]; |
| 249 if (virtual_register == kNodeUnmapped) return false; | 259 if (virtual_register == UnallocatedOperand::kInvalidVirtualRegister) { |
| 260 return false; |
| 261 } |
| 250 return sequence()->IsReference(virtual_register); | 262 return sequence()->IsReference(virtual_register); |
| 251 } | 263 } |
| 252 | 264 |
| 253 | 265 |
| 254 void InstructionSelector::MarkAsReference(Node* node) { | 266 void InstructionSelector::MarkAsReference(Node* node) { |
| 255 DCHECK_NOT_NULL(node); | 267 DCHECK_NOT_NULL(node); |
| 256 DCHECK(!IsDouble(node)); | 268 DCHECK(!IsDouble(node)); |
| 257 sequence()->MarkAsReference(GetVirtualRegister(node)); | 269 sequence()->MarkAsReference(GetVirtualRegister(node)); |
| 258 } | 270 } |
| 259 | 271 |
| (...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 MachineOperatorBuilder::Flags | 1149 MachineOperatorBuilder::Flags |
| 1138 InstructionSelector::SupportedMachineOperatorFlags() { | 1150 InstructionSelector::SupportedMachineOperatorFlags() { |
| 1139 return MachineOperatorBuilder::Flag::kNoFlags; | 1151 return MachineOperatorBuilder::Flag::kNoFlags; |
| 1140 } | 1152 } |
| 1141 | 1153 |
| 1142 #endif // !V8_TURBOFAN_BACKEND | 1154 #endif // !V8_TURBOFAN_BACKEND |
| 1143 | 1155 |
| 1144 } // namespace compiler | 1156 } // namespace compiler |
| 1145 } // namespace internal | 1157 } // namespace internal |
| 1146 } // namespace v8 | 1158 } // namespace v8 |
| OLD | NEW |