blob: 6e0df2ab44115f18cf6da30596d5dbef0f47d2aa [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,
20 public ::testing::WithParamInterface< ::testing::tuple<MachineType, T> > {
21 protected:
22 MachineType type() const { return ::testing::get<0>(B::GetParam()); }
23 const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
24
25 private:
26 typedef ::testing::WithParamInterface< ::testing::tuple<MachineType, T> > B;
27};
28
29
30namespace {
31
32const MachineType kMachineReps[] = {kRepWord32, kRepWord64};
33
34
35const MachineType kMachineTypes[] = {
36 kMachFloat32, kMachFloat64, kMachInt8, kMachUint8, kMachInt16,
37 kMachUint16, kMachInt32, kMachUint32, kMachInt64, kMachUint64,
38 kMachPtr, kMachAnyTagged, kRepBit, kRepWord8, kRepWord16,
39 kRepWord32, kRepWord64, kRepFloat32, kRepFloat64, kRepTagged};
40
41} // namespace
42
43
44// -----------------------------------------------------------------------------
45// Load operator.
46
47
48typedef MachineOperatorTestWithParam<LoadRepresentation>
49 MachineLoadOperatorTest;
50
51
52TEST_P(MachineLoadOperatorTest, InstancesAreGloballyShared) {
53 MachineOperatorBuilder machine1(zone(), type());
54 MachineOperatorBuilder machine2(zone(), type());
55 EXPECT_EQ(machine1.Load(GetParam()), machine2.Load(GetParam()));
56}
57
58
59TEST_P(MachineLoadOperatorTest, NumberOfInputsAndOutputs) {
60 MachineOperatorBuilder machine(zone(), type());
61 const Operator* op = machine.Load(GetParam());
62
63 EXPECT_EQ(2, op->ValueInputCount());
64 EXPECT_EQ(1, op->EffectInputCount());
65 EXPECT_EQ(1, op->ControlInputCount());
66 EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
67
68 EXPECT_EQ(1, op->ValueOutputCount());
69 EXPECT_EQ(1, op->EffectOutputCount());
70 EXPECT_EQ(0, op->ControlOutputCount());
71}
72
73
74TEST_P(MachineLoadOperatorTest, OpcodeIsCorrect) {
75 MachineOperatorBuilder machine(zone(), type());
76 EXPECT_EQ(IrOpcode::kLoad, machine.Load(GetParam())->opcode());
77}
78
79
80TEST_P(MachineLoadOperatorTest, ParameterIsCorrect) {
81 MachineOperatorBuilder machine(zone(), type());
82 EXPECT_EQ(GetParam(),
83 OpParameter<LoadRepresentation>(machine.Load(GetParam())));
84}
85
86
87INSTANTIATE_TEST_CASE_P(MachineOperatorTest, MachineLoadOperatorTest,
88 ::testing::Combine(::testing::ValuesIn(kMachineReps),
89 ::testing::ValuesIn(kMachineTypes)));
90
91
92// -----------------------------------------------------------------------------
93// Store operator.
94
95
96class MachineStoreOperatorTest
97 : public MachineOperatorTestWithParam<
98 ::testing::tuple<MachineType, WriteBarrierKind> > {
99 protected:
100 StoreRepresentation GetParam() const {
101 return StoreRepresentation(
102 ::testing::get<0>(MachineOperatorTestWithParam<
103 ::testing::tuple<MachineType, WriteBarrierKind> >::GetParam()),
104 ::testing::get<1>(MachineOperatorTestWithParam<
105 ::testing::tuple<MachineType, WriteBarrierKind> >::GetParam()));
106 }
107};
108
109
110TEST_P(MachineStoreOperatorTest, InstancesAreGloballyShared) {
111 MachineOperatorBuilder machine1(zone(), type());
112 MachineOperatorBuilder machine2(zone(), type());
113 EXPECT_EQ(machine1.Store(GetParam()), machine2.Store(GetParam()));
114}
115
116
117TEST_P(MachineStoreOperatorTest, NumberOfInputsAndOutputs) {
118 MachineOperatorBuilder machine(zone(), type());
119 const Operator* op = machine.Store(GetParam());
120
121 EXPECT_EQ(3, op->ValueInputCount());
122 EXPECT_EQ(1, op->EffectInputCount());
123 EXPECT_EQ(1, op->ControlInputCount());
124 EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
125
126 EXPECT_EQ(0, op->ValueOutputCount());
127 EXPECT_EQ(1, op->EffectOutputCount());
128 EXPECT_EQ(0, op->ControlOutputCount());
129}
130
131
132TEST_P(MachineStoreOperatorTest, OpcodeIsCorrect) {
133 MachineOperatorBuilder machine(zone(), type());
134 EXPECT_EQ(IrOpcode::kStore, machine.Store(GetParam())->opcode());
135}
136
137
138TEST_P(MachineStoreOperatorTest, ParameterIsCorrect) {
139 MachineOperatorBuilder machine(zone(), type());
140 EXPECT_EQ(GetParam(),
141 OpParameter<StoreRepresentation>(machine.Store(GetParam())));
142}
143
144
145INSTANTIATE_TEST_CASE_P(
146 MachineOperatorTest, MachineStoreOperatorTest,
147 ::testing::Combine(
148 ::testing::ValuesIn(kMachineReps),
149 ::testing::Combine(::testing::ValuesIn(kMachineTypes),
150 ::testing::Values(kNoWriteBarrier,
151 kFullWriteBarrier))));
152
153
154// -----------------------------------------------------------------------------
155// Pure operators.
156
157
158namespace {
159
160struct PureOperator {
161 const Operator* (MachineOperatorBuilder::*constructor)();
162 IrOpcode::Value opcode;
163 int value_input_count;
164 int control_input_count;
165 int value_output_count;
166};
167
168
169std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
170 return os << IrOpcode::Mnemonic(pop.opcode);
171}
172
173
174const PureOperator kPureOperators[] = {
175#define PURE(Name, value_input_count, control_input_count, value_output_count) \
176 { \
177 &MachineOperatorBuilder::Name, IrOpcode::k##Name, value_input_count, \
178 control_input_count, value_output_count \
179 }
180 PURE(Word32And, 2, 0, 1), PURE(Word32Or, 2, 0, 1), PURE(Word32Xor, 2, 0, 1),
181 PURE(Word32Shl, 2, 0, 1), PURE(Word32Shr, 2, 0, 1),
182 PURE(Word32Sar, 2, 0, 1), PURE(Word32Ror, 2, 0, 1),
183 PURE(Word32Equal, 2, 0, 1), PURE(Word64And, 2, 0, 1),
184 PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1), PURE(Word64Shl, 2, 0, 1),
185 PURE(Word64Shr, 2, 0, 1), PURE(Word64Sar, 2, 0, 1),
186 PURE(Word64Ror, 2, 0, 1), PURE(Word64Equal, 2, 0, 1),
187 PURE(Int32Add, 2, 0, 1), PURE(Int32AddWithOverflow, 2, 0, 2),
188 PURE(Int32Sub, 2, 0, 1), PURE(Int32SubWithOverflow, 2, 0, 2),
189 PURE(Int32Mul, 2, 0, 1), PURE(Int32MulHigh, 2, 0, 1),
190 PURE(Int32Div, 2, 1, 1), PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1),
191 PURE(Uint32Mod, 2, 1, 1), PURE(Int32LessThan, 2, 0, 1),
192 PURE(Int32LessThanOrEqual, 2, 0, 1), PURE(Uint32LessThan, 2, 0, 1),
193 PURE(Uint32LessThanOrEqual, 2, 0, 1), PURE(Int64Add, 2, 0, 1),
194 PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1), PURE(Int64Div, 2, 0, 1),
195 PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1), PURE(Uint64Mod, 2, 0, 1),
196 PURE(Int64LessThan, 2, 0, 1), PURE(Int64LessThanOrEqual, 2, 0, 1),
197 PURE(Uint64LessThan, 2, 0, 1), PURE(ChangeFloat32ToFloat64, 1, 0, 1),
198 PURE(ChangeFloat64ToInt32, 1, 0, 1), PURE(ChangeFloat64ToUint32, 1, 0, 1),
199 PURE(ChangeInt32ToInt64, 1, 0, 1), PURE(ChangeUint32ToFloat64, 1, 0, 1),
200 PURE(ChangeUint32ToUint64, 1, 0, 1),
201 PURE(TruncateFloat64ToFloat32, 1, 0, 1),
202 PURE(TruncateFloat64ToInt32, 1, 0, 1), PURE(TruncateInt64ToInt32, 1, 0, 1),
203 PURE(Float64Add, 2, 0, 1), PURE(Float64Sub, 2, 0, 1),
204 PURE(Float64Mul, 2, 0, 1), PURE(Float64Div, 2, 0, 1),
205 PURE(Float64Mod, 2, 0, 1), PURE(Float64Sqrt, 1, 0, 1),
206 PURE(Float64Equal, 2, 0, 1), PURE(Float64LessThan, 2, 0, 1),
207 PURE(Float64LessThanOrEqual, 2, 0, 1), PURE(LoadStackPointer, 0, 0, 1),
208 PURE(Float64Floor, 1, 0, 1), PURE(Float64Ceil, 1, 0, 1),
209 PURE(Float64RoundTruncate, 1, 0, 1), PURE(Float64RoundTiesAway, 1, 0, 1)
210#undef PURE
211};
212
213
214typedef MachineOperatorTestWithParam<PureOperator> MachinePureOperatorTest;
215
216} // namespace
217
218
219TEST_P(MachinePureOperatorTest, InstancesAreGloballyShared) {
220 const PureOperator& pop = GetParam();
221 MachineOperatorBuilder machine1(zone(), type());
222 MachineOperatorBuilder machine2(zone(), type());
223 EXPECT_EQ((machine1.*pop.constructor)(), (machine2.*pop.constructor)());
224}
225
226
227TEST_P(MachinePureOperatorTest, NumberOfInputsAndOutputs) {
228 MachineOperatorBuilder machine(zone(), type());
229 const PureOperator& pop = GetParam();
230 const Operator* op = (machine.*pop.constructor)();
231
232 EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
233 EXPECT_EQ(0, op->EffectInputCount());
234 EXPECT_EQ(pop.control_input_count, op->ControlInputCount());
235 EXPECT_EQ(pop.value_input_count + pop.control_input_count,
236 OperatorProperties::GetTotalInputCount(op));
237
238 EXPECT_EQ(pop.value_output_count, op->ValueOutputCount());
239 EXPECT_EQ(0, op->EffectOutputCount());
240 EXPECT_EQ(0, op->ControlOutputCount());
241}
242
243
244TEST_P(MachinePureOperatorTest, MarkedAsPure) {
245 MachineOperatorBuilder machine(zone(), type());
246 const PureOperator& pop = GetParam();
247 const Operator* op = (machine.*pop.constructor)();
248 EXPECT_TRUE(op->HasProperty(Operator::kPure));
249}
250
251
252TEST_P(MachinePureOperatorTest, OpcodeIsCorrect) {
253 MachineOperatorBuilder machine(zone(), type());
254 const PureOperator& pop = GetParam();
255 const Operator* op = (machine.*pop.constructor)();
256 EXPECT_EQ(pop.opcode, op->opcode());
257}
258
259
260INSTANTIATE_TEST_CASE_P(
261 MachineOperatorTest, MachinePureOperatorTest,
262 ::testing::Combine(::testing::ValuesIn(kMachineReps),
263 ::testing::ValuesIn(kPureOperators)));
264
265#endif // GTEST_HAS_COMBINE
266
267
268// -----------------------------------------------------------------------------
269// Pseudo operators.
270
271
272namespace {
273
274typedef TestWithZone MachineOperatorTest;
275
276} // namespace
277
278
279TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs32Bit) {
280 MachineOperatorBuilder machine(zone(), kRepWord32);
281 EXPECT_EQ(machine.Word32And(), machine.WordAnd());
282 EXPECT_EQ(machine.Word32Or(), machine.WordOr());
283 EXPECT_EQ(machine.Word32Xor(), machine.WordXor());
284 EXPECT_EQ(machine.Word32Shl(), machine.WordShl());
285 EXPECT_EQ(machine.Word32Shr(), machine.WordShr());
286 EXPECT_EQ(machine.Word32Sar(), machine.WordSar());
287 EXPECT_EQ(machine.Word32Ror(), machine.WordRor());
288 EXPECT_EQ(machine.Word32Equal(), machine.WordEqual());
289 EXPECT_EQ(machine.Int32Add(), machine.IntAdd());
290 EXPECT_EQ(machine.Int32Sub(), machine.IntSub());
291 EXPECT_EQ(machine.Int32Mul(), machine.IntMul());
292 EXPECT_EQ(machine.Int32Div(), machine.IntDiv());
293 EXPECT_EQ(machine.Uint32Div(), machine.UintDiv());
294 EXPECT_EQ(machine.Int32Mod(), machine.IntMod());
295 EXPECT_EQ(machine.Uint32Mod(), machine.UintMod());
296 EXPECT_EQ(machine.Int32LessThan(), machine.IntLessThan());
297 EXPECT_EQ(machine.Int32LessThanOrEqual(), machine.IntLessThanOrEqual());
298}
299
300
301TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs64Bit) {
302 MachineOperatorBuilder machine(zone(), kRepWord64);
303 EXPECT_EQ(machine.Word64And(), machine.WordAnd());
304 EXPECT_EQ(machine.Word64Or(), machine.WordOr());
305 EXPECT_EQ(machine.Word64Xor(), machine.WordXor());
306 EXPECT_EQ(machine.Word64Shl(), machine.WordShl());
307 EXPECT_EQ(machine.Word64Shr(), machine.WordShr());
308 EXPECT_EQ(machine.Word64Sar(), machine.WordSar());
309 EXPECT_EQ(machine.Word64Ror(), machine.WordRor());
310 EXPECT_EQ(machine.Word64Equal(), machine.WordEqual());
311 EXPECT_EQ(machine.Int64Add(), machine.IntAdd());
312 EXPECT_EQ(machine.Int64Sub(), machine.IntSub());
313 EXPECT_EQ(machine.Int64Mul(), machine.IntMul());
314 EXPECT_EQ(machine.Int64Div(), machine.IntDiv());
315 EXPECT_EQ(machine.Uint64Div(), machine.UintDiv());
316 EXPECT_EQ(machine.Int64Mod(), machine.IntMod());
317 EXPECT_EQ(machine.Uint64Mod(), machine.UintMod());
318 EXPECT_EQ(machine.Int64LessThan(), machine.IntLessThan());
319 EXPECT_EQ(machine.Int64LessThanOrEqual(), machine.IntLessThanOrEqual());
320}
321
322} // namespace compiler
323} // namespace internal
324} // namespace v8