Index: src/compiler/arm/instruction-selector-arm.cc |
diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc |
index e3c4f9b276a0862add51125b7c25098bc15c1f75..d60eee7a671d0627acc85df79d2a1d5e836d5fb0 100644 |
--- a/src/compiler/arm/instruction-selector-arm.cc |
+++ b/src/compiler/arm/instruction-selector-arm.cc |
@@ -249,46 +249,12 @@ static inline bool TryMatchImmediateOrShift(InstructionSelector* selector, |
} |
-// Shared routine for multiple binary operations. |
static void VisitBinop(InstructionSelector* selector, Node* node, |
- InstructionCode opcode, InstructionCode reverse_opcode) { |
- ArmOperandGenerator g(selector); |
- Int32BinopMatcher m(node); |
- InstructionOperand* inputs[3]; |
- size_t input_count = 0; |
- InstructionOperand* outputs[1] = {g.DefineAsRegister(node)}; |
- const size_t output_count = ARRAY_SIZE(outputs); |
- |
- if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), |
- &input_count, &inputs[1])) { |
- inputs[0] = g.UseRegister(m.left().node()); |
- input_count++; |
- } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, |
- m.left().node(), &input_count, |
- &inputs[1])) { |
- inputs[0] = g.UseRegister(m.right().node()); |
- opcode = reverse_opcode; |
- input_count++; |
- } else { |
- opcode |= AddressingModeField::encode(kMode_Operand2_R); |
- inputs[input_count++] = g.UseRegister(m.left().node()); |
- inputs[input_count++] = g.UseRegister(m.right().node()); |
- } |
- |
- ASSERT_NE(0, input_count); |
- ASSERT_GE(ARRAY_SIZE(inputs), input_count); |
- ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); |
- |
- selector->Emit(opcode, output_count, outputs, input_count, inputs); |
-} |
- |
- |
-static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node, |
- InstructionCode opcode, |
- InstructionCode reverse_opcode) { |
+ InstructionCode opcode, InstructionCode reverse_opcode, |
+ FlagsContinuation* cont) { |
ArmOperandGenerator g(selector); |
Int32BinopMatcher m(node); |
- InstructionOperand* inputs[3]; |
+ InstructionOperand* inputs[5]; |
size_t input_count = 0; |
InstructionOperand* outputs[2]; |
size_t output_count = 0; |
@@ -309,16 +275,14 @@ static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node, |
inputs[input_count++] = g.UseRegister(m.right().node()); |
} |
- // Define outputs depending on the projections. |
- Node* projections[2]; |
- node->CollectProjections(ARRAY_SIZE(projections), projections); |
- if (projections[0]) { |
- outputs[output_count++] = g.DefineAsRegister(projections[0]); |
+ if (cont->IsBranch()) { |
+ inputs[input_count++] = g.Label(cont->true_block()); |
+ inputs[input_count++] = g.Label(cont->false_block()); |
} |
- if (projections[1]) { |
- opcode |= FlagsModeField::encode(kFlags_set); |
- opcode |= FlagsConditionField::encode(kOverflow); |
- outputs[output_count++] = g.DefineAsRegister(projections[1]); |
+ |
+ outputs[output_count++] = g.DefineAsRegister(node); |
+ if (cont->IsSet()) { |
+ outputs[output_count++] = g.DefineAsRegister(cont->result()); |
} |
ASSERT_NE(0, input_count); |
@@ -327,7 +291,16 @@ static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node, |
ASSERT_GE(ARRAY_SIZE(outputs), output_count); |
ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); |
- selector->Emit(opcode, output_count, outputs, input_count, inputs); |
+ Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
+ outputs, input_count, inputs); |
+ if (cont->IsBranch()) instr->MarkAsControl(); |
+} |
+ |
+ |
+static void VisitBinop(InstructionSelector* selector, Node* node, |
+ InstructionCode opcode, InstructionCode reverse_opcode) { |
+ FlagsContinuation cont; |
+ VisitBinop(selector, node, opcode, reverse_opcode, &cont); |
} |
@@ -597,11 +570,6 @@ void InstructionSelector::VisitInt32Add(Node* node) { |
} |
-void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
- VisitBinopWithOverflow(this, node, kArmAdd, kArmAdd); |
-} |
- |
- |
void InstructionSelector::VisitInt32Sub(Node* node) { |
ArmOperandGenerator g(this); |
Int32BinopMatcher m(node); |
@@ -616,11 +584,6 @@ void InstructionSelector::VisitInt32Sub(Node* node) { |
} |
-void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
- VisitBinopWithOverflow(this, node, kArmSub, kArmRsb); |
-} |
- |
- |
void InstructionSelector::VisitInt32Mul(Node* node) { |
ArmOperandGenerator g(this); |
Int32BinopMatcher m(node); |
@@ -867,10 +830,22 @@ void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
} |
+void InstructionSelector::VisitInt32AddWithOverflow(Node* node, |
+ FlagsContinuation* cont) { |
+ VisitBinop(this, node, kArmAdd, kArmAdd, cont); |
+} |
+ |
+ |
+void InstructionSelector::VisitInt32SubWithOverflow(Node* node, |
+ FlagsContinuation* cont) { |
+ VisitBinop(this, node, kArmSub, kArmRsb, cont); |
+} |
+ |
+ |
// Shared routine for multiple compare operations. |
static void VisitWordCompare(InstructionSelector* selector, Node* node, |
InstructionCode opcode, FlagsContinuation* cont, |
- bool commutative, bool requires_output) { |
+ bool commutative) { |
ArmOperandGenerator g(selector); |
Int32BinopMatcher m(node); |
InstructionOperand* inputs[5]; |
@@ -894,9 +869,6 @@ static void VisitWordCompare(InstructionSelector* selector, Node* node, |
} |
if (cont->IsBranch()) { |
- if (requires_output) { |
- outputs[output_count++] = g.DefineAsRegister(node); |
- } |
inputs[input_count++] = g.Label(cont->true_block()); |
inputs[input_count++] = g.Label(cont->false_block()); |
} else { |
@@ -917,15 +889,15 @@ static void VisitWordCompare(InstructionSelector* selector, Node* node, |
void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { |
switch (node->opcode()) { |
case IrOpcode::kInt32Add: |
- return VisitWordCompare(this, node, kArmCmn, cont, true, false); |
+ return VisitWordCompare(this, node, kArmCmn, cont, true); |
case IrOpcode::kInt32Sub: |
- return VisitWordCompare(this, node, kArmCmp, cont, false, false); |
+ return VisitWordCompare(this, node, kArmCmp, cont, false); |
case IrOpcode::kWord32And: |
- return VisitWordCompare(this, node, kArmTst, cont, true, false); |
+ return VisitWordCompare(this, node, kArmTst, cont, true); |
case IrOpcode::kWord32Or: |
- return VisitWordCompare(this, node, kArmOrr, cont, true, true); |
+ return VisitBinop(this, node, kArmOrr, kArmOrr, cont); |
case IrOpcode::kWord32Xor: |
- return VisitWordCompare(this, node, kArmTeq, cont, true, false); |
+ return VisitWordCompare(this, node, kArmTeq, cont, true); |
default: |
break; |
} |
@@ -946,7 +918,7 @@ void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { |
void InstructionSelector::VisitWord32Compare(Node* node, |
FlagsContinuation* cont) { |
- VisitWordCompare(this, node, kArmCmp, cont, false, false); |
+ VisitWordCompare(this, node, kArmCmp, cont, false); |
} |