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/simplified-operator.h"
6
7 #include "src/compiler/operator-properties-inl.h"
8 #include "src/test/test-utils.h"
9
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13
14 // TODO(bmeurer): Drop once we use std::ostream instead of our OStream.
operator <<(std::ostream & os,const ElementAccess & access)15 inline std::ostream& operator<<(std::ostream& os, const ElementAccess& access) {
16 OStringStream ost;
17 ost << access;
18 return os << ost.c_str();
19 }
20
21
22 // -----------------------------------------------------------------------------
23 // Pure operators.
24
25
26 namespace {
27
28 struct PureOperator {
29 const Operator* (SimplifiedOperatorBuilder::*constructor)();
30 IrOpcode::Value opcode;
31 Operator::Properties properties;
32 int value_input_count;
33 };
34
35
operator <<(std::ostream & os,const PureOperator & pop)36 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
37 return os << IrOpcode::Mnemonic(pop.opcode);
38 }
39
40
41 const PureOperator kPureOperators[] = {
42 #define PURE(Name, properties, input_count) \
43 { \
44 &SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
45 Operator::kPure | properties, input_count \
46 }
47 PURE(BooleanNot, Operator::kNoProperties, 1),
48 PURE(NumberEqual, Operator::kCommutative, 2),
49 PURE(NumberLessThan, Operator::kNoProperties, 2),
50 PURE(NumberLessThanOrEqual, Operator::kNoProperties, 2),
51 PURE(NumberAdd, Operator::kCommutative, 2),
52 PURE(NumberSubtract, Operator::kNoProperties, 2),
53 PURE(NumberMultiply, Operator::kCommutative, 2),
54 PURE(NumberDivide, Operator::kNoProperties, 2),
55 PURE(NumberModulus, Operator::kNoProperties, 2),
56 PURE(NumberToInt32, Operator::kNoProperties, 1),
57 PURE(NumberToUint32, Operator::kNoProperties, 1),
58 PURE(StringEqual, Operator::kCommutative, 2),
59 PURE(StringLessThan, Operator::kNoProperties, 2),
60 PURE(StringLessThanOrEqual, Operator::kNoProperties, 2),
61 PURE(StringAdd, Operator::kNoProperties, 2),
62 PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
63 PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
64 PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
65 PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
66 PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
67 PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
68 PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
69 PURE(ChangeBitToBool, Operator::kNoProperties, 1)
70 #undef PURE
71 };
72
73 } // namespace
74
75
76 class SimplifiedPureOperatorTest
77 : public TestWithZone,
78 public ::testing::WithParamInterface<PureOperator> {};
79
80
TEST_P(SimplifiedPureOperatorTest,InstancesAreGloballyShared)81 TEST_P(SimplifiedPureOperatorTest, InstancesAreGloballyShared) {
82 const PureOperator& pop = GetParam();
83 SimplifiedOperatorBuilder simplified1(zone());
84 SimplifiedOperatorBuilder simplified2(zone());
85 EXPECT_EQ((simplified1.*pop.constructor)(), (simplified2.*pop.constructor)());
86 }
87
88
TEST_P(SimplifiedPureOperatorTest,NumberOfInputsAndOutputs)89 TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
90 SimplifiedOperatorBuilder simplified(zone());
91 const PureOperator& pop = GetParam();
92 const Operator* op = (simplified.*pop.constructor)();
93
94 EXPECT_EQ(pop.value_input_count, OperatorProperties::GetValueInputCount(op));
95 EXPECT_EQ(0, OperatorProperties::GetEffectInputCount(op));
96 EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op));
97 EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
98
99 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
100 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
101 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
102 }
103
104
TEST_P(SimplifiedPureOperatorTest,OpcodeIsCorrect)105 TEST_P(SimplifiedPureOperatorTest, OpcodeIsCorrect) {
106 SimplifiedOperatorBuilder simplified(zone());
107 const PureOperator& pop = GetParam();
108 const Operator* op = (simplified.*pop.constructor)();
109 EXPECT_EQ(pop.opcode, op->opcode());
110 }
111
112
TEST_P(SimplifiedPureOperatorTest,Properties)113 TEST_P(SimplifiedPureOperatorTest, Properties) {
114 SimplifiedOperatorBuilder simplified(zone());
115 const PureOperator& pop = GetParam();
116 const Operator* op = (simplified.*pop.constructor)();
117 EXPECT_EQ(pop.properties, op->properties() & pop.properties);
118 }
119
120 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
121 ::testing::ValuesIn(kPureOperators));
122
123
124 // -----------------------------------------------------------------------------
125 // Element access operators.
126
127 namespace {
128
129 const ElementAccess kElementAccesses[] = {
130 {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged},
131 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
132 kMachInt8},
133 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
134 kMachInt16},
135 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
136 kMachInt32},
137 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
138 kMachUint8},
139 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
140 kMachUint16},
141 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
142 kMachUint32},
143 {kUntaggedBase, 0, Type::Signed32(), kMachInt8},
144 {kUntaggedBase, 0, Type::Unsigned32(), kMachUint8},
145 {kUntaggedBase, 0, Type::Signed32(), kMachInt16},
146 {kUntaggedBase, 0, Type::Unsigned32(), kMachUint16},
147 {kUntaggedBase, 0, Type::Signed32(), kMachInt32},
148 {kUntaggedBase, 0, Type::Unsigned32(), kMachUint32},
149 {kUntaggedBase, 0, Type::Number(), kRepFloat32},
150 {kUntaggedBase, 0, Type::Number(), kRepFloat64},
151 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
152 kMachInt8},
153 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
154 kMachUint8},
155 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
156 kMachInt16},
157 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
158 kMachUint16},
159 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
160 kMachInt32},
161 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
162 kMachUint32},
163 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
164 kRepFloat32},
165 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
166 kRepFloat64}};
167
168 } // namespace
169
170
171 class SimplifiedElementAccessOperatorTest
172 : public TestWithZone,
173 public ::testing::WithParamInterface<ElementAccess> {};
174
175
TEST_P(SimplifiedElementAccessOperatorTest,LoadElement)176 TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
177 SimplifiedOperatorBuilder simplified(zone());
178 const ElementAccess& access = GetParam();
179 const Operator* op = simplified.LoadElement(access);
180
181 EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
182 EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
183 EXPECT_EQ(access, ElementAccessOf(op));
184
185 EXPECT_EQ(3, OperatorProperties::GetValueInputCount(op));
186 EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op));
187 EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op));
188 EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
189
190 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
191 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
192 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
193 }
194
195
TEST_P(SimplifiedElementAccessOperatorTest,StoreElement)196 TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
197 SimplifiedOperatorBuilder simplified(zone());
198 const ElementAccess& access = GetParam();
199 const Operator* op = simplified.StoreElement(access);
200
201 EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
202 EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
203 EXPECT_EQ(access, ElementAccessOf(op));
204
205 EXPECT_EQ(4, OperatorProperties::GetValueInputCount(op));
206 EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op));
207 EXPECT_EQ(1, OperatorProperties::GetControlInputCount(op));
208 EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op));
209
210 EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
211 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
212 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
213 }
214
215
216 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
217 SimplifiedElementAccessOperatorTest,
218 ::testing::ValuesIn(kElementAccesses));
219
220 } // namespace compiler
221 } // namespace internal
222 } // namespace v8
223