| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x | 144 if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x |
| 145 if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1 | 145 if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1 |
| 146 if (m.IsFoldable()) { // K | K => K | 146 if (m.IsFoldable()) { // K | K => K |
| 147 return ReplaceInt32(m.left().Value() | m.right().Value()); | 147 return ReplaceInt32(m.left().Value() | m.right().Value()); |
| 148 } | 148 } |
| 149 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x | 149 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x |
| 150 if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) { | 150 if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) { |
| 151 Int32BinopMatcher mleft(m.left().node()); | 151 Int32BinopMatcher mleft(m.left().node()); |
| 152 Int32BinopMatcher mright(m.right().node()); | 152 Int32BinopMatcher mright(m.right().node()); |
| 153 if (mleft.left().node() == mright.left().node()) { | 153 if (mleft.left().node() == mright.left().node()) { |
| 154 // (x << y) | (x >> (32 - y)) => x ror y | 154 // TODO(turbofan): here we are matching rotate left, shall we add |
| 155 // support for rotate right? |
| 156 // (x << y) | (x >>> (32 - y)) => x ror (32 - y) |
| 155 if (mright.right().IsInt32Sub()) { | 157 if (mright.right().IsInt32Sub()) { |
| 156 Int32BinopMatcher mrightright(mright.right().node()); | 158 Int32BinopMatcher mrightright(mright.right().node()); |
| 157 if (mrightright.left().Is(32) && | 159 if (mrightright.left().Is(32) && |
| 158 mrightright.right().node() == mleft.right().node()) { | 160 mrightright.right().node() == mleft.right().node()) { |
| 159 node->set_op(machine()->Word32Ror()); | 161 node->set_op(machine()->Word32Ror()); |
| 160 node->ReplaceInput(0, mleft.left().node()); | 162 node->ReplaceInput(0, mleft.left().node()); |
| 161 node->ReplaceInput(1, mleft.right().node()); | 163 node->ReplaceInput(1, mright.right().node()); |
| 162 return Changed(node); | 164 return Changed(node); |
| 163 } | 165 } |
| 164 } | 166 } |
| 165 // (x << K) | (x >> (32 - K)) => x ror K | 167 // (x << K) | (x >>> (32 - K)) => x ror (32 - K) |
| 166 if (mleft.right().IsInRange(0, 31) && | 168 if (mleft.right().IsInRange(0, 31) && |
| 167 mright.right().Is(32 - mleft.right().Value())) { | 169 mright.right().Is(32 - mleft.right().Value())) { |
| 168 node->set_op(machine()->Word32Ror()); | 170 node->set_op(machine()->Word32Ror()); |
| 169 node->ReplaceInput(0, mleft.left().node()); | 171 node->ReplaceInput(0, mleft.left().node()); |
| 170 node->ReplaceInput(1, mleft.right().node()); | 172 node->ReplaceInput(1, mright.right().node()); |
| 171 return Changed(node); | 173 return Changed(node); |
| 172 } | 174 } |
| 173 } | 175 } |
| 174 } | 176 } |
| 175 if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) { | 177 if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) { |
| 176 // (x >> (32 - y)) | (x << y) => x ror y | 178 // (x >>> (32 - y)) | (x << y) => x ror (32 -y) |
| 177 Int32BinopMatcher mleft(m.left().node()); | 179 Int32BinopMatcher mleft(m.left().node()); |
| 178 Int32BinopMatcher mright(m.right().node()); | 180 Int32BinopMatcher mright(m.right().node()); |
| 179 if (mleft.left().node() == mright.left().node()) { | 181 if (mleft.left().node() == mright.left().node()) { |
| 180 if (mleft.right().IsInt32Sub()) { | 182 if (mleft.right().IsInt32Sub()) { |
| 181 Int32BinopMatcher mleftright(mleft.right().node()); | 183 Int32BinopMatcher mleftright(mleft.right().node()); |
| 182 if (mleftright.left().Is(32) && | 184 if (mleftright.left().Is(32) && |
| 183 mleftright.right().node() == mright.right().node()) { | 185 mleftright.right().node() == mright.right().node()) { |
| 184 node->set_op(machine()->Word32Ror()); | 186 node->set_op(machine()->Word32Ror()); |
| 185 node->ReplaceInput(0, mright.left().node()); | 187 node->ReplaceInput(0, mright.left().node()); |
| 186 node->ReplaceInput(1, mright.right().node()); | 188 node->ReplaceInput(1, mleft.right().node()); |
| 187 return Changed(node); | 189 return Changed(node); |
| 188 } | 190 } |
| 189 } | 191 } |
| 190 // (x >> (32 - K)) | (x << K) => x ror K | 192 // (x >>> (32 - K)) | (x << K) => x ror (32 - K) |
| 191 if (mright.right().IsInRange(0, 31) && | 193 if (mright.right().IsInRange(0, 31) && |
| 192 mleft.right().Is(32 - mright.right().Value())) { | 194 mleft.right().Is(32 - mright.right().Value())) { |
| 193 node->set_op(machine()->Word32Ror()); | 195 node->set_op(machine()->Word32Ror()); |
| 194 node->ReplaceInput(0, mright.left().node()); | 196 node->ReplaceInput(0, mright.left().node()); |
| 195 node->ReplaceInput(1, mright.right().node()); | 197 node->ReplaceInput(1, mleft.right().node()); |
| 196 return Changed(node); | 198 return Changed(node); |
| 197 } | 199 } |
| 198 } | 200 } |
| 199 } | 201 } |
| 200 break; | 202 break; |
| 201 } | 203 } |
| 202 case IrOpcode::kWord32Xor: { | 204 case IrOpcode::kWord32Xor: { |
| 203 Int32BinopMatcher m(node); | 205 Int32BinopMatcher m(node); |
| 204 if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x | 206 if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x |
| 205 if (m.IsFoldable()) { // K ^ K => K | 207 if (m.IsFoldable()) { // K ^ K => K |
| (...skipping 21 matching lines...) Expand all Loading... |
| 227 Int32BinopMatcher mleft(m.left().node()); | 229 Int32BinopMatcher mleft(m.left().node()); |
| 228 if (mleft.right().Is(m.right().Value())) { | 230 if (mleft.right().Is(m.right().Value())) { |
| 229 node->set_op(machine()->Word32And()); | 231 node->set_op(machine()->Word32And()); |
| 230 node->ReplaceInput(0, mleft.left().node()); | 232 node->ReplaceInput(0, mleft.left().node()); |
| 231 node->ReplaceInput( | 233 node->ReplaceInput( |
| 232 1, Uint32Constant(~((1U << m.right().Value()) - 1U))); | 234 1, Uint32Constant(~((1U << m.right().Value()) - 1U))); |
| 233 return Changed(node); | 235 return Changed(node); |
| 234 } | 236 } |
| 235 } | 237 } |
| 236 } | 238 } |
| 237 break; | 239 return ReduceWord32Shifts(node); |
| 238 } | 240 } |
| 239 case IrOpcode::kWord32Shr: { | 241 case IrOpcode::kWord32Shr: { |
| 240 Uint32BinopMatcher m(node); | 242 Uint32BinopMatcher m(node); |
| 241 if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x | 243 if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x |
| 242 if (m.IsFoldable()) { // K >>> K => K | 244 if (m.IsFoldable()) { // K >>> K => K |
| 243 return ReplaceInt32(m.left().Value() >> m.right().Value()); | 245 return ReplaceInt32(m.left().Value() >> m.right().Value()); |
| 244 } | 246 } |
| 245 break; | 247 return ReduceWord32Shifts(node); |
| 246 } | 248 } |
| 247 case IrOpcode::kWord32Sar: { | 249 case IrOpcode::kWord32Sar: { |
| 248 Int32BinopMatcher m(node); | 250 Int32BinopMatcher m(node); |
| 249 if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x | 251 if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x |
| 250 if (m.IsFoldable()) { // K >> K => K | 252 if (m.IsFoldable()) { // K >> K => K |
| 251 return ReplaceInt32(m.left().Value() >> m.right().Value()); | 253 return ReplaceInt32(m.left().Value() >> m.right().Value()); |
| 252 } | 254 } |
| 253 if (m.left().IsWord32Shl()) { | 255 if (m.left().IsWord32Shl()) { |
| 254 Int32BinopMatcher mleft(m.left().node()); | 256 Int32BinopMatcher mleft(m.left().node()); |
| 255 if (mleft.left().IsLoad()) { | 257 if (mleft.left().IsLoad()) { |
| 256 LoadRepresentation const rep = | 258 LoadRepresentation const rep = |
| 257 OpParameter<LoadRepresentation>(mleft.left().node()); | 259 OpParameter<LoadRepresentation>(mleft.left().node()); |
| 258 if (m.right().Is(24) && mleft.right().Is(24) && rep == kMachInt8) { | 260 if (m.right().Is(24) && mleft.right().Is(24) && rep == kMachInt8) { |
| 259 // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8] | 261 // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8] |
| 260 return Replace(mleft.left().node()); | 262 return Replace(mleft.left().node()); |
| 261 } | 263 } |
| 262 if (m.right().Is(16) && mleft.right().Is(16) && rep == kMachInt16) { | 264 if (m.right().Is(16) && mleft.right().Is(16) && rep == kMachInt16) { |
| 263 // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8] | 265 // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8] |
| 264 return Replace(mleft.left().node()); | 266 return Replace(mleft.left().node()); |
| 265 } | 267 } |
| 266 } | 268 } |
| 267 } | 269 } |
| 268 break; | 270 return ReduceWord32Shifts(node); |
| 269 } | 271 } |
| 270 case IrOpcode::kWord32Ror: { | 272 case IrOpcode::kWord32Ror: { |
| 271 Int32BinopMatcher m(node); | 273 Int32BinopMatcher m(node); |
| 272 if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x | 274 if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x |
| 273 if (m.IsFoldable()) { // K ror K => K | 275 if (m.IsFoldable()) { // K ror K => K |
| 274 return ReplaceInt32( | 276 return ReplaceInt32( |
| 275 base::bits::RotateRight32(m.left().Value(), m.right().Value())); | 277 base::bits::RotateRight32(m.left().Value(), m.right().Value())); |
| 276 } | 278 } |
| 277 break; | 279 break; |
| 278 } | 280 } |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 } | 800 } |
| 799 break; | 801 break; |
| 800 } | 802 } |
| 801 default: | 803 default: |
| 802 break; | 804 break; |
| 803 } | 805 } |
| 804 return NoChange(); | 806 return NoChange(); |
| 805 } | 807 } |
| 806 | 808 |
| 807 | 809 |
| 810 Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) { |
| 811 DCHECK((node->opcode() == IrOpcode::kWord32Shl) || |
| 812 (node->opcode() == IrOpcode::kWord32Shr) || |
| 813 (node->opcode() == IrOpcode::kWord32Sar)); |
| 814 |
| 815 if (machine()->Word32ShiftIsSafe()) { |
| 816 // Remove the explicit 'and' with 0x1f if the shift provided by the machine |
| 817 // instruction matches that required by JavaScript. |
| 818 Int32BinopMatcher m(node); |
| 819 if (m.right().IsWord32And()) { |
| 820 Int32BinopMatcher mright(m.right().node()); |
| 821 if (mright.right().Is(0x1f)) { |
| 822 node->ReplaceInput(1, mright.left().node()); |
| 823 return Changed(node); |
| 824 } |
| 825 } |
| 826 } |
| 827 return NoChange(); |
| 828 } |
| 829 |
| 830 |
| 808 CommonOperatorBuilder* MachineOperatorReducer::common() const { | 831 CommonOperatorBuilder* MachineOperatorReducer::common() const { |
| 809 return jsgraph()->common(); | 832 return jsgraph()->common(); |
| 810 } | 833 } |
| 811 | 834 |
| 812 | 835 |
| 813 MachineOperatorBuilder* MachineOperatorReducer::machine() const { | 836 MachineOperatorBuilder* MachineOperatorReducer::machine() const { |
| 814 return jsgraph()->machine(); | 837 return jsgraph()->machine(); |
| 815 } | 838 } |
| 816 | 839 |
| 817 | 840 |
| 818 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } | 841 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
| 819 | 842 |
| 820 } // namespace compiler | 843 } // namespace compiler |
| 821 } // namespace internal | 844 } // namespace internal |
| 822 } // namespace v8 | 845 } // namespace v8 |
| OLD | NEW |