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/bits.h" | 5 #include "src/base/bits.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { | 361 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { |
362 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), | 362 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), |
363 value_operand, shift_operand); | 363 value_operand, shift_operand); |
364 return; | 364 return; |
365 } | 365 } |
366 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), | 366 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), |
367 g.DefineAsRegister(node), g.UseRegister(left), | 367 g.DefineAsRegister(node), g.UseRegister(left), |
368 g.UseRegister(right)); | 368 g.UseRegister(right)); |
369 } | 369 } |
370 | 370 |
| 371 |
| 372 void EmitUbfx(InstructionSelector* selector, Node* node, Node* left, |
| 373 uint32_t lsb, uint32_t width) { |
| 374 DCHECK_LE(1, width); |
| 375 DCHECK_LE(width, 32 - lsb); |
| 376 ArmOperandGenerator g(selector); |
| 377 selector->Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(left), |
| 378 g.TempImmediate(lsb), g.TempImmediate(width)); |
| 379 } |
| 380 |
371 } // namespace | 381 } // namespace |
372 | 382 |
373 | 383 |
374 void InstructionSelector::VisitWord32And(Node* node) { | 384 void InstructionSelector::VisitWord32And(Node* node) { |
375 ArmOperandGenerator g(this); | 385 ArmOperandGenerator g(this); |
376 Int32BinopMatcher m(node); | 386 Int32BinopMatcher m(node); |
377 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { | 387 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { |
378 Int32BinopMatcher mleft(m.left().node()); | 388 Int32BinopMatcher mleft(m.left().node()); |
379 if (mleft.right().Is(-1)) { | 389 if (mleft.right().Is(-1)) { |
380 EmitBic(this, node, m.right().node(), mleft.left().node()); | 390 EmitBic(this, node, m.right().node(), mleft.left().node()); |
(...skipping 10 matching lines...) Expand all Loading... |
391 if (m.right().HasValue()) { | 401 if (m.right().HasValue()) { |
392 uint32_t const value = m.right().Value(); | 402 uint32_t const value = m.right().Value(); |
393 uint32_t width = base::bits::CountPopulation32(value); | 403 uint32_t width = base::bits::CountPopulation32(value); |
394 uint32_t msb = base::bits::CountLeadingZeros32(value); | 404 uint32_t msb = base::bits::CountLeadingZeros32(value); |
395 // Try to interpret this AND as UBFX. | 405 // Try to interpret this AND as UBFX. |
396 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { | 406 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { |
397 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); | 407 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); |
398 if (m.left().IsWord32Shr()) { | 408 if (m.left().IsWord32Shr()) { |
399 Int32BinopMatcher mleft(m.left().node()); | 409 Int32BinopMatcher mleft(m.left().node()); |
400 if (mleft.right().IsInRange(0, 31)) { | 410 if (mleft.right().IsInRange(0, 31)) { |
401 Emit(kArmUbfx, g.DefineAsRegister(node), | 411 // UBFX cannot extract bits past the register size, however since |
402 g.UseRegister(mleft.left().node()), | 412 // shifting the original value would have introduced some zeros we can |
403 g.UseImmediate(mleft.right().node()), g.TempImmediate(width)); | 413 // still use UBFX with a smaller mask and the remaining bits will be |
404 return; | 414 // zeros. |
| 415 uint32_t const lsb = mleft.right().Value(); |
| 416 return EmitUbfx(this, node, mleft.left().node(), lsb, |
| 417 std::min(width, 32 - lsb)); |
405 } | 418 } |
406 } | 419 } |
407 Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 420 return EmitUbfx(this, node, m.left().node(), 0, width); |
408 g.TempImmediate(0), g.TempImmediate(width)); | |
409 return; | |
410 } | 421 } |
411 // Try to interpret this AND as BIC. | 422 // Try to interpret this AND as BIC. |
412 if (g.CanBeImmediate(~value)) { | 423 if (g.CanBeImmediate(~value)) { |
413 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), | 424 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), |
414 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 425 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
415 g.TempImmediate(~value)); | 426 g.TempImmediate(~value)); |
416 return; | 427 return; |
417 } | 428 } |
418 // Try to interpret this AND as UXTH. | 429 // Try to interpret this AND as UXTH. |
419 if (value == 0xffff) { | 430 if (value == 0xffff) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 if (IsSupported(ARMv7) && m.left().IsWord32And() && | 527 if (IsSupported(ARMv7) && m.left().IsWord32And() && |
517 m.right().IsInRange(0, 31)) { | 528 m.right().IsInRange(0, 31)) { |
518 int32_t lsb = m.right().Value(); | 529 int32_t lsb = m.right().Value(); |
519 Int32BinopMatcher mleft(m.left().node()); | 530 Int32BinopMatcher mleft(m.left().node()); |
520 if (mleft.right().HasValue()) { | 531 if (mleft.right().HasValue()) { |
521 uint32_t value = (mleft.right().Value() >> lsb) << lsb; | 532 uint32_t value = (mleft.right().Value() >> lsb) << lsb; |
522 uint32_t width = base::bits::CountPopulation32(value); | 533 uint32_t width = base::bits::CountPopulation32(value); |
523 uint32_t msb = base::bits::CountLeadingZeros32(value); | 534 uint32_t msb = base::bits::CountLeadingZeros32(value); |
524 if (msb + width + lsb == 32) { | 535 if (msb + width + lsb == 32) { |
525 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); | 536 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); |
526 Emit(kArmUbfx, g.DefineAsRegister(node), | 537 return EmitUbfx(this, node, mleft.left().node(), lsb, width); |
527 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), | |
528 g.TempImmediate(width)); | |
529 return; | |
530 } | 538 } |
531 } | 539 } |
532 } | 540 } |
533 VisitShift(this, node, TryMatchLSR); | 541 VisitShift(this, node, TryMatchLSR); |
534 } | 542 } |
535 | 543 |
536 | 544 |
537 void InstructionSelector::VisitWord32Sar(Node* node) { | 545 void InstructionSelector::VisitWord32Sar(Node* node) { |
538 ArmOperandGenerator g(this); | 546 ArmOperandGenerator g(this); |
539 Int32BinopMatcher m(node); | 547 Int32BinopMatcher m(node); |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 MachineOperatorBuilder::kFloat64Ceil | | 1264 MachineOperatorBuilder::kFloat64Ceil | |
1257 MachineOperatorBuilder::kFloat64RoundTruncate | | 1265 MachineOperatorBuilder::kFloat64RoundTruncate | |
1258 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1266 MachineOperatorBuilder::kFloat64RoundTiesAway; |
1259 } | 1267 } |
1260 return flags; | 1268 return flags; |
1261 } | 1269 } |
1262 | 1270 |
1263 } // namespace compiler | 1271 } // namespace compiler |
1264 } // namespace internal | 1272 } // namespace internal |
1265 } // namespace v8 | 1273 } // namespace v8 |
OLD | NEW |