Revision: 22791
Author: [email protected]
Date: Fri Aug 1 12:18:20 2014 UTC
Log: [turbofan] Add support for Int32SubWithOverflow.
TEST=cctest/test-run-machops,cctest/test-instruction-selector-arm
[email protected]
Review URL: https://codereview.chromium.org/432373002
http://code.google.com/p/v8/source/detail?r=22791
Modified:
/branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
/branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
/branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
/branches/bleeding_edge/src/compiler/instruction-selector.cc
/branches/bleeding_edge/src/compiler/machine-node-factory.h
/branches/bleeding_edge/src/compiler/machine-operator.h
/branches/bleeding_edge/src/compiler/opcodes.h
/branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
/branches/bleeding_edge/test/cctest/compiler/test-instruction-selector-arm.cc
/branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Fri Aug 1 11:14:47 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Fri Aug 1 12:18:20 2014 UTC
@@ -614,6 +614,11 @@
}
VisitBinop(this, node, kArmSub, kArmRsb);
}
+
+
+void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
+ VisitBinopWithOverflow(this, node, kArmSub, kArmRsb);
+}
void InstructionSelector::VisitInt32Mul(Node* node) {
=======================================
--- /branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc Fri
Aug 1 09:32:58 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc Fri
Aug 1 12:18:20 2014 UTC
@@ -243,7 +243,12 @@
__ Sub(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kArm64Sub32:
- __ Sub(i.OutputRegister32(), i.InputRegister32(0),
i.InputOperand32(1));
+ if (FlagsModeField::decode(opcode) != kFlags_none) {
+ __ Subs(i.OutputRegister32(), i.InputRegister32(0),
+ i.InputOperand32(1));
+ } else {
+ __ Sub(i.OutputRegister32(), i.InputRegister32(0),
i.InputOperand32(1));
+ }
break;
case kArm64Shl:
ASSEMBLE_SHIFT(Lsl, 64);
=======================================
---
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
Fri Aug 1 10:54:58 2014 UTC
+++
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
Fri Aug 1 12:18:20 2014 UTC
@@ -359,6 +359,11 @@
void InstructionSelector::VisitInt32Sub(Node* node) {
VisitSub<int32_t>(this, node, kArm64Sub32, kArm64Neg32);
}
+
+
+void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
+ VisitBinopWithOverflow(this, node, kArm64Sub32);
+}
void InstructionSelector::VisitInt64Sub(Node* node) {
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Fri Aug 1 10:54:58 2014 UTC
+++ /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Fri Aug 1 12:18:20 2014 UTC
@@ -301,6 +301,11 @@
VisitBinop(this, node, kIA32Sub);
}
}
+
+
+void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
+ VisitBinopWithOverflow(this, node, kIA32Sub);
+}
void InstructionSelector::VisitInt32Mul(Node* node) {
=======================================
--- /branches/bleeding_edge/src/compiler/instruction-selector.cc Fri Aug 1
10:54:58 2014 UTC
+++ /branches/bleeding_edge/src/compiler/instruction-selector.cc Fri Aug 1
12:18:20 2014 UTC
@@ -511,6 +511,8 @@
return VisitInt32AddWithOverflow(node);
case IrOpcode::kInt32Sub:
return VisitInt32Sub(node);
+ case IrOpcode::kInt32SubWithOverflow:
+ return VisitInt32SubWithOverflow(node);
case IrOpcode::kInt32Mul:
return VisitInt32Mul(node);
case IrOpcode::kInt32Div:
=======================================
--- /branches/bleeding_edge/src/compiler/machine-node-factory.h Fri Aug 1
10:54:58 2014 UTC
+++ /branches/bleeding_edge/src/compiler/machine-node-factory.h Fri Aug 1
12:18:20 2014 UTC
@@ -84,6 +84,10 @@
PrintableUnique<Object>::CreateUninitialized(ZONE(), object);
return NEW_NODE_0(COMMON()->HeapConstant(val));
}
+
+ Node* Projection(int index, Node* a) {
+ return NEW_NODE_1(COMMON()->Projection(index), a);
+ }
// Memory Operations.
Node* Load(MachineRepresentation rep, Node* base) {
@@ -198,12 +202,18 @@
void Int32AddWithOverflow(Node* a, Node* b, Node** val_return,
Node** ovf_return) {
Node* add = NEW_NODE_2(MACHINE()->Int32AddWithOverflow(), a, b);
- if (val_return) *val_return = NEW_NODE_1(COMMON()->Projection(0), add);
- if (ovf_return) *ovf_return = NEW_NODE_1(COMMON()->Projection(1), add);
+ if (val_return) *val_return = Projection(0, add);
+ if (ovf_return) *ovf_return = Projection(1, add);
}
Node* Int32Sub(Node* a, Node* b) {
return NEW_NODE_2(MACHINE()->Int32Sub(), a, b);
}
+ void Int32SubWithOverflow(Node* a, Node* b, Node** val_return,
+ Node** ovf_return) {
+ Node* add = NEW_NODE_2(MACHINE()->Int32SubWithOverflow(), a, b);
+ if (val_return) *val_return = Projection(0, add);
+ if (ovf_return) *ovf_return = Projection(1, add);
+ }
Node* Int32Mul(Node* a, Node* b) {
return NEW_NODE_2(MACHINE()->Int32Mul(), a, b);
}
=======================================
--- /branches/bleeding_edge/src/compiler/machine-operator.h Fri Aug 1
10:54:58 2014 UTC
+++ /branches/bleeding_edge/src/compiler/machine-operator.h Fri Aug 1
12:18:20 2014 UTC
@@ -68,6 +68,7 @@
inputs, outputs, #name, pname)
#define BINOP(name) SIMPLE(name, Operator::kPure, 2, 1)
+#define BINOP_O(name) SIMPLE(name, Operator::kPure, 2, 2)
#define BINOP_C(name) \
SIMPLE(name, Operator::kCommutative | Operator::kPure, 2, 1)
#define
BINOP_AC(name) \
@@ -119,6 +120,7 @@
Operator* Int32Add() { BINOP_AC(Int32Add); }
Operator* Int32AddWithOverflow() { BINOP_ACO(Int32AddWithOverflow); }
Operator* Int32Sub() { BINOP(Int32Sub); }
+ Operator* Int32SubWithOverflow() { BINOP_O(Int32SubWithOverflow); }
Operator* Int32Mul() { BINOP_AC(Int32Mul); }
Operator* Int32Div() { BINOP(Int32Div); }
Operator* Int32UDiv() { BINOP(Int32UDiv); }
=======================================
--- /branches/bleeding_edge/src/compiler/opcodes.h Fri Aug 1 10:54:58 2014
UTC
+++ /branches/bleeding_edge/src/compiler/opcodes.h Fri Aug 1 12:18:20 2014
UTC
@@ -175,6 +175,7 @@
V(Int32Add) \
V(Int32AddWithOverflow) \
V(Int32Sub) \
+ V(Int32SubWithOverflow) \
V(Int32Mul) \
V(Int32Div) \
V(Int32UDiv) \
=======================================
--- /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Fri Aug 1 10:54:58 2014 UTC
+++ /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Fri Aug 1 12:18:20 2014 UTC
@@ -397,6 +397,11 @@
void InstructionSelector::VisitInt32Sub(Node* node) {
VisitSub<int32_t>(this, node, kX64Sub32, kX64Neg32);
}
+
+
+void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
+ VisitBinopWithOverflow(this, node, kX64Sub32);
+}
void InstructionSelector::VisitInt64Sub(Node* node) {
=======================================
---
/branches/bleeding_edge/test/cctest/compiler/test-instruction-selector-arm.cc
Fri Aug 1 11:14:47 2014 UTC
+++
/branches/bleeding_edge/test/cctest/compiler/test-instruction-selector-arm.cc
Fri Aug 1 12:18:20 2014 UTC
@@ -41,6 +41,26 @@
};
+struct ODPI {
+ Operator* op;
+ ArchOpcode arch_opcode;
+ ArchOpcode reverse_arch_opcode;
+};
+
+
+// ARM data processing instructions with overflow.
+class ODPIs V8_FINAL : public std::list<ODPI>, private HandleAndZoneScope {
+ public:
+ ODPIs() {
+ MachineOperatorBuilder machine(main_zone());
+ ODPI add = {machine.Int32AddWithOverflow(), kArmAdd, kArmAdd};
+ push_back(add);
+ ODPI sub = {machine.Int32SubWithOverflow(), kArmSub, kArmRsb};
+ push_back(sub);
+ }
+};
+
+
// ARM immediates.
class Immediates V8_FINAL : public std::list<int32_t> {
public:
@@ -225,361 +245,349 @@
}
-TEST(InstructionSelectorInt32AddWithOverflowP) {
- {
- InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(m.Parameter(0), m.Parameter(1), NULL, &ovf);
- m.Return(ovf);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(m.Parameter(0), m.Parameter(1), &val, NULL);
- m.Return(val);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(m.Parameter(0), m.Parameter(1), &val, &ovf);
- m.Return(m.Word32Equal(val, ovf));
- m.SelectInstructions();
- CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(2, m.code[0]->OutputCount());
- }
-}
-
-
-TEST(InstructionSelectorInt32AddWithOverflowImm) {
- Immediates immediates;
- for (Immediates::const_iterator i = immediates.begin(); i !=
immediates.end();
- ++i) {
- int32_t imm = *i;
+TEST(InstructionSelectorODPIP) {
+ ODPIs odpis;
+ for (ODPIs::const_iterator i = odpis.begin(); i != odpis.end(); ++i) {
+ ODPI odpi = *i;
{
InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(m.Parameter(0), m.Int32Constant(imm), NULL,
&ovf);
- m.Return(ovf);
+ m.Return(
+ m.Projection(1, m.NewNode(odpi.op, m.Parameter(0),
m.Parameter(1))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
CHECK_EQ(kOverflow, m.code[0]->flags_condition());
CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
CHECK_EQ(1, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0), NULL,
&ovf);
- m.Return(ovf);
+ m.Return(
+ m.Projection(0, m.NewNode(odpi.op, m.Parameter(0),
m.Parameter(1))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(m.Parameter(0), m.Int32Constant(imm), &val,
NULL);
- m.Return(val);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
CHECK_EQ(1, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0), &val,
NULL);
- m.Return(val);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(m.Parameter(0), m.Int32Constant(imm), &val,
&ovf);
- m.Return(m.Word32Equal(val, ovf));
+ Node* node = m.NewNode(odpi.op, m.Parameter(0), m.Parameter(1));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
m.SelectInstructions();
CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
CHECK_EQ(kOverflow, m.code[0]->flags_condition());
CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
CHECK_EQ(2, m.code[0]->OutputCount());
}
- {
- InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0), &val,
&ovf);
- m.Return(m.Word32Equal(val, ovf));
- m.SelectInstructions();
- CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(2, m.code[0]->OutputCount());
- }
}
}
-TEST(InstructionSelectorInt32AddWithOverflowAndShiftP) {
- Shifts shifts;
- for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
- Shift shift = *i;
- {
- InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(
- m.Parameter(0), m.NewNode(shift.op, m.Parameter(1),
m.Parameter(2)),
- NULL, &ovf);
- m.Return(ovf);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(
- m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
m.Parameter(2),
- NULL, &ovf);
- m.Return(ovf);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(
- m.Parameter(0), m.NewNode(shift.op, m.Parameter(1),
m.Parameter(2)),
- &val, NULL);
- m.Return(val);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(
- m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
m.Parameter(2),
- &val, NULL);
- m.Return(val);
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(1, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(
- m.Parameter(0), m.NewNode(shift.op, m.Parameter(1),
m.Parameter(2)),
- &val, &ovf);
- m.Return(m.Word32Equal(val, ovf));
- m.SelectInstructions();
- CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(2, m.code[0]->OutputCount());
- }
- {
- InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(
- m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
m.Parameter(2),
- &val, &ovf);
- m.Return(m.Word32Equal(val, ovf));
- m.SelectInstructions();
- CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kOverflow, m.code[0]->flags_condition());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(2, m.code[0]->OutputCount());
+TEST(InstructionSelectorODPIImm) {
+ ODPIs odpis;
+ Immediates immediates;
+ for (ODPIs::const_iterator i = odpis.begin(); i != odpis.end(); ++i) {
+ ODPI odpi = *i;
+ for (Immediates::const_iterator j = immediates.begin();
+ j != immediates.end(); ++j) {
+ int32_t imm = *j;
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(
+ 1, m.NewNode(odpi.op, m.Parameter(0), m.Int32Constant(imm))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(
+ 1, m.NewNode(odpi.op, m.Int32Constant(imm), m.Parameter(0))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(
+ 0, m.NewNode(odpi.op, m.Parameter(0), m.Int32Constant(imm))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(
+ 0, m.NewNode(odpi.op, m.Int32Constant(imm), m.Parameter(0))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* node = m.NewNode(odpi.op, m.Parameter(0),
m.Int32Constant(imm));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
+ m.SelectInstructions();
+ CHECK_LE(1, m.code.size());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ CHECK_EQ(2, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* node = m.NewNode(odpi.op, m.Int32Constant(imm),
m.Parameter(0));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
+ m.SelectInstructions();
+ CHECK_LE(1, m.code.size());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ CHECK_EQ(2, m.code[0]->OutputCount());
+ }
}
}
}
-TEST(InstructionSelectorInt32AddWithOverflowAndShiftImm) {
+TEST(InstructionSelectorODPIAndShiftP) {
+ ODPIs odpis;
Shifts shifts;
- for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
- Shift shift = *i;
- for (int32_t imm = shift.i_low; imm <= shift.i_high; ++imm) {
+ for (ODPIs::const_iterator i = odpis.begin(); i != odpis.end(); ++i) {
+ ODPI odpi = *i;
+ for (Shifts::const_iterator j = shifts.begin(); j != shifts.end();
++j) {
+ Shift shift = *j;
{
InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(
- m.Parameter(0),
- m.NewNode(shift.op, m.Parameter(1), m.Int32Constant(imm)),
NULL,
- &ovf);
- m.Return(ovf);
+ m.Return(m.Projection(
+ 1, m.NewNode(odpi.op, m.Parameter(0),
+ m.NewNode(shift.op, m.Parameter(1),
m.Parameter(2)))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
CHECK_EQ(kOverflow, m.code[0]->flags_condition());
CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
CHECK_EQ(1, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* ovf;
- m.Int32AddWithOverflow(
- m.NewNode(shift.op, m.Parameter(0), m.Int32Constant(imm)),
- m.Parameter(1), NULL, &ovf);
- m.Return(ovf);
+ m.Return(m.Projection(
+ 1, m.NewNode(odpi.op,
+ m.NewNode(shift.op, m.Parameter(0),
m.Parameter(1)),
+ m.Parameter(2))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
CHECK_EQ(kOverflow, m.code[0]->flags_condition());
CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
CHECK_EQ(1, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(
- m.Parameter(0),
- m.NewNode(shift.op, m.Parameter(1), m.Int32Constant(imm)),
&val,
- NULL);
- m.Return(val);
+ m.Return(m.Projection(
+ 0, m.NewNode(odpi.op, m.Parameter(0),
+ m.NewNode(shift.op, m.Parameter(1),
m.Parameter(2)))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
CHECK_EQ(1, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* val;
- m.Int32AddWithOverflow(
- m.NewNode(shift.op, m.Parameter(0), m.Int32Constant(imm)),
- m.Parameter(1), &val, NULL);
- m.Return(val);
+ m.Return(m.Projection(
+ 0, m.NewNode(odpi.op,
+ m.NewNode(shift.op, m.Parameter(0),
m.Parameter(1)),
+ m.Parameter(2))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
CHECK_EQ(1, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(
- m.Parameter(0),
- m.NewNode(shift.op, m.Parameter(1), m.Int32Constant(imm)),
&val,
- &ovf);
- m.Return(m.Word32Equal(val, ovf));
+ Node* node =
+ m.NewNode(odpi.op, m.Parameter(0),
+ m.NewNode(shift.op, m.Parameter(1), m.Parameter(2)));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
m.SelectInstructions();
CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
CHECK_EQ(kOverflow, m.code[0]->flags_condition());
CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
CHECK_EQ(2, m.code[0]->OutputCount());
}
{
InstructionSelectorTester m;
- Node* val, *ovf;
- m.Int32AddWithOverflow(
- m.NewNode(shift.op, m.Parameter(0), m.Int32Constant(imm)),
- m.Parameter(1), &val, &ovf);
- m.Return(m.Word32Equal(val, ovf));
+ Node* node = m.NewNode(
+ odpi.op, m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
+ m.Parameter(2));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
m.SelectInstructions();
CHECK_LE(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
CHECK_EQ(kOverflow, m.code[0]->flags_condition());
CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
CHECK_EQ(2, m.code[0]->OutputCount());
}
}
}
}
+
+
+TEST(InstructionSelectorODPIAndShiftImm) {
+ ODPIs odpis;
+ Shifts shifts;
+ for (ODPIs::const_iterator i = odpis.begin(); i != odpis.end(); ++i) {
+ ODPI odpi = *i;
+ for (Shifts::const_iterator j = shifts.begin(); j != shifts.end();
++j) {
+ Shift shift = *j;
+ for (int32_t imm = shift.i_low; imm <= shift.i_high; ++imm) {
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(1, m.NewNode(odpi.op, m.Parameter(0),
+ m.NewNode(shift.op,
m.Parameter(1),
+
m.Int32Constant(imm)))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(3, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(
+ 1, m.NewNode(odpi.op, m.NewNode(shift.op, m.Parameter(0),
+ m.Int32Constant(imm)),
+ m.Parameter(1))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(3, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(0, m.NewNode(odpi.op, m.Parameter(0),
+ m.NewNode(shift.op,
m.Parameter(1),
+
m.Int32Constant(imm)))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
+ CHECK_EQ(3, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ m.Return(m.Projection(
+ 0, m.NewNode(odpi.op, m.NewNode(shift.op, m.Parameter(0),
+ m.Int32Constant(imm)),
+ m.Parameter(1))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_none, m.code[0]->flags_mode());
+ CHECK_EQ(3, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
+ CHECK_EQ(1, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* node = m.NewNode(
+ odpi.op, m.Parameter(0),
+ m.NewNode(shift.op, m.Parameter(1), m.Int32Constant(imm)));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
+ m.SelectInstructions();
+ CHECK_LE(1, m.code.size());
+ CHECK_EQ(odpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(3, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
+ CHECK_EQ(2, m.code[0]->OutputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* node = m.NewNode(odpi.op, m.NewNode(shift.op,
m.Parameter(0),
+ m.Int32Constant(imm)),
+ m.Parameter(1));
+ m.Return(m.Word32Equal(m.Projection(0, node), m.Projection(1,
node)));
+ m.SelectInstructions();
+ CHECK_LE(1, m.code.size());
+ CHECK_EQ(odpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
+ CHECK_EQ(kOverflow, m.code[0]->flags_condition());
+ CHECK_EQ(3, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(2)));
+ CHECK_EQ(2, m.code[0]->OutputCount());
+ }
+ }
+ }
+ }
+}
TEST(InstructionSelectorWord32AndAndWord32XorWithMinus1P) {
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Fri
Aug 1 10:54:58 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Fri
Aug 1 12:18:20 2014 UTC
@@ -3889,6 +3889,14 @@
*val = v;
return (((v ^ x) & (v ^ y)) >> 31) & 1;
}
+
+
+static bool ssub_overflow(int32_t x, int32_t y, int32_t* val) {
+ int32_t v =
+ static_cast<int32_t>(static_cast<uint32_t>(x) -
static_cast<uint32_t>(y));
+ *val = v;
+ return (((v ^ x) & (v ^ ~y)) >> 31) & 1;
+}
TEST(RunInt32AddWithOverflowP) {
@@ -3971,5 +3979,87 @@
}
}
}
+
+
+TEST(RunInt32SubWithOverflowP) {
+ int32_t actual_val = -1;
+ RawMachineAssemblerTester<int32_t> m;
+ Int32BinopTester bt(&m);
+ Node* val, *ovf;
+ m.Int32SubWithOverflow(bt.param0, bt.param1, &val, &ovf);
+ m.StoreToPointer(&actual_val, kMachineWord32, val);
+ bt.AddReturn(ovf);
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ int32_t expected_val;
+ int expected_ovf = ssub_overflow(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, bt.call(*i, *j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+}
+
+
+TEST(RunInt32SubWithOverflowImm) {
+ int32_t actual_val = -1, expected_val = 0;
+ FOR_INT32_INPUTS(i) {
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachineWord32);
+ Node* val, *ovf;
+ m.Int32SubWithOverflow(m.Int32Constant(*i), m.Parameter(0), &val,
&ovf);
+ m.StoreToPointer(&actual_val, kMachineWord32, val);
+ m.Return(ovf);
+ FOR_INT32_INPUTS(j) {
+ int expected_ovf = ssub_overflow(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call(*j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachineWord32);
+ Node* val, *ovf;
+ m.Int32SubWithOverflow(m.Parameter(0), m.Int32Constant(*i), &val,
&ovf);
+ m.StoreToPointer(&actual_val, kMachineWord32, val);
+ m.Return(ovf);
+ FOR_INT32_INPUTS(j) {
+ int expected_ovf = ssub_overflow(*j, *i, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call(*j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+ FOR_INT32_INPUTS(j) {
+ RawMachineAssemblerTester<int32_t> m;
+ Node* val, *ovf;
+ m.Int32SubWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j),
&val,
+ &ovf);
+ m.StoreToPointer(&actual_val, kMachineWord32, val);
+ m.Return(ovf);
+ int expected_ovf = ssub_overflow(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call());
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+}
+
+
+TEST(RunInt32SubWithOverflowInBranchP) {
+ MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m;
+ Int32BinopTester bt(&m);
+ Node* val, *ovf;
+ m.Int32SubWithOverflow(bt.param0, bt.param1, &val, &ovf);
+ m.Branch(ovf, &blocka, &blockb);
+ m.Bind(&blocka);
+ bt.AddReturn(m.Word32Not(val));
+ m.Bind(&blockb);
+ bt.AddReturn(val);
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_INPUTS(j) {
+ int32_t expected;
+ if (ssub_overflow(*i, *j, &expected)) expected = ~expected;
+ CHECK_EQ(expected, bt.call(*i, *j));
+ }
+ }
+}
#endif // V8_TURBOFAN_TARGET
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.