Index: src/compiler/ia32/instruction-selector-ia32-unittest.cc |
diff --git a/src/compiler/ia32/instruction-selector-ia32-unittest.cc b/src/compiler/ia32/instruction-selector-ia32-unittest.cc |
index 50e1358d17569fc6ae5fb8ddaddd1f48e7d1185c..89d150f26e4e8d73e8166ae8f6bd44106de25f41 100644 |
--- a/src/compiler/ia32/instruction-selector-ia32-unittest.cc |
+++ b/src/compiler/ia32/instruction-selector-ia32-unittest.cc |
@@ -189,9 +189,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { |
Stream s = m.Build(); |
ASSERT_EQ(1U, s.size()); |
EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
+ if (base == 0) { |
+ ASSERT_EQ(1U, s[0]->InputCount()); |
+ } else { |
ASSERT_EQ(2U, s[0]->InputCount()); |
ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); |
+ } |
EXPECT_EQ(1U, s[0]->OutputCount()); |
} |
} |
@@ -205,9 +209,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { |
Stream s = m.Build(); |
ASSERT_EQ(1U, s.size()); |
EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
+ if (index == 0) { |
+ ASSERT_EQ(1U, s[0]->InputCount()); |
+ } else { |
ASSERT_EQ(2U, s[0]->InputCount()); |
ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
+ } |
EXPECT_EQ(1U, s[0]->OutputCount()); |
} |
} |
@@ -235,9 +243,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { |
Stream s = m.Build(); |
ASSERT_EQ(1U, s.size()); |
EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
+ if (base == 0) { |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ } else { |
ASSERT_EQ(3U, s[0]->InputCount()); |
ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); |
+ } |
EXPECT_EQ(0U, s[0]->OutputCount()); |
} |
} |
@@ -253,9 +265,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { |
Stream s = m.Build(); |
ASSERT_EQ(1U, s.size()); |
EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
- ASSERT_EQ(3U, s[0]->InputCount()); |
- ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
- EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
+ if (index == 0) { |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ } else { |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
+ EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
+ } |
EXPECT_EQ(0U, s[0]->OutputCount()); |
} |
} |
@@ -265,6 +281,149 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
InstructionSelectorMemoryAccessTest, |
::testing::ValuesIn(kMemoryAccesses)); |
+ |
+// ----------------------------------------------------------------------------- |
+// AddressingMode for loads and stores. |
+ |
+class AddressingModeUnitTest : public InstructionSelectorTest { |
+ public: |
+ AddressingModeUnitTest() : m(NULL) { Reset(); } |
+ ~AddressingModeUnitTest() { delete m; } |
+ |
+ void Run(Node* base, Node* index, AddressingMode mode) { |
+ Node* load = m->Load(kMachInt32, base, index); |
+ m->Store(kMachInt32, base, index, load); |
+ m->Return(m->Int32Constant(0)); |
+ Stream s = m->Build(); |
+ ASSERT_EQ(2U, s.size()); |
+ EXPECT_EQ(mode, s[0]->addressing_mode()); |
+ EXPECT_EQ(mode, s[1]->addressing_mode()); |
+ } |
+ |
+ Node* zero; |
+ Node* null_ptr; |
+ 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]; |
+ StreamBuilder* m; |
+ |
+ void Reset() { |
+ delete m; |
+ m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32); |
+ zero = m->Int32Constant(0); |
+ null_ptr = m->Int32Constant(0); |
+ 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); |
+ } |
+}; |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MR) { |
+ Node* base = base_reg; |
+ Node* index = zero; |
+ Run(base, index, kMode_MR); |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MRI) { |
+ Node* base = base_reg; |
+ Node* index = non_zero; |
+ Run(base, index, kMode_MRI); |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MR1) { |
+ Node* base = base_reg; |
+ Node* index = index_reg; |
+ Run(base, index, kMode_MR1); |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MRN) { |
+ AddressingMode expected[] = {kMode_MR1, kMode_MR2, kMode_MR4, kMode_MR8}; |
+ for (size_t i = 0; i < arraysize(scales); ++i) { |
+ Reset(); |
+ Node* base = base_reg; |
+ Node* index = m->Int32Mul(index_reg, scales[i]); |
+ Run(base, index, expected[i]); |
+ } |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MR1I) { |
+ Node* base = base_reg; |
+ Node* index = m->Int32Add(index_reg, non_zero); |
+ Run(base, index, kMode_MR1I); |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) { |
+ AddressingMode expected[] = {kMode_MR1I, kMode_MR2I, kMode_MR4I, kMode_MR8I}; |
+ for (size_t i = 0; i < arraysize(scales); ++i) { |
+ Reset(); |
+ Node* base = base_reg; |
+ Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero); |
+ Run(base, index, expected[i]); |
+ } |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_M1) { |
+ Node* base = null_ptr; |
+ Node* index = index_reg; |
+ Run(base, index, kMode_MR); |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MN) { |
+ AddressingMode expected[] = {kMode_MR, kMode_M2, kMode_M4, kMode_M8}; |
+ for (size_t i = 0; i < arraysize(scales); ++i) { |
+ Reset(); |
+ Node* base = null_ptr; |
+ Node* index = m->Int32Mul(index_reg, scales[i]); |
+ Run(base, index, expected[i]); |
+ } |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_M1I) { |
+ Node* base = null_ptr; |
+ Node* index = m->Int32Add(index_reg, non_zero); |
+ Run(base, index, kMode_MRI); |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MNI) { |
+ AddressingMode expected[] = {kMode_MRI, kMode_M2I, kMode_M4I, kMode_M8I}; |
+ for (size_t i = 0; i < arraysize(scales); ++i) { |
+ Reset(); |
+ Node* base = null_ptr; |
+ Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero); |
+ Run(base, index, expected[i]); |
+ } |
+} |
+ |
+ |
+TEST_F(AddressingModeUnitTest, AddressingMode_MI) { |
+ Node* bases[] = {null_ptr, non_zero}; |
+ Node* indices[] = {zero, non_zero}; |
+ for (size_t i = 0; i < arraysize(bases); ++i) { |
+ for (size_t j = 0; j < arraysize(indices); ++j) { |
+ Reset(); |
+ Node* base = bases[i]; |
+ Node* index = indices[j]; |
+ Run(base, index, kMode_MI); |
+ } |
+ } |
+} |
+ |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |