Index: src/compiler/arm64/instruction-selector-arm64-unittest.cc |
diff --git a/src/compiler/arm64/instruction-selector-arm64-unittest.cc b/src/compiler/arm64/instruction-selector-arm64-unittest.cc |
index 581e89c6e0392d52f16c90b8cf26546b60e3a366..42765be27917ec761ecba1a63e43f33c242460c7 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64-unittest.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64-unittest.cc |
@@ -88,6 +88,14 @@ static const int32_t kAddSubImmediates[] = { |
15597568, 15892480, 16773120}; |
+// ARM64 arithmetic with overflow instructions. |
+static const MachInst2 kOvfAddSubInstructions[] = { |
+ {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", |
+ kArm64Add32, kMachInt32}, |
+ {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", |
+ kArm64Sub32, kMachInt32}}; |
+ |
+ |
// ARM64 shift instructions. |
static const MachInst2 kShiftInstructions[] = { |
{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Shl32, kMachInt32}, |
@@ -336,6 +344,193 @@ TEST_F(InstructionSelectorTest, SubZeroOnLeft) { |
// ----------------------------------------------------------------------------- |
+// Add and subtract instructions with overflow. |
+ |
+ |
+typedef InstructionSelectorTestWithParam<MachInst2> |
+ InstructionSelectorOvfAddSubTest; |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ StreamBuilder m(this, type, type, type); |
+ m.Return( |
+ m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_LE(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
+ StreamBuilder m(this, type, type); |
+ m.Return(m.Projection( |
+ 1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
+ EXPECT_LE(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
+ } |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnLeft) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
+ StreamBuilder m(this, type, type); |
+ m.Return(m.Projection( |
+ 1, (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); |
+ Stream s = m.Build(); |
+ |
+ // Add can support an immediate on the left by commuting, but Sub can't |
+ // commute. |
+ if (strstr(dpi.constructor_name, "Add") != NULL) { |
Benedikt Meurer
2014/09/05 10:31:25
Hm, that looks rather fragile to me. Can we limit
m.m.capewell
2014/09/05 10:38:34
Sure, I'll replace these cases with TEST_F.
m.m.capewell
2014/09/05 14:26:52
Done.
|
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
+ EXPECT_LE(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
+ } |
+ } |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ StreamBuilder m(this, type, type, type); |
+ m.Return( |
+ m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_LE(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
+ StreamBuilder m(this, type, type); |
+ m.Return(m.Projection( |
+ 0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
+ EXPECT_LE(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+ } |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnLeft) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
+ StreamBuilder m(this, type, type); |
+ m.Return(m.Projection( |
+ 0, (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); |
+ Stream s = m.Build(); |
+ |
+ // Add can support an immediate on the left by commuting, but Sub can't |
+ // commute. |
+ if (strstr(dpi.constructor_name, "Add") != NULL) { |
Benedikt Meurer
2014/09/05 10:31:25
Hm, that looks rather fragile to me. Can we limit
m.m.capewell
2014/09/05 14:26:52
Done.
|
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
+ EXPECT_LE(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+ } |
+ } |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ StreamBuilder m(this, type, type, type); |
+ Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)); |
+ m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
+ Stream s = m.Build(); |
+ ASSERT_LE(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(2U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
+ StreamBuilder m(this, type, type); |
+ Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); |
+ m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
+ Stream s = m.Build(); |
+ ASSERT_LE(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
+ EXPECT_EQ(2U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
+ } |
+} |
+ |
+ |
+TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnLeft) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
+ StreamBuilder m(this, type, type); |
+ Node* n = (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); |
+ m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
+ Stream s = m.Build(); |
+ |
+ // Add can support an immediate on the left by commuting, but Sub can't |
+ // commute. |
+ if (strstr(dpi.constructor_name, "Add") != NULL) { |
Benedikt Meurer
2014/09/05 10:31:25
Hm, that looks rather fragile to me. Can we limit
m.m.capewell
2014/09/05 14:26:52
Done.
|
+ ASSERT_LE(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
+ EXPECT_EQ(2U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
+ } |
+ } |
+} |
+ |
+ |
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
+ InstructionSelectorOvfAddSubTest, |
+ ::testing::ValuesIn(kOvfAddSubInstructions)); |
+ |
+ |
+// ----------------------------------------------------------------------------- |
// Shift instructions. |