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 |