| 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/machine-operator-reducer.h" | 5 #include "src/compiler/machine-operator-reducer.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/compiler/generic-node-inl.h" | 10 #include "src/compiler/generic-node-inl.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) { | 51 Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) { |
| 52 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs)); | 52 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs)); |
| 53 } | 53 } |
| 54 | 54 |
| 55 | 55 |
| 56 Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) { | 56 Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) { |
| 57 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs)); | 57 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs)); |
| 58 } | 58 } |
| 59 | 59 |
| 60 | 60 |
| 61 Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) { |
| 62 return graph()->NewNode(machine()->Word32Equal(), lhs, rhs); |
| 63 } |
| 64 |
| 65 |
| 61 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { | 66 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { |
| 62 return graph()->NewNode(machine()->Int32Add(), lhs, rhs); | 67 return graph()->NewNode(machine()->Int32Add(), lhs, rhs); |
| 63 } | 68 } |
| 64 | 69 |
| 65 | 70 |
| 66 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { | 71 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { |
| 67 return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); | 72 return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); |
| 68 } | 73 } |
| 69 | 74 |
| 70 | 75 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 } | 297 } |
| 293 if (m.right().IsPowerOf2()) { // x * 2^n => x << n | 298 if (m.right().IsPowerOf2()) { // x * 2^n => x << n |
| 294 node->set_op(machine()->Word32Shl()); | 299 node->set_op(machine()->Word32Shl()); |
| 295 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); | 300 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); |
| 296 return Changed(node); | 301 return Changed(node); |
| 297 } | 302 } |
| 298 break; | 303 break; |
| 299 } | 304 } |
| 300 case IrOpcode::kInt32Div: | 305 case IrOpcode::kInt32Div: |
| 301 return ReduceInt32Div(node); | 306 return ReduceInt32Div(node); |
| 302 case IrOpcode::kUint32Div: { | 307 case IrOpcode::kUint32Div: |
| 303 Uint32BinopMatcher m(node); | 308 return ReduceUint32Div(node); |
| 304 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x | |
| 305 // TODO(turbofan): if (m.left().Is(0)) | |
| 306 // TODO(turbofan): if (m.right().Is(0)) | |
| 307 // TODO(turbofan): if (m.LeftEqualsRight()) | |
| 308 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K | |
| 309 return ReplaceInt32(m.left().Value() / m.right().Value()); | |
| 310 } | |
| 311 if (m.right().IsPowerOf2()) { // x / 2^n => x >> n | |
| 312 node->set_op(machine()->Word32Shr()); | |
| 313 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); | |
| 314 return Changed(node); | |
| 315 } | |
| 316 break; | |
| 317 } | |
| 318 case IrOpcode::kInt32Mod: | 309 case IrOpcode::kInt32Mod: |
| 319 return ReduceInt32Mod(node); | 310 return ReduceInt32Mod(node); |
| 320 case IrOpcode::kUint32Mod: { | 311 case IrOpcode::kUint32Mod: |
| 321 Uint32BinopMatcher m(node); | 312 return ReduceUint32Mod(node); |
| 322 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 | |
| 323 // TODO(turbofan): if (m.left().Is(0)) | |
| 324 // TODO(turbofan): if (m.right().Is(0)) | |
| 325 // TODO(turbofan): if (m.LeftEqualsRight()) | |
| 326 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K | |
| 327 return ReplaceInt32(m.left().Value() % m.right().Value()); | |
| 328 } | |
| 329 if (m.right().IsPowerOf2()) { // x % 2^n => x & 2^n-1 | |
| 330 node->set_op(machine()->Word32And()); | |
| 331 node->ReplaceInput(1, Int32Constant(m.right().Value() - 1)); | |
| 332 return Changed(node); | |
| 333 } | |
| 334 break; | |
| 335 } | |
| 336 case IrOpcode::kInt32LessThan: { | 313 case IrOpcode::kInt32LessThan: { |
| 337 Int32BinopMatcher m(node); | 314 Int32BinopMatcher m(node); |
| 338 if (m.IsFoldable()) { // K < K => K | 315 if (m.IsFoldable()) { // K < K => K |
| 339 return ReplaceBool(m.left().Value() < m.right().Value()); | 316 return ReplaceBool(m.left().Value() < m.right().Value()); |
| 340 } | 317 } |
| 341 if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y < 0 => x < y | 318 if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y < 0 => x < y |
| 342 Int32BinopMatcher msub(m.left().node()); | 319 Int32BinopMatcher msub(m.left().node()); |
| 343 node->ReplaceInput(0, msub.left().node()); | 320 node->ReplaceInput(0, msub.left().node()); |
| 344 node->ReplaceInput(1, msub.right().node()); | 321 node->ReplaceInput(1, msub.right().node()); |
| 345 return Changed(node); | 322 return Changed(node); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 } | 524 } |
| 548 default: | 525 default: |
| 549 break; | 526 break; |
| 550 } | 527 } |
| 551 return NoChange(); | 528 return NoChange(); |
| 552 } | 529 } |
| 553 | 530 |
| 554 | 531 |
| 555 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { | 532 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { |
| 556 Int32BinopMatcher m(node); | 533 Int32BinopMatcher m(node); |
| 534 if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0 |
| 557 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 | 535 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 |
| 558 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x | 536 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
| 559 // TODO(turbofan): if (m.left().Is(0)) | 537 if (m.IsFoldable()) { // K / K => K |
| 560 // TODO(turbofan): if (m.LeftEqualsRight()) | 538 return ReplaceInt32( |
| 561 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K | 539 base::bits::SignedDiv32(m.left().Value(), m.right().Value())); |
| 562 if (m.right().Is(-1)) return ReplaceInt32(-m.left().Value()); | 540 } |
| 563 return ReplaceInt32(m.left().Value() / m.right().Value()); | 541 if (m.LeftEqualsRight()) { // x / x => x != 0 |
| 542 Node* const zero = Int32Constant(0); |
| 543 return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero)); |
| 564 } | 544 } |
| 565 if (m.right().Is(-1)) { // x / -1 => 0 - x | 545 if (m.right().Is(-1)) { // x / -1 => 0 - x |
| 566 node->set_op(machine()->Int32Sub()); | 546 node->set_op(machine()->Int32Sub()); |
| 567 node->ReplaceInput(0, Int32Constant(0)); | 547 node->ReplaceInput(0, Int32Constant(0)); |
| 568 node->ReplaceInput(1, m.left().node()); | 548 node->ReplaceInput(1, m.left().node()); |
| 569 return Changed(node); | 549 return Changed(node); |
| 570 } | 550 } |
| 571 if (m.right().HasValue()) { | 551 if (m.right().HasValue()) { |
| 572 int32_t const divisor = m.right().Value(); | 552 int32_t const divisor = m.right().Value(); |
| 573 Node* const dividend = m.left().node(); | 553 Node* const dividend = m.left().node(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 588 node->ReplaceInput(0, Int32Constant(0)); | 568 node->ReplaceInput(0, Int32Constant(0)); |
| 589 node->ReplaceInput(1, quotient); | 569 node->ReplaceInput(1, quotient); |
| 590 return Changed(node); | 570 return Changed(node); |
| 591 } | 571 } |
| 592 return Replace(quotient); | 572 return Replace(quotient); |
| 593 } | 573 } |
| 594 return NoChange(); | 574 return NoChange(); |
| 595 } | 575 } |
| 596 | 576 |
| 597 | 577 |
| 578 Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) { |
| 579 Uint32BinopMatcher m(node); |
| 580 if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0 |
| 581 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 |
| 582 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
| 583 if (m.IsFoldable()) { // K / K => K |
| 584 return ReplaceUint32( |
| 585 base::bits::UnsignedDiv32(m.left().Value(), m.right().Value())); |
| 586 } |
| 587 if (m.LeftEqualsRight()) { // x / x => x != 0 |
| 588 Node* const zero = Int32Constant(0); |
| 589 return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero)); |
| 590 } |
| 591 if (m.right().IsPowerOf2()) { // x / 2^n => x >> n |
| 592 node->set_op(machine()->Word32Shr()); |
| 593 node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value()))); |
| 594 return Changed(node); |
| 595 } |
| 596 return NoChange(); |
| 597 } |
| 598 |
| 599 |
| 598 Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) { | 600 Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) { |
| 599 Int32BinopMatcher m(node); | 601 Int32BinopMatcher m(node); |
| 600 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 | 602 if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0 |
| 601 if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0 | 603 if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0 |
| 602 // TODO(turbofan): if (m.left().Is(0)) | 604 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 |
| 603 // TODO(turbofan): if (m.right().Is(0)) | 605 if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0 |
| 604 // TODO(turbofan): if (m.LeftEqualsRight()) | 606 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0 |
| 605 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K | 607 if (m.IsFoldable()) { // K % K => K |
| 606 return ReplaceInt32(m.left().Value() % m.right().Value()); | 608 return ReplaceInt32( |
| 609 base::bits::SignedMod32(m.left().Value(), m.right().Value())); |
| 607 } | 610 } |
| 608 if (m.right().HasValue()) { | 611 if (m.right().HasValue()) { |
| 609 Node* const dividend = m.left().node(); | 612 Node* const dividend = m.left().node(); |
| 610 int32_t const divisor = Abs(m.right().Value()); | 613 int32_t const divisor = Abs(m.right().Value()); |
| 611 if (base::bits::IsPowerOfTwo32(divisor)) { | 614 if (base::bits::IsPowerOfTwo32(divisor)) { |
| 612 uint32_t const mask = divisor - 1; | 615 uint32_t const mask = divisor - 1; |
| 613 Node* const zero = Int32Constant(0); | 616 Node* const zero = Int32Constant(0); |
| 614 | 617 |
| 615 Node* check = | 618 Node* check = |
| 616 graph()->NewNode(machine()->Int32LessThan(), dividend, zero); | 619 graph()->NewNode(machine()->Int32LessThan(), dividend, zero); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 632 node->set_op(machine()->Int32Sub()); | 635 node->set_op(machine()->Int32Sub()); |
| 633 DCHECK_EQ(dividend, node->InputAt(0)); | 636 DCHECK_EQ(dividend, node->InputAt(0)); |
| 634 node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor))); | 637 node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor))); |
| 635 return Changed(node); | 638 return Changed(node); |
| 636 } | 639 } |
| 637 } | 640 } |
| 638 return NoChange(); | 641 return NoChange(); |
| 639 } | 642 } |
| 640 | 643 |
| 641 | 644 |
| 645 Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) { |
| 646 Uint32BinopMatcher m(node); |
| 647 if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0 |
| 648 if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0 |
| 649 if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0 |
| 650 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0 |
| 651 if (m.IsFoldable()) { // K % K => K |
| 652 return ReplaceUint32( |
| 653 base::bits::UnsignedMod32(m.left().Value(), m.right().Value())); |
| 654 } |
| 655 if (m.right().IsPowerOf2()) { // x % 2^n => x & 2^n-1 |
| 656 node->set_op(machine()->Word32And()); |
| 657 node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1)); |
| 658 return Changed(node); |
| 659 } |
| 660 return NoChange(); |
| 661 } |
| 662 |
| 663 |
| 642 Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) { | 664 Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) { |
| 643 switch (node->opcode()) { | 665 switch (node->opcode()) { |
| 644 case IrOpcode::kInt32AddWithOverflow: { | 666 case IrOpcode::kInt32AddWithOverflow: { |
| 645 DCHECK(index == 0 || index == 1); | 667 DCHECK(index == 0 || index == 1); |
| 646 Int32BinopMatcher m(node); | 668 Int32BinopMatcher m(node); |
| 647 if (m.IsFoldable()) { | 669 if (m.IsFoldable()) { |
| 648 int32_t val; | 670 int32_t val; |
| 649 bool ovf = base::bits::SignedAddOverflow32(m.left().Value(), | 671 bool ovf = base::bits::SignedAddOverflow32(m.left().Value(), |
| 650 m.right().Value(), &val); | 672 m.right().Value(), &val); |
| 651 return ReplaceInt32((index == 0) ? val : ovf); | 673 return ReplaceInt32((index == 0) ? val : ovf); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 MachineOperatorBuilder* MachineOperatorReducer::machine() const { | 706 MachineOperatorBuilder* MachineOperatorReducer::machine() const { |
| 685 return jsgraph()->machine(); | 707 return jsgraph()->machine(); |
| 686 } | 708 } |
| 687 | 709 |
| 688 | 710 |
| 689 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } | 711 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
| 690 | 712 |
| 691 } // namespace compiler | 713 } // namespace compiler |
| 692 } // namespace internal | 714 } // namespace internal |
| 693 } // namespace v8 | 715 } // namespace v8 |
| OLD | NEW |