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
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13 #if GTEST_HAS_COMBINE
14
15 // TODO(bmeurer): Find a new home for these.
operator <<(std::ostream & os,const MachineType & type)16 inline std::ostream& operator<<(std::ostream& os, const MachineType& type) {
17 OStringStream ost;
18 ost << type;
19 return os << ost.c_str();
20 }
operator <<(std::ostream & os,const WriteBarrierKind & write_barrier_kind)21 inline 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
29 template <typename T>
30 class MachineOperatorTestWithParam
31 : public ::testing::TestWithParam< ::testing::tuple<MachineType, T> > {
32 protected:
type() const33 MachineType type() const { return ::testing::get<0>(B::GetParam()); }
GetParam() const34 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
41 namespace {
42
43 const MachineType kMachineReps[] = {kRepWord32, kRepWord64};
44
45
46 const 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
59 typedef MachineOperatorTestWithParam<LoadRepresentation>
60 MachineLoadOperatorTest;
61
62
TEST_P(MachineLoadOperatorTest,InstancesAreGloballyShared)63 TEST_P(MachineLoadOperatorTest, InstancesAreGloballyShared) {
64 MachineOperatorBuilder machine1(type());
65 MachineOperatorBuilder machine2(type());
66 EXPECT_EQ(machine1.Load(GetParam()), machine2.Load(GetParam()));
67 }
68
69
TEST_P(MachineLoadOperatorTest,NumberOfInputsAndOutputs)70 TEST_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
TEST_P(MachineLoadOperatorTest,OpcodeIsCorrect)85 TEST_P(MachineLoadOperatorTest, OpcodeIsCorrect) {
86 MachineOperatorBuilder machine(type());
87 EXPECT_EQ(IrOpcode::kLoad, machine.Load(GetParam())->opcode());
88 }
89
90
TEST_P(MachineLoadOperatorTest,ParameterIsCorrect)91 TEST_P(MachineLoadOperatorTest, ParameterIsCorrect) {
92 MachineOperatorBuilder machine(type());
93 EXPECT_EQ(GetParam(),
94 OpParameter<LoadRepresentation>(machine.Load(GetParam())));
95 }
96
97
98 INSTANTIATE_TEST_CASE_P(MachineOperatorTest, MachineLoadOperatorTest,
99 ::testing::Combine(::testing::ValuesIn(kMachineReps),
100 ::testing::ValuesIn(kMachineTypes)));
101
102
103 // -----------------------------------------------------------------------------
104 // Store operator.
105
106
107 class MachineStoreOperatorTest
108 : public MachineOperatorTestWithParam<
109 ::testing::tuple<MachineType, WriteBarrierKind> > {
110 protected:
GetParam() const111 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
TEST_P(MachineStoreOperatorTest,InstancesAreGloballyShared)121 TEST_P(MachineStoreOperatorTest, InstancesAreGloballyShared) {
122 MachineOperatorBuilder machine1(type());
123 MachineOperatorBuilder machine2(type());
124 EXPECT_EQ(machine1.Store(GetParam()), machine2.Store(GetParam()));
125 }
126
127
TEST_P(MachineStoreOperatorTest,NumberOfInputsAndOutputs)128 TEST_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
TEST_P(MachineStoreOperatorTest,OpcodeIsCorrect)143 TEST_P(MachineStoreOperatorTest, OpcodeIsCorrect) {
144 MachineOperatorBuilder machine(type());
145 EXPECT_EQ(IrOpcode::kStore, machine.Store(GetParam())->opcode());
146 }
147
148
TEST_P(MachineStoreOperatorTest,ParameterIsCorrect)149 TEST_P(MachineStoreOperatorTest, ParameterIsCorrect) {
150 MachineOperatorBuilder machine(type());
151 EXPECT_EQ(GetParam(),
152 OpParameter<StoreRepresentation>(machine.Store(GetParam())));
153 }
154
155
156 INSTANTIATE_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
169 namespace {
170
171 struct PureOperator {
172 const Operator* (MachineOperatorBuilder::*constructor)();
173 IrOpcode::Value opcode;
174 int value_input_count;
175 int value_output_count;
176 };
177
178
operator <<(std::ostream & os,const PureOperator & pop)179 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
180 return os << IrOpcode::Mnemonic(pop.opcode);
181 }
182
183
184 const 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
222 typedef MachineOperatorTestWithParam<PureOperator> MachinePureOperatorTest;
223
224 } // namespace
225
226
TEST_P(MachinePureOperatorTest,InstancesAreGloballyShared)227 TEST_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
TEST_P(MachinePureOperatorTest,NumberOfInputsAndOutputs)235 TEST_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
TEST_P(MachinePureOperatorTest,MarkedAsPure)252 TEST_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
TEST_P(MachinePureOperatorTest,OpcodeIsCorrect)260 TEST_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
268 INSTANTIATE_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
TEST(MachineOperatorTest,PseudoOperatorsWhenWordSizeIs32Bit)280 TEST(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
TEST(MachineOperatorTest,PseudoOperatorsWhenWordSizeIs64Bit)302 TEST(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