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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 g.UseRegister(index), g.UseRegister(base)); | 245 g.UseRegister(index), g.UseRegister(base)); |
246 // Emit desired store opcode, using temp addr_reg. | 246 // Emit desired store opcode, using temp addr_reg. |
247 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 247 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
248 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 248 addr_reg, g.TempImmediate(0), g.UseRegister(value)); |
249 } | 249 } |
250 } | 250 } |
251 } | 251 } |
252 | 252 |
253 | 253 |
254 void InstructionSelector::VisitWord32And(Node* node) { | 254 void InstructionSelector::VisitWord32And(Node* node) { |
| 255 MipsOperandGenerator g(this); |
| 256 Int32BinopMatcher m(node); |
| 257 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && |
| 258 m.right().HasValue()) { |
| 259 uint32_t mask = m.right().Value(); |
| 260 uint32_t mask_width = base::bits::CountPopulation32(mask); |
| 261 uint32_t mask_msb = base::bits::CountLeadingZeros32(mask); |
| 262 if ((mask_width != 0) && (mask_msb + mask_width == 32)) { |
| 263 // The mask must be contiguous, and occupy the least-significant bits. |
| 264 DCHECK_EQ(0u, base::bits::CountTrailingZeros32(mask)); |
| 265 |
| 266 // Select Ext for And(Shr(x, imm), mask) where the mask is in the least |
| 267 // significant bits. |
| 268 Int32BinopMatcher mleft(m.left().node()); |
| 269 if (mleft.right().HasValue()) { |
| 270 // Any shift value can match; int32 shifts use `value % 32`. |
| 271 uint32_t lsb = mleft.right().Value() & 0x1f; |
| 272 |
| 273 // Ext cannot extract bits past the register size, however since |
| 274 // shifting the original value would have introduced some zeros we can |
| 275 // still use Ext with a smaller mask and the remaining bits will be |
| 276 // zeros. |
| 277 if (lsb + mask_width > 32) mask_width = 32 - lsb; |
| 278 |
| 279 Emit(kMipsExt, g.DefineAsRegister(node), |
| 280 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), |
| 281 g.TempImmediate(mask_width)); |
| 282 return; |
| 283 } |
| 284 // Other cases fall through to the normal And operation. |
| 285 } |
| 286 } |
255 VisitBinop(this, node, kMipsAnd); | 287 VisitBinop(this, node, kMipsAnd); |
256 } | 288 } |
257 | 289 |
258 | 290 |
259 void InstructionSelector::VisitWord32Or(Node* node) { | 291 void InstructionSelector::VisitWord32Or(Node* node) { |
260 VisitBinop(this, node, kMipsOr); | 292 VisitBinop(this, node, kMipsOr); |
261 } | 293 } |
262 | 294 |
263 | 295 |
264 void InstructionSelector::VisitWord32Xor(Node* node) { | 296 void InstructionSelector::VisitWord32Xor(Node* node) { |
265 VisitBinop(this, node, kMipsXor); | 297 VisitBinop(this, node, kMipsXor); |
266 } | 298 } |
267 | 299 |
268 | 300 |
269 void InstructionSelector::VisitWord32Shl(Node* node) { | 301 void InstructionSelector::VisitWord32Shl(Node* node) { |
270 VisitRRO(this, kMipsShl, node); | 302 VisitRRO(this, kMipsShl, node); |
271 } | 303 } |
272 | 304 |
273 | 305 |
274 void InstructionSelector::VisitWord32Shr(Node* node) { | 306 void InstructionSelector::VisitWord32Shr(Node* node) { |
| 307 Int32BinopMatcher m(node); |
| 308 if (m.left().IsWord32And() && m.right().HasValue()) { |
| 309 uint32_t lsb = m.right().Value() & 0x1f; |
| 310 Int32BinopMatcher mleft(m.left().node()); |
| 311 if (mleft.right().HasValue()) { |
| 312 // Select Ext for Shr(And(x, mask), imm) where the result of the mask is |
| 313 // shifted into the least-significant bits. |
| 314 uint32_t mask = (mleft.right().Value() >> lsb) << lsb; |
| 315 unsigned mask_width = base::bits::CountPopulation32(mask); |
| 316 unsigned mask_msb = base::bits::CountLeadingZeros32(mask); |
| 317 if ((mask_msb + mask_width + lsb) == 32) { |
| 318 MipsOperandGenerator g(this); |
| 319 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(mask)); |
| 320 Emit(kMipsExt, g.DefineAsRegister(node), |
| 321 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), |
| 322 g.TempImmediate(mask_width)); |
| 323 return; |
| 324 } |
| 325 } |
| 326 } |
275 VisitRRO(this, kMipsShr, node); | 327 VisitRRO(this, kMipsShr, node); |
276 } | 328 } |
277 | 329 |
278 | 330 |
279 void InstructionSelector::VisitWord32Sar(Node* node) { | 331 void InstructionSelector::VisitWord32Sar(Node* node) { |
280 VisitRRO(this, kMipsSar, node); | 332 VisitRRO(this, kMipsSar, node); |
281 } | 333 } |
282 | 334 |
283 | 335 |
284 void InstructionSelector::VisitWord32Ror(Node* node) { | 336 void InstructionSelector::VisitWord32Ror(Node* node) { |
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 } | 1166 } |
1115 return flags | MachineOperatorBuilder::kFloat64Min | | 1167 return flags | MachineOperatorBuilder::kFloat64Min | |
1116 MachineOperatorBuilder::kFloat64Max | | 1168 MachineOperatorBuilder::kFloat64Max | |
1117 MachineOperatorBuilder::kFloat32Min | | 1169 MachineOperatorBuilder::kFloat32Min | |
1118 MachineOperatorBuilder::kFloat32Max; | 1170 MachineOperatorBuilder::kFloat32Max; |
1119 } | 1171 } |
1120 | 1172 |
1121 } // namespace compiler | 1173 } // namespace compiler |
1122 } // namespace internal | 1174 } // namespace internal |
1123 } // namespace v8 | 1175 } // namespace v8 |
OLD | NEW |