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/generic-node-inl.h" | 5 #include "src/compiler/generic-node-inl.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 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 return mode; | 420 return mode; |
421 } | 421 } |
422 | 422 |
423 } // namespace | 423 } // namespace |
424 | 424 |
425 | 425 |
426 void InstructionSelector::VisitInt32Add(Node* node) { | 426 void InstructionSelector::VisitInt32Add(Node* node) { |
427 // Try to match the Add to a leal pattern | 427 // Try to match the Add to a leal pattern |
428 ScaledWithOffset32Matcher m(node); | 428 ScaledWithOffset32Matcher m(node); |
429 X64OperandGenerator g(this); | 429 X64OperandGenerator g(this); |
| 430 // It's possible to use a "leal", but it may not be smaller/cheaper. In the |
| 431 // case that there are only two operands to the add and one of them isn't |
| 432 // live, use a plain "addl". |
430 if (m.matches() && (m.constant() == NULL || g.CanBeImmediate(m.constant()))) { | 433 if (m.matches() && (m.constant() == NULL || g.CanBeImmediate(m.constant()))) { |
431 // The add can be represented as a "leal", but there may be a smaller | |
432 // representation that is better and no more expensive. | |
433 if (m.offset() != NULL) { | 434 if (m.offset() != NULL) { |
434 if (m.scaled() == NULL) { | 435 if (m.constant() == NULL) { |
435 if (!IsLive(m.offset())) { | 436 if (m.scaled() != NULL && m.scale_exponent() == 0) { |
436 // If the add is of the form (r1 + immediate) and the non-constant | 437 if (!IsLive(m.offset())) { |
437 // input to the add is owned by the add, then it doesn't need to be | 438 Emit(kX64Add32, g.DefineSameAsFirst(node), |
438 // preserved across the operation, so use more compact, | 439 g.UseRegister(m.offset()), g.Use(m.scaled())); |
439 // source-register-overwriting versions when they are available and | |
440 // smaller, e.g. "incl" and "decl". | |
441 int32_t value = | |
442 m.constant() == NULL ? 0 : OpParameter<int32_t>(m.constant()); | |
443 if (value == 1) { | |
444 Emit(kX64Inc32, g.DefineSameAsFirst(node), | |
445 g.UseRegister(m.offset())); | |
446 return; | 440 return; |
447 } else if (value == -1) { | 441 } else if (!IsLive(m.scaled())) { |
448 Emit(kX64Dec32, g.DefineSameAsFirst(node), | 442 Emit(kX64Add32, g.DefineSameAsFirst(node), |
449 g.UseRegister(m.offset())); | 443 g.UseRegister(m.scaled()), g.Use(m.offset())); |
450 return; | 444 return; |
451 } | 445 } |
452 } | 446 } |
| 447 } else { |
| 448 if (m.scale_exponent() == 0) { |
| 449 if (m.scaled() == NULL || m.offset() == NULL) { |
| 450 Node* non_constant = m.scaled() == NULL ? m.offset() : m.scaled(); |
| 451 if (!IsLive(non_constant)) { |
| 452 Emit(kX64Add32, g.DefineSameAsFirst(node), |
| 453 g.UseRegister(non_constant), g.UseImmediate(m.constant())); |
| 454 return; |
| 455 } |
| 456 } |
| 457 } |
453 } | 458 } |
454 } | 459 } |
455 | 460 |
456 InstructionOperand* inputs[4]; | 461 InstructionOperand* inputs[4]; |
457 size_t input_count = 0; | 462 size_t input_count = 0; |
458 AddressingMode mode = GenerateMemoryOperandInputs( | 463 AddressingMode mode = GenerateMemoryOperandInputs( |
459 &g, m.scaled(), m.scale_exponent(), m.offset(), m.constant(), inputs, | 464 &g, m.scaled(), m.scale_exponent(), m.offset(), m.constant(), inputs, |
460 &input_count); | 465 &input_count); |
461 | 466 |
462 DCHECK_NE(0, static_cast<int>(input_count)); | 467 DCHECK_NE(0, static_cast<int>(input_count)); |
(...skipping 17 matching lines...) Expand all Loading... |
480 } | 485 } |
481 | 486 |
482 | 487 |
483 void InstructionSelector::VisitInt32Sub(Node* node) { | 488 void InstructionSelector::VisitInt32Sub(Node* node) { |
484 X64OperandGenerator g(this); | 489 X64OperandGenerator g(this); |
485 Int32BinopMatcher m(node); | 490 Int32BinopMatcher m(node); |
486 if (m.left().Is(0)) { | 491 if (m.left().Is(0)) { |
487 Emit(kX64Neg32, g.DefineSameAsFirst(node), g.UseRegister(m.right().node())); | 492 Emit(kX64Neg32, g.DefineSameAsFirst(node), g.UseRegister(m.right().node())); |
488 } else { | 493 } else { |
489 if (m.right().HasValue() && g.CanBeImmediate(m.right().node())) { | 494 if (m.right().HasValue() && g.CanBeImmediate(m.right().node())) { |
490 // If the Non-constant input is owned by the subtract, using a "decl" or | 495 if (IsLive(m.left().node())) { |
491 // "incl" that overwrites that input is smaller and probably an overall | |
492 // win. | |
493 if (!IsLive(m.left().node())) { | |
494 if (m.right().Value() == 1) { | |
495 Emit(kX64Dec32, g.DefineSameAsFirst(node), | |
496 g.UseRegister(m.left().node())); | |
497 return; | |
498 } | |
499 if (m.right().Value() == -1) { | |
500 Emit(kX64Inc32, g.DefineSameAsFirst(node), | |
501 g.UseRegister(m.left().node())); | |
502 return; | |
503 } | |
504 } else { | |
505 // Special handling for subtraction of constants where the non-constant | 496 // Special handling for subtraction of constants where the non-constant |
506 // input is used elsewhere. To eliminate the gap move before the sub to | 497 // input is used elsewhere. To eliminate the gap move before the sub to |
507 // copy the destination register, use a "leal" instead. | 498 // copy the destination register, use a "leal" instead. |
508 Emit(kX64Lea32 | AddressingModeField::encode(kMode_MRI), | 499 Emit(kX64Lea32 | AddressingModeField::encode(kMode_MRI), |
509 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 500 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
510 g.TempImmediate(-m.right().Value())); | 501 g.TempImmediate(-m.right().Value())); |
511 return; | 502 return; |
512 } | 503 } |
513 } | 504 } |
514 VisitBinop(this, node, kX64Sub32); | 505 VisitBinop(this, node, kX64Sub32); |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 MachineOperatorBuilder::kFloat64Ceil | | 1200 MachineOperatorBuilder::kFloat64Ceil | |
1210 MachineOperatorBuilder::kFloat64RoundTruncate | | 1201 MachineOperatorBuilder::kFloat64RoundTruncate | |
1211 MachineOperatorBuilder::kWord32ShiftIsSafe; | 1202 MachineOperatorBuilder::kWord32ShiftIsSafe; |
1212 } | 1203 } |
1213 return MachineOperatorBuilder::kNoFlags; | 1204 return MachineOperatorBuilder::kNoFlags; |
1214 } | 1205 } |
1215 | 1206 |
1216 } // namespace compiler | 1207 } // namespace compiler |
1217 } // namespace internal | 1208 } // namespace internal |
1218 } // namespace v8 | 1209 } // namespace v8 |
OLD | NEW |