| Index: src/compiler/arm64/instruction-selector-arm64.cc
|
| diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc
|
| index da43b417d980fc5f2cc5d59abe3ea69602cdeeab..476be9f9a6652547a17b73203a560f9986d41c69 100644
|
| --- a/src/compiler/arm64/instruction-selector-arm64.cc
|
| +++ b/src/compiler/arm64/instruction-selector-arm64.cc
|
| @@ -223,14 +223,14 @@ void VisitBinop(InstructionSelector* selector, Node* node,
|
| size_t input_count = 0;
|
| InstructionOperand outputs[2];
|
| size_t output_count = 0;
|
| - bool is_cmp = opcode == kArm64Cmp32;
|
| + bool is_cmp = (opcode == kArm64Cmp32) || (opcode == kArm64Cmn32);
|
|
|
| // We can commute cmp by switching the inputs and commuting the flags
|
| // continuation.
|
| bool can_commute = m.HasProperty(Operator::kCommutative) || is_cmp;
|
|
|
| - // The cmp instruction is encoded as sub with zero output register, and
|
| - // therefore supports the same operand modes.
|
| + // The cmp and cmn instructions are encoded as sub or add with zero output
|
| + // register, and therefore support the same operand modes.
|
| bool is_add_sub = m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() ||
|
| m.IsInt64Sub() || is_cmp;
|
|
|
| @@ -1510,8 +1510,29 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
|
|
|
| void VisitWord32Compare(InstructionSelector* selector, Node* node,
|
| FlagsContinuation* cont) {
|
| - VisitBinop<Int32BinopMatcher>(selector, node, kArm64Cmp32, kArithmeticImm,
|
| - cont);
|
| + Int32BinopMatcher m(node);
|
| + ArchOpcode opcode = kArm64Cmp32;
|
| +
|
| + // Select negated compare for comparisons with negated right input.
|
| + if (m.right().IsInt32Sub()) {
|
| + Node* sub = m.right().node();
|
| + Int32BinopMatcher msub(sub);
|
| + if (msub.left().Is(0)) {
|
| + bool can_cover = selector->CanCover(node, sub);
|
| + node->ReplaceInput(1, msub.right().node());
|
| + // Even if the comparison node covers the subtraction, after the input
|
| + // replacement above, the node still won't cover the input to the
|
| + // subtraction; the subtraction still uses it.
|
| + // In order to get shifted operations to work, we must remove the rhs
|
| + // input to the subtraction, as TryMatchAnyShift requires this node to
|
| + // cover the input shift. We do this by setting it to the lhs input,
|
| + // as we know it's zero, and the result of the subtraction isn't used by
|
| + // any other node.
|
| + if (can_cover) sub->ReplaceInput(1, msub.left().node());
|
| + opcode = kArm64Cmn32;
|
| + }
|
| + }
|
| + VisitBinop<Int32BinopMatcher>(selector, node, opcode, kArithmeticImm, cont);
|
| }
|
|
|
|
|
|
|