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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 } | 112 } |
113 return quotient; | 113 return quotient; |
114 } | 114 } |
115 | 115 |
116 | 116 |
117 // Perform constant folding and strength reduction on machine operators. | 117 // Perform constant folding and strength reduction on machine operators. |
118 Reduction MachineOperatorReducer::Reduce(Node* node) { | 118 Reduction MachineOperatorReducer::Reduce(Node* node) { |
119 switch (node->opcode()) { | 119 switch (node->opcode()) { |
120 case IrOpcode::kProjection: | 120 case IrOpcode::kProjection: |
121 return ReduceProjection(OpParameter<size_t>(node), node->InputAt(0)); | 121 return ReduceProjection(OpParameter<size_t>(node), node->InputAt(0)); |
122 case IrOpcode::kWord32And: { | 122 case IrOpcode::kWord32And: |
123 Int32BinopMatcher m(node); | 123 return ReduceWord32And(node); |
124 if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0 | |
125 if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x | |
126 if (m.IsFoldable()) { // K & K => K | |
127 return ReplaceInt32(m.left().Value() & m.right().Value()); | |
128 } | |
129 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x | |
130 if (m.left().IsWord32And() && m.right().HasValue()) { | |
131 Int32BinopMatcher mleft(m.left().node()); | |
132 if (mleft.right().HasValue()) { // (x & K) & K => x & K | |
133 node->ReplaceInput(0, mleft.left().node()); | |
134 node->ReplaceInput( | |
135 1, Int32Constant(m.right().Value() & mleft.right().Value())); | |
136 return Changed(node); | |
137 } | |
138 } | |
139 if (m.left().IsInt32Add() && m.right().IsNegativePowerOf2()) { | |
140 Int32BinopMatcher mleft(m.left().node()); | |
141 if (mleft.right().HasValue() && | |
142 (mleft.right().Value() & m.right().Value()) == | |
143 mleft.right().Value()) { | |
144 // (x + K) & K => (x & K) + K | |
145 return Replace(graph()->NewNode( | |
146 machine()->Int32Add(), | |
147 graph()->NewNode(machine()->Word32And(), mleft.left().node(), | |
148 m.right().node()), | |
149 mleft.right().node())); | |
150 } | |
151 } | |
152 break; | |
153 } | |
154 case IrOpcode::kWord32Or: | 124 case IrOpcode::kWord32Or: |
155 return ReduceWord32Or(node); | 125 return ReduceWord32Or(node); |
156 case IrOpcode::kWord32Xor: { | 126 case IrOpcode::kWord32Xor: { |
157 Int32BinopMatcher m(node); | 127 Int32BinopMatcher m(node); |
158 if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x | 128 if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x |
159 if (m.IsFoldable()) { // K ^ K => K | 129 if (m.IsFoldable()) { // K ^ K => K |
160 return ReplaceInt32(m.left().Value() ^ m.right().Value()); | 130 return ReplaceInt32(m.left().Value() ^ m.right().Value()); |
161 } | 131 } |
162 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0 | 132 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0 |
163 if (m.left().IsWord32Xor() && m.right().Is(-1)) { | 133 if (m.left().IsWord32Xor() && m.right().Is(-1)) { |
164 Int32BinopMatcher mleft(m.left().node()); | 134 Int32BinopMatcher mleft(m.left().node()); |
165 if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x | 135 if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x |
166 return Replace(mleft.left().node()); | 136 return Replace(mleft.left().node()); |
167 } | 137 } |
168 } | 138 } |
169 break; | 139 break; |
170 } | 140 } |
171 case IrOpcode::kWord32Shl: { | 141 case IrOpcode::kWord32Shl: |
172 Int32BinopMatcher m(node); | 142 return ReduceWord32Shl(node); |
173 if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x | |
174 if (m.IsFoldable()) { // K << K => K | |
175 return ReplaceInt32(m.left().Value() << m.right().Value()); | |
176 } | |
177 if (m.right().IsInRange(1, 31)) { | |
178 // (x >>> K) << K => x & ~(2^K - 1) | |
179 // (x >> K) << K => x & ~(2^K - 1) | |
180 if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) { | |
181 Int32BinopMatcher mleft(m.left().node()); | |
182 if (mleft.right().Is(m.right().Value())) { | |
183 node->set_op(machine()->Word32And()); | |
184 node->ReplaceInput(0, mleft.left().node()); | |
185 node->ReplaceInput( | |
186 1, Uint32Constant(~((1U << m.right().Value()) - 1U))); | |
187 return Changed(node); | |
188 } | |
189 } | |
190 } | |
191 return ReduceWord32Shifts(node); | |
192 } | |
193 case IrOpcode::kWord32Shr: { | 143 case IrOpcode::kWord32Shr: { |
194 Uint32BinopMatcher m(node); | 144 Uint32BinopMatcher m(node); |
195 if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x | 145 if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x |
196 if (m.IsFoldable()) { // K >>> K => K | 146 if (m.IsFoldable()) { // K >>> K => K |
197 return ReplaceInt32(m.left().Value() >> m.right().Value()); | 147 return ReplaceInt32(m.left().Value() >> m.right().Value()); |
198 } | 148 } |
199 return ReduceWord32Shifts(node); | 149 return ReduceWord32Shifts(node); |
200 } | 150 } |
201 case IrOpcode::kWord32Sar: { | 151 case IrOpcode::kWord32Sar: { |
202 Int32BinopMatcher m(node); | 152 Int32BinopMatcher m(node); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 238 } |
289 if (m.right().Is(-1)) { // x * -1 => 0 - x | 239 if (m.right().Is(-1)) { // x * -1 => 0 - x |
290 node->set_op(machine()->Int32Sub()); | 240 node->set_op(machine()->Int32Sub()); |
291 node->ReplaceInput(0, Int32Constant(0)); | 241 node->ReplaceInput(0, Int32Constant(0)); |
292 node->ReplaceInput(1, m.left().node()); | 242 node->ReplaceInput(1, m.left().node()); |
293 return Changed(node); | 243 return Changed(node); |
294 } | 244 } |
295 if (m.right().IsPowerOf2()) { // x * 2^n => x << n | 245 if (m.right().IsPowerOf2()) { // x * 2^n => x << n |
296 node->set_op(machine()->Word32Shl()); | 246 node->set_op(machine()->Word32Shl()); |
297 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); | 247 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); |
298 return Changed(node); | 248 Reduction reduction = ReduceWord32Shl(node); |
| 249 return reduction.Changed() ? reduction : Changed(node); |
299 } | 250 } |
300 break; | 251 break; |
301 } | 252 } |
302 case IrOpcode::kInt32Div: | 253 case IrOpcode::kInt32Div: |
303 return ReduceInt32Div(node); | 254 return ReduceInt32Div(node); |
304 case IrOpcode::kUint32Div: | 255 case IrOpcode::kUint32Div: |
305 return ReduceUint32Div(node); | 256 return ReduceUint32Div(node); |
306 case IrOpcode::kInt32Mod: | 257 case IrOpcode::kInt32Mod: |
307 return ReduceInt32Mod(node); | 258 return ReduceInt32Mod(node); |
308 case IrOpcode::kUint32Mod: | 259 case IrOpcode::kUint32Mod: |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 break; | 707 break; |
757 } | 708 } |
758 return NoChange(); | 709 return NoChange(); |
759 } | 710 } |
760 | 711 |
761 | 712 |
762 Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) { | 713 Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) { |
763 DCHECK((node->opcode() == IrOpcode::kWord32Shl) || | 714 DCHECK((node->opcode() == IrOpcode::kWord32Shl) || |
764 (node->opcode() == IrOpcode::kWord32Shr) || | 715 (node->opcode() == IrOpcode::kWord32Shr) || |
765 (node->opcode() == IrOpcode::kWord32Sar)); | 716 (node->opcode() == IrOpcode::kWord32Sar)); |
766 | |
767 if (machine()->Word32ShiftIsSafe()) { | 717 if (machine()->Word32ShiftIsSafe()) { |
768 // Remove the explicit 'and' with 0x1f if the shift provided by the machine | 718 // Remove the explicit 'and' with 0x1f if the shift provided by the machine |
769 // instruction matches that required by JavaScript. | 719 // instruction matches that required by JavaScript. |
770 Int32BinopMatcher m(node); | 720 Int32BinopMatcher m(node); |
771 if (m.right().IsWord32And()) { | 721 if (m.right().IsWord32And()) { |
772 Int32BinopMatcher mright(m.right().node()); | 722 Int32BinopMatcher mright(m.right().node()); |
773 if (mright.right().Is(0x1f)) { | 723 if (mright.right().Is(0x1f)) { |
774 node->ReplaceInput(1, mright.left().node()); | 724 node->ReplaceInput(1, mright.left().node()); |
775 return Changed(node); | 725 return Changed(node); |
776 } | 726 } |
777 } | 727 } |
778 } | 728 } |
779 return NoChange(); | 729 return NoChange(); |
780 } | 730 } |
781 | 731 |
782 | 732 |
| 733 Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) { |
| 734 DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode()); |
| 735 Int32BinopMatcher m(node); |
| 736 if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x |
| 737 if (m.IsFoldable()) { // K << K => K |
| 738 return ReplaceInt32(m.left().Value() << m.right().Value()); |
| 739 } |
| 740 if (m.right().IsInRange(1, 31)) { |
| 741 // (x >>> K) << K => x & ~(2^K - 1) |
| 742 // (x >> K) << K => x & ~(2^K - 1) |
| 743 if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) { |
| 744 Int32BinopMatcher mleft(m.left().node()); |
| 745 if (mleft.right().Is(m.right().Value())) { |
| 746 node->set_op(machine()->Word32And()); |
| 747 node->ReplaceInput(0, mleft.left().node()); |
| 748 node->ReplaceInput(1, |
| 749 Uint32Constant(~((1U << m.right().Value()) - 1U))); |
| 750 Reduction reduction = ReduceWord32And(node); |
| 751 return reduction.Changed() ? reduction : Changed(node); |
| 752 } |
| 753 } |
| 754 } |
| 755 return ReduceWord32Shifts(node); |
| 756 } |
| 757 |
| 758 |
| 759 Reduction MachineOperatorReducer::ReduceWord32And(Node* node) { |
| 760 DCHECK_EQ(IrOpcode::kWord32And, node->opcode()); |
| 761 Int32BinopMatcher m(node); |
| 762 if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0 |
| 763 if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x |
| 764 if (m.IsFoldable()) { // K & K => K |
| 765 return ReplaceInt32(m.left().Value() & m.right().Value()); |
| 766 } |
| 767 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x |
| 768 if (m.left().IsWord32And() && m.right().HasValue()) { |
| 769 Int32BinopMatcher mleft(m.left().node()); |
| 770 if (mleft.right().HasValue()) { // (x & K) & K => x & K |
| 771 node->ReplaceInput(0, mleft.left().node()); |
| 772 node->ReplaceInput( |
| 773 1, Int32Constant(m.right().Value() & mleft.right().Value())); |
| 774 Reduction reduction = ReduceWord32And(node); |
| 775 return reduction.Changed() ? reduction : Changed(node); |
| 776 } |
| 777 } |
| 778 if (m.left().IsInt32Add() && m.right().IsNegativePowerOf2()) { |
| 779 Int32BinopMatcher mleft(m.left().node()); |
| 780 if (mleft.right().HasValue() && |
| 781 (mleft.right().Value() & m.right().Value()) == mleft.right().Value()) { |
| 782 // (x + K) & K => (x & K) + K |
| 783 return Replace(graph()->NewNode( |
| 784 machine()->Int32Add(), |
| 785 graph()->NewNode(machine()->Word32And(), mleft.left().node(), |
| 786 m.right().node()), |
| 787 mleft.right().node())); |
| 788 } |
| 789 } |
| 790 return NoChange(); |
| 791 } |
| 792 |
| 793 |
783 Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) { | 794 Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) { |
784 DCHECK(node->opcode() == IrOpcode::kWord32Or); | 795 DCHECK_EQ(IrOpcode::kWord32Or, node->opcode()); |
785 | |
786 Int32BinopMatcher m(node); | 796 Int32BinopMatcher m(node); |
787 if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x | 797 if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x |
788 if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1 | 798 if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1 |
789 if (m.IsFoldable()) { // K | K => K | 799 if (m.IsFoldable()) { // K | K => K |
790 return ReplaceInt32(m.left().Value() | m.right().Value()); | 800 return ReplaceInt32(m.left().Value() | m.right().Value()); |
791 } | 801 } |
792 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x | 802 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x |
793 | 803 |
794 Node* shl = NULL; | 804 Node* shl = NULL; |
795 Node* shr = NULL; | 805 Node* shr = NULL; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 MachineOperatorBuilder* MachineOperatorReducer::machine() const { | 856 MachineOperatorBuilder* MachineOperatorReducer::machine() const { |
847 return jsgraph()->machine(); | 857 return jsgraph()->machine(); |
848 } | 858 } |
849 | 859 |
850 | 860 |
851 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } | 861 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
852 | 862 |
853 } // namespace compiler | 863 } // namespace compiler |
854 } // namespace internal | 864 } // namespace internal |
855 } // namespace v8 | 865 } // namespace v8 |
OLD | NEW |