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/base/bits.h" | 5 #include "src/base/bits.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 if (cont->IsSet()) { | 232 if (cont->IsSet()) { |
233 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 233 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
234 } | 234 } |
235 | 235 |
236 DCHECK_NE(0u, input_count); | 236 DCHECK_NE(0u, input_count); |
237 DCHECK_NE(0u, output_count); | 237 DCHECK_NE(0u, output_count); |
238 DCHECK_GE(arraysize(inputs), input_count); | 238 DCHECK_GE(arraysize(inputs), input_count); |
239 DCHECK_GE(arraysize(outputs), output_count); | 239 DCHECK_GE(arraysize(outputs), output_count); |
240 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 240 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
241 | 241 |
242 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 242 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
243 outputs, input_count, inputs); | 243 inputs); |
244 if (cont->IsBranch()) instr->MarkAsControl(); | |
245 } | 244 } |
246 | 245 |
247 | 246 |
248 void VisitBinop(InstructionSelector* selector, Node* node, | 247 void VisitBinop(InstructionSelector* selector, Node* node, |
249 InstructionCode opcode, InstructionCode reverse_opcode) { | 248 InstructionCode opcode, InstructionCode reverse_opcode) { |
250 FlagsContinuation cont; | 249 FlagsContinuation cont; |
251 VisitBinop(selector, node, opcode, reverse_opcode, &cont); | 250 VisitBinop(selector, node, opcode, reverse_opcode, &cont); |
252 } | 251 } |
253 | 252 |
254 | 253 |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 if (cont->IsSet()) { | 571 if (cont->IsSet()) { |
573 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 572 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
574 } | 573 } |
575 | 574 |
576 DCHECK_NE(0u, input_count); | 575 DCHECK_NE(0u, input_count); |
577 DCHECK_NE(0u, output_count); | 576 DCHECK_NE(0u, output_count); |
578 DCHECK_GE(arraysize(inputs), input_count); | 577 DCHECK_GE(arraysize(inputs), input_count); |
579 DCHECK_GE(arraysize(outputs), output_count); | 578 DCHECK_GE(arraysize(outputs), output_count); |
580 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 579 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
581 | 580 |
582 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 581 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
583 outputs, input_count, inputs); | 582 inputs); |
584 if (cont->IsBranch()) instr->MarkAsControl(); | |
585 } | 583 } |
586 | 584 |
587 | 585 |
588 template <typename TryMatchShift> | 586 template <typename TryMatchShift> |
589 void VisitShift(InstructionSelector* selector, Node* node, | 587 void VisitShift(InstructionSelector* selector, Node* node, |
590 TryMatchShift try_match_shift) { | 588 TryMatchShift try_match_shift) { |
591 FlagsContinuation cont; | 589 FlagsContinuation cont; |
592 VisitShift(selector, node, try_match_shift, &cont); | 590 VisitShift(selector, node, try_match_shift, &cont); |
593 } | 591 } |
594 | 592 |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 // Shared routine for multiple float compare operations. | 1094 // Shared routine for multiple float compare operations. |
1097 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1095 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
1098 FlagsContinuation* cont) { | 1096 FlagsContinuation* cont) { |
1099 ArmOperandGenerator g(selector); | 1097 ArmOperandGenerator g(selector); |
1100 Float64BinopMatcher m(node); | 1098 Float64BinopMatcher m(node); |
1101 InstructionOperand rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node()) | 1099 InstructionOperand rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node()) |
1102 : g.UseRegister(m.right().node()); | 1100 : g.UseRegister(m.right().node()); |
1103 if (cont->IsBranch()) { | 1101 if (cont->IsBranch()) { |
1104 selector->Emit(cont->Encode(kArmVcmpF64), g.NoOutput(), | 1102 selector->Emit(cont->Encode(kArmVcmpF64), g.NoOutput(), |
1105 g.UseRegister(m.left().node()), rhs, | 1103 g.UseRegister(m.left().node()), rhs, |
1106 g.Label(cont->true_block()), | 1104 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1107 g.Label(cont->false_block()))->MarkAsControl(); | |
1108 } else { | 1105 } else { |
1109 DCHECK(cont->IsSet()); | 1106 DCHECK(cont->IsSet()); |
1110 selector->Emit(cont->Encode(kArmVcmpF64), | 1107 selector->Emit(cont->Encode(kArmVcmpF64), |
1111 g.DefineAsRegister(cont->result()), | 1108 g.DefineAsRegister(cont->result()), |
1112 g.UseRegister(m.left().node()), rhs); | 1109 g.UseRegister(m.left().node()), rhs); |
1113 } | 1110 } |
1114 } | 1111 } |
1115 | 1112 |
1116 | 1113 |
1117 // Shared routine for multiple word compare operations. | 1114 // Shared routine for multiple word compare operations. |
(...skipping 26 matching lines...) Expand all Loading... |
1144 inputs[input_count++] = g.Label(cont->false_block()); | 1141 inputs[input_count++] = g.Label(cont->false_block()); |
1145 } else { | 1142 } else { |
1146 DCHECK(cont->IsSet()); | 1143 DCHECK(cont->IsSet()); |
1147 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 1144 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
1148 } | 1145 } |
1149 | 1146 |
1150 DCHECK_NE(0u, input_count); | 1147 DCHECK_NE(0u, input_count); |
1151 DCHECK_GE(arraysize(inputs), input_count); | 1148 DCHECK_GE(arraysize(inputs), input_count); |
1152 DCHECK_GE(arraysize(outputs), output_count); | 1149 DCHECK_GE(arraysize(outputs), output_count); |
1153 | 1150 |
1154 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 1151 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
1155 outputs, input_count, inputs); | 1152 inputs); |
1156 if (cont->IsBranch()) instr->MarkAsControl(); | |
1157 } | 1153 } |
1158 | 1154 |
1159 | 1155 |
1160 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1156 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1161 FlagsContinuation* cont) { | 1157 FlagsContinuation* cont) { |
1162 VisitWordCompare(selector, node, kArmCmp, cont); | 1158 VisitWordCompare(selector, node, kArmCmp, cont); |
1163 } | 1159 } |
1164 | 1160 |
1165 | 1161 |
1166 // Shared routine for word comparisons against zero. | 1162 // Shared routine for word comparisons against zero. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1251 break; | 1247 break; |
1252 } | 1248 } |
1253 | 1249 |
1254 // Continuation could not be combined with a compare, emit compare against 0. | 1250 // Continuation could not be combined with a compare, emit compare against 0. |
1255 ArmOperandGenerator g(selector); | 1251 ArmOperandGenerator g(selector); |
1256 InstructionCode const opcode = | 1252 InstructionCode const opcode = |
1257 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); | 1253 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); |
1258 InstructionOperand const value_operand = g.UseRegister(value); | 1254 InstructionOperand const value_operand = g.UseRegister(value); |
1259 if (cont->IsBranch()) { | 1255 if (cont->IsBranch()) { |
1260 selector->Emit(opcode, g.NoOutput(), value_operand, value_operand, | 1256 selector->Emit(opcode, g.NoOutput(), value_operand, value_operand, |
1261 g.Label(cont->true_block()), | 1257 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1262 g.Label(cont->false_block()))->MarkAsControl(); | |
1263 } else { | 1258 } else { |
1264 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, | 1259 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, |
1265 value_operand); | 1260 value_operand); |
1266 } | 1261 } |
1267 } | 1262 } |
1268 | 1263 |
1269 } // namespace | 1264 } // namespace |
1270 | 1265 |
1271 | 1266 |
1272 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1267 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1304 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1310 inputs[0] = index_operand; | 1305 inputs[0] = index_operand; |
1311 std::fill(&inputs[1], &inputs[input_count], default_operand); | 1306 std::fill(&inputs[1], &inputs[input_count], default_operand); |
1312 for (size_t index = 0; index < case_count; ++index) { | 1307 for (size_t index = 0; index < case_count; ++index) { |
1313 size_t value = case_values[index] - min_value; | 1308 size_t value = case_values[index] - min_value; |
1314 BasicBlock* branch = case_branches[index]; | 1309 BasicBlock* branch = case_branches[index]; |
1315 DCHECK_LE(0u, value); | 1310 DCHECK_LE(0u, value); |
1316 DCHECK_LT(value + 2, input_count); | 1311 DCHECK_LT(value + 2, input_count); |
1317 inputs[value + 2] = g.Label(branch); | 1312 inputs[value + 2] = g.Label(branch); |
1318 } | 1313 } |
1319 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1314 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1320 ->MarkAsControl(); | |
1321 return; | 1315 return; |
1322 } | 1316 } |
1323 | 1317 |
1324 // Generate a sequence of conditional jumps. | 1318 // Generate a sequence of conditional jumps. |
1325 size_t input_count = 2 + case_count * 2; | 1319 size_t input_count = 2 + case_count * 2; |
1326 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1320 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1327 inputs[0] = value_operand; | 1321 inputs[0] = value_operand; |
1328 inputs[1] = default_operand; | 1322 inputs[1] = default_operand; |
1329 for (size_t index = 0; index < case_count; ++index) { | 1323 for (size_t index = 0; index < case_count; ++index) { |
1330 int32_t value = case_values[index]; | 1324 int32_t value = case_values[index]; |
1331 BasicBlock* branch = case_branches[index]; | 1325 BasicBlock* branch = case_branches[index]; |
1332 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); | 1326 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
1333 inputs[index * 2 + 2 + 1] = g.Label(branch); | 1327 inputs[index * 2 + 2 + 1] = g.Label(branch); |
1334 } | 1328 } |
1335 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1329 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1336 ->MarkAsControl(); | |
1337 } | 1330 } |
1338 | 1331 |
1339 | 1332 |
1340 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1333 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1341 FlagsContinuation cont(kEqual, node); | 1334 FlagsContinuation cont(kEqual, node); |
1342 Int32BinopMatcher m(node); | 1335 Int32BinopMatcher m(node); |
1343 if (m.right().Is(0)) { | 1336 if (m.right().Is(0)) { |
1344 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); | 1337 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); |
1345 } | 1338 } |
1346 VisitWordCompare(this, node, &cont); | 1339 VisitWordCompare(this, node, &cont); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1459 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
1467 MachineOperatorBuilder::kFloat64RoundTruncate | | 1460 MachineOperatorBuilder::kFloat64RoundTruncate | |
1468 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1461 MachineOperatorBuilder::kFloat64RoundTiesAway; |
1469 } | 1462 } |
1470 return flags; | 1463 return flags; |
1471 } | 1464 } |
1472 | 1465 |
1473 } // namespace compiler | 1466 } // namespace compiler |
1474 } // namespace internal | 1467 } // namespace internal |
1475 } // namespace v8 | 1468 } // namespace v8 |
OLD | NEW |