Line data Source code
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 : #include "src/compiler/opcodes.h"
7 : #include "src/compiler/operator-properties.h"
8 : #include "src/compiler/operator.h"
9 : #include "src/compiler/types.h"
10 : #include "test/unittests/test-utils.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace compiler {
15 : namespace simplified_operator_unittest {
16 :
17 : // -----------------------------------------------------------------------------
18 :
19 : // Pure operators.
20 :
21 : struct PureOperator {
22 : const Operator* (SimplifiedOperatorBuilder::*constructor)();
23 : IrOpcode::Value opcode;
24 : Operator::Properties properties;
25 : int value_input_count;
26 : };
27 :
28 :
29 376588 : std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
30 376588 : return os << IrOpcode::Mnemonic(pop.opcode);
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(NumberBitwiseOr, Operator::kCommutative, 2),
49 : PURE(NumberBitwiseXor, Operator::kCommutative, 2),
50 : PURE(NumberBitwiseAnd, Operator::kCommutative, 2),
51 : PURE(NumberShiftLeft, Operator::kNoProperties, 2),
52 : PURE(NumberShiftRight, Operator::kNoProperties, 2),
53 : PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
54 : PURE(NumberToInt32, Operator::kNoProperties, 1),
55 : PURE(NumberToUint32, Operator::kNoProperties, 1),
56 : PURE(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1),
57 : PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
58 : PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
59 : PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
60 : PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
61 : PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
62 : PURE(ChangeTaggedToBit, Operator::kNoProperties, 1),
63 : PURE(ChangeBitToTagged, Operator::kNoProperties, 1),
64 : PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1),
65 : PURE(TruncateTaggedToFloat64, Operator::kNoProperties, 1),
66 : PURE(TruncateTaggedToBit, Operator::kNoProperties, 1),
67 : PURE(ObjectIsNumber, Operator::kNoProperties, 1),
68 : PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
69 : PURE(ObjectIsSmi, Operator::kNoProperties, 1),
70 : #undef PURE
71 3037 : };
72 :
73 :
74 496 : class SimplifiedPureOperatorTest
75 : : public TestWithZone,
76 : public ::testing::WithParamInterface<PureOperator> {};
77 :
78 :
79 18346 : TEST_P(SimplifiedPureOperatorTest, InstancesAreGloballyShared) {
80 31 : const PureOperator& pop = GetParam();
81 31 : SimplifiedOperatorBuilder simplified1(zone());
82 31 : SimplifiedOperatorBuilder simplified2(zone());
83 62 : EXPECT_EQ((simplified1.*pop.constructor)(), (simplified2.*pop.constructor)());
84 31 : }
85 :
86 :
87 18346 : TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
88 31 : SimplifiedOperatorBuilder simplified(zone());
89 31 : const PureOperator& pop = GetParam();
90 186 : const Operator* op = (simplified.*pop.constructor)();
91 :
92 62 : EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
93 62 : EXPECT_EQ(0, op->EffectInputCount());
94 62 : EXPECT_EQ(0, op->ControlInputCount());
95 62 : EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
96 :
97 62 : EXPECT_EQ(1, op->ValueOutputCount());
98 62 : EXPECT_EQ(0, op->EffectOutputCount());
99 62 : EXPECT_EQ(0, op->ControlOutputCount());
100 31 : }
101 :
102 :
103 18346 : TEST_P(SimplifiedPureOperatorTest, OpcodeIsCorrect) {
104 31 : SimplifiedOperatorBuilder simplified(zone());
105 31 : const PureOperator& pop = GetParam();
106 31 : const Operator* op = (simplified.*pop.constructor)();
107 62 : EXPECT_EQ(pop.opcode, op->opcode());
108 31 : }
109 :
110 :
111 18346 : TEST_P(SimplifiedPureOperatorTest, Properties) {
112 31 : SimplifiedOperatorBuilder simplified(zone());
113 31 : const PureOperator& pop = GetParam();
114 31 : const Operator* op = (simplified.*pop.constructor)();
115 62 : EXPECT_EQ(pop.properties, op->properties() & pop.properties);
116 31 : }
117 :
118 416069 : INSTANTIATE_TEST_SUITE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
119 : ::testing::ValuesIn(kPureOperators));
120 :
121 : // -----------------------------------------------------------------------------
122 :
123 : // Element access operators.
124 :
125 : const ElementAccess kElementAccesses[] = {
126 : {kTaggedBase, FixedArray::kHeaderSize, Type::Any(),
127 : MachineType::AnyTagged(), kFullWriteBarrier},
128 : {kUntaggedBase, 0, Type::Any(), MachineType::Int8(), kNoWriteBarrier},
129 : {kUntaggedBase, 0, Type::Any(), MachineType::Int16(), kNoWriteBarrier},
130 : {kUntaggedBase, 0, Type::Any(), MachineType::Int32(), kNoWriteBarrier},
131 : {kUntaggedBase, 0, Type::Any(), MachineType::Uint8(), kNoWriteBarrier},
132 : {kUntaggedBase, 0, Type::Any(), MachineType::Uint16(), kNoWriteBarrier},
133 : {kUntaggedBase, 0, Type::Any(), MachineType::Uint32(), kNoWriteBarrier},
134 : {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8(), kNoWriteBarrier},
135 : {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8(),
136 : kNoWriteBarrier},
137 : {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16(), kNoWriteBarrier},
138 : {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16(),
139 : kNoWriteBarrier},
140 : {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32(), kNoWriteBarrier},
141 : {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32(),
142 : kNoWriteBarrier},
143 : {kUntaggedBase, 0, Type::Number(),
144 : MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
145 : kNoWriteBarrier},
146 : {kUntaggedBase, 0, Type::Number(),
147 : MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone),
148 : kNoWriteBarrier},
149 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
150 : MachineType::Int8(), kNoWriteBarrier},
151 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
152 : MachineType::Uint8(), kNoWriteBarrier},
153 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
154 : MachineType::Int16(), kNoWriteBarrier},
155 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
156 : MachineType::Uint16(), kNoWriteBarrier},
157 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
158 : MachineType::Int32(), kNoWriteBarrier},
159 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
160 : MachineType::Uint32(), kNoWriteBarrier},
161 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
162 : MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
163 : kNoWriteBarrier},
164 : {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
165 : MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
166 : kNoWriteBarrier}};
167 :
168 :
169 184 : class SimplifiedElementAccessOperatorTest
170 : : public TestWithZone,
171 : public ::testing::WithParamInterface<ElementAccess> {};
172 :
173 :
174 18314 : TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
175 23 : SimplifiedOperatorBuilder simplified(zone());
176 23 : const ElementAccess& access = GetParam();
177 161 : const Operator* op = simplified.LoadElement(access);
178 :
179 46 : EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
180 46 : EXPECT_EQ(Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
181 0 : op->properties());
182 46 : EXPECT_EQ(access, ElementAccessOf(op));
183 :
184 46 : EXPECT_EQ(2, op->ValueInputCount());
185 46 : EXPECT_EQ(1, op->EffectInputCount());
186 46 : EXPECT_EQ(1, op->ControlInputCount());
187 46 : EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
188 :
189 46 : EXPECT_EQ(1, op->ValueOutputCount());
190 46 : EXPECT_EQ(1, op->EffectOutputCount());
191 46 : EXPECT_EQ(0, op->ControlOutputCount());
192 23 : }
193 :
194 :
195 18314 : TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
196 23 : SimplifiedOperatorBuilder simplified(zone());
197 23 : const ElementAccess& access = GetParam();
198 161 : const Operator* op = simplified.StoreElement(access);
199 :
200 46 : EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
201 46 : EXPECT_EQ(Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,
202 0 : op->properties());
203 46 : EXPECT_EQ(access, ElementAccessOf(op));
204 :
205 46 : EXPECT_EQ(3, op->ValueInputCount());
206 46 : EXPECT_EQ(1, op->EffectInputCount());
207 46 : EXPECT_EQ(1, op->ControlInputCount());
208 46 : EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
209 :
210 46 : EXPECT_EQ(0, op->ValueOutputCount());
211 46 : EXPECT_EQ(1, op->EffectOutputCount());
212 46 : EXPECT_EQ(0, op->ControlOutputCount());
213 23 : }
214 :
215 167035 : INSTANTIATE_TEST_SUITE_P(SimplifiedOperatorTest,
216 : SimplifiedElementAccessOperatorTest,
217 : ::testing::ValuesIn(kElementAccesses));
218 :
219 : } // namespace simplified_operator_unittest
220 : } // namespace compiler
221 : } // namespace internal
222 9111 : } // namespace v8
|