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