blob: d0ac14519fc43ea3865012a2464c84547af73748 [file] [log] [blame]
Emily Bernier958fae72015-03-24 16:35:39 -04001// 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 <limits>
6
7#include "src/compiler/common-operator.h"
8#include "src/compiler/opcodes.h"
9#include "src/compiler/operator.h"
10#include "src/compiler/operator-properties.h"
11#include "test/unittests/test-utils.h"
12
13namespace v8 {
14namespace internal {
15namespace compiler {
16
17
18// -----------------------------------------------------------------------------
19// Shared operators.
20
21
22namespace {
23
24struct SharedOperator {
25 const Operator* (CommonOperatorBuilder::*constructor)();
26 IrOpcode::Value opcode;
27 Operator::Properties properties;
28 int value_input_count;
29 int effect_input_count;
30 int control_input_count;
31 int effect_output_count;
32 int control_output_count;
33};
34
35
36std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
37 return os << IrOpcode::Mnemonic(fop.opcode);
38}
39
40
41const SharedOperator kSharedOperators[] = {
42#define SHARED(Name, properties, value_input_count, effect_input_count, \
43 control_input_count, effect_output_count, control_output_count) \
44 { \
45 &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties, \
46 value_input_count, effect_input_count, control_input_count, \
47 effect_output_count, control_output_count \
48 }
49 SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 1),
50 SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0),
51 SHARED(IfTrue, Operator::kFoldable, 0, 0, 1, 0, 1),
52 SHARED(IfFalse, Operator::kFoldable, 0, 0, 1, 0, 1),
53 SHARED(Throw, Operator::kFoldable, 1, 1, 1, 0, 1),
54 SHARED(Return, Operator::kNoProperties, 1, 1, 1, 0, 1)
55#undef SHARED
56};
57
58
59class CommonSharedOperatorTest
60 : public TestWithZone,
61 public ::testing::WithParamInterface<SharedOperator> {};
62
63} // namespace
64
65
66TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
67 const SharedOperator& sop = GetParam();
68 CommonOperatorBuilder common1(zone());
69 CommonOperatorBuilder common2(zone());
70 EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
71}
72
73
74TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
75 CommonOperatorBuilder common(zone());
76 const SharedOperator& sop = GetParam();
77 const Operator* op = (common.*sop.constructor)();
78
79 EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
80 EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
81 EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
82 EXPECT_EQ(
83 sop.value_input_count + sop.effect_input_count + sop.control_input_count,
84 OperatorProperties::GetTotalInputCount(op));
85
86 EXPECT_EQ(0, op->ValueOutputCount());
87 EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
88 EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
89}
90
91
92TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
93 CommonOperatorBuilder common(zone());
94 const SharedOperator& sop = GetParam();
95 const Operator* op = (common.*sop.constructor)();
96 EXPECT_EQ(sop.opcode, op->opcode());
97}
98
99
100TEST_P(CommonSharedOperatorTest, Properties) {
101 CommonOperatorBuilder common(zone());
102 const SharedOperator& sop = GetParam();
103 const Operator* op = (common.*sop.constructor)();
104 EXPECT_EQ(sop.properties, op->properties());
105}
106
107
108INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
109 ::testing::ValuesIn(kSharedOperators));
110
111
112// -----------------------------------------------------------------------------
113// Other operators.
114
115
116namespace {
117
118class CommonOperatorTest : public TestWithZone {
119 public:
120 CommonOperatorTest() : common_(zone()) {}
121 ~CommonOperatorTest() OVERRIDE {}
122
123 CommonOperatorBuilder* common() { return &common_; }
124
125 private:
126 CommonOperatorBuilder common_;
127};
128
129
130const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
131
132
133const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),
134 std::numeric_limits<float>::min(),
135 -1.0f,
136 -0.0f,
137 0.0f,
138 1.0f,
139 std::numeric_limits<float>::max(),
140 std::numeric_limits<float>::infinity(),
141 std::numeric_limits<float>::quiet_NaN(),
142 std::numeric_limits<float>::signaling_NaN()};
143
144
145const double kDoubleValues[] = {-std::numeric_limits<double>::infinity(),
146 std::numeric_limits<double>::min(),
147 -1.0,
148 -0.0,
149 0.0,
150 1.0,
151 std::numeric_limits<double>::max(),
152 std::numeric_limits<double>::infinity(),
153 std::numeric_limits<double>::quiet_NaN(),
154 std::numeric_limits<double>::signaling_NaN()};
155
156
157const BranchHint kHints[] = {BranchHint::kNone, BranchHint::kTrue,
158 BranchHint::kFalse};
159
160} // namespace
161
162
163TEST_F(CommonOperatorTest, Branch) {
164 TRACED_FOREACH(BranchHint, hint, kHints) {
165 const Operator* const op = common()->Branch(hint);
166 EXPECT_EQ(IrOpcode::kBranch, op->opcode());
167 EXPECT_EQ(Operator::kFoldable, op->properties());
168 EXPECT_EQ(hint, BranchHintOf(op));
169 EXPECT_EQ(1, op->ValueInputCount());
170 EXPECT_EQ(0, op->EffectInputCount());
171 EXPECT_EQ(1, op->ControlInputCount());
172 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
173 EXPECT_EQ(0, op->ValueOutputCount());
174 EXPECT_EQ(0, op->EffectOutputCount());
175 EXPECT_EQ(2, op->ControlOutputCount());
176 }
177}
178
179
180TEST_F(CommonOperatorTest, Select) {
181 static const MachineType kTypes[] = {
182 kMachInt8, kMachUint8, kMachInt16, kMachUint16,
183 kMachInt32, kMachUint32, kMachInt64, kMachUint64,
184 kMachFloat32, kMachFloat64, kMachAnyTagged};
185 TRACED_FOREACH(MachineType, type, kTypes) {
186 TRACED_FOREACH(BranchHint, hint, kHints) {
187 const Operator* const op = common()->Select(type, hint);
188 EXPECT_EQ(IrOpcode::kSelect, op->opcode());
189 EXPECT_EQ(Operator::kPure, op->properties());
190 EXPECT_EQ(type, SelectParametersOf(op).type());
191 EXPECT_EQ(hint, SelectParametersOf(op).hint());
192 EXPECT_EQ(3, op->ValueInputCount());
193 EXPECT_EQ(0, op->EffectInputCount());
194 EXPECT_EQ(0, op->ControlInputCount());
195 EXPECT_EQ(3, OperatorProperties::GetTotalInputCount(op));
196 EXPECT_EQ(1, op->ValueOutputCount());
197 EXPECT_EQ(0, op->EffectOutputCount());
198 EXPECT_EQ(0, op->ControlOutputCount());
199 }
200 }
201}
202
203
204TEST_F(CommonOperatorTest, Float32Constant) {
205 TRACED_FOREACH(float, value, kFloatValues) {
206 const Operator* op = common()->Float32Constant(value);
207 EXPECT_PRED2(base::bit_equal_to<float>(), value, OpParameter<float>(op));
208 EXPECT_EQ(0, op->ValueInputCount());
209 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
210 EXPECT_EQ(0, op->ControlOutputCount());
211 EXPECT_EQ(0, op->EffectOutputCount());
212 EXPECT_EQ(1, op->ValueOutputCount());
213 }
214 TRACED_FOREACH(float, v1, kFloatValues) {
215 TRACED_FOREACH(float, v2, kFloatValues) {
216 const Operator* op1 = common()->Float32Constant(v1);
217 const Operator* op2 = common()->Float32Constant(v2);
218 EXPECT_EQ(bit_cast<uint32_t>(v1) == bit_cast<uint32_t>(v2),
219 op1->Equals(op2));
220 }
221 }
222}
223
224
225TEST_F(CommonOperatorTest, Float64Constant) {
226 TRACED_FOREACH(double, value, kFloatValues) {
227 const Operator* op = common()->Float64Constant(value);
228 EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
229 EXPECT_EQ(0, op->ValueInputCount());
230 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
231 EXPECT_EQ(0, op->ControlOutputCount());
232 EXPECT_EQ(0, op->EffectOutputCount());
233 EXPECT_EQ(1, op->ValueOutputCount());
234 }
235 TRACED_FOREACH(double, v1, kFloatValues) {
236 TRACED_FOREACH(double, v2, kFloatValues) {
237 const Operator* op1 = common()->Float64Constant(v1);
238 const Operator* op2 = common()->Float64Constant(v2);
239 EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
240 op1->Equals(op2));
241 }
242 }
243}
244
245
246TEST_F(CommonOperatorTest, NumberConstant) {
247 TRACED_FOREACH(double, value, kFloatValues) {
248 const Operator* op = common()->NumberConstant(value);
249 EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
250 EXPECT_EQ(0, op->ValueInputCount());
251 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
252 EXPECT_EQ(0, op->ControlOutputCount());
253 EXPECT_EQ(0, op->EffectOutputCount());
254 EXPECT_EQ(1, op->ValueOutputCount());
255 }
256 TRACED_FOREACH(double, v1, kFloatValues) {
257 TRACED_FOREACH(double, v2, kFloatValues) {
258 const Operator* op1 = common()->NumberConstant(v1);
259 const Operator* op2 = common()->NumberConstant(v2);
260 EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
261 op1->Equals(op2));
262 }
263 }
264}
265
266
267TEST_F(CommonOperatorTest, ValueEffect) {
268 TRACED_FOREACH(int, arguments, kArguments) {
269 const Operator* op = common()->ValueEffect(arguments);
270 EXPECT_EQ(arguments, op->ValueInputCount());
271 EXPECT_EQ(arguments, OperatorProperties::GetTotalInputCount(op));
272 EXPECT_EQ(0, op->ControlOutputCount());
273 EXPECT_EQ(1, op->EffectOutputCount());
274 EXPECT_EQ(0, op->ValueOutputCount());
275 }
276}
277
278
279TEST_F(CommonOperatorTest, Finish) {
280 TRACED_FOREACH(int, arguments, kArguments) {
281 const Operator* op = common()->Finish(arguments);
282 EXPECT_EQ(1, op->ValueInputCount());
283 EXPECT_EQ(arguments, op->EffectInputCount());
284 EXPECT_EQ(arguments + 1, OperatorProperties::GetTotalInputCount(op));
285 EXPECT_EQ(0, op->ControlOutputCount());
286 EXPECT_EQ(0, op->EffectOutputCount());
287 EXPECT_EQ(1, op->ValueOutputCount());
288 }
289}
290
291} // namespace compiler
292} // namespace internal
293} // namespace v8