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