Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: src/compiler/arm/instruction-selector-arm.cc

Issue 2152253002: [ARM] Generate flag setting instructions for arm. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/unittests/compiler/arm/instruction-selector-arm-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1574 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 } else if (m.left().Is(0.0)) { 1585 } else if (m.left().Is(0.0)) {
1586 cont->Commute(); 1586 cont->Commute();
1587 VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.right().node()), 1587 VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.right().node()),
1588 g.UseImmediate(m.left().node()), cont); 1588 g.UseImmediate(m.left().node()), cont);
1589 } else { 1589 } else {
1590 VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.left().node()), 1590 VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.left().node()),
1591 g.UseRegister(m.right().node()), cont); 1591 g.UseRegister(m.right().node()), cont);
1592 } 1592 }
1593 } 1593 }
1594 1594
1595 // Check whether we can convert:
1596 // ((a <op> b) cmp 0), b.<cond>
1597 // to:
1598 // (a <ops> b), b.<cond'>
1599 // where <ops> is the flag setting version of <op>.
1600 // We only generate conditions <cond'> that are a combination of the N
1601 // and Z flags. This avoids the need to make this function dependent on
1602 // the flag-setting operation.
1603 bool CanUseFlagSettingBinop(FlagsCondition cond) {
1604 switch (cond) {
1605 case kEqual:
1606 case kNotEqual:
1607 case kSignedLessThan:
1608 case kSignedGreaterThanOrEqual:
1609 case kUnsignedLessThanOrEqual: // x <= 0 -> x == 0
1610 case kUnsignedGreaterThan: // x > 0 -> x != 0
1611 return true;
1612 default:
1613 return false;
1614 }
1615 }
1616
1617 // Map <cond> to <cond'> so that the following transformation is possible:
1618 // ((a <op> b) cmp 0), b.<cond>
1619 // to:
1620 // (a <ops> b), b.<cond'>
1621 // where <ops> is the flag setting version of <op>.
1622 FlagsCondition MapForFlagSettingBinop(FlagsCondition cond) {
1623 DCHECK(CanUseFlagSettingBinop(cond));
1624 switch (cond) {
1625 case kEqual:
1626 case kNotEqual:
1627 return cond;
1628 case kSignedLessThan:
1629 return kNegative;
1630 case kSignedGreaterThanOrEqual:
1631 return kPositiveOrZero;
1632 case kUnsignedLessThanOrEqual: // x <= 0 -> x == 0
1633 return kEqual;
1634 case kUnsignedGreaterThan: // x > 0 -> x != 0
1635 return kNotEqual;
1636 default:
1637 UNREACHABLE();
1638 return cond;
1639 }
1640 }
1641
1642 // Check if we can perform the transformation:
1643 // ((a <op> b) cmp 0), b.<cond>
1644 // to:
1645 // (a <ops> b), b.<cond'>
1646 // where <ops> is the flag setting version of <op>, and if so,
1647 // updates {node}, {opcode} and {cont} accordingly.
1648 void MaybeReplaceCmpZeroWithFlagSettingBinop(InstructionSelector* selector,
1649 Node** node, Node* binop,
1650 InstructionCode* opcode,
1651 FlagsCondition cond,
1652 FlagsContinuation* cont) {
1653 InstructionCode binop_opcode;
1654 InstructionCode no_output_opcode;
1655 switch (binop->opcode()) {
1656 case IrOpcode::kInt32Add:
1657 binop_opcode = kArmAdd;
1658 no_output_opcode = kArmCmn;
1659 break;
1660 case IrOpcode::kWord32And:
1661 binop_opcode = kArmAnd;
1662 no_output_opcode = kArmTst;
1663 break;
1664 case IrOpcode::kWord32Or:
1665 binop_opcode = kArmOrr;
1666 no_output_opcode = kArmOrr;
1667 break;
1668 case IrOpcode::kWord32Xor:
1669 binop_opcode = kArmEor;
1670 no_output_opcode = kArmTeq;
1671 break;
1672 default:
1673 UNREACHABLE();
1674 return;
1675 }
1676 if (selector->CanCover(*node, binop)) {
1677 // The comparison is the only user of {node}.
1678 cont->Overwrite(MapForFlagSettingBinop(cond));
1679 *opcode = no_output_opcode;
1680 *node = binop;
1681 } else if (selector->IsOnlyUserOfNodeInSameBlock(*node, binop)) {
1682 // We can also handle the case where the {node} and the comparison are in
1683 // the same basic block, and the comparison is the only user of {node} in
1684 // this basic block ({node} has users in other basic blocks).
1685 cont->Overwrite(MapForFlagSettingBinop(cond));
1686 *opcode = binop_opcode;
1687 *node = binop;
1688 }
1689 }
1595 1690
1596 // Shared routine for multiple word compare operations. 1691 // Shared routine for multiple word compare operations.
1597 void VisitWordCompare(InstructionSelector* selector, Node* node, 1692 void VisitWordCompare(InstructionSelector* selector, Node* node,
1598 InstructionCode opcode, FlagsContinuation* cont) { 1693 InstructionCode opcode, FlagsContinuation* cont) {
1599 ArmOperandGenerator g(selector); 1694 ArmOperandGenerator g(selector);
1600 Int32BinopMatcher m(node); 1695 Int32BinopMatcher m(node);
1601 InstructionOperand inputs[5]; 1696 InstructionOperand inputs[5];
1602 size_t input_count = 0; 1697 size_t input_count = 0;
1603 InstructionOperand outputs[1]; 1698 InstructionOperand outputs[2];
1604 size_t output_count = 0; 1699 size_t output_count = 0;
1700 bool has_result = (opcode != kArmCmp) && (opcode != kArmCmn) &&
1701 (opcode != kArmTst) && (opcode != kArmTeq);
1605 1702
1606 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 1703 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
1607 &input_count, &inputs[1])) { 1704 &input_count, &inputs[1])) {
1608 inputs[0] = g.UseRegister(m.left().node()); 1705 inputs[0] = g.UseRegister(m.left().node());
1609 input_count++; 1706 input_count++;
1610 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(), 1707 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
1611 &input_count, &inputs[1])) { 1708 &input_count, &inputs[1])) {
1612 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); 1709 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1613 inputs[0] = g.UseRegister(m.right().node()); 1710 inputs[0] = g.UseRegister(m.right().node());
1614 input_count++; 1711 input_count++;
1615 } else { 1712 } else {
1616 opcode |= AddressingModeField::encode(kMode_Operand2_R); 1713 opcode |= AddressingModeField::encode(kMode_Operand2_R);
1617 inputs[input_count++] = g.UseRegister(m.left().node()); 1714 inputs[input_count++] = g.UseRegister(m.left().node());
1618 inputs[input_count++] = g.UseRegister(m.right().node()); 1715 inputs[input_count++] = g.UseRegister(m.right().node());
1619 } 1716 }
1620 1717
1718 if (has_result) {
1719 if (cont->IsDeoptimize()) {
1720 // If we can deoptimize as a result of the binop, we need to make sure
1721 // that the deopt inputs are not overwritten by the binop result. One way
1722 // to achieve that is to declare the output register as same-as-first.
1723 outputs[output_count++] = g.DefineSameAsFirst(node);
1724 } else {
1725 outputs[output_count++] = g.DefineAsRegister(node);
1726 }
1727 }
1728
1621 if (cont->IsBranch()) { 1729 if (cont->IsBranch()) {
1622 inputs[input_count++] = g.Label(cont->true_block()); 1730 inputs[input_count++] = g.Label(cont->true_block());
1623 inputs[input_count++] = g.Label(cont->false_block()); 1731 inputs[input_count++] = g.Label(cont->false_block());
1624 } else if (cont->IsSet()) { 1732 } else if (cont->IsSet()) {
1625 outputs[output_count++] = g.DefineAsRegister(cont->result()); 1733 outputs[output_count++] = g.DefineAsRegister(cont->result());
1626 } 1734 }
1627 1735
1628 DCHECK_NE(0u, input_count); 1736 DCHECK_NE(0u, input_count);
1629 DCHECK_GE(arraysize(inputs), input_count); 1737 DCHECK_GE(arraysize(inputs), input_count);
1630 DCHECK_GE(arraysize(outputs), output_count); 1738 DCHECK_GE(arraysize(outputs), output_count);
1631 1739
1632 opcode = cont->Encode(opcode); 1740 opcode = cont->Encode(opcode);
1633 if (cont->IsDeoptimize()) { 1741 if (cont->IsDeoptimize()) {
1634 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, 1742 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
1635 cont->frame_state()); 1743 cont->frame_state());
1636 } else { 1744 } else {
1637 selector->Emit(opcode, output_count, outputs, input_count, inputs); 1745 selector->Emit(opcode, output_count, outputs, input_count, inputs);
1638 } 1746 }
1639 } 1747 }
1640 1748
1641 1749
1642 void VisitWordCompare(InstructionSelector* selector, Node* node, 1750 void VisitWordCompare(InstructionSelector* selector, Node* node,
1643 FlagsContinuation* cont) { 1751 FlagsContinuation* cont) {
1644 VisitWordCompare(selector, node, kArmCmp, cont); 1752 InstructionCode opcode = kArmCmp;
1753 Int32BinopMatcher m(node);
1754
1755 FlagsCondition cond = cont->condition();
1756 if (m.right().Is(0) && (m.left().IsInt32Add() || m.left().IsWord32Or() ||
1757 m.left().IsWord32And() || m.left().IsWord32Xor())) {
1758 // Emit flag setting instructions for comparisons against zero.
1759 if (CanUseFlagSettingBinop(cond)) {
1760 Node* binop = m.left().node();
1761 MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode,
1762 cond, cont);
1763 }
1764 } else if (m.left().Is(0) &&
1765 (m.right().IsInt32Add() || m.right().IsWord32Or() ||
1766 m.right().IsWord32And() || m.right().IsWord32Xor())) {
1767 // Same as above, but we need to commute the condition before we
1768 // continue with the rest of the checks.
1769 cond = CommuteFlagsCondition(cond);
1770 if (CanUseFlagSettingBinop(cond)) {
1771 Node* binop = m.right().node();
1772 MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode,
1773 cond, cont);
1774 }
1775 }
1776
1777 VisitWordCompare(selector, node, opcode, cont);
1645 } 1778 }
1646 1779
1647 1780
1648 // Shared routine for word comparisons against zero. 1781 // Shared routine for word comparisons against zero.
1649 void VisitWordCompareZero(InstructionSelector* selector, Node* user, 1782 void VisitWordCompareZero(InstructionSelector* selector, Node* user,
1650 Node* value, FlagsContinuation* cont) { 1783 Node* value, FlagsContinuation* cont) {
1651 while (selector->CanCover(user, value)) { 1784 while (selector->CanCover(user, value)) {
1652 switch (value->opcode()) { 1785 switch (value->opcode()) {
1653 case IrOpcode::kWord32Equal: { 1786 case IrOpcode::kWord32Equal: {
1654 // Combine with comparisons against 0 by simply inverting the 1787 // Combine with comparisons against 0 by simply inverting the
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 // static 2186 // static
2054 MachineOperatorBuilder::AlignmentRequirements 2187 MachineOperatorBuilder::AlignmentRequirements
2055 InstructionSelector::AlignmentRequirements() { 2188 InstructionSelector::AlignmentRequirements() {
2056 return MachineOperatorBuilder::AlignmentRequirements:: 2189 return MachineOperatorBuilder::AlignmentRequirements::
2057 FullUnalignedAccessSupport(); 2190 FullUnalignedAccessSupport();
2058 } 2191 }
2059 2192
2060 } // namespace compiler 2193 } // namespace compiler
2061 } // namespace internal 2194 } // namespace internal
2062 } // namespace v8 2195 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/unittests/compiler/arm/instruction-selector-arm-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698