| Index: test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
|
| diff --git a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
|
| index 6287a719b6c14980849af6c3a1753630d3f24789..dc74a7ba67b33885a03a2e2f588c5f3247b6b64d 100644
|
| --- a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
|
| +++ b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
|
| @@ -84,11 +84,26 @@ static const uint32_t kLogicalImmediates[] = {
|
|
|
|
|
| // ARM64 arithmetic instructions.
|
| -static const MachInst2 kAddSubInstructions[] = {
|
| - {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
|
| - {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
|
| - {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
|
| - {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}};
|
| +struct AddSub {
|
| + MachInst2 mi;
|
| + ArchOpcode negate_arch_opcode;
|
| +};
|
| +
|
| +
|
| +std::ostream& operator<<(std::ostream& os, const AddSub& op) {
|
| + return os << op.mi;
|
| +}
|
| +
|
| +
|
| +static const AddSub kAddSubInstructions[] = {
|
| + {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
|
| + kArm64Sub32},
|
| + {{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
|
| + kArm64Sub},
|
| + {{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
|
| + kArm64Add32},
|
| + {{&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64},
|
| + kArm64Add}};
|
|
|
|
|
| // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
|
| @@ -288,32 +303,32 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
|
| // -----------------------------------------------------------------------------
|
| // Add and Sub instructions.
|
|
|
| -typedef InstructionSelectorTestWithParam<MachInst2>
|
| - InstructionSelectorAddSubTest;
|
| +typedef InstructionSelectorTestWithParam<AddSub> InstructionSelectorAddSubTest;
|
|
|
|
|
| TEST_P(InstructionSelectorAddSubTest, Parameter) {
|
| - const MachInst2 dpi = GetParam();
|
| - const MachineType type = dpi.machine_type;
|
| + const AddSub dpi = GetParam();
|
| + const MachineType type = dpi.mi.machine_type;
|
| StreamBuilder m(this, type, type, type);
|
| - m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
|
| + m.Return((m.*dpi.mi.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(dpi.mi.arch_opcode, s[0]->arch_opcode());
|
| EXPECT_EQ(2U, s[0]->InputCount());
|
| EXPECT_EQ(1U, s[0]->OutputCount());
|
| }
|
|
|
|
|
| TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
|
| - const MachInst2 dpi = GetParam();
|
| - const MachineType type = dpi.machine_type;
|
| + const AddSub dpi = GetParam();
|
| + const MachineType type = dpi.mi.machine_type;
|
| TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
|
| StreamBuilder m(this, type, type);
|
| - m.Return((m.*dpi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
|
| + m.Return(
|
| + (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
|
| Stream s = m.Build();
|
| ASSERT_EQ(1U, s.size());
|
| - EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
|
| + EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
|
| ASSERT_EQ(2U, s[0]->InputCount());
|
| EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
|
| EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
|
| @@ -322,20 +337,52 @@ TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
|
| }
|
|
|
|
|
| -TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) {
|
| - const MachInst2 dpi = GetParam();
|
| - const MachineType type = dpi.machine_type;
|
| -
|
| +TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) {
|
| + const AddSub dpi = GetParam();
|
| + const MachineType type = dpi.mi.machine_type;
|
| TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
|
| + if (imm == 0) continue;
|
| StreamBuilder m(this, type, type);
|
| - m.Return((m.*dpi.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
|
| + m.Return(
|
| + (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, -imm)));
|
| Stream s = m.Build();
|
| + ASSERT_EQ(1U, s.size());
|
| + EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode());
|
| + ASSERT_EQ(2U, s[0]->InputCount());
|
| + ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
|
| + EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
|
| + EXPECT_EQ(1U, s[0]->OutputCount());
|
| + }
|
| +}
|
| +
|
|
|
| - // Add can support an immediate on the left by commuting, but Sub can't
|
| - // commute. We test zero-on-left Sub later.
|
| - if (strstr(dpi.constructor_name, "Add") != NULL) {
|
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
|
| + ::testing::ValuesIn(kAddSubInstructions));
|
| +
|
| +
|
| +TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
|
| + {
|
| + // 32-bit add.
|
| + TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
|
| + StreamBuilder m(this, kMachInt32, kMachInt32);
|
| + m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
|
| + Stream s = m.Build();
|
| ASSERT_EQ(1U, s.size());
|
| - EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
|
| + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
|
| + ASSERT_EQ(2U, s[0]->InputCount());
|
| + EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
|
| + EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
|
| + EXPECT_EQ(1U, s[0]->OutputCount());
|
| + }
|
| + }
|
| + {
|
| + // 64-bit add.
|
| + TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
|
| + StreamBuilder m(this, kMachInt64, kMachInt64);
|
| + m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
|
| + Stream s = m.Build();
|
| + ASSERT_EQ(1U, s.size());
|
| + EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
|
| ASSERT_EQ(2U, s[0]->InputCount());
|
| EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
|
| EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
|
| @@ -345,10 +392,6 @@ TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) {
|
| }
|
|
|
|
|
| -INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
|
| - ::testing::ValuesIn(kAddSubInstructions));
|
| -
|
| -
|
| TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
|
| // Subtraction with zero on the left maps to Neg.
|
| {
|
| @@ -376,6 +419,42 @@ TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
|
| }
|
|
|
|
|
| +TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
|
| + {
|
| + // 32-bit add.
|
| + TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
|
| + if (imm == 0) continue;
|
| + StreamBuilder m(this, kMachInt32, kMachInt32);
|
| + m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
|
| + Stream s = m.Build();
|
| +
|
| + ASSERT_EQ(1U, s.size());
|
| + EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
|
| + ASSERT_EQ(2U, s[0]->InputCount());
|
| + ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
|
| + EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
|
| + EXPECT_EQ(1U, s[0]->OutputCount());
|
| + }
|
| + }
|
| + {
|
| + // 64-bit add.
|
| + TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
|
| + if (imm == 0) continue;
|
| + StreamBuilder m(this, kMachInt64, kMachInt64);
|
| + m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
|
| + Stream s = m.Build();
|
| +
|
| + ASSERT_EQ(1U, s.size());
|
| + EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
|
| + ASSERT_EQ(2U, s[0]->InputCount());
|
| + ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
|
| + EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
|
| + EXPECT_EQ(1U, s[0]->OutputCount());
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| // -----------------------------------------------------------------------------
|
| // Data processing controlled branches.
|
|
|
|
|