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.
5 #include "src/compiler/simplified-operator.h"
7 #include "src/compiler/operator-properties-inl.h"
8 #include "src/test/test-utils.h"
14 // TODO(bmeurer): Drop once we use std::ostream instead of our OStream.
15 inline std::ostream& operator<<(std::ostream& os, const ElementAccess& access) {
18 return os << ost.c_str();
22 // -----------------------------------------------------------------------------
29 const Operator* (SimplifiedOperatorBuilder::*constructor)();
30 IrOpcode::Value opcode;
31 Operator::Properties properties;
32 int value_input_count;
36 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
37 return os << IrOpcode::Mnemonic(pop.opcode);
41 const PureOperator kPureOperators[] = {
42 #define PURE(Name, properties, input_count) \
44 &SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
45 Operator::kPure | properties, input_count \
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)
76 class SimplifiedPureOperatorTest
77 : public TestWithZone,
78 public ::testing::WithParamInterface<PureOperator> {};
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)());
89 TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
90 SimplifiedOperatorBuilder simplified(zone());
91 const PureOperator& pop = GetParam();
92 const Operator* op = (simplified.*pop.constructor)();
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));
99 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
100 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
101 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
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());
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);
120 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
121 ::testing::ValuesIn(kPureOperators));
124 // -----------------------------------------------------------------------------
125 // Element access operators.
129 const ElementAccess kElementAccesses[] = {
130 {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged},
131 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
133 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
135 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
137 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
139 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
141 {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
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(),
153 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
155 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
157 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
159 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
161 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
163 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
165 {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
171 class SimplifiedElementAccessOperatorTest
172 : public TestWithZone,
173 public ::testing::WithParamInterface<ElementAccess> {};
176 TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
177 SimplifiedOperatorBuilder simplified(zone());
178 const ElementAccess& access = GetParam();
179 const Operator* op = simplified.LoadElement(access);
181 EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
182 EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
183 EXPECT_EQ(access, ElementAccessOf(op));
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));
190 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
191 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
192 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
196 TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
197 SimplifiedOperatorBuilder simplified(zone());
198 const ElementAccess& access = GetParam();
199 const Operator* op = simplified.StoreElement(access);
201 EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
202 EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
203 EXPECT_EQ(access, ElementAccessOf(op));
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));
210 EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
211 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
212 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
216 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
217 SimplifiedElementAccessOperatorTest,
218 ::testing::ValuesIn(kElementAccesses));
220 } // namespace compiler
221 } // namespace internal