blob: 52f99a5e127c17b121c9c3ddb0bf34e1721746fe [file] [log] [blame]
Emily Bernierd0a1eb72015-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;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031 int value_output_count;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040032 int effect_output_count;
33 int control_output_count;
34};
35
36
37std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
38 return os << IrOpcode::Mnemonic(fop.opcode);
39}
40
41
42const SharedOperator kSharedOperators[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043#define SHARED(Name, properties, value_input_count, effect_input_count, \
44 control_input_count, value_output_count, effect_output_count, \
45 control_output_count) \
46 { \
47 &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties, \
48 value_input_count, effect_input_count, control_input_count, \
49 value_output_count, effect_output_count, control_output_count \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 SHARED(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1),
52 SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
53 SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
54 SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
55 SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1),
56 SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057#undef SHARED
58};
59
60
61class CommonSharedOperatorTest
62 : public TestWithZone,
63 public ::testing::WithParamInterface<SharedOperator> {};
64
65} // namespace
66
67
68TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
69 const SharedOperator& sop = GetParam();
70 CommonOperatorBuilder common1(zone());
71 CommonOperatorBuilder common2(zone());
72 EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
73}
74
75
76TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
77 CommonOperatorBuilder common(zone());
78 const SharedOperator& sop = GetParam();
79 const Operator* op = (common.*sop.constructor)();
80
81 EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
82 EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
83 EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
84 EXPECT_EQ(
85 sop.value_input_count + sop.effect_input_count + sop.control_input_count,
86 OperatorProperties::GetTotalInputCount(op));
87
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089 EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
90 EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
91}
92
93
94TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
95 CommonOperatorBuilder common(zone());
96 const SharedOperator& sop = GetParam();
97 const Operator* op = (common.*sop.constructor)();
98 EXPECT_EQ(sop.opcode, op->opcode());
99}
100
101
102TEST_P(CommonSharedOperatorTest, Properties) {
103 CommonOperatorBuilder common(zone());
104 const SharedOperator& sop = GetParam();
105 const Operator* op = (common.*sop.constructor)();
106 EXPECT_EQ(sop.properties, op->properties());
107}
108
109
110INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
111 ::testing::ValuesIn(kSharedOperators));
112
113
114// -----------------------------------------------------------------------------
115// Other operators.
116
117
118namespace {
119
120class CommonOperatorTest : public TestWithZone {
121 public:
122 CommonOperatorTest() : common_(zone()) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 ~CommonOperatorTest() override {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400124
125 CommonOperatorBuilder* common() { return &common_; }
126
127 private:
128 CommonOperatorBuilder common_;
129};
130
131
132const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
133
134
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135const size_t kCases[] = {3, 4, 100, 255, 1024, 65000};
136
137
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),
139 std::numeric_limits<float>::min(),
140 -1.0f,
141 -0.0f,
142 0.0f,
143 1.0f,
144 std::numeric_limits<float>::max(),
145 std::numeric_limits<float>::infinity(),
146 std::numeric_limits<float>::quiet_NaN(),
147 std::numeric_limits<float>::signaling_NaN()};
148
149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151
152
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153const int32_t kInt32Values[] = {
154 std::numeric_limits<int32_t>::min(), -1914954528, -1698749618, -1578693386,
155 -1577976073, -1573998034, -1529085059, -1499540537, -1299205097,
156 -1090814845, -938186388, -806828902, -750927650, -520676892, -513661538,
157 -453036354, -433622833, -282638793, -28375, -27788, -22770, -18806, -14173,
158 -11956, -11200, -10212, -8160, -3751, -2758, -1522, -121, -120, -118, -117,
159 -106, -84, -80, -74, -59, -52, -48, -39, -35, -17, -11, -10, -9, -7, -5, 0,
160 9, 12, 17, 23, 29, 31, 33, 35, 40, 47, 55, 56, 62, 64, 67, 68, 69, 74, 79,
161 84, 89, 90, 97, 104, 118, 124, 126, 127, 7278, 17787, 24136, 24202, 25570,
162 26680, 30242, 32399, 420886487, 642166225, 821912648, 822577803, 851385718,
163 1212241078, 1411419304, 1589626102, 1596437184, 1876245816, 1954730266,
164 2008792749, 2045320228, std::numeric_limits<int32_t>::max()};
165
166
167const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kTrue,
168 BranchHint::kFalse};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400169
170} // namespace
171
172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173TEST_F(CommonOperatorTest, End) {
174 TRACED_FOREACH(size_t, input_count, kInputCounts) {
175 const Operator* const op = common()->End(input_count);
176 EXPECT_EQ(IrOpcode::kEnd, op->opcode());
177 EXPECT_EQ(Operator::kKontrol, op->properties());
178 EXPECT_EQ(0, op->ValueInputCount());
179 EXPECT_EQ(0, op->EffectInputCount());
180 EXPECT_EQ(input_count, static_cast<uint32_t>(op->ControlInputCount()));
181 EXPECT_EQ(input_count, static_cast<uint32_t>(
182 OperatorProperties::GetTotalInputCount(op)));
183 EXPECT_EQ(0, op->ValueOutputCount());
184 EXPECT_EQ(0, op->EffectOutputCount());
185 EXPECT_EQ(0, op->ControlOutputCount());
186 }
187}
188
189
190TEST_F(CommonOperatorTest, Return) {
191 TRACED_FOREACH(int, input_count, kArguments) {
192 const Operator* const op = common()->Return(input_count);
193 EXPECT_EQ(IrOpcode::kReturn, op->opcode());
194 EXPECT_EQ(Operator::kNoThrow, op->properties());
195 EXPECT_EQ(input_count, op->ValueInputCount());
196 EXPECT_EQ(1, op->EffectInputCount());
197 EXPECT_EQ(1, op->ControlInputCount());
198 EXPECT_EQ(2 + input_count, OperatorProperties::GetTotalInputCount(op));
199 EXPECT_EQ(0, op->ValueOutputCount());
200 EXPECT_EQ(0, op->EffectOutputCount());
201 EXPECT_EQ(1, op->ControlOutputCount());
202 }
203}
204
205
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206TEST_F(CommonOperatorTest, Branch) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 TRACED_FOREACH(BranchHint, hint, kBranchHints) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208 const Operator* const op = common()->Branch(hint);
209 EXPECT_EQ(IrOpcode::kBranch, op->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 EXPECT_EQ(Operator::kKontrol, op->properties());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211 EXPECT_EQ(hint, BranchHintOf(op));
212 EXPECT_EQ(1, op->ValueInputCount());
213 EXPECT_EQ(0, op->EffectInputCount());
214 EXPECT_EQ(1, op->ControlInputCount());
215 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
216 EXPECT_EQ(0, op->ValueOutputCount());
217 EXPECT_EQ(0, op->EffectOutputCount());
218 EXPECT_EQ(2, op->ControlOutputCount());
219 }
220}
221
222
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223TEST_F(CommonOperatorTest, IfException) {
224 static const IfExceptionHint kIfExceptionHints[] = {
225 IfExceptionHint::kLocallyCaught, IfExceptionHint::kLocallyUncaught};
226 TRACED_FOREACH(IfExceptionHint, hint, kIfExceptionHints) {
227 const Operator* const op = common()->IfException(hint);
228 EXPECT_EQ(IrOpcode::kIfException, op->opcode());
229 EXPECT_EQ(Operator::kKontrol, op->properties());
230 EXPECT_EQ(0, op->ValueInputCount());
231 EXPECT_EQ(1, op->EffectInputCount());
232 EXPECT_EQ(1, op->ControlInputCount());
233 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
234 EXPECT_EQ(1, op->ValueOutputCount());
235 EXPECT_EQ(1, op->EffectOutputCount());
236 EXPECT_EQ(1, op->ControlOutputCount());
237 }
238}
239
240
241TEST_F(CommonOperatorTest, Switch) {
242 TRACED_FOREACH(size_t, cases, kCases) {
243 const Operator* const op = common()->Switch(cases);
244 EXPECT_EQ(IrOpcode::kSwitch, op->opcode());
245 EXPECT_EQ(Operator::kKontrol, op->properties());
246 EXPECT_EQ(1, op->ValueInputCount());
247 EXPECT_EQ(0, op->EffectInputCount());
248 EXPECT_EQ(1, op->ControlInputCount());
249 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
250 EXPECT_EQ(0, op->ValueOutputCount());
251 EXPECT_EQ(0, op->EffectOutputCount());
252 EXPECT_EQ(static_cast<int>(cases), op->ControlOutputCount());
253 }
254}
255
256
257TEST_F(CommonOperatorTest, IfValue) {
258 TRACED_FOREACH(int32_t, value, kInt32Values) {
259 const Operator* const op = common()->IfValue(value);
260 EXPECT_EQ(IrOpcode::kIfValue, op->opcode());
261 EXPECT_EQ(Operator::kKontrol, op->properties());
262 EXPECT_EQ(value, OpParameter<int32_t>(op));
263 EXPECT_EQ(0, op->ValueInputCount());
264 EXPECT_EQ(0, op->EffectInputCount());
265 EXPECT_EQ(1, op->ControlInputCount());
266 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
267 EXPECT_EQ(0, op->ValueOutputCount());
268 EXPECT_EQ(0, op->EffectOutputCount());
269 EXPECT_EQ(1, op->ControlOutputCount());
270 }
271}
272
273
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400274TEST_F(CommonOperatorTest, Select) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 static const MachineRepresentation kMachineRepresentations[] = {
276 MachineRepresentation::kBit, MachineRepresentation::kWord8,
277 MachineRepresentation::kWord16, MachineRepresentation::kWord32,
278 MachineRepresentation::kWord64, MachineRepresentation::kFloat32,
279 MachineRepresentation::kFloat64, MachineRepresentation::kTagged};
280
281
282 TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
283 TRACED_FOREACH(BranchHint, hint, kBranchHints) {
284 const Operator* const op = common()->Select(rep, hint);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400285 EXPECT_EQ(IrOpcode::kSelect, op->opcode());
286 EXPECT_EQ(Operator::kPure, op->properties());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 EXPECT_EQ(rep, SelectParametersOf(op).representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400288 EXPECT_EQ(hint, SelectParametersOf(op).hint());
289 EXPECT_EQ(3, op->ValueInputCount());
290 EXPECT_EQ(0, op->EffectInputCount());
291 EXPECT_EQ(0, op->ControlInputCount());
292 EXPECT_EQ(3, OperatorProperties::GetTotalInputCount(op));
293 EXPECT_EQ(1, op->ValueOutputCount());
294 EXPECT_EQ(0, op->EffectOutputCount());
295 EXPECT_EQ(0, op->ControlOutputCount());
296 }
297 }
298}
299
300
301TEST_F(CommonOperatorTest, Float32Constant) {
302 TRACED_FOREACH(float, value, kFloatValues) {
303 const Operator* op = common()->Float32Constant(value);
304 EXPECT_PRED2(base::bit_equal_to<float>(), value, OpParameter<float>(op));
305 EXPECT_EQ(0, op->ValueInputCount());
306 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
307 EXPECT_EQ(0, op->ControlOutputCount());
308 EXPECT_EQ(0, op->EffectOutputCount());
309 EXPECT_EQ(1, op->ValueOutputCount());
310 }
311 TRACED_FOREACH(float, v1, kFloatValues) {
312 TRACED_FOREACH(float, v2, kFloatValues) {
313 const Operator* op1 = common()->Float32Constant(v1);
314 const Operator* op2 = common()->Float32Constant(v2);
315 EXPECT_EQ(bit_cast<uint32_t>(v1) == bit_cast<uint32_t>(v2),
316 op1->Equals(op2));
317 }
318 }
319}
320
321
322TEST_F(CommonOperatorTest, Float64Constant) {
323 TRACED_FOREACH(double, value, kFloatValues) {
324 const Operator* op = common()->Float64Constant(value);
325 EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
326 EXPECT_EQ(0, op->ValueInputCount());
327 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
328 EXPECT_EQ(0, op->ControlOutputCount());
329 EXPECT_EQ(0, op->EffectOutputCount());
330 EXPECT_EQ(1, op->ValueOutputCount());
331 }
332 TRACED_FOREACH(double, v1, kFloatValues) {
333 TRACED_FOREACH(double, v2, kFloatValues) {
334 const Operator* op1 = common()->Float64Constant(v1);
335 const Operator* op2 = common()->Float64Constant(v2);
336 EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
337 op1->Equals(op2));
338 }
339 }
340}
341
342
343TEST_F(CommonOperatorTest, NumberConstant) {
344 TRACED_FOREACH(double, value, kFloatValues) {
345 const Operator* op = common()->NumberConstant(value);
346 EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
347 EXPECT_EQ(0, op->ValueInputCount());
348 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
349 EXPECT_EQ(0, op->ControlOutputCount());
350 EXPECT_EQ(0, op->EffectOutputCount());
351 EXPECT_EQ(1, op->ValueOutputCount());
352 }
353 TRACED_FOREACH(double, v1, kFloatValues) {
354 TRACED_FOREACH(double, v2, kFloatValues) {
355 const Operator* op1 = common()->NumberConstant(v1);
356 const Operator* op2 = common()->NumberConstant(v2);
357 EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
358 op1->Equals(op2));
359 }
360 }
361}
362
363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364TEST_F(CommonOperatorTest, BeginRegion) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100365 {
366 const Operator* op =
367 common()->BeginRegion(RegionObservability::kObservable);
368 EXPECT_EQ(1, op->EffectInputCount());
369 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
370 EXPECT_EQ(0, op->ControlOutputCount());
371 EXPECT_EQ(1, op->EffectOutputCount());
372 EXPECT_EQ(0, op->ValueOutputCount());
373 }
374 {
375 const Operator* op =
376 common()->BeginRegion(RegionObservability::kNotObservable);
377 EXPECT_EQ(1, op->EffectInputCount());
378 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
379 EXPECT_EQ(0, op->ControlOutputCount());
380 EXPECT_EQ(1, op->EffectOutputCount());
381 EXPECT_EQ(0, op->ValueOutputCount());
382 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400383}
384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385TEST_F(CommonOperatorTest, FinishRegion) {
386 const Operator* op = common()->FinishRegion();
387 EXPECT_EQ(1, op->ValueInputCount());
388 EXPECT_EQ(1, op->EffectInputCount());
389 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
390 EXPECT_EQ(0, op->ControlOutputCount());
391 EXPECT_EQ(1, op->EffectOutputCount());
392 EXPECT_EQ(1, op->ValueOutputCount());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400393}
394
Ben Murdoch61f157c2016-09-16 13:49:30 +0100395TEST_F(CommonOperatorTest, Projection) {
396 TRACED_FORRANGE(size_t, index, 0, 3) {
397 const Operator* op = common()->Projection(index);
398 EXPECT_EQ(index, ProjectionIndexOf(op));
399 EXPECT_EQ(1, op->ValueInputCount());
400 EXPECT_EQ(1, op->ControlInputCount());
401 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
402 EXPECT_EQ(0, op->ControlOutputCount());
403 EXPECT_EQ(0, op->EffectOutputCount());
404 EXPECT_EQ(1, op->ValueOutputCount());
405 }
406}
407
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400408} // namespace compiler
409} // namespace internal
410} // namespace v8