| 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);
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |