Chromium Code Reviews| 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. |