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 <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
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
16
17
18 // -----------------------------------------------------------------------------
19 // Shared operators.
20
21
22 namespace {
23
24 struct 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 value_output_count;
32 int effect_output_count;
33 int control_output_count;
34 };
35
36
operator <<(std::ostream & os,const SharedOperator & fop)37 std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
38 return os << IrOpcode::Mnemonic(fop.opcode);
39 }
40
41
42 const SharedOperator kSharedOperators[] = {
43 #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 \
50 }
51 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)
57 #undef SHARED
58 };
59
60
61 class CommonSharedOperatorTest
62 : public TestWithZone,
63 public ::testing::WithParamInterface<SharedOperator> {};
64
65 } // namespace
66
67
TEST_P(CommonSharedOperatorTest,InstancesAreGloballyShared)68 TEST_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
TEST_P(CommonSharedOperatorTest,NumberOfInputsAndOutputs)76 TEST_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
88 EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
89 EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
90 EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
91 }
92
93
TEST_P(CommonSharedOperatorTest,OpcodeIsCorrect)94 TEST_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
TEST_P(CommonSharedOperatorTest,Properties)102 TEST_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
110 INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
111 ::testing::ValuesIn(kSharedOperators));
112
113
114 // -----------------------------------------------------------------------------
115 // Other operators.
116
117
118 namespace {
119
120 class CommonOperatorTest : public TestWithZone {
121 public:
CommonOperatorTest()122 CommonOperatorTest() : common_(zone()) {}
~CommonOperatorTest()123 ~CommonOperatorTest() override {}
124
common()125 CommonOperatorBuilder* common() { return &common_; }
126
127 private:
128 CommonOperatorBuilder common_;
129 };
130
131
132 const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
133
134
135 const size_t kCases[] = {3, 4, 100, 255, 1024, 65000};
136
137
138 const 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
150 const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000};
151
152
153 const 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
167 const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kTrue,
168 BranchHint::kFalse};
169
170 } // namespace
171
172
TEST_F(CommonOperatorTest,End)173 TEST_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
TEST_F(CommonOperatorTest,Return)190 TEST_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
TEST_F(CommonOperatorTest,Branch)206 TEST_F(CommonOperatorTest, Branch) {
207 TRACED_FOREACH(BranchHint, hint, kBranchHints) {
208 const Operator* const op = common()->Branch(hint);
209 EXPECT_EQ(IrOpcode::kBranch, op->opcode());
210 EXPECT_EQ(Operator::kKontrol, op->properties());
211 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
TEST_F(CommonOperatorTest,IfException)223 TEST_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
TEST_F(CommonOperatorTest,Switch)241 TEST_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
TEST_F(CommonOperatorTest,IfValue)257 TEST_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
TEST_F(CommonOperatorTest,Select)274 TEST_F(CommonOperatorTest, Select) {
275 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);
285 EXPECT_EQ(IrOpcode::kSelect, op->opcode());
286 EXPECT_EQ(Operator::kPure, op->properties());
287 EXPECT_EQ(rep, SelectParametersOf(op).representation());
288 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
TEST_F(CommonOperatorTest,Float32Constant)301 TEST_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
TEST_F(CommonOperatorTest,Float64Constant)322 TEST_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
TEST_F(CommonOperatorTest,NumberConstant)343 TEST_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
TEST_F(CommonOperatorTest,BeginRegion)364 TEST_F(CommonOperatorTest, BeginRegion) {
365 const Operator* op = common()->BeginRegion();
366 EXPECT_EQ(1, op->EffectInputCount());
367 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
368 EXPECT_EQ(0, op->ControlOutputCount());
369 EXPECT_EQ(1, op->EffectOutputCount());
370 EXPECT_EQ(0, op->ValueOutputCount());
371 }
372
373
TEST_F(CommonOperatorTest,FinishRegion)374 TEST_F(CommonOperatorTest, FinishRegion) {
375 const Operator* op = common()->FinishRegion();
376 EXPECT_EQ(1, op->ValueInputCount());
377 EXPECT_EQ(1, op->EffectInputCount());
378 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
379 EXPECT_EQ(0, op->ControlOutputCount());
380 EXPECT_EQ(1, op->EffectOutputCount());
381 EXPECT_EQ(1, op->ValueOutputCount());
382 }
383
384 } // namespace compiler
385 } // namespace internal
386 } // namespace v8
387