OLD | NEW |
| (Empty) |
1 // Copyright 2014 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "test/compiler-unittests/instruction-selector-unittest.h" | |
6 | |
7 namespace v8 { | |
8 namespace internal { | |
9 namespace compiler { | |
10 | |
11 namespace { | |
12 | |
13 // Immediates (random subset). | |
14 static const int32_t kImmediates[] = { | |
15 kMinInt, -42, -1, 0, 1, 2, 3, 4, 5, | |
16 6, 7, 8, 16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt}; | |
17 | |
18 } // namespace | |
19 | |
20 | |
21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) { | |
22 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
23 m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1))); | |
24 Stream s = m.Build(); | |
25 ASSERT_EQ(1U, s.size()); | |
26 EXPECT_EQ(kIA32Add, s[0]->arch_opcode()); | |
27 } | |
28 | |
29 | |
30 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) { | |
31 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
32 { | |
33 StreamBuilder m(this, kMachInt32, kMachInt32); | |
34 m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm))); | |
35 Stream s = m.Build(); | |
36 ASSERT_EQ(1U, s.size()); | |
37 EXPECT_EQ(kIA32Add, s[0]->arch_opcode()); | |
38 ASSERT_EQ(2U, s[0]->InputCount()); | |
39 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
40 } | |
41 { | |
42 StreamBuilder m(this, kMachInt32, kMachInt32); | |
43 m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0))); | |
44 Stream s = m.Build(); | |
45 ASSERT_EQ(1U, s.size()); | |
46 EXPECT_EQ(kIA32Add, s[0]->arch_opcode()); | |
47 ASSERT_EQ(2U, s[0]->InputCount()); | |
48 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
49 } | |
50 } | |
51 } | |
52 | |
53 | |
54 TEST_F(InstructionSelectorTest, Int32SubWithParameter) { | |
55 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
56 m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1))); | |
57 Stream s = m.Build(); | |
58 ASSERT_EQ(1U, s.size()); | |
59 EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | |
60 EXPECT_EQ(1U, s[0]->OutputCount()); | |
61 } | |
62 | |
63 | |
64 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) { | |
65 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
66 StreamBuilder m(this, kMachInt32, kMachInt32); | |
67 m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm))); | |
68 Stream s = m.Build(); | |
69 ASSERT_EQ(1U, s.size()); | |
70 EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | |
71 ASSERT_EQ(2U, s[0]->InputCount()); | |
72 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
73 } | |
74 } | |
75 | |
76 | |
77 // ----------------------------------------------------------------------------- | |
78 // Loads and stores | |
79 | |
80 namespace { | |
81 | |
82 struct MemoryAccess { | |
83 MachineType type; | |
84 ArchOpcode load_opcode; | |
85 ArchOpcode store_opcode; | |
86 }; | |
87 | |
88 | |
89 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | |
90 OStringStream ost; | |
91 ost << memacc.type; | |
92 return os << ost.c_str(); | |
93 } | |
94 | |
95 | |
96 static const MemoryAccess kMemoryAccesses[] = { | |
97 {kMachInt8, kIA32Movsxbl, kIA32Movb}, | |
98 {kMachUint8, kIA32Movzxbl, kIA32Movb}, | |
99 {kMachInt16, kIA32Movsxwl, kIA32Movw}, | |
100 {kMachUint16, kIA32Movzxwl, kIA32Movw}, | |
101 {kMachInt32, kIA32Movl, kIA32Movl}, | |
102 {kMachUint32, kIA32Movl, kIA32Movl}, | |
103 {kMachFloat32, kIA32Movss, kIA32Movss}, | |
104 {kMachFloat64, kIA32Movsd, kIA32Movsd}}; | |
105 | |
106 } // namespace | |
107 | |
108 | |
109 typedef InstructionSelectorTestWithParam<MemoryAccess> | |
110 InstructionSelectorMemoryAccessTest; | |
111 | |
112 | |
113 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | |
114 const MemoryAccess memacc = GetParam(); | |
115 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | |
116 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | |
117 Stream s = m.Build(); | |
118 ASSERT_EQ(1U, s.size()); | |
119 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
120 EXPECT_EQ(2U, s[0]->InputCount()); | |
121 EXPECT_EQ(1U, s[0]->OutputCount()); | |
122 } | |
123 | |
124 | |
125 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { | |
126 const MemoryAccess memacc = GetParam(); | |
127 TRACED_FOREACH(int32_t, base, kImmediates) { | |
128 StreamBuilder m(this, memacc.type, kMachPtr); | |
129 m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); | |
130 Stream s = m.Build(); | |
131 ASSERT_EQ(1U, s.size()); | |
132 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
133 ASSERT_EQ(2U, s[0]->InputCount()); | |
134 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
135 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | |
136 EXPECT_EQ(1U, s[0]->OutputCount()); | |
137 } | |
138 } | |
139 | |
140 | |
141 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { | |
142 const MemoryAccess memacc = GetParam(); | |
143 TRACED_FOREACH(int32_t, index, kImmediates) { | |
144 StreamBuilder m(this, memacc.type, kMachPtr); | |
145 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | |
146 Stream s = m.Build(); | |
147 ASSERT_EQ(1U, s.size()); | |
148 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
149 ASSERT_EQ(2U, s[0]->InputCount()); | |
150 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
151 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
152 EXPECT_EQ(1U, s[0]->OutputCount()); | |
153 } | |
154 } | |
155 | |
156 | |
157 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | |
158 const MemoryAccess memacc = GetParam(); | |
159 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | |
160 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2)); | |
161 m.Return(m.Int32Constant(0)); | |
162 Stream s = m.Build(); | |
163 ASSERT_EQ(1U, s.size()); | |
164 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
165 EXPECT_EQ(3U, s[0]->InputCount()); | |
166 EXPECT_EQ(0U, s[0]->OutputCount()); | |
167 } | |
168 | |
169 | |
170 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { | |
171 const MemoryAccess memacc = GetParam(); | |
172 TRACED_FOREACH(int32_t, base, kImmediates) { | |
173 StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type); | |
174 m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1)); | |
175 m.Return(m.Int32Constant(0)); | |
176 Stream s = m.Build(); | |
177 ASSERT_EQ(1U, s.size()); | |
178 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
179 ASSERT_EQ(3U, s[0]->InputCount()); | |
180 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
181 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | |
182 EXPECT_EQ(0U, s[0]->OutputCount()); | |
183 } | |
184 } | |
185 | |
186 | |
187 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { | |
188 const MemoryAccess memacc = GetParam(); | |
189 TRACED_FOREACH(int32_t, index, kImmediates) { | |
190 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | |
191 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | |
192 m.Parameter(1)); | |
193 m.Return(m.Int32Constant(0)); | |
194 Stream s = m.Build(); | |
195 ASSERT_EQ(1U, s.size()); | |
196 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
197 ASSERT_EQ(3U, s[0]->InputCount()); | |
198 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
199 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
200 EXPECT_EQ(0U, s[0]->OutputCount()); | |
201 } | |
202 } | |
203 | |
204 | |
205 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
206 InstructionSelectorMemoryAccessTest, | |
207 ::testing::ValuesIn(kMemoryAccesses)); | |
208 | |
209 } // namespace compiler | |
210 } // namespace internal | |
211 } // namespace v8 | |
OLD | NEW |