| 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 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { | 544 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { |
| 545 Int32BinopMatcher mright(m.right().node()); | 545 Int32BinopMatcher mright(m.right().node()); |
| 546 if (mright.right().Is(-1)) { | 546 if (mright.right().Is(-1)) { |
| 547 EmitBic(this, node, m.left().node(), mright.left().node()); | 547 EmitBic(this, node, m.left().node(), mright.left().node()); |
| 548 return; | 548 return; |
| 549 } | 549 } |
| 550 } | 550 } |
| 551 if (m.right().HasValue()) { | 551 if (m.right().HasValue()) { |
| 552 uint32_t const value = m.right().Value(); | 552 uint32_t const value = m.right().Value(); |
| 553 uint32_t width = base::bits::CountPopulation32(value); | 553 uint32_t width = base::bits::CountPopulation32(value); |
| 554 uint32_t leading_zeros = base::bits::CountLeadingZeros32(value); | 554 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 555 | 555 // Try to interpret this AND as UBFX. |
| 556 // Try to merge SHR operations on the left hand input into this AND. | 556 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { |
| 557 if (m.left().IsWord32Shr()) { | 557 DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value)); |
| 558 Int32BinopMatcher mshr(m.left().node()); | 558 if (m.left().IsWord32Shr()) { |
| 559 if (mshr.right().HasValue()) { | 559 Int32BinopMatcher mleft(m.left().node()); |
| 560 uint32_t const shift = mshr.right().Value(); | 560 if (mleft.right().IsInRange(0, 31)) { |
| 561 | 561 // UBFX cannot extract bits past the register size, however since |
| 562 if (((shift == 8) || (shift == 16) || (shift == 24)) && | 562 // shifting the original value would have introduced some zeros we can |
| 563 ((value == 0xff) || (value == 0xffff))) { | 563 // still use UBFX with a smaller mask and the remaining bits will be |
| 564 // Merge SHR into AND by emitting a UXTB or UXTH instruction with a | 564 // zeros. |
| 565 // bytewise rotation. | 565 uint32_t const lsb = mleft.right().Value(); |
| 566 Emit((value == 0xff) ? kArmUxtb : kArmUxth, | 566 return EmitUbfx(this, node, mleft.left().node(), lsb, |
| 567 g.DefineAsRegister(m.node()), g.UseRegister(mshr.left().node()), | 567 std::min(width, 32 - lsb)); |
| 568 g.TempImmediate(mshr.right().Value())); | |
| 569 return; | |
| 570 } else if (IsSupported(ARMv7) && (width != 0) && | |
| 571 ((leading_zeros + width) == 32)) { | |
| 572 // Merge Shr into And by emitting a UBFX instruction. | |
| 573 DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value)); | |
| 574 if ((1 <= shift) && (shift <= 31)) { | |
| 575 // UBFX cannot extract bits past the register size, however since | |
| 576 // shifting the original value would have introduced some zeros we | |
| 577 // can still use UBFX with a smaller mask and the remaining bits | |
| 578 // will be zeros. | |
| 579 EmitUbfx(this, node, mshr.left().node(), shift, | |
| 580 std::min(width, 32 - shift)); | |
| 581 return; | |
| 582 } | |
| 583 } | 568 } |
| 584 } | 569 } |
| 585 } else if (value == 0xffff) { | 570 return EmitUbfx(this, node, m.left().node(), 0, width); |
| 586 // Emit UXTH for this AND. We don't bother testing for UXTB, as it's no | |
| 587 // better than AND 0xff for this operation. | |
| 588 Emit(kArmUxth, g.DefineAsRegister(m.node()), | |
| 589 g.UseRegister(m.left().node()), g.TempImmediate(0)); | |
| 590 return; | |
| 591 } | 571 } |
| 572 // Try to interpret this AND as BIC. |
| 592 if (g.CanBeImmediate(~value)) { | 573 if (g.CanBeImmediate(~value)) { |
| 593 // Emit BIC for this AND by inverting the immediate value first. | |
| 594 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), | 574 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), |
| 595 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 575 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 596 g.TempImmediate(~value)); | 576 g.TempImmediate(~value)); |
| 597 return; | 577 return; |
| 598 } | 578 } |
| 599 if (!g.CanBeImmediate(value) && IsSupported(ARMv7)) { | 579 // Try to interpret this AND as UXTH. |
| 600 // If value has 9 to 23 contiguous set bits, and has the lsb set, we can | 580 if (value == 0xffff) { |
| 601 // replace this AND with UBFX. Other contiguous bit patterns have already | 581 Emit(kArmUxth, g.DefineAsRegister(m.node()), |
| 602 // been handled by BIC or will be handled by AND. | 582 g.UseRegister(m.left().node()), g.TempImmediate(0)); |
| 603 if ((width != 0) && ((leading_zeros + width) == 32) && | 583 return; |
| 604 (9 <= leading_zeros) && (leading_zeros <= 23)) { | 584 } |
| 605 DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value)); | 585 // Try to interpret this AND as BFC. |
| 606 EmitUbfx(this, node, m.left().node(), 0, width); | 586 if (IsSupported(ARMv7)) { |
| 607 return; | |
| 608 } | |
| 609 | |
| 610 width = 32 - width; | 587 width = 32 - width; |
| 611 leading_zeros = base::bits::CountLeadingZeros32(~value); | 588 msb = base::bits::CountLeadingZeros32(~value); |
| 612 uint32_t lsb = base::bits::CountTrailingZeros32(~value); | 589 uint32_t lsb = base::bits::CountTrailingZeros32(~value); |
| 613 if ((leading_zeros + width + lsb) == 32) { | 590 if (msb + width + lsb == 32) { |
| 614 // This AND can be replaced with BFC. | |
| 615 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), | 591 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), |
| 616 g.TempImmediate(lsb), g.TempImmediate(width)); | 592 g.TempImmediate(lsb), g.TempImmediate(width)); |
| 617 return; | 593 return; |
| 618 } | 594 } |
| 619 } | 595 } |
| 620 } | 596 } |
| 621 VisitBinop(this, node, kArmAnd, kArmAnd); | 597 VisitBinop(this, node, kArmAnd, kArmAnd); |
| 622 } | 598 } |
| 623 | 599 |
| 624 | 600 |
| (...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1621 MachineOperatorBuilder::kFloat64RoundTiesAway | |
| 1646 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1622 MachineOperatorBuilder::kFloat32RoundTiesEven | |
| 1647 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1623 MachineOperatorBuilder::kFloat64RoundTiesEven; |
| 1648 } | 1624 } |
| 1649 return flags; | 1625 return flags; |
| 1650 } | 1626 } |
| 1651 | 1627 |
| 1652 } // namespace compiler | 1628 } // namespace compiler |
| 1653 } // namespace internal | 1629 } // namespace internal |
| 1654 } // namespace v8 | 1630 } // namespace v8 |
| OLD | NEW |