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-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler-intrinsics.h" | 7 #include "src/compiler-intrinsics.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 // Shared routine for multiple binary operations. | 243 // Shared routine for multiple binary operations. |
244 static void VisitBinop(InstructionSelector* selector, Node* node, | 244 static void VisitBinop(InstructionSelector* selector, Node* node, |
245 InstructionCode opcode, InstructionCode reverse_opcode) { | 245 InstructionCode opcode, InstructionCode reverse_opcode) { |
246 ArmOperandGenerator g(selector); | 246 ArmOperandGenerator g(selector); |
247 Int32BinopMatcher m(node); | 247 Int32BinopMatcher m(node); |
248 InstructionOperand* inputs[3]; | 248 InstructionOperand* inputs[3]; |
249 size_t input_count = 0; | 249 size_t input_count = 0; |
| 250 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)}; |
| 251 const size_t output_count = ARRAY_SIZE(outputs); |
250 | 252 |
251 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), | 253 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), |
252 &input_count, &inputs[1])) { | 254 &input_count, &inputs[1])) { |
253 inputs[0] = g.UseRegister(m.left().node()); | 255 inputs[0] = g.UseRegister(m.left().node()); |
254 input_count++; | 256 input_count++; |
255 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, | 257 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, |
256 m.left().node(), &input_count, | 258 m.left().node(), &input_count, |
257 &inputs[1])) { | 259 &inputs[1])) { |
258 inputs[0] = g.UseRegister(m.right().node()); | 260 inputs[0] = g.UseRegister(m.right().node()); |
259 opcode = reverse_opcode; | 261 opcode = reverse_opcode; |
260 input_count++; | 262 input_count++; |
261 } else { | 263 } else { |
262 opcode |= AddressingModeField::encode(kMode_Operand2_R); | 264 opcode |= AddressingModeField::encode(kMode_Operand2_R); |
263 inputs[input_count++] = g.UseRegister(m.left().node()); | 265 inputs[input_count++] = g.UseRegister(m.left().node()); |
264 inputs[input_count++] = g.UseRegister(m.right().node()); | 266 inputs[input_count++] = g.UseRegister(m.right().node()); |
265 } | 267 } |
266 | 268 |
267 ASSERT_NE(0, input_count); | 269 ASSERT_NE(0, input_count); |
268 ASSERT_GE(ARRAY_SIZE(inputs), input_count); | 270 ASSERT_GE(ARRAY_SIZE(inputs), input_count); |
269 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); | 271 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); |
270 | 272 |
271 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)}; | |
272 const size_t output_count = ARRAY_SIZE(outputs); | |
273 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 273 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
274 } | 274 } |
275 | 275 |
| 276 |
| 277 static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node, |
| 278 InstructionCode opcode, |
| 279 InstructionCode reverse_opcode) { |
| 280 ArmOperandGenerator g(selector); |
| 281 Int32BinopMatcher m(node); |
| 282 InstructionOperand* inputs[3]; |
| 283 size_t input_count = 0; |
| 284 InstructionOperand* outputs[2]; |
| 285 size_t output_count = 0; |
| 286 |
| 287 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), |
| 288 &input_count, &inputs[1])) { |
| 289 inputs[0] = g.UseRegister(m.left().node()); |
| 290 input_count++; |
| 291 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, |
| 292 m.left().node(), &input_count, |
| 293 &inputs[1])) { |
| 294 inputs[0] = g.UseRegister(m.right().node()); |
| 295 opcode = reverse_opcode; |
| 296 input_count++; |
| 297 } else { |
| 298 opcode |= AddressingModeField::encode(kMode_Operand2_R); |
| 299 inputs[input_count++] = g.UseRegister(m.left().node()); |
| 300 inputs[input_count++] = g.UseRegister(m.right().node()); |
| 301 } |
| 302 |
| 303 // Define outputs depending on the projections. |
| 304 Node* projections[2]; |
| 305 node->CollectProjections(ARRAY_SIZE(projections), projections); |
| 306 if (projections[0]) { |
| 307 outputs[output_count++] = g.DefineAsRegister(projections[0]); |
| 308 } |
| 309 if (projections[1]) { |
| 310 opcode |= FlagsModeField::encode(kFlags_set); |
| 311 opcode |= FlagsConditionField::encode(kOverflow); |
| 312 outputs[output_count++] = g.DefineAsRegister(projections[1]); |
| 313 } |
| 314 |
| 315 ASSERT_NE(0, input_count); |
| 316 ASSERT_NE(0, output_count); |
| 317 ASSERT_GE(ARRAY_SIZE(inputs), input_count); |
| 318 ASSERT_GE(ARRAY_SIZE(outputs), output_count); |
| 319 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); |
| 320 |
| 321 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 322 } |
| 323 |
276 | 324 |
277 void InstructionSelector::VisitLoad(Node* node) { | 325 void InstructionSelector::VisitLoad(Node* node) { |
278 MachineRepresentation rep = OpParameter<MachineRepresentation>(node); | 326 MachineRepresentation rep = OpParameter<MachineRepresentation>(node); |
279 ArmOperandGenerator g(this); | 327 ArmOperandGenerator g(this); |
280 Node* base = node->InputAt(0); | 328 Node* base = node->InputAt(0); |
281 Node* index = node->InputAt(1); | 329 Node* index = node->InputAt(1); |
282 | 330 |
283 InstructionOperand* result = rep == kMachineFloat64 | 331 InstructionOperand* result = rep == kMachineFloat64 |
284 ? g.DefineAsDoubleRegister(node) | 332 ? g.DefineAsDoubleRegister(node) |
285 : g.DefineAsRegister(node); | 333 : g.DefineAsRegister(node); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 580 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { |
533 Int32BinopMatcher mright(m.right().node()); | 581 Int32BinopMatcher mright(m.right().node()); |
534 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), | 582 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), |
535 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 583 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
536 return; | 584 return; |
537 } | 585 } |
538 VisitBinop(this, node, kArmAdd, kArmAdd); | 586 VisitBinop(this, node, kArmAdd, kArmAdd); |
539 } | 587 } |
540 | 588 |
541 | 589 |
| 590 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
| 591 VisitBinopWithOverflow(this, node, kArmAdd, kArmAdd); |
| 592 } |
| 593 |
| 594 |
542 void InstructionSelector::VisitInt32Sub(Node* node) { | 595 void InstructionSelector::VisitInt32Sub(Node* node) { |
543 ArmOperandGenerator g(this); | 596 ArmOperandGenerator g(this); |
544 Int32BinopMatcher m(node); | 597 Int32BinopMatcher m(node); |
545 if (CpuFeatures::IsSupported(MLS) && m.right().IsInt32Mul() && | 598 if (CpuFeatures::IsSupported(MLS) && m.right().IsInt32Mul() && |
546 CanCover(node, m.right().node())) { | 599 CanCover(node, m.right().node())) { |
547 Int32BinopMatcher mright(m.right().node()); | 600 Int32BinopMatcher mright(m.right().node()); |
548 Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), | 601 Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), |
549 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 602 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
550 return; | 603 return; |
551 } | 604 } |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 ASSERT(cont->IsSet()); | 947 ASSERT(cont->IsSet()); |
895 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), | 948 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), |
896 g.UseDoubleRegister(m.left().node()), | 949 g.UseDoubleRegister(m.left().node()), |
897 g.UseDoubleRegister(m.right().node())); | 950 g.UseDoubleRegister(m.right().node())); |
898 } | 951 } |
899 } | 952 } |
900 | 953 |
901 } // namespace compiler | 954 } // namespace compiler |
902 } // namespace internal | 955 } // namespace internal |
903 } // namespace v8 | 956 } // namespace v8 |
OLD | NEW |