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