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 589d469f92e7da101b9833be968ffee4f0ec5e6a..3a2a820ae2b0562c935c2876b7a361d3017fd287 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -44,6 +44,10 @@ class Arm64OperandGenerator FINAL : public OperandGenerator { |
value = OpParameter<int64_t>(node); |
else |
return false; |
+ return CanBeImmediate(value, mode); |
+ } |
+ |
+ bool CanBeImmediate(int64_t value, ImmediateMode mode) { |
unsigned ignored; |
switch (mode) { |
case kLogical32Imm: |
@@ -55,7 +59,6 @@ class Arm64OperandGenerator FINAL : public OperandGenerator { |
return Assembler::IsImmLogical(static_cast<uint64_t>(value), 64, |
&ignored, &ignored, &ignored); |
case kArithmeticImm: |
- // TODO(dcarney): -values can be handled by instruction swapping |
return Assembler::IsImmAddSub(value); |
case kShift32Imm: |
return 0 <= value && value < 32; |
@@ -155,6 +158,22 @@ static void VisitBinop(InstructionSelector* selector, Node* node, |
} |
+template <typename Matcher> |
+static void VisitAddSub(InstructionSelector* selector, Node* node, |
+ ArchOpcode opcode, ArchOpcode negate_opcode) { |
+ Arm64OperandGenerator g(selector); |
+ Matcher m(node); |
+ if (m.right().HasValue() && (m.right().Value() < 0) && |
+ g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { |
+ selector->Emit(negate_opcode, g.DefineAsRegister(node), |
+ g.UseRegister(m.left().node()), |
+ g.TempImmediate(-m.right().Value())); |
+ } else { |
+ VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); |
+ } |
+} |
+ |
+ |
void InstructionSelector::VisitLoad(Node* node) { |
MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
@@ -442,7 +461,7 @@ void InstructionSelector::VisitInt32Add(Node* node) { |
g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
return; |
} |
- VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm); |
+ VisitAddSub<Int32BinopMatcher>(this, node, kArm64Add32, kArm64Sub32); |
} |
@@ -465,7 +484,7 @@ void InstructionSelector::VisitInt64Add(Node* node) { |
g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
return; |
} |
- VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm); |
+ VisitAddSub<Int64BinopMatcher>(this, node, kArm64Add, kArm64Sub); |
} |
@@ -486,7 +505,7 @@ void InstructionSelector::VisitInt32Sub(Node* node) { |
Emit(kArm64Neg32, g.DefineAsRegister(node), |
g.UseRegister(m.right().node())); |
} else { |
- VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm); |
+ VisitAddSub<Int32BinopMatcher>(this, node, kArm64Sub32, kArm64Add32); |
} |
} |
@@ -507,7 +526,7 @@ void InstructionSelector::VisitInt64Sub(Node* node) { |
if (m.left().Is(0)) { |
Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); |
} else { |
- VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm); |
+ VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); |
} |
} |