Line data Source code
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 "src/compiler/machine-operator.h"
6 : #include "src/compiler/opcodes.h"
7 : #include "src/compiler/operator.h"
8 : #include "src/compiler/operator-properties.h"
9 : #include "test/unittests/test-utils.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 : namespace compiler {
14 : namespace machine_operator_unittest {
15 :
16 : template <typename T>
17 800 : class MachineOperatorTestWithParam
18 : : public TestWithZone,
19 : public ::testing::WithParamInterface<
20 : ::testing::tuple<MachineRepresentation, T> > {
21 : protected:
22 : MachineRepresentation representation() const {
23 250 : return ::testing::get<0>(B::GetParam());
24 : }
25 468 : const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
26 :
27 : private:
28 : typedef ::testing::WithParamInterface<
29 : ::testing::tuple<MachineRepresentation, T> > B;
30 : };
31 :
32 :
33 : const MachineRepresentation kMachineReps[] = {MachineRepresentation::kWord32,
34 : MachineRepresentation::kWord64};
35 :
36 :
37 : const MachineType kMachineTypesForAccess[] = {
38 : MachineType::Float32(), MachineType::Float64(), MachineType::Int8(),
39 : MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(),
40 : MachineType::Int32(), MachineType::Uint32(), MachineType::Int64(),
41 : MachineType::Uint64(), MachineType::AnyTagged()};
42 :
43 :
44 : const MachineRepresentation kRepresentationsForStore[] = {
45 : MachineRepresentation::kFloat32, MachineRepresentation::kFloat64,
46 : MachineRepresentation::kWord8, MachineRepresentation::kWord16,
47 : MachineRepresentation::kWord32, MachineRepresentation::kWord64,
48 : MachineRepresentation::kTagged};
49 :
50 :
51 : // -----------------------------------------------------------------------------
52 : // Load operator.
53 :
54 :
55 : typedef MachineOperatorTestWithParam<LoadRepresentation>
56 : MachineLoadOperatorTest;
57 :
58 :
59 18238 : TEST_P(MachineLoadOperatorTest, InstancesAreGloballyShared) {
60 22 : MachineOperatorBuilder machine1(zone(), representation());
61 22 : MachineOperatorBuilder machine2(zone(), representation());
62 66 : EXPECT_EQ(machine1.Load(GetParam()), machine2.Load(GetParam()));
63 22 : }
64 :
65 :
66 18238 : TEST_P(MachineLoadOperatorTest, NumberOfInputsAndOutputs) {
67 22 : MachineOperatorBuilder machine(zone(), representation());
68 132 : const Operator* op = machine.Load(GetParam());
69 :
70 44 : EXPECT_EQ(2, op->ValueInputCount());
71 44 : EXPECT_EQ(1, op->EffectInputCount());
72 44 : EXPECT_EQ(1, op->ControlInputCount());
73 44 : EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
74 :
75 44 : EXPECT_EQ(1, op->ValueOutputCount());
76 44 : EXPECT_EQ(1, op->EffectOutputCount());
77 44 : EXPECT_EQ(0, op->ControlOutputCount());
78 22 : }
79 :
80 :
81 18238 : TEST_P(MachineLoadOperatorTest, OpcodeIsCorrect) {
82 22 : MachineOperatorBuilder machine(zone(), representation());
83 44 : EXPECT_EQ(IrOpcode::kLoad, machine.Load(GetParam())->opcode());
84 22 : }
85 :
86 :
87 18238 : TEST_P(MachineLoadOperatorTest, ParameterIsCorrect) {
88 22 : MachineOperatorBuilder machine(zone(), representation());
89 66 : EXPECT_EQ(GetParam(), LoadRepresentationOf(machine.Load(GetParam())));
90 22 : }
91 :
92 :
93 329725 : INSTANTIATE_TEST_CASE_P(
94 : MachineOperatorTest, MachineLoadOperatorTest,
95 : ::testing::Combine(::testing::ValuesIn(kMachineReps),
96 : ::testing::ValuesIn(kMachineTypesForAccess)));
97 :
98 :
99 : // -----------------------------------------------------------------------------
100 : // Store operator.
101 :
102 :
103 224 : class MachineStoreOperatorTest
104 : : public MachineOperatorTestWithParam<
105 : ::testing::tuple<MachineRepresentation, WriteBarrierKind> > {
106 : protected:
107 168 : StoreRepresentation GetParam() const {
108 : return StoreRepresentation(
109 : ::testing::get<0>(
110 : MachineOperatorTestWithParam< ::testing::tuple<
111 : MachineRepresentation, WriteBarrierKind> >::GetParam()),
112 : ::testing::get<1>(
113 : MachineOperatorTestWithParam< ::testing::tuple<
114 336 : MachineRepresentation, WriteBarrierKind> >::GetParam()));
115 : }
116 : };
117 :
118 :
119 18262 : TEST_P(MachineStoreOperatorTest, InstancesAreGloballyShared) {
120 28 : MachineOperatorBuilder machine1(zone(), representation());
121 28 : MachineOperatorBuilder machine2(zone(), representation());
122 56 : EXPECT_EQ(machine1.Store(GetParam()), machine2.Store(GetParam()));
123 28 : }
124 :
125 :
126 18262 : TEST_P(MachineStoreOperatorTest, NumberOfInputsAndOutputs) {
127 28 : MachineOperatorBuilder machine(zone(), representation());
128 168 : const Operator* op = machine.Store(GetParam());
129 :
130 56 : EXPECT_EQ(3, op->ValueInputCount());
131 56 : EXPECT_EQ(1, op->EffectInputCount());
132 56 : EXPECT_EQ(1, op->ControlInputCount());
133 56 : EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
134 :
135 56 : EXPECT_EQ(0, op->ValueOutputCount());
136 56 : EXPECT_EQ(1, op->EffectOutputCount());
137 56 : EXPECT_EQ(0, op->ControlOutputCount());
138 28 : }
139 :
140 :
141 18262 : TEST_P(MachineStoreOperatorTest, OpcodeIsCorrect) {
142 28 : MachineOperatorBuilder machine(zone(), representation());
143 56 : EXPECT_EQ(IrOpcode::kStore, machine.Store(GetParam())->opcode());
144 28 : }
145 :
146 :
147 18262 : TEST_P(MachineStoreOperatorTest, ParameterIsCorrect) {
148 28 : MachineOperatorBuilder machine(zone(), representation());
149 56 : EXPECT_EQ(GetParam(), StoreRepresentationOf(machine.Store(GetParam())));
150 28 : }
151 :
152 :
153 414425 : INSTANTIATE_TEST_CASE_P(
154 : MachineOperatorTest, MachineStoreOperatorTest,
155 : ::testing::Combine(
156 : ::testing::ValuesIn(kMachineReps),
157 : ::testing::Combine(::testing::ValuesIn(kRepresentationsForStore),
158 : ::testing::Values(kNoWriteBarrier,
159 : kFullWriteBarrier))));
160 :
161 : // -----------------------------------------------------------------------------
162 : // Pure operators.
163 :
164 : struct PureOperator {
165 : const Operator* (MachineOperatorBuilder::*constructor)();
166 : char const* const constructor_name;
167 : int value_input_count;
168 : int control_input_count;
169 : int value_output_count;
170 : };
171 :
172 :
173 0 : std::ostream& operator<<(std::ostream& os, PureOperator const& pop) {
174 304 : return os << pop.constructor_name;
175 : }
176 :
177 : const PureOperator kPureOperators[] = {
178 : #define PURE(Name, value_input_count, control_input_count, value_output_count) \
179 : { \
180 : &MachineOperatorBuilder::Name, #Name, value_input_count, \
181 : control_input_count, value_output_count \
182 : }
183 : PURE(Word32And, 2, 0, 1), // --
184 : PURE(Word32Or, 2, 0, 1), // --
185 : PURE(Word32Xor, 2, 0, 1), // --
186 : PURE(Word32Shl, 2, 0, 1), // --
187 : PURE(Word32Shr, 2, 0, 1), // --
188 : PURE(Word32Sar, 2, 0, 1), // --
189 : PURE(Word32Ror, 2, 0, 1), // --
190 : PURE(Word32Equal, 2, 0, 1), // --
191 : PURE(Word32Clz, 1, 0, 1), // --
192 : PURE(Word64And, 2, 0, 1), // --
193 : PURE(Word64Or, 2, 0, 1), // --
194 : PURE(Word64Xor, 2, 0, 1), // --
195 : PURE(Word64Shl, 2, 0, 1), // --
196 : PURE(Word64Shr, 2, 0, 1), // --
197 : PURE(Word64Sar, 2, 0, 1), // --
198 : PURE(Word64Ror, 2, 0, 1), // --
199 : PURE(Word64Equal, 2, 0, 1), // --
200 : PURE(Int32Add, 2, 0, 1), // --
201 : PURE(Int32Sub, 2, 0, 1), // --
202 : PURE(Int32Mul, 2, 0, 1), // --
203 : PURE(Int32MulHigh, 2, 0, 1), // --
204 : PURE(Int32Div, 2, 1, 1), // --
205 : PURE(Uint32Div, 2, 1, 1), // --
206 : PURE(Int32Mod, 2, 1, 1), // --
207 : PURE(Uint32Mod, 2, 1, 1), // --
208 : PURE(Int32LessThan, 2, 0, 1), // --
209 : PURE(Int32LessThanOrEqual, 2, 0, 1), // --
210 : PURE(Uint32LessThan, 2, 0, 1), // --
211 : PURE(Uint32LessThanOrEqual, 2, 0, 1), // --
212 : PURE(Int64Add, 2, 0, 1), // --
213 : PURE(Int64Sub, 2, 0, 1), // --
214 : PURE(Int64Mul, 2, 0, 1), // --
215 : PURE(Int64Div, 2, 1, 1), // --
216 : PURE(Uint64Div, 2, 1, 1), // --
217 : PURE(Int64Mod, 2, 1, 1), // --
218 : PURE(Uint64Mod, 2, 1, 1), // --
219 : PURE(Int64LessThan, 2, 0, 1), // --
220 : PURE(Int64LessThanOrEqual, 2, 0, 1), // --
221 : PURE(Uint64LessThan, 2, 0, 1), // --
222 : PURE(Uint64LessThanOrEqual, 2, 0, 1), // --
223 : PURE(ChangeFloat32ToFloat64, 1, 0, 1), // --
224 : PURE(ChangeFloat64ToInt32, 1, 0, 1), // --
225 : PURE(ChangeFloat64ToUint32, 1, 0, 1), // --
226 : PURE(ChangeInt32ToInt64, 1, 0, 1), // --
227 : PURE(ChangeUint32ToFloat64, 1, 0, 1), // --
228 : PURE(ChangeUint32ToUint64, 1, 0, 1), // --
229 : PURE(TruncateFloat64ToFloat32, 1, 0, 1), // --
230 : PURE(TruncateInt64ToInt32, 1, 0, 1), // --
231 : PURE(Float32Abs, 1, 0, 1), // --
232 : PURE(Float32Add, 2, 0, 1), // --
233 : PURE(Float32Sub, 2, 0, 1), // --
234 : PURE(Float32Mul, 2, 0, 1), // --
235 : PURE(Float32Div, 2, 0, 1), // --
236 : PURE(Float32Sqrt, 1, 0, 1), // --
237 : PURE(Float32Equal, 2, 0, 1), // --
238 : PURE(Float32LessThan, 2, 0, 1), // --
239 : PURE(Float32LessThanOrEqual, 2, 0, 1), // --
240 : PURE(Float32Neg, 1, 0, 1), // --
241 : PURE(Float64Abs, 1, 0, 1), // --
242 : PURE(Float64Add, 2, 0, 1), // --
243 : PURE(Float64Sub, 2, 0, 1), // --
244 : PURE(Float64Mul, 2, 0, 1), // --
245 : PURE(Float64Div, 2, 0, 1), // --
246 : PURE(Float64Mod, 2, 0, 1), // --
247 : PURE(Float64Sqrt, 1, 0, 1), // --
248 : PURE(Float64Max, 2, 0, 1), // --
249 : PURE(Float64Min, 2, 0, 1), // --
250 : PURE(Float64Equal, 2, 0, 1), // --
251 : PURE(Float64LessThan, 2, 0, 1), // --
252 : PURE(Float64LessThanOrEqual, 2, 0, 1), // --
253 : PURE(LoadStackPointer, 0, 0, 1), // --
254 : PURE(Float64ExtractLowWord32, 1, 0, 1), // --
255 : PURE(Float64ExtractHighWord32, 1, 0, 1), // --
256 : PURE(Float64InsertLowWord32, 2, 0, 1), // --
257 : PURE(Float64InsertHighWord32, 2, 0, 1), // --
258 : PURE(Float64Neg, 1, 0, 1), // --
259 : #undef PURE
260 : };
261 :
262 :
263 2 : class MachinePureOperatorTest : public TestWithZone {
264 : protected:
265 : MachineRepresentation word_type() {
266 : return MachineType::PointerRepresentation();
267 : }
268 : };
269 :
270 :
271 15129 : TEST_F(MachinePureOperatorTest, PureOperators) {
272 13 : TRACED_FOREACH(MachineRepresentation, machine_rep1, kMachineReps) {
273 2 : MachineOperatorBuilder machine1(zone(), machine_rep1);
274 26 : TRACED_FOREACH(MachineRepresentation, machine_rep2, kMachineReps) {
275 4 : MachineOperatorBuilder machine2(zone(), machine_rep2);
276 2132 : TRACED_FOREACH(PureOperator, pop, kPureOperators) {
277 304 : const Operator* op1 = (machine1.*pop.constructor)();
278 304 : const Operator* op2 = (machine2.*pop.constructor)();
279 304 : EXPECT_EQ(op1, op2);
280 1520 : EXPECT_EQ(pop.value_input_count, op1->ValueInputCount());
281 912 : EXPECT_EQ(pop.control_input_count, op1->ControlInputCount());
282 912 : EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount());
283 304 : }
284 4 : }
285 2 : }
286 1 : }
287 :
288 :
289 : // Optional operators.
290 :
291 : struct OptionalOperatorEntry {
292 : const OptionalOperator (MachineOperatorBuilder::*constructor)();
293 : MachineOperatorBuilder::Flag enabling_flag;
294 : char const* const constructor_name;
295 : int value_input_count;
296 : int control_input_count;
297 : int value_output_count;
298 : };
299 :
300 :
301 0 : std::ostream& operator<<(std::ostream& os, OptionalOperatorEntry const& pop) {
302 3 : return os << pop.constructor_name;
303 : }
304 :
305 : const OptionalOperatorEntry kOptionalOperators[] = {
306 : #define OPTIONAL_ENTRY(Name, value_input_count, control_input_count, \
307 : value_output_count) \
308 : { \
309 : &MachineOperatorBuilder::Name, MachineOperatorBuilder::k##Name, #Name, \
310 : value_input_count, control_input_count, value_output_count \
311 : }
312 : OPTIONAL_ENTRY(Float64RoundDown, 1, 0, 1), // --
313 : OPTIONAL_ENTRY(Float64RoundTruncate, 1, 0, 1), // --
314 : OPTIONAL_ENTRY(Float64RoundTiesAway, 1, 0, 1), // --
315 : #undef OPTIONAL_ENTRY
316 : };
317 :
318 :
319 2 : class MachineOptionalOperatorTest : public TestWithZone {
320 : protected:
321 : MachineRepresentation word_rep() {
322 : return MachineType::PointerRepresentation();
323 : }
324 : };
325 :
326 :
327 15129 : TEST_F(MachineOptionalOperatorTest, OptionalOperators) {
328 22 : TRACED_FOREACH(OptionalOperatorEntry, pop, kOptionalOperators) {
329 42 : TRACED_FOREACH(MachineRepresentation, machine_rep1, kMachineReps) {
330 12 : MachineOperatorBuilder machine1(zone(), machine_rep1, pop.enabling_flag);
331 78 : TRACED_FOREACH(MachineRepresentation, machine_rep2, kMachineReps) {
332 : MachineOperatorBuilder machine2(zone(), machine_rep2,
333 24 : pop.enabling_flag);
334 12 : const Operator* op1 = (machine1.*pop.constructor)().op();
335 12 : const Operator* op2 = (machine2.*pop.constructor)().op();
336 12 : EXPECT_EQ(op1, op2);
337 60 : EXPECT_EQ(pop.value_input_count, op1->ValueInputCount());
338 36 : EXPECT_EQ(pop.control_input_count, op1->ControlInputCount());
339 36 : EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount());
340 :
341 12 : MachineOperatorBuilder machine3(zone(), word_rep());
342 24 : EXPECT_TRUE((machine1.*pop.constructor)().IsSupported());
343 24 : EXPECT_FALSE((machine3.*pop.constructor)().IsSupported());
344 12 : }
345 6 : }
346 3 : }
347 1 : }
348 :
349 :
350 : // -----------------------------------------------------------------------------
351 : // Pseudo operators.
352 :
353 :
354 : typedef TestWithZone MachineOperatorTest;
355 :
356 :
357 15128 : TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs32Bit) {
358 1 : MachineOperatorBuilder machine(zone(), MachineRepresentation::kWord32);
359 2 : EXPECT_EQ(machine.Word32And(), machine.WordAnd());
360 2 : EXPECT_EQ(machine.Word32Or(), machine.WordOr());
361 2 : EXPECT_EQ(machine.Word32Xor(), machine.WordXor());
362 2 : EXPECT_EQ(machine.Word32Shl(), machine.WordShl());
363 2 : EXPECT_EQ(machine.Word32Shr(), machine.WordShr());
364 2 : EXPECT_EQ(machine.Word32Sar(), machine.WordSar());
365 2 : EXPECT_EQ(machine.Word32Ror(), machine.WordRor());
366 2 : EXPECT_EQ(machine.Word32Equal(), machine.WordEqual());
367 2 : EXPECT_EQ(machine.Int32Add(), machine.IntAdd());
368 2 : EXPECT_EQ(machine.Int32Sub(), machine.IntSub());
369 2 : EXPECT_EQ(machine.Int32Mul(), machine.IntMul());
370 2 : EXPECT_EQ(machine.Int32Div(), machine.IntDiv());
371 2 : EXPECT_EQ(machine.Uint32Div(), machine.UintDiv());
372 2 : EXPECT_EQ(machine.Int32Mod(), machine.IntMod());
373 2 : EXPECT_EQ(machine.Uint32Mod(), machine.UintMod());
374 2 : EXPECT_EQ(machine.Int32LessThan(), machine.IntLessThan());
375 2 : EXPECT_EQ(machine.Int32LessThanOrEqual(), machine.IntLessThanOrEqual());
376 1 : }
377 :
378 :
379 15128 : TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs64Bit) {
380 1 : MachineOperatorBuilder machine(zone(), MachineRepresentation::kWord64);
381 2 : EXPECT_EQ(machine.Word64And(), machine.WordAnd());
382 2 : EXPECT_EQ(machine.Word64Or(), machine.WordOr());
383 2 : EXPECT_EQ(machine.Word64Xor(), machine.WordXor());
384 2 : EXPECT_EQ(machine.Word64Shl(), machine.WordShl());
385 2 : EXPECT_EQ(machine.Word64Shr(), machine.WordShr());
386 2 : EXPECT_EQ(machine.Word64Sar(), machine.WordSar());
387 2 : EXPECT_EQ(machine.Word64Ror(), machine.WordRor());
388 2 : EXPECT_EQ(machine.Word64Equal(), machine.WordEqual());
389 2 : EXPECT_EQ(machine.Int64Add(), machine.IntAdd());
390 2 : EXPECT_EQ(machine.Int64Sub(), machine.IntSub());
391 2 : EXPECT_EQ(machine.Int64Mul(), machine.IntMul());
392 2 : EXPECT_EQ(machine.Int64Div(), machine.IntDiv());
393 2 : EXPECT_EQ(machine.Uint64Div(), machine.UintDiv());
394 2 : EXPECT_EQ(machine.Int64Mod(), machine.IntMod());
395 2 : EXPECT_EQ(machine.Uint64Mod(), machine.UintMod());
396 2 : EXPECT_EQ(machine.Int64LessThan(), machine.IntLessThan());
397 2 : EXPECT_EQ(machine.Int64LessThanOrEqual(), machine.IntLessThanOrEqual());
398 1 : }
399 :
400 : } // namespace machine_operator_unittest
401 : } // namespace compiler
402 : } // namespace internal
403 9075 : } // namespace v8
|