blob: 4367705a84a01c696a41624c0c2b4e1fe5172dd0 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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
11namespace v8 {
12namespace internal {
13namespace compiler {
14
15#if GTEST_HAS_COMBINE
16
17template <typename T>
18class MachineOperatorTestWithParam
19 : public TestWithZone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020 public ::testing::WithParamInterface<
21 ::testing::tuple<MachineRepresentation, T> > {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023 MachineRepresentation representation() const {
24 return ::testing::get<0>(B::GetParam());
25 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040026 const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
27
28 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 typedef ::testing::WithParamInterface<
30 ::testing::tuple<MachineRepresentation, T> > B;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031};
32
33
34namespace {
35
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036const MachineRepresentation kMachineReps[] = {MachineRepresentation::kWord32,
37 MachineRepresentation::kWord64};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038
39
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040const MachineType kMachineTypesForAccess[] = {
41 MachineType::Float32(), MachineType::Float64(), MachineType::Int8(),
42 MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(),
43 MachineType::Int32(), MachineType::Uint32(), MachineType::Int64(),
44 MachineType::Uint64(), MachineType::AnyTagged()};
45
46
47const MachineRepresentation kRepresentationsForStore[] = {
48 MachineRepresentation::kFloat32, MachineRepresentation::kFloat64,
49 MachineRepresentation::kWord8, MachineRepresentation::kWord16,
50 MachineRepresentation::kWord32, MachineRepresentation::kWord64,
51 MachineRepresentation::kTagged};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040052
53} // namespace
54
55
56// -----------------------------------------------------------------------------
57// Load operator.
58
59
60typedef MachineOperatorTestWithParam<LoadRepresentation>
61 MachineLoadOperatorTest;
62
63
64TEST_P(MachineLoadOperatorTest, InstancesAreGloballyShared) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 MachineOperatorBuilder machine1(zone(), representation());
66 MachineOperatorBuilder machine2(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067 EXPECT_EQ(machine1.Load(GetParam()), machine2.Load(GetParam()));
68}
69
70
71TEST_P(MachineLoadOperatorTest, NumberOfInputsAndOutputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 MachineOperatorBuilder machine(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040073 const Operator* op = machine.Load(GetParam());
74
75 EXPECT_EQ(2, op->ValueInputCount());
76 EXPECT_EQ(1, op->EffectInputCount());
77 EXPECT_EQ(1, op->ControlInputCount());
78 EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
79
80 EXPECT_EQ(1, op->ValueOutputCount());
81 EXPECT_EQ(1, op->EffectOutputCount());
82 EXPECT_EQ(0, op->ControlOutputCount());
83}
84
85
86TEST_P(MachineLoadOperatorTest, OpcodeIsCorrect) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 MachineOperatorBuilder machine(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088 EXPECT_EQ(IrOpcode::kLoad, machine.Load(GetParam())->opcode());
89}
90
91
92TEST_P(MachineLoadOperatorTest, ParameterIsCorrect) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 MachineOperatorBuilder machine(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040094 EXPECT_EQ(GetParam(),
95 OpParameter<LoadRepresentation>(machine.Load(GetParam())));
96}
97
98
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099INSTANTIATE_TEST_CASE_P(
100 MachineOperatorTest, MachineLoadOperatorTest,
101 ::testing::Combine(::testing::ValuesIn(kMachineReps),
102 ::testing::ValuesIn(kMachineTypesForAccess)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103
104
105// -----------------------------------------------------------------------------
106// Store operator.
107
108
109class MachineStoreOperatorTest
110 : public MachineOperatorTestWithParam<
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 ::testing::tuple<MachineRepresentation, WriteBarrierKind> > {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112 protected:
113 StoreRepresentation GetParam() const {
114 return StoreRepresentation(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 ::testing::get<0>(
116 MachineOperatorTestWithParam< ::testing::tuple<
117 MachineRepresentation, WriteBarrierKind> >::GetParam()),
118 ::testing::get<1>(
119 MachineOperatorTestWithParam< ::testing::tuple<
120 MachineRepresentation, WriteBarrierKind> >::GetParam()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121 }
122};
123
124
125TEST_P(MachineStoreOperatorTest, InstancesAreGloballyShared) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 MachineOperatorBuilder machine1(zone(), representation());
127 MachineOperatorBuilder machine2(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128 EXPECT_EQ(machine1.Store(GetParam()), machine2.Store(GetParam()));
129}
130
131
132TEST_P(MachineStoreOperatorTest, NumberOfInputsAndOutputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 MachineOperatorBuilder machine(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400134 const Operator* op = machine.Store(GetParam());
135
136 EXPECT_EQ(3, op->ValueInputCount());
137 EXPECT_EQ(1, op->EffectInputCount());
138 EXPECT_EQ(1, op->ControlInputCount());
139 EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
140
141 EXPECT_EQ(0, op->ValueOutputCount());
142 EXPECT_EQ(1, op->EffectOutputCount());
143 EXPECT_EQ(0, op->ControlOutputCount());
144}
145
146
147TEST_P(MachineStoreOperatorTest, OpcodeIsCorrect) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 MachineOperatorBuilder machine(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 EXPECT_EQ(IrOpcode::kStore, machine.Store(GetParam())->opcode());
150}
151
152
153TEST_P(MachineStoreOperatorTest, ParameterIsCorrect) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 MachineOperatorBuilder machine(zone(), representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155 EXPECT_EQ(GetParam(),
156 OpParameter<StoreRepresentation>(machine.Store(GetParam())));
157}
158
159
160INSTANTIATE_TEST_CASE_P(
161 MachineOperatorTest, MachineStoreOperatorTest,
162 ::testing::Combine(
163 ::testing::ValuesIn(kMachineReps),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 ::testing::Combine(::testing::ValuesIn(kRepresentationsForStore),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 ::testing::Values(kNoWriteBarrier,
166 kFullWriteBarrier))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168
169// -----------------------------------------------------------------------------
170// Pure operators.
171
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400172namespace {
173
174struct PureOperator {
175 const Operator* (MachineOperatorBuilder::*constructor)();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 char const* const constructor_name;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400177 int value_input_count;
178 int control_input_count;
179 int value_output_count;
180};
181
182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183std::ostream& operator<<(std::ostream& os, PureOperator const& pop) {
184 return os << pop.constructor_name;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185}
186
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400187const PureOperator kPureOperators[] = {
188#define PURE(Name, value_input_count, control_input_count, value_output_count) \
189 { \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000190 &MachineOperatorBuilder::Name, #Name, value_input_count, \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400191 control_input_count, value_output_count \
192 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 PURE(Word32And, 2, 0, 1), // --
194 PURE(Word32Or, 2, 0, 1), // --
195 PURE(Word32Xor, 2, 0, 1), // --
196 PURE(Word32Shl, 2, 0, 1), // --
197 PURE(Word32Shr, 2, 0, 1), // --
198 PURE(Word32Sar, 2, 0, 1), // --
199 PURE(Word32Ror, 2, 0, 1), // --
200 PURE(Word32Equal, 2, 0, 1), // --
201 PURE(Word32Clz, 1, 0, 1), // --
202 PURE(Word64And, 2, 0, 1), // --
203 PURE(Word64Or, 2, 0, 1), // --
204 PURE(Word64Xor, 2, 0, 1), // --
205 PURE(Word64Shl, 2, 0, 1), // --
206 PURE(Word64Shr, 2, 0, 1), // --
207 PURE(Word64Sar, 2, 0, 1), // --
208 PURE(Word64Ror, 2, 0, 1), // --
209 PURE(Word64Equal, 2, 0, 1), // --
210 PURE(Int32Add, 2, 0, 1), // --
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 PURE(Int32Sub, 2, 0, 1), // --
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 PURE(Int32Mul, 2, 0, 1), // --
213 PURE(Int32MulHigh, 2, 0, 1), // --
214 PURE(Int32Div, 2, 1, 1), // --
215 PURE(Uint32Div, 2, 1, 1), // --
216 PURE(Int32Mod, 2, 1, 1), // --
217 PURE(Uint32Mod, 2, 1, 1), // --
218 PURE(Int32LessThan, 2, 0, 1), // --
219 PURE(Int32LessThanOrEqual, 2, 0, 1), // --
220 PURE(Uint32LessThan, 2, 0, 1), // --
221 PURE(Uint32LessThanOrEqual, 2, 0, 1), // --
222 PURE(Int64Add, 2, 0, 1), // --
223 PURE(Int64Sub, 2, 0, 1), // --
224 PURE(Int64Mul, 2, 0, 1), // --
225 PURE(Int64Div, 2, 1, 1), // --
226 PURE(Uint64Div, 2, 1, 1), // --
227 PURE(Int64Mod, 2, 1, 1), // --
228 PURE(Uint64Mod, 2, 1, 1), // --
229 PURE(Int64LessThan, 2, 0, 1), // --
230 PURE(Int64LessThanOrEqual, 2, 0, 1), // --
231 PURE(Uint64LessThan, 2, 0, 1), // --
232 PURE(Uint64LessThanOrEqual, 2, 0, 1), // --
233 PURE(ChangeFloat32ToFloat64, 1, 0, 1), // --
234 PURE(ChangeFloat64ToInt32, 1, 0, 1), // --
235 PURE(ChangeFloat64ToUint32, 1, 0, 1), // --
236 PURE(ChangeInt32ToInt64, 1, 0, 1), // --
237 PURE(ChangeUint32ToFloat64, 1, 0, 1), // --
238 PURE(ChangeUint32ToUint64, 1, 0, 1), // --
239 PURE(TruncateFloat64ToFloat32, 1, 0, 1), // --
240 PURE(TruncateInt64ToInt32, 1, 0, 1), // --
241 PURE(Float32Abs, 1, 0, 1), // --
242 PURE(Float32Add, 2, 0, 1), // --
243 PURE(Float32Sub, 2, 0, 1), // --
244 PURE(Float32Mul, 2, 0, 1), // --
245 PURE(Float32Div, 2, 0, 1), // --
246 PURE(Float32Sqrt, 1, 0, 1), // --
247 PURE(Float32Equal, 2, 0, 1), // --
248 PURE(Float32LessThan, 2, 0, 1), // --
249 PURE(Float32LessThanOrEqual, 2, 0, 1), // --
250 PURE(Float64Abs, 1, 0, 1), // --
251 PURE(Float64Add, 2, 0, 1), // --
252 PURE(Float64Sub, 2, 0, 1), // --
253 PURE(Float64Mul, 2, 0, 1), // --
254 PURE(Float64Div, 2, 0, 1), // --
255 PURE(Float64Mod, 2, 0, 1), // --
256 PURE(Float64Sqrt, 1, 0, 1), // --
257 PURE(Float64Equal, 2, 0, 1), // --
258 PURE(Float64LessThan, 2, 0, 1), // --
259 PURE(Float64LessThanOrEqual, 2, 0, 1), // --
260 PURE(LoadStackPointer, 0, 0, 1), // --
261 PURE(Float64ExtractLowWord32, 1, 0, 1), // --
262 PURE(Float64ExtractHighWord32, 1, 0, 1), // --
263 PURE(Float64InsertLowWord32, 2, 0, 1), // --
264 PURE(Float64InsertHighWord32, 2, 0, 1), // --
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400265#undef PURE
266};
267
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268} // namespace
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270class MachinePureOperatorTest : public TestWithZone {
271 protected:
272 MachineRepresentation word_type() {
273 return MachineType::PointerRepresentation();
274 }
275};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277
278TEST_F(MachinePureOperatorTest, PureOperators) {
279 TRACED_FOREACH(MachineRepresentation, machine_rep1, kMachineReps) {
280 MachineOperatorBuilder machine1(zone(), machine_rep1);
281 TRACED_FOREACH(MachineRepresentation, machine_rep2, kMachineReps) {
282 MachineOperatorBuilder machine2(zone(), machine_rep2);
283 TRACED_FOREACH(PureOperator, pop, kPureOperators) {
284 const Operator* op1 = (machine1.*pop.constructor)();
285 const Operator* op2 = (machine2.*pop.constructor)();
286 EXPECT_EQ(op1, op2);
287 EXPECT_EQ(pop.value_input_count, op1->ValueInputCount());
288 EXPECT_EQ(pop.control_input_count, op1->ControlInputCount());
289 EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount());
290 }
291 }
292 }
293}
294
295
296// Optional operators.
297
298namespace {
299
300struct OptionalOperatorEntry {
301 const OptionalOperator (MachineOperatorBuilder::*constructor)();
302 MachineOperatorBuilder::Flag enabling_flag;
303 char const* const constructor_name;
304 int value_input_count;
305 int control_input_count;
306 int value_output_count;
307};
308
309
310std::ostream& operator<<(std::ostream& os, OptionalOperatorEntry const& pop) {
311 return os << pop.constructor_name;
312}
313
314const OptionalOperatorEntry kOptionalOperators[] = {
315#define OPTIONAL_ENTRY(Name, value_input_count, control_input_count, \
316 value_output_count) \
317 { \
318 &MachineOperatorBuilder::Name, MachineOperatorBuilder::k##Name, #Name, \
319 value_input_count, control_input_count, value_output_count \
320 }
321 OPTIONAL_ENTRY(Float32Max, 2, 0, 1), // --
322 OPTIONAL_ENTRY(Float32Min, 2, 0, 1), // --
323 OPTIONAL_ENTRY(Float64Max, 2, 0, 1), // --
324 OPTIONAL_ENTRY(Float64Min, 2, 0, 1), // --
325 OPTIONAL_ENTRY(Float64RoundDown, 1, 0, 1), // --
326 OPTIONAL_ENTRY(Float64RoundTruncate, 1, 0, 1), // --
327 OPTIONAL_ENTRY(Float64RoundTiesAway, 1, 0, 1), // --
Ben Murdoch61f157c2016-09-16 13:49:30 +0100328 OPTIONAL_ENTRY(Float32Neg, 1, 0, 1), // --
329 OPTIONAL_ENTRY(Float64Neg, 1, 0, 1), // --
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330#undef OPTIONAL_ENTRY
331};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400332} // namespace
333
334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335class MachineOptionalOperatorTest : public TestWithZone {
336 protected:
337 MachineRepresentation word_rep() {
338 return MachineType::PointerRepresentation();
339 }
340};
341
342
343TEST_F(MachineOptionalOperatorTest, OptionalOperators) {
344 TRACED_FOREACH(OptionalOperatorEntry, pop, kOptionalOperators) {
345 TRACED_FOREACH(MachineRepresentation, machine_rep1, kMachineReps) {
346 MachineOperatorBuilder machine1(zone(), machine_rep1, pop.enabling_flag);
347 TRACED_FOREACH(MachineRepresentation, machine_rep2, kMachineReps) {
348 MachineOperatorBuilder machine2(zone(), machine_rep2,
349 pop.enabling_flag);
350 const Operator* op1 = (machine1.*pop.constructor)().op();
351 const Operator* op2 = (machine2.*pop.constructor)().op();
352 EXPECT_EQ(op1, op2);
353 EXPECT_EQ(pop.value_input_count, op1->ValueInputCount());
354 EXPECT_EQ(pop.control_input_count, op1->ControlInputCount());
355 EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount());
356
357 MachineOperatorBuilder machine3(zone(), word_rep());
358 EXPECT_TRUE((machine1.*pop.constructor)().IsSupported());
359 EXPECT_FALSE((machine3.*pop.constructor)().IsSupported());
360 }
361 }
362 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400363}
364
365
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400366// -----------------------------------------------------------------------------
367// Pseudo operators.
368
369
370namespace {
371
372typedef TestWithZone MachineOperatorTest;
373
374} // namespace
375
376
377TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs32Bit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000378 MachineOperatorBuilder machine(zone(), MachineRepresentation::kWord32);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379 EXPECT_EQ(machine.Word32And(), machine.WordAnd());
380 EXPECT_EQ(machine.Word32Or(), machine.WordOr());
381 EXPECT_EQ(machine.Word32Xor(), machine.WordXor());
382 EXPECT_EQ(machine.Word32Shl(), machine.WordShl());
383 EXPECT_EQ(machine.Word32Shr(), machine.WordShr());
384 EXPECT_EQ(machine.Word32Sar(), machine.WordSar());
385 EXPECT_EQ(machine.Word32Ror(), machine.WordRor());
386 EXPECT_EQ(machine.Word32Equal(), machine.WordEqual());
387 EXPECT_EQ(machine.Int32Add(), machine.IntAdd());
388 EXPECT_EQ(machine.Int32Sub(), machine.IntSub());
389 EXPECT_EQ(machine.Int32Mul(), machine.IntMul());
390 EXPECT_EQ(machine.Int32Div(), machine.IntDiv());
391 EXPECT_EQ(machine.Uint32Div(), machine.UintDiv());
392 EXPECT_EQ(machine.Int32Mod(), machine.IntMod());
393 EXPECT_EQ(machine.Uint32Mod(), machine.UintMod());
394 EXPECT_EQ(machine.Int32LessThan(), machine.IntLessThan());
395 EXPECT_EQ(machine.Int32LessThanOrEqual(), machine.IntLessThanOrEqual());
396}
397
398
399TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs64Bit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 MachineOperatorBuilder machine(zone(), MachineRepresentation::kWord64);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400401 EXPECT_EQ(machine.Word64And(), machine.WordAnd());
402 EXPECT_EQ(machine.Word64Or(), machine.WordOr());
403 EXPECT_EQ(machine.Word64Xor(), machine.WordXor());
404 EXPECT_EQ(machine.Word64Shl(), machine.WordShl());
405 EXPECT_EQ(machine.Word64Shr(), machine.WordShr());
406 EXPECT_EQ(machine.Word64Sar(), machine.WordSar());
407 EXPECT_EQ(machine.Word64Ror(), machine.WordRor());
408 EXPECT_EQ(machine.Word64Equal(), machine.WordEqual());
409 EXPECT_EQ(machine.Int64Add(), machine.IntAdd());
410 EXPECT_EQ(machine.Int64Sub(), machine.IntSub());
411 EXPECT_EQ(machine.Int64Mul(), machine.IntMul());
412 EXPECT_EQ(machine.Int64Div(), machine.IntDiv());
413 EXPECT_EQ(machine.Uint64Div(), machine.UintDiv());
414 EXPECT_EQ(machine.Int64Mod(), machine.IntMod());
415 EXPECT_EQ(machine.Uint64Mod(), machine.UintMod());
416 EXPECT_EQ(machine.Int64LessThan(), machine.IntLessThan());
417 EXPECT_EQ(machine.Int64LessThanOrEqual(), machine.IntLessThanOrEqual());
418}
419
420} // namespace compiler
421} // namespace internal
422} // namespace v8