blob: bc537fd952ef0c1243f3733a74560efafd83ee66 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/compiler/opcodes.h"
6#include "src/compiler/operator.h"
7#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler/simplified-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "src/types-inl.h"
10#include "test/unittests/test-utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011
12namespace v8 {
13namespace internal {
14namespace compiler {
15
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016// -----------------------------------------------------------------------------
17// Pure operators.
18
19
20namespace {
21
22struct PureOperator {
23 const Operator* (SimplifiedOperatorBuilder::*constructor)();
24 IrOpcode::Value opcode;
25 Operator::Properties properties;
26 int value_input_count;
27};
28
29
30std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
31 return os << IrOpcode::Mnemonic(pop.opcode);
32}
33
34
35const PureOperator kPureOperators[] = {
36#define PURE(Name, properties, input_count) \
37 { \
38 &SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
39 Operator::kPure | properties, input_count \
40 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 PURE(AnyToBoolean, Operator::kNoProperties, 1),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 PURE(BooleanNot, Operator::kNoProperties, 1),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 PURE(BooleanToNumber, Operator::kNoProperties, 1),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 PURE(NumberEqual, Operator::kCommutative, 2),
45 PURE(NumberLessThan, Operator::kNoProperties, 2),
46 PURE(NumberLessThanOrEqual, Operator::kNoProperties, 2),
47 PURE(NumberAdd, Operator::kCommutative, 2),
48 PURE(NumberSubtract, Operator::kNoProperties, 2),
49 PURE(NumberMultiply, Operator::kCommutative, 2),
50 PURE(NumberDivide, Operator::kNoProperties, 2),
51 PURE(NumberModulus, Operator::kNoProperties, 2),
52 PURE(NumberToInt32, Operator::kNoProperties, 1),
53 PURE(NumberToUint32, Operator::kNoProperties, 1),
54 PURE(StringEqual, Operator::kCommutative, 2),
55 PURE(StringLessThan, Operator::kNoProperties, 2),
56 PURE(StringLessThanOrEqual, Operator::kNoProperties, 2),
57 PURE(StringAdd, Operator::kNoProperties, 2),
58 PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
59 PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
60 PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
61 PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
62 PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
63 PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
64 PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 PURE(ChangeBitToBool, Operator::kNoProperties, 1),
66 PURE(ObjectIsSmi, Operator::kNoProperties, 1),
67 PURE(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068#undef PURE
69};
70
71} // namespace
72
73
74class SimplifiedPureOperatorTest
75 : public TestWithZone,
76 public ::testing::WithParamInterface<PureOperator> {};
77
78
79TEST_P(SimplifiedPureOperatorTest, InstancesAreGloballyShared) {
80 const PureOperator& pop = GetParam();
81 SimplifiedOperatorBuilder simplified1(zone());
82 SimplifiedOperatorBuilder simplified2(zone());
83 EXPECT_EQ((simplified1.*pop.constructor)(), (simplified2.*pop.constructor)());
84}
85
86
87TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
88 SimplifiedOperatorBuilder simplified(zone());
89 const PureOperator& pop = GetParam();
90 const Operator* op = (simplified.*pop.constructor)();
91
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092 EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
93 EXPECT_EQ(0, op->EffectInputCount());
94 EXPECT_EQ(0, op->ControlInputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
96
Emily Bernierd0a1eb72015-03-24 16:35:39 -040097 EXPECT_EQ(1, op->ValueOutputCount());
98 EXPECT_EQ(0, op->EffectOutputCount());
99 EXPECT_EQ(0, op->ControlOutputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100}
101
102
103TEST_P(SimplifiedPureOperatorTest, OpcodeIsCorrect) {
104 SimplifiedOperatorBuilder simplified(zone());
105 const PureOperator& pop = GetParam();
106 const Operator* op = (simplified.*pop.constructor)();
107 EXPECT_EQ(pop.opcode, op->opcode());
108}
109
110
111TEST_P(SimplifiedPureOperatorTest, Properties) {
112 SimplifiedOperatorBuilder simplified(zone());
113 const PureOperator& pop = GetParam();
114 const Operator* op = (simplified.*pop.constructor)();
115 EXPECT_EQ(pop.properties, op->properties() & pop.properties);
116}
117
118INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
119 ::testing::ValuesIn(kPureOperators));
120
121
122// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123// Buffer access operators.
124
125
126namespace {
127
128const ExternalArrayType kExternalArrayTypes[] = {
129 kExternalUint8Array, kExternalInt8Array, kExternalUint16Array,
130 kExternalInt16Array, kExternalUint32Array, kExternalInt32Array,
131 kExternalFloat32Array, kExternalFloat64Array};
132
133} // namespace
134
135
136class SimplifiedBufferAccessOperatorTest
137 : public TestWithZone,
138 public ::testing::WithParamInterface<ExternalArrayType> {};
139
140
141TEST_P(SimplifiedBufferAccessOperatorTest, InstancesAreGloballyShared) {
142 BufferAccess const access(GetParam());
143 SimplifiedOperatorBuilder simplified1(zone());
144 SimplifiedOperatorBuilder simplified2(zone());
145 EXPECT_EQ(simplified1.LoadBuffer(access), simplified2.LoadBuffer(access));
146 EXPECT_EQ(simplified1.StoreBuffer(access), simplified2.StoreBuffer(access));
147}
148
149
150TEST_P(SimplifiedBufferAccessOperatorTest, LoadBuffer) {
151 SimplifiedOperatorBuilder simplified(zone());
152 BufferAccess const access(GetParam());
153 const Operator* op = simplified.LoadBuffer(access);
154
155 EXPECT_EQ(IrOpcode::kLoadBuffer, op->opcode());
156 EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
157 EXPECT_EQ(access, BufferAccessOf(op));
158
159 EXPECT_EQ(3, op->ValueInputCount());
160 EXPECT_EQ(1, op->EffectInputCount());
161 EXPECT_EQ(1, op->ControlInputCount());
162 EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
163
164 EXPECT_EQ(1, op->ValueOutputCount());
165 EXPECT_EQ(1, op->EffectOutputCount());
166 EXPECT_EQ(0, op->ControlOutputCount());
167}
168
169
170TEST_P(SimplifiedBufferAccessOperatorTest, StoreBuffer) {
171 SimplifiedOperatorBuilder simplified(zone());
172 BufferAccess const access(GetParam());
173 const Operator* op = simplified.StoreBuffer(access);
174
175 EXPECT_EQ(IrOpcode::kStoreBuffer, op->opcode());
176 EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
177 EXPECT_EQ(access, BufferAccessOf(op));
178
179 EXPECT_EQ(4, op->ValueInputCount());
180 EXPECT_EQ(1, op->EffectInputCount());
181 EXPECT_EQ(1, op->ControlInputCount());
182 EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op));
183
184 EXPECT_EQ(0, op->ValueOutputCount());
185 EXPECT_EQ(1, op->EffectOutputCount());
186 EXPECT_EQ(0, op->ControlOutputCount());
187}
188
189
190INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
191 SimplifiedBufferAccessOperatorTest,
192 ::testing::ValuesIn(kExternalArrayTypes));
193
194
195// -----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196// Element access operators.
197
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400198
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199namespace {
200
201const ElementAccess kElementAccesses[] = {
202 {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400203 {kUntaggedBase, 0, Type::Any(), kMachInt8},
204 {kUntaggedBase, 0, Type::Any(), kMachInt16},
205 {kUntaggedBase, 0, Type::Any(), kMachInt32},
206 {kUntaggedBase, 0, Type::Any(), kMachUint8},
207 {kUntaggedBase, 0, Type::Any(), kMachUint16},
208 {kUntaggedBase, 0, Type::Any(), kMachUint32},
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 {kUntaggedBase, 0, Type::Signed32(), kMachInt8},
210 {kUntaggedBase, 0, Type::Unsigned32(), kMachUint8},
211 {kUntaggedBase, 0, Type::Signed32(), kMachInt16},
212 {kUntaggedBase, 0, Type::Unsigned32(), kMachUint16},
213 {kUntaggedBase, 0, Type::Signed32(), kMachInt32},
214 {kUntaggedBase, 0, Type::Unsigned32(), kMachUint32},
215 {kUntaggedBase, 0, Type::Number(), kRepFloat32},
216 {kUntaggedBase, 0, Type::Number(), kRepFloat64},
217 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
218 kMachInt8},
219 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
220 kMachUint8},
221 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
222 kMachInt16},
223 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
224 kMachUint16},
225 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
226 kMachInt32},
227 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
228 kMachUint32},
229 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
230 kRepFloat32},
231 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
232 kRepFloat64}};
233
234} // namespace
235
236
237class SimplifiedElementAccessOperatorTest
238 : public TestWithZone,
239 public ::testing::WithParamInterface<ElementAccess> {};
240
241
242TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
243 SimplifiedOperatorBuilder simplified(zone());
244 const ElementAccess& access = GetParam();
245 const Operator* op = simplified.LoadElement(access);
246
247 EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
248 EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
249 EXPECT_EQ(access, ElementAccessOf(op));
250
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400251 EXPECT_EQ(2, op->ValueInputCount());
252 EXPECT_EQ(1, op->EffectInputCount());
253 EXPECT_EQ(1, op->ControlInputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
255
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400256 EXPECT_EQ(1, op->ValueOutputCount());
257 EXPECT_EQ(1, op->EffectOutputCount());
258 EXPECT_EQ(0, op->ControlOutputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259}
260
261
262TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
263 SimplifiedOperatorBuilder simplified(zone());
264 const ElementAccess& access = GetParam();
265 const Operator* op = simplified.StoreElement(access);
266
267 EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
268 EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
269 EXPECT_EQ(access, ElementAccessOf(op));
270
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400271 EXPECT_EQ(3, op->ValueInputCount());
272 EXPECT_EQ(1, op->EffectInputCount());
273 EXPECT_EQ(1, op->ControlInputCount());
274 EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400276 EXPECT_EQ(0, op->ValueOutputCount());
277 EXPECT_EQ(1, op->EffectOutputCount());
278 EXPECT_EQ(0, op->ControlOutputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279}
280
281
282INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
283 SimplifiedElementAccessOperatorTest,
284 ::testing::ValuesIn(kElementAccesses));
285
286} // namespace compiler
287} // namespace internal
288} // namespace v8