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.
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"
18 class MachineOperatorTestWithParam
19 : public TestWithZone,
20 public ::testing::WithParamInterface< ::testing::tuple<MachineType, T> > {
22 MachineType type() const { return ::testing::get<0>(B::GetParam()); }
23 const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
26 typedef ::testing::WithParamInterface< ::testing::tuple<MachineType, T> > B;
32 const MachineType kMachineReps[] = {kRepWord32, kRepWord64};
35 const 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};
44 // -----------------------------------------------------------------------------
48 typedef MachineOperatorTestWithParam<LoadRepresentation>
49 MachineLoadOperatorTest;
52 TEST_P(MachineLoadOperatorTest, InstancesAreGloballyShared) {
53 MachineOperatorBuilder machine1(zone(), type());
54 MachineOperatorBuilder machine2(zone(), type());
55 EXPECT_EQ(machine1.Load(GetParam()), machine2.Load(GetParam()));
59 TEST_P(MachineLoadOperatorTest, NumberOfInputsAndOutputs) {
60 MachineOperatorBuilder machine(zone(), type());
61 const Operator* op = machine.Load(GetParam());
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));
68 EXPECT_EQ(1, op->ValueOutputCount());
69 EXPECT_EQ(1, op->EffectOutputCount());
70 EXPECT_EQ(0, op->ControlOutputCount());
74 TEST_P(MachineLoadOperatorTest, OpcodeIsCorrect) {
75 MachineOperatorBuilder machine(zone(), type());
76 EXPECT_EQ(IrOpcode::kLoad, machine.Load(GetParam())->opcode());
80 TEST_P(MachineLoadOperatorTest, ParameterIsCorrect) {
81 MachineOperatorBuilder machine(zone(), type());
83 OpParameter<LoadRepresentation>(machine.Load(GetParam())));
87 INSTANTIATE_TEST_CASE_P(MachineOperatorTest, MachineLoadOperatorTest,
88 ::testing::Combine(::testing::ValuesIn(kMachineReps),
89 ::testing::ValuesIn(kMachineTypes)));
92 // -----------------------------------------------------------------------------
96 class MachineStoreOperatorTest
97 : public MachineOperatorTestWithParam<
98 ::testing::tuple<MachineType, WriteBarrierKind> > {
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()));
110 TEST_P(MachineStoreOperatorTest, InstancesAreGloballyShared) {
111 MachineOperatorBuilder machine1(zone(), type());
112 MachineOperatorBuilder machine2(zone(), type());
113 EXPECT_EQ(machine1.Store(GetParam()), machine2.Store(GetParam()));
117 TEST_P(MachineStoreOperatorTest, NumberOfInputsAndOutputs) {
118 MachineOperatorBuilder machine(zone(), type());
119 const Operator* op = machine.Store(GetParam());
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));
126 EXPECT_EQ(0, op->ValueOutputCount());
127 EXPECT_EQ(1, op->EffectOutputCount());
128 EXPECT_EQ(0, op->ControlOutputCount());
132 TEST_P(MachineStoreOperatorTest, OpcodeIsCorrect) {
133 MachineOperatorBuilder machine(zone(), type());
134 EXPECT_EQ(IrOpcode::kStore, machine.Store(GetParam())->opcode());
138 TEST_P(MachineStoreOperatorTest, ParameterIsCorrect) {
139 MachineOperatorBuilder machine(zone(), type());
140 EXPECT_EQ(GetParam(),
141 OpParameter<StoreRepresentation>(machine.Store(GetParam())));
145 INSTANTIATE_TEST_CASE_P(
146 MachineOperatorTest, MachineStoreOperatorTest,
148 ::testing::ValuesIn(kMachineReps),
149 ::testing::Combine(::testing::ValuesIn(kMachineTypes),
150 ::testing::Values(kNoWriteBarrier,
151 kFullWriteBarrier))));
154 // -----------------------------------------------------------------------------
160 struct 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;
169 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
170 return os << IrOpcode::Mnemonic(pop.opcode);
174 const PureOperator kPureOperators[] = {
175 #define PURE(Name, value_input_count, control_input_count, value_output_count) \
177 &MachineOperatorBuilder::Name, IrOpcode::k##Name, value_input_count, \
178 control_input_count, value_output_count \
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(Word32Clz, 1, 0, 1),
184 PURE(Word64And, 2, 0, 1), PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1),
185 PURE(Word64Shl, 2, 0, 1), PURE(Word64Shr, 2, 0, 1),
186 PURE(Word64Sar, 2, 0, 1), PURE(Word64Ror, 2, 0, 1),
187 PURE(Word64Equal, 2, 0, 1), PURE(Int32Add, 2, 0, 1),
188 PURE(Int32AddWithOverflow, 2, 0, 2), PURE(Int32Sub, 2, 0, 1),
189 PURE(Int32SubWithOverflow, 2, 0, 2), PURE(Int32Mul, 2, 0, 1),
190 PURE(Int32MulHigh, 2, 0, 1), PURE(Int32Div, 2, 1, 1),
191 PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1), PURE(Uint32Mod, 2, 1, 1),
192 PURE(Int32LessThan, 2, 0, 1), PURE(Int32LessThanOrEqual, 2, 0, 1),
193 PURE(Uint32LessThan, 2, 0, 1), PURE(Uint32LessThanOrEqual, 2, 0, 1),
194 PURE(Int64Add, 2, 0, 1), PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1),
195 PURE(Int64Div, 2, 0, 1), PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1),
196 PURE(Uint64Mod, 2, 0, 1), PURE(Int64LessThan, 2, 0, 1),
197 PURE(Int64LessThanOrEqual, 2, 0, 1), PURE(Uint64LessThan, 2, 0, 1),
198 PURE(ChangeFloat32ToFloat64, 1, 0, 1), PURE(ChangeFloat64ToInt32, 1, 0, 1),
199 PURE(ChangeFloat64ToUint32, 1, 0, 1), PURE(ChangeInt32ToInt64, 1, 0, 1),
200 PURE(ChangeUint32ToFloat64, 1, 0, 1), 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(Float64RoundDown, 1, 0, 1), PURE(Float64RoundTruncate, 1, 0, 1),
209 PURE(Float64RoundTiesAway, 1, 0, 1), PURE(Float64ExtractLowWord32, 1, 0, 1),
210 PURE(Float64ExtractHighWord32, 1, 0, 1),
211 PURE(Float64InsertLowWord32, 2, 0, 1),
212 PURE(Float64InsertHighWord32, 2, 0, 1), PURE(Float64Max, 2, 0, 1),
213 PURE(Float64Min, 2, 0, 1)
218 typedef MachineOperatorTestWithParam<PureOperator> MachinePureOperatorTest;
223 TEST_P(MachinePureOperatorTest, InstancesAreGloballyShared) {
224 const PureOperator& pop = GetParam();
225 MachineOperatorBuilder machine1(zone(), type());
226 MachineOperatorBuilder machine2(zone(), type());
227 EXPECT_EQ((machine1.*pop.constructor)(), (machine2.*pop.constructor)());
231 TEST_P(MachinePureOperatorTest, NumberOfInputsAndOutputs) {
232 MachineOperatorBuilder machine(zone(), type());
233 const PureOperator& pop = GetParam();
234 const Operator* op = (machine.*pop.constructor)();
236 EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
237 EXPECT_EQ(0, op->EffectInputCount());
238 EXPECT_EQ(pop.control_input_count, op->ControlInputCount());
239 EXPECT_EQ(pop.value_input_count + pop.control_input_count,
240 OperatorProperties::GetTotalInputCount(op));
242 EXPECT_EQ(pop.value_output_count, op->ValueOutputCount());
243 EXPECT_EQ(0, op->EffectOutputCount());
244 EXPECT_EQ(0, op->ControlOutputCount());
248 TEST_P(MachinePureOperatorTest, MarkedAsPure) {
249 MachineOperatorBuilder machine(zone(), type());
250 const PureOperator& pop = GetParam();
251 const Operator* op = (machine.*pop.constructor)();
252 EXPECT_TRUE(op->HasProperty(Operator::kPure));
256 TEST_P(MachinePureOperatorTest, OpcodeIsCorrect) {
257 MachineOperatorBuilder machine(zone(), type());
258 const PureOperator& pop = GetParam();
259 const Operator* op = (machine.*pop.constructor)();
260 EXPECT_EQ(pop.opcode, op->opcode());
264 INSTANTIATE_TEST_CASE_P(
265 MachineOperatorTest, MachinePureOperatorTest,
266 ::testing::Combine(::testing::ValuesIn(kMachineReps),
267 ::testing::ValuesIn(kPureOperators)));
269 #endif // GTEST_HAS_COMBINE
272 // -----------------------------------------------------------------------------
278 typedef TestWithZone MachineOperatorTest;
283 TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs32Bit) {
284 MachineOperatorBuilder machine(zone(), kRepWord32);
285 EXPECT_EQ(machine.Word32And(), machine.WordAnd());
286 EXPECT_EQ(machine.Word32Or(), machine.WordOr());
287 EXPECT_EQ(machine.Word32Xor(), machine.WordXor());
288 EXPECT_EQ(machine.Word32Shl(), machine.WordShl());
289 EXPECT_EQ(machine.Word32Shr(), machine.WordShr());
290 EXPECT_EQ(machine.Word32Sar(), machine.WordSar());
291 EXPECT_EQ(machine.Word32Ror(), machine.WordRor());
292 EXPECT_EQ(machine.Word32Equal(), machine.WordEqual());
293 EXPECT_EQ(machine.Int32Add(), machine.IntAdd());
294 EXPECT_EQ(machine.Int32Sub(), machine.IntSub());
295 EXPECT_EQ(machine.Int32Mul(), machine.IntMul());
296 EXPECT_EQ(machine.Int32Div(), machine.IntDiv());
297 EXPECT_EQ(machine.Uint32Div(), machine.UintDiv());
298 EXPECT_EQ(machine.Int32Mod(), machine.IntMod());
299 EXPECT_EQ(machine.Uint32Mod(), machine.UintMod());
300 EXPECT_EQ(machine.Int32LessThan(), machine.IntLessThan());
301 EXPECT_EQ(machine.Int32LessThanOrEqual(), machine.IntLessThanOrEqual());
305 TEST_F(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs64Bit) {
306 MachineOperatorBuilder machine(zone(), kRepWord64);
307 EXPECT_EQ(machine.Word64And(), machine.WordAnd());
308 EXPECT_EQ(machine.Word64Or(), machine.WordOr());
309 EXPECT_EQ(machine.Word64Xor(), machine.WordXor());
310 EXPECT_EQ(machine.Word64Shl(), machine.WordShl());
311 EXPECT_EQ(machine.Word64Shr(), machine.WordShr());
312 EXPECT_EQ(machine.Word64Sar(), machine.WordSar());
313 EXPECT_EQ(machine.Word64Ror(), machine.WordRor());
314 EXPECT_EQ(machine.Word64Equal(), machine.WordEqual());
315 EXPECT_EQ(machine.Int64Add(), machine.IntAdd());
316 EXPECT_EQ(machine.Int64Sub(), machine.IntSub());
317 EXPECT_EQ(machine.Int64Mul(), machine.IntMul());
318 EXPECT_EQ(machine.Int64Div(), machine.IntDiv());
319 EXPECT_EQ(machine.Uint64Div(), machine.UintDiv());
320 EXPECT_EQ(machine.Int64Mod(), machine.IntMod());
321 EXPECT_EQ(machine.Uint64Mod(), machine.UintMod());
322 EXPECT_EQ(machine.Int64LessThan(), machine.IntLessThan());
323 EXPECT_EQ(machine.Int64LessThanOrEqual(), machine.IntLessThanOrEqual());
326 } // namespace compiler
327 } // namespace internal