| Index: src/compiler/x64/instruction-selector-x64-unittest.cc
|
| diff --git a/src/compiler/x64/instruction-selector-x64-unittest.cc b/src/compiler/x64/instruction-selector-x64-unittest.cc
|
| index f5545a789d9200992d536e603f624ad7a2a36543..cc2fedb3fcf3707acc20f54f02fac34145a69864 100644
|
| --- a/src/compiler/x64/instruction-selector-x64-unittest.cc
|
| +++ b/src/compiler/x64/instruction-selector-x64-unittest.cc
|
| @@ -3,6 +3,7 @@
|
| // found in the LICENSE file.
|
|
|
| #include "src/compiler/instruction-selector-unittest.h"
|
| +#include "src/compiler/node-matchers.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -184,7 +185,7 @@ class AddressingModeUnitTest : public InstructionSelectorTest {
|
| Node* non_zero;
|
| Node* base_reg; // opaque value to generate base as register
|
| Node* index_reg; // opaque value to generate index as register
|
| - Node* scales[4];
|
| + Node* scales[arraysize(ScaleFactorMatcher::kMatchedFactors)];
|
| StreamBuilder* m;
|
|
|
| void Reset() {
|
| @@ -195,11 +196,10 @@ class AddressingModeUnitTest : public InstructionSelectorTest {
|
| non_zero = m->Int32Constant(127);
|
| base_reg = m->Parameter(0);
|
| index_reg = m->Parameter(0);
|
| -
|
| - scales[0] = m->Int32Constant(1);
|
| - scales[1] = m->Int32Constant(2);
|
| - scales[2] = m->Int32Constant(4);
|
| - scales[3] = m->Int32Constant(8);
|
| + for (size_t i = 0; i < arraysize(ScaleFactorMatcher::kMatchedFactors);
|
| + ++i) {
|
| + scales[i] = m->Int32Constant(ScaleFactorMatcher::kMatchedFactors[i]);
|
| + }
|
| }
|
| };
|
|
|
| @@ -289,6 +289,110 @@ TEST_F(AddressingModeUnitTest, AddressingMode_MNI) {
|
| }
|
| }
|
|
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +// Multiplication.
|
| +
|
| +namespace {
|
| +
|
| +struct MultParam {
|
| + int value;
|
| + bool lea_expected;
|
| + AddressingMode addressing_mode;
|
| +};
|
| +
|
| +
|
| +std::ostream& operator<<(std::ostream& os, const MultParam& m) {
|
| + OStringStream ost;
|
| + ost << m.value << "." << m.lea_expected << "." << m.addressing_mode;
|
| + return os << ost.c_str();
|
| +}
|
| +
|
| +
|
| +const MultParam kMultParams[] = {{-1, false, kMode_None},
|
| + {0, false, kMode_None},
|
| + {1, true, kMode_M1},
|
| + {2, true, kMode_M2},
|
| + {3, true, kMode_MR2},
|
| + {4, true, kMode_M4},
|
| + {5, true, kMode_MR4},
|
| + {6, false, kMode_None},
|
| + {7, false, kMode_None},
|
| + {8, true, kMode_M8},
|
| + {9, true, kMode_MR8},
|
| + {10, false, kMode_None},
|
| + {11, false, kMode_None}};
|
| +
|
| +} // namespace
|
| +
|
| +
|
| +typedef InstructionSelectorTestWithParam<MultParam> InstructionSelectorMultTest;
|
| +
|
| +
|
| +static unsigned InputCountForLea(AddressingMode mode) {
|
| + switch (mode) {
|
| + case kMode_MR1:
|
| + case kMode_MR2:
|
| + case kMode_MR4:
|
| + case kMode_MR8:
|
| + return 2U;
|
| + case kMode_M1:
|
| + case kMode_M2:
|
| + case kMode_M4:
|
| + case kMode_M8:
|
| + return 1U;
|
| + default:
|
| + UNREACHABLE();
|
| + return 0U;
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST_P(InstructionSelectorMultTest, Mult32) {
|
| + const MultParam m_param = GetParam();
|
| + StreamBuilder m(this, kMachInt32, kMachInt32);
|
| + Node* param = m.Parameter(0);
|
| + Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value));
|
| + m.Return(mult);
|
| + Stream s = m.Build();
|
| + ASSERT_EQ(1U, s.size());
|
| + EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode());
|
| + if (m_param.lea_expected) {
|
| + EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
|
| + ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount());
|
| + } else {
|
| + EXPECT_EQ(kX64Imul32, s[0]->arch_opcode());
|
| + ASSERT_EQ(2U, s[0]->InputCount());
|
| + }
|
| + EXPECT_EQ(param->id(), s.ToVreg(s[0]->InputAt(0)));
|
| +}
|
| +
|
| +
|
| +TEST_P(InstructionSelectorMultTest, Mult64) {
|
| + const MultParam m_param = GetParam();
|
| + StreamBuilder m(this, kMachInt64, kMachInt64);
|
| + Node* param = m.Parameter(0);
|
| + Node* mult = m.Int64Mul(param, m.Int64Constant(m_param.value));
|
| + m.Return(mult);
|
| + Stream s = m.Build();
|
| + ASSERT_EQ(1U, s.size());
|
| + EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode());
|
| + if (m_param.lea_expected) {
|
| + EXPECT_EQ(kX64Lea, s[0]->arch_opcode());
|
| + ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount());
|
| + EXPECT_EQ(param->id(), s.ToVreg(s[0]->InputAt(0)));
|
| + } else {
|
| + EXPECT_EQ(kX64Imul, s[0]->arch_opcode());
|
| + ASSERT_EQ(2U, s[0]->InputCount());
|
| + // TODO(dcarney): why is this happening?
|
| + EXPECT_EQ(param->id(), s.ToVreg(s[0]->InputAt(1)));
|
| + }
|
| +}
|
| +
|
| +
|
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMultTest,
|
| + ::testing::ValuesIn(kMultParams));
|
| +
|
| } // namespace compiler
|
| } // namespace internal
|
| } // namespace v8
|
|
|