• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/opcodes.h"
6 #include "src/compiler/operator.h"
7 #include "src/compiler/operator-properties.h"
8 #include "src/compiler/simplified-operator.h"
9 #include "src/types-inl.h"
10 #include "test/unittests/test-utils.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 // -----------------------------------------------------------------------------
17 // Pure operators.
18 
19 
20 namespace {
21 
22 struct PureOperator {
23   const Operator* (SimplifiedOperatorBuilder::*constructor)();
24   IrOpcode::Value opcode;
25   Operator::Properties properties;
26   int value_input_count;
27 };
28 
29 
operator <<(std::ostream & os,const PureOperator & pop)30 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
31   return os << IrOpcode::Mnemonic(pop.opcode);
32 }
33 
34 
35 const PureOperator kPureOperators[] = {
36 #define PURE(Name, properties, input_count)              \
37   {                                                      \
38     &SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
39         Operator::kPure | properties, input_count        \
40   }
41     PURE(BooleanNot, Operator::kNoProperties, 1),
42     PURE(BooleanToNumber, Operator::kNoProperties, 1),
43     PURE(NumberEqual, Operator::kCommutative, 2),
44     PURE(NumberLessThan, Operator::kNoProperties, 2),
45     PURE(NumberLessThanOrEqual, Operator::kNoProperties, 2),
46     PURE(NumberAdd, Operator::kCommutative, 2),
47     PURE(NumberSubtract, Operator::kNoProperties, 2),
48     PURE(NumberMultiply, Operator::kCommutative, 2),
49     PURE(NumberDivide, Operator::kNoProperties, 2),
50     PURE(NumberModulus, Operator::kNoProperties, 2),
51     PURE(NumberBitwiseOr, Operator::kCommutative, 2),
52     PURE(NumberBitwiseXor, Operator::kCommutative, 2),
53     PURE(NumberBitwiseAnd, Operator::kCommutative, 2),
54     PURE(NumberShiftLeft, Operator::kNoProperties, 2),
55     PURE(NumberShiftRight, Operator::kNoProperties, 2),
56     PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
57     PURE(NumberToInt32, Operator::kNoProperties, 1),
58     PURE(NumberToUint32, Operator::kNoProperties, 1),
59     PURE(PlainPrimitiveToNumber, Operator::kNoProperties, 1),
60     PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
61     PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
62     PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
63     PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
64     PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
65     PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
66     PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
67     PURE(ChangeBitToBool, Operator::kNoProperties, 1),
68     PURE(ObjectIsSmi, Operator::kNoProperties, 1)
69 #undef PURE
70 };
71 
72 }  // namespace
73 
74 
75 class SimplifiedPureOperatorTest
76     : public TestWithZone,
77       public ::testing::WithParamInterface<PureOperator> {};
78 
79 
TEST_P(SimplifiedPureOperatorTest,InstancesAreGloballyShared)80 TEST_P(SimplifiedPureOperatorTest, InstancesAreGloballyShared) {
81   const PureOperator& pop = GetParam();
82   SimplifiedOperatorBuilder simplified1(zone());
83   SimplifiedOperatorBuilder simplified2(zone());
84   EXPECT_EQ((simplified1.*pop.constructor)(), (simplified2.*pop.constructor)());
85 }
86 
87 
TEST_P(SimplifiedPureOperatorTest,NumberOfInputsAndOutputs)88 TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
89   SimplifiedOperatorBuilder simplified(zone());
90   const PureOperator& pop = GetParam();
91   const Operator* op = (simplified.*pop.constructor)();
92 
93   EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
94   EXPECT_EQ(0, op->EffectInputCount());
95   EXPECT_EQ(0, op->ControlInputCount());
96   EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
97 
98   EXPECT_EQ(1, op->ValueOutputCount());
99   EXPECT_EQ(0, op->EffectOutputCount());
100   EXPECT_EQ(0, op->ControlOutputCount());
101 }
102 
103 
TEST_P(SimplifiedPureOperatorTest,OpcodeIsCorrect)104 TEST_P(SimplifiedPureOperatorTest, OpcodeIsCorrect) {
105   SimplifiedOperatorBuilder simplified(zone());
106   const PureOperator& pop = GetParam();
107   const Operator* op = (simplified.*pop.constructor)();
108   EXPECT_EQ(pop.opcode, op->opcode());
109 }
110 
111 
TEST_P(SimplifiedPureOperatorTest,Properties)112 TEST_P(SimplifiedPureOperatorTest, Properties) {
113   SimplifiedOperatorBuilder simplified(zone());
114   const PureOperator& pop = GetParam();
115   const Operator* op = (simplified.*pop.constructor)();
116   EXPECT_EQ(pop.properties, op->properties() & pop.properties);
117 }
118 
119 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
120                         ::testing::ValuesIn(kPureOperators));
121 
122 
123 // -----------------------------------------------------------------------------
124 // Buffer access operators.
125 
126 
127 namespace {
128 
129 const ExternalArrayType kExternalArrayTypes[] = {
130     kExternalUint8Array,   kExternalInt8Array,   kExternalUint16Array,
131     kExternalInt16Array,   kExternalUint32Array, kExternalInt32Array,
132     kExternalFloat32Array, kExternalFloat64Array};
133 
134 }  // namespace
135 
136 
137 class SimplifiedBufferAccessOperatorTest
138     : public TestWithZone,
139       public ::testing::WithParamInterface<ExternalArrayType> {};
140 
141 
TEST_P(SimplifiedBufferAccessOperatorTest,InstancesAreGloballyShared)142 TEST_P(SimplifiedBufferAccessOperatorTest, InstancesAreGloballyShared) {
143   BufferAccess const access(GetParam());
144   SimplifiedOperatorBuilder simplified1(zone());
145   SimplifiedOperatorBuilder simplified2(zone());
146   EXPECT_EQ(simplified1.LoadBuffer(access), simplified2.LoadBuffer(access));
147   EXPECT_EQ(simplified1.StoreBuffer(access), simplified2.StoreBuffer(access));
148 }
149 
150 
TEST_P(SimplifiedBufferAccessOperatorTest,LoadBuffer)151 TEST_P(SimplifiedBufferAccessOperatorTest, LoadBuffer) {
152   SimplifiedOperatorBuilder simplified(zone());
153   BufferAccess const access(GetParam());
154   const Operator* op = simplified.LoadBuffer(access);
155 
156   EXPECT_EQ(IrOpcode::kLoadBuffer, op->opcode());
157   EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
158   EXPECT_EQ(access, BufferAccessOf(op));
159 
160   EXPECT_EQ(3, op->ValueInputCount());
161   EXPECT_EQ(1, op->EffectInputCount());
162   EXPECT_EQ(1, op->ControlInputCount());
163   EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
164 
165   EXPECT_EQ(1, op->ValueOutputCount());
166   EXPECT_EQ(1, op->EffectOutputCount());
167   EXPECT_EQ(0, op->ControlOutputCount());
168 }
169 
170 
TEST_P(SimplifiedBufferAccessOperatorTest,StoreBuffer)171 TEST_P(SimplifiedBufferAccessOperatorTest, StoreBuffer) {
172   SimplifiedOperatorBuilder simplified(zone());
173   BufferAccess const access(GetParam());
174   const Operator* op = simplified.StoreBuffer(access);
175 
176   EXPECT_EQ(IrOpcode::kStoreBuffer, op->opcode());
177   EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
178   EXPECT_EQ(access, BufferAccessOf(op));
179 
180   EXPECT_EQ(4, op->ValueInputCount());
181   EXPECT_EQ(1, op->EffectInputCount());
182   EXPECT_EQ(1, op->ControlInputCount());
183   EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op));
184 
185   EXPECT_EQ(0, op->ValueOutputCount());
186   EXPECT_EQ(1, op->EffectOutputCount());
187   EXPECT_EQ(0, op->ControlOutputCount());
188 }
189 
190 
191 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
192                         SimplifiedBufferAccessOperatorTest,
193                         ::testing::ValuesIn(kExternalArrayTypes));
194 
195 
196 // -----------------------------------------------------------------------------
197 // Element access operators.
198 
199 
200 namespace {
201 
202 const ElementAccess kElementAccesses[] = {
203     {kTaggedBase, FixedArray::kHeaderSize, Type::Any(),
204      MachineType::AnyTagged()},
205     {kUntaggedBase, 0, Type::Any(), MachineType::Int8()},
206     {kUntaggedBase, 0, Type::Any(), MachineType::Int16()},
207     {kUntaggedBase, 0, Type::Any(), MachineType::Int32()},
208     {kUntaggedBase, 0, Type::Any(), MachineType::Uint8()},
209     {kUntaggedBase, 0, Type::Any(), MachineType::Uint16()},
210     {kUntaggedBase, 0, Type::Any(), MachineType::Uint32()},
211     {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8()},
212     {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8()},
213     {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16()},
214     {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16()},
215     {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32()},
216     {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32()},
217     {kUntaggedBase, 0, Type::Number(),
218      MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
219     {kUntaggedBase, 0, Type::Number(),
220      MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone)},
221     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
222      MachineType::Int8()},
223     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
224      MachineType::Uint8()},
225     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
226      MachineType::Int16()},
227     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
228      MachineType::Uint16()},
229     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
230      MachineType::Int32()},
231     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
232      MachineType::Uint32()},
233     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
234      MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
235     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
236      MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)}};
237 
238 }  // namespace
239 
240 
241 class SimplifiedElementAccessOperatorTest
242     : public TestWithZone,
243       public ::testing::WithParamInterface<ElementAccess> {};
244 
245 
TEST_P(SimplifiedElementAccessOperatorTest,LoadElement)246 TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
247   SimplifiedOperatorBuilder simplified(zone());
248   const ElementAccess& access = GetParam();
249   const Operator* op = simplified.LoadElement(access);
250 
251   EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
252   EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
253   EXPECT_EQ(access, ElementAccessOf(op));
254 
255   EXPECT_EQ(2, op->ValueInputCount());
256   EXPECT_EQ(1, op->EffectInputCount());
257   EXPECT_EQ(1, op->ControlInputCount());
258   EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
259 
260   EXPECT_EQ(1, op->ValueOutputCount());
261   EXPECT_EQ(1, op->EffectOutputCount());
262   EXPECT_EQ(0, op->ControlOutputCount());
263 }
264 
265 
TEST_P(SimplifiedElementAccessOperatorTest,StoreElement)266 TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
267   SimplifiedOperatorBuilder simplified(zone());
268   const ElementAccess& access = GetParam();
269   const Operator* op = simplified.StoreElement(access);
270 
271   EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
272   EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
273   EXPECT_EQ(access, ElementAccessOf(op));
274 
275   EXPECT_EQ(3, op->ValueInputCount());
276   EXPECT_EQ(1, op->EffectInputCount());
277   EXPECT_EQ(1, op->ControlInputCount());
278   EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
279 
280   EXPECT_EQ(0, op->ValueOutputCount());
281   EXPECT_EQ(1, op->EffectOutputCount());
282   EXPECT_EQ(0, op->ControlOutputCount());
283 }
284 
285 
286 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
287                         SimplifiedElementAccessOperatorTest,
288                         ::testing::ValuesIn(kElementAccesses));
289 
290 }  // namespace compiler
291 }  // namespace internal
292 }  // namespace v8
293