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 fedda248d8272e43da6037ae772471d5b34e851f..edef43837b3fe264c646b7da37fe99b61e04904e 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -167,6 +167,25 @@ static bool TryMatchAnyShift(InstructionSelector* selector, Node* node, |
} |
+static bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, |
+ InstructionCode* opcode) { |
+ NodeMatcher nm(node); |
+ if (nm.IsWord32And()) { |
+ Int32BinopMatcher m(node); |
+ if (m.right().HasValue()) { |
+ if (m.right().Value() == 0xff) { |
+ *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTB); |
+ return true; |
+ } else if (m.right().Value() == 0xffff) { |
+ *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTH); |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
// Shared routine for multiple binary operations. |
template <typename Matcher> |
static void VisitBinop(InstructionSelector* selector, Node* node, |
@@ -178,28 +197,38 @@ static void VisitBinop(InstructionSelector* selector, Node* node, |
size_t input_count = 0; |
InstructionOperand outputs[2]; |
size_t output_count = 0; |
- bool try_ror_operand = true; |
+ bool is_add_sub = false; |
if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { |
- try_ror_operand = false; |
+ is_add_sub = true; |
} |
if (g.CanBeImmediate(m.right().node(), operand_mode)) { |
inputs[input_count++] = g.UseRegister(m.left().node()); |
inputs[input_count++] = g.UseImmediate(m.right().node()); |
} else if (TryMatchAnyShift(selector, m.right().node(), &opcode, |
- try_ror_operand)) { |
+ !is_add_sub)) { |
Matcher m_shift(m.right().node()); |
inputs[input_count++] = g.UseRegister(m.left().node()); |
inputs[input_count++] = g.UseRegister(m_shift.left().node()); |
inputs[input_count++] = g.UseImmediate(m_shift.right().node()); |
} else if (m.HasProperty(Operator::kCommutative) && |
TryMatchAnyShift(selector, m.left().node(), &opcode, |
- try_ror_operand)) { |
+ !is_add_sub)) { |
Matcher m_shift(m.left().node()); |
inputs[input_count++] = g.UseRegister(m.right().node()); |
inputs[input_count++] = g.UseRegister(m_shift.left().node()); |
inputs[input_count++] = g.UseImmediate(m_shift.right().node()); |
+ } else if (is_add_sub && |
+ TryMatchAnyExtend(selector, m.right().node(), &opcode)) { |
+ Matcher mright(m.right().node()); |
+ inputs[input_count++] = g.UseRegister(m.left().node()); |
+ inputs[input_count++] = g.UseRegister(mright.left().node()); |
+ } else if (is_add_sub && m.HasProperty(Operator::kCommutative) && |
+ TryMatchAnyExtend(selector, m.left().node(), &opcode)) { |
+ Matcher mleft(m.left().node()); |
+ inputs[input_count++] = g.UseRegister(m.right().node()); |
+ inputs[input_count++] = g.UseRegister(mleft.left().node()); |
} else { |
inputs[input_count++] = g.UseRegister(m.left().node()); |
inputs[input_count++] = g.UseRegister(m.right().node()); |