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
10namespace v8 {
11namespace internal {
12namespace compiler {
13
14// TODO(bmeurer): Drop once we use std::ostream instead of our OStream.
15inline 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
26namespace {
27
28struct PureOperator {
29  const Operator* (SimplifiedOperatorBuilder::*constructor)();
30  IrOpcode::Value opcode;
31  Operator::Properties properties;
32  int value_input_count;
33};
34
35
36std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
37  return os << IrOpcode::Mnemonic(pop.opcode);
38}
39
40
41const 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
76class SimplifiedPureOperatorTest
77    : public TestWithZone,
78      public ::testing::WithParamInterface<PureOperator> {};
79
80
81TEST_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
89TEST_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
105TEST_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
113TEST_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
120INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
121                        ::testing::ValuesIn(kPureOperators));
122
123
124// -----------------------------------------------------------------------------
125// Element access operators.
126
127namespace {
128
129const 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
171class SimplifiedElementAccessOperatorTest
172    : public TestWithZone,
173      public ::testing::WithParamInterface<ElementAccess> {};
174
175
176TEST_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
196TEST_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
216INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
217                        SimplifiedElementAccessOperatorTest,
218                        ::testing::ValuesIn(kElementAccesses));
219
220}  // namespace compiler
221}  // namespace internal
222}  // namespace v8
223