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/diamond.h" | 10 #include "src/compiler/diamond.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 Node* MachineOperatorReducer::Int32Constant(int32_t value) { | 36 Node* MachineOperatorReducer::Int32Constant(int32_t value) { |
37 return jsgraph()->Int32Constant(value); | 37 return jsgraph()->Int32Constant(value); |
38 } | 38 } |
39 | 39 |
40 | 40 |
41 Node* MachineOperatorReducer::Int64Constant(int64_t value) { | 41 Node* MachineOperatorReducer::Int64Constant(int64_t value) { |
42 return graph()->NewNode(common()->Int64Constant(value)); | 42 return graph()->NewNode(common()->Int64Constant(value)); |
43 } | 43 } |
44 | 44 |
45 | 45 |
46 Node* MachineOperatorReducer::Word32And(Node* lhs, uint32_t rhs) { | 46 Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) { |
47 return graph()->NewNode(machine()->Word32And(), lhs, Uint32Constant(rhs)); | 47 Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs); |
| 48 Reduction const reduction = ReduceWord32And(node); |
| 49 return reduction.Changed() ? reduction.replacement() : node; |
48 } | 50 } |
49 | 51 |
50 | 52 |
51 Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) { | 53 Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) { |
52 if (rhs == 0) return lhs; | 54 if (rhs == 0) return lhs; |
53 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs)); | 55 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs)); |
54 } | 56 } |
55 | 57 |
56 | 58 |
57 Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) { | 59 Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) { |
58 if (rhs == 0) return lhs; | 60 if (rhs == 0) return lhs; |
59 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs)); | 61 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs)); |
60 } | 62 } |
61 | 63 |
62 | 64 |
63 Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) { | 65 Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) { |
64 return graph()->NewNode(machine()->Word32Equal(), lhs, rhs); | 66 return graph()->NewNode(machine()->Word32Equal(), lhs, rhs); |
65 } | 67 } |
66 | 68 |
67 | 69 |
68 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { | 70 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { |
69 return graph()->NewNode(machine()->Int32Add(), lhs, rhs); | 71 Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs); |
| 72 Reduction const reduction = ReduceInt32Add(node); |
| 73 return reduction.Changed() ? reduction.replacement() : node; |
70 } | 74 } |
71 | 75 |
72 | 76 |
73 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { | 77 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { |
74 return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); | 78 return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); |
75 } | 79 } |
76 | 80 |
77 | 81 |
78 Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) { | 82 Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) { |
79 return graph()->NewNode(machine()->Int32Mul(), lhs, rhs); | 83 return graph()->NewNode(machine()->Int32Mul(), lhs, rhs); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y | 207 if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y |
204 Int64BinopMatcher msub(m.left().node()); | 208 Int64BinopMatcher msub(m.left().node()); |
205 node->ReplaceInput(0, msub.left().node()); | 209 node->ReplaceInput(0, msub.left().node()); |
206 node->ReplaceInput(1, msub.right().node()); | 210 node->ReplaceInput(1, msub.right().node()); |
207 return Changed(node); | 211 return Changed(node); |
208 } | 212 } |
209 // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares | 213 // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares |
210 if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true | 214 if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true |
211 break; | 215 break; |
212 } | 216 } |
213 case IrOpcode::kInt32Add: { | 217 case IrOpcode::kInt32Add: |
214 Int32BinopMatcher m(node); | 218 return ReduceInt32Add(node); |
215 if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x | |
216 if (m.IsFoldable()) { // K + K => K | |
217 return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) + | |
218 static_cast<uint32_t>(m.right().Value())); | |
219 } | |
220 break; | |
221 } | |
222 case IrOpcode::kInt32Sub: { | 219 case IrOpcode::kInt32Sub: { |
223 Int32BinopMatcher m(node); | 220 Int32BinopMatcher m(node); |
224 if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x | 221 if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x |
225 if (m.IsFoldable()) { // K - K => K | 222 if (m.IsFoldable()) { // K - K => K |
226 return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) - | 223 return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) - |
227 static_cast<uint32_t>(m.right().Value())); | 224 static_cast<uint32_t>(m.right().Value())); |
228 } | 225 } |
229 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0 | 226 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0 |
230 break; | 227 break; |
231 } | 228 } |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } | 456 } |
460 case IrOpcode::kStore: | 457 case IrOpcode::kStore: |
461 return ReduceStore(node); | 458 return ReduceStore(node); |
462 default: | 459 default: |
463 break; | 460 break; |
464 } | 461 } |
465 return NoChange(); | 462 return NoChange(); |
466 } | 463 } |
467 | 464 |
468 | 465 |
| 466 Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) { |
| 467 DCHECK_EQ(IrOpcode::kInt32Add, node->opcode()); |
| 468 Int32BinopMatcher m(node); |
| 469 if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x |
| 470 if (m.IsFoldable()) { // K + K => K |
| 471 return ReplaceUint32(bit_cast<uint32_t>(m.left().Value()) + |
| 472 bit_cast<uint32_t>(m.right().Value())); |
| 473 } |
| 474 return NoChange(); |
| 475 } |
| 476 |
| 477 |
469 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { | 478 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { |
470 Int32BinopMatcher m(node); | 479 Int32BinopMatcher m(node); |
471 if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0 | 480 if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0 |
472 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 | 481 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 |
473 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x | 482 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
474 if (m.IsFoldable()) { // K / K => K | 483 if (m.IsFoldable()) { // K / K => K |
475 return ReplaceInt32( | 484 return ReplaceInt32( |
476 base::bits::SignedDiv32(m.left().Value(), m.right().Value())); | 485 base::bits::SignedDiv32(m.left().Value(), m.right().Value())); |
477 } | 486 } |
478 if (m.LeftEqualsRight()) { // x / x => x != 0 | 487 if (m.LeftEqualsRight()) { // x / x => x != 0 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 if (m.IsFoldable()) { // K & K => K | 773 if (m.IsFoldable()) { // K & K => K |
765 return ReplaceInt32(m.left().Value() & m.right().Value()); | 774 return ReplaceInt32(m.left().Value() & m.right().Value()); |
766 } | 775 } |
767 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x | 776 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x |
768 if (m.left().IsWord32And() && m.right().HasValue()) { | 777 if (m.left().IsWord32And() && m.right().HasValue()) { |
769 Int32BinopMatcher mleft(m.left().node()); | 778 Int32BinopMatcher mleft(m.left().node()); |
770 if (mleft.right().HasValue()) { // (x & K) & K => x & K | 779 if (mleft.right().HasValue()) { // (x & K) & K => x & K |
771 node->ReplaceInput(0, mleft.left().node()); | 780 node->ReplaceInput(0, mleft.left().node()); |
772 node->ReplaceInput( | 781 node->ReplaceInput( |
773 1, Int32Constant(m.right().Value() & mleft.right().Value())); | 782 1, Int32Constant(m.right().Value() & mleft.right().Value())); |
774 Reduction reduction = ReduceWord32And(node); | 783 Reduction const reduction = ReduceWord32And(node); |
775 return reduction.Changed() ? reduction : Changed(node); | 784 return reduction.Changed() ? reduction : Changed(node); |
776 } | 785 } |
777 } | 786 } |
778 if (m.left().IsInt32Add() && m.right().IsNegativePowerOf2()) { | 787 if (m.left().IsInt32Add() && m.right().IsNegativePowerOf2()) { |
779 Int32BinopMatcher mleft(m.left().node()); | 788 Int32BinopMatcher mleft(m.left().node()); |
780 if (mleft.right().HasValue() && | 789 if (mleft.right().HasValue() && |
781 (mleft.right().Value() & m.right().Value()) == mleft.right().Value()) { | 790 (mleft.right().Value() & m.right().Value()) == mleft.right().Value()) { |
782 // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L) | 791 // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L) |
783 return Replace(graph()->NewNode( | 792 node->set_op(machine()->Int32Add()); |
784 machine()->Int32Add(), | 793 node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node())); |
785 graph()->NewNode(machine()->Word32And(), mleft.left().node(), | 794 node->ReplaceInput(1, mleft.right().node()); |
786 m.right().node()), | 795 Reduction const reduction = ReduceInt32Add(node); |
787 mleft.right().node())); | 796 return reduction.Changed() ? reduction : Changed(node); |
788 } | 797 } |
789 if (mleft.left().IsWord32Shl()) { | 798 if (mleft.left().IsWord32Shl()) { |
790 Int32BinopMatcher mleftleft(mleft.left().node()); | 799 Int32BinopMatcher mleftleft(mleft.left().node()); |
791 if (mleftleft.right().Is( | 800 if (mleftleft.right().Is( |
792 base::bits::CountTrailingZeros32(m.right().Value()))) { | 801 base::bits::CountTrailingZeros32(m.right().Value()))) { |
793 // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L | 802 // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L |
794 return Replace(graph()->NewNode( | 803 node->set_op(machine()->Int32Add()); |
795 machine()->Int32Add(), | 804 node->ReplaceInput(0, |
796 graph()->NewNode(machine()->Word32And(), mleft.right().node(), | 805 Word32And(mleft.right().node(), m.right().node())); |
797 m.right().node()), | 806 node->ReplaceInput(1, mleftleft.node()); |
798 mleftleft.node())); | 807 Reduction const reduction = ReduceInt32Add(node); |
| 808 return reduction.Changed() ? reduction : Changed(node); |
799 } | 809 } |
800 } | 810 } |
801 if (mleft.right().IsWord32Shl()) { | 811 if (mleft.right().IsWord32Shl()) { |
802 Int32BinopMatcher mleftright(mleft.right().node()); | 812 Int32BinopMatcher mleftright(mleft.right().node()); |
803 if (mleftright.right().Is( | 813 if (mleftright.right().Is( |
804 base::bits::CountTrailingZeros32(m.right().Value()))) { | 814 base::bits::CountTrailingZeros32(m.right().Value()))) { |
805 // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L | 815 // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L |
806 return Replace(graph()->NewNode( | 816 node->set_op(machine()->Int32Add()); |
807 machine()->Int32Add(), | 817 node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node())); |
808 graph()->NewNode(machine()->Word32And(), mleft.left().node(), | 818 node->ReplaceInput(1, mleftright.node()); |
809 m.right().node()), | 819 Reduction const reduction = ReduceInt32Add(node); |
810 mleftright.node())); | 820 return reduction.Changed() ? reduction : Changed(node); |
811 } | 821 } |
812 } | 822 } |
813 } | 823 } |
814 return NoChange(); | 824 return NoChange(); |
815 } | 825 } |
816 | 826 |
817 | 827 |
818 Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) { | 828 Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) { |
819 DCHECK_EQ(IrOpcode::kWord32Or, node->opcode()); | 829 DCHECK_EQ(IrOpcode::kWord32Or, node->opcode()); |
820 Int32BinopMatcher m(node); | 830 Int32BinopMatcher m(node); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 MachineOperatorBuilder* MachineOperatorReducer::machine() const { | 890 MachineOperatorBuilder* MachineOperatorReducer::machine() const { |
881 return jsgraph()->machine(); | 891 return jsgraph()->machine(); |
882 } | 892 } |
883 | 893 |
884 | 894 |
885 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } | 895 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
886 | 896 |
887 } // namespace compiler | 897 } // namespace compiler |
888 } // namespace internal | 898 } // namespace internal |
889 } // namespace v8 | 899 } // namespace v8 |
OLD | NEW |