blob: 9a1378a53915eef55daa1798d1a4ea2a9d7b4d17 [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 "src/compiler/js-builtin-reducer.h"
6#include "src/compiler/js-graph.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/compiler/node-properties.h"
8#include "src/compiler/simplified-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "src/compiler/typer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/isolate-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "test/unittests/compiler/graph-unittest.h"
12#include "test/unittests/compiler/node-test-utils.h"
13#include "testing/gmock-support.h"
14
15using testing::BitEq;
16using testing::Capture;
17
18namespace v8 {
19namespace internal {
20namespace compiler {
21
22class JSBuiltinReducerTest : public TypedGraphTest {
23 public:
24 JSBuiltinReducerTest() : javascript_(zone()) {}
25
26 protected:
27 Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
28 MachineOperatorBuilder::Flag::kNoFlags) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
30 flags);
31 SimplifiedOperatorBuilder simplified(zone());
32 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
33 &machine);
34 // TODO(titzer): mock the GraphReducer here for better unit testing.
35 GraphReducer graph_reducer(zone(), graph());
36 JSBuiltinReducer reducer(&graph_reducer, &jsgraph);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040037 return reducer.Reduce(node);
38 }
39
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 Node* MathFunction(const char* name) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 Handle<Object> m =
42 JSObject::GetProperty(isolate()->global_object(),
43 isolate()->factory()->NewStringFromAsciiChecked(
44 "Math")).ToHandleChecked();
45 Handle<JSFunction> f = Handle<JSFunction>::cast(
Ben Murdochda12d292016-06-02 14:46:10 +010046 Object::GetProperty(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047 m, isolate()->factory()->NewStringFromAsciiChecked(name))
48 .ToHandleChecked());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 return HeapConstant(f);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 }
51
Ben Murdoch61f157c2016-09-16 13:49:30 +010052 Node* StringFunction(const char* name) {
53 Handle<Object> m =
54 JSObject::GetProperty(
55 isolate()->global_object(),
56 isolate()->factory()->NewStringFromAsciiChecked("String"))
57 .ToHandleChecked();
58 Handle<JSFunction> f = Handle<JSFunction>::cast(
59 Object::GetProperty(
60 m, isolate()->factory()->NewStringFromAsciiChecked(name))
61 .ToHandleChecked());
62 return HeapConstant(f);
63 }
64
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 JSOperatorBuilder* javascript() { return &javascript_; }
66
67 private:
68 JSOperatorBuilder javascript_;
69};
70
71
72namespace {
73
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074Type* const kIntegral32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
75 Type::Unsigned31(), Type::SignedSmall(),
76 Type::Signed32(), Type::Unsigned32(),
77 Type::Integral32()};
78
79
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080Type* const kNumberTypes[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
82 Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
83 Type::Integral32(), Type::MinusZero(), Type::NaN(),
84 Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085
86} // namespace
87
88
89// -----------------------------------------------------------------------------
Ben Murdoch61f157c2016-09-16 13:49:30 +010090// Math.abs
91
92TEST_F(JSBuiltinReducerTest, MathAbsWithNumber) {
93 Node* function = MathFunction("abs");
94
95 Node* effect = graph()->start();
96 Node* control = graph()->start();
97 Node* context = UndefinedConstant();
98 Node* frame_state = graph()->start();
99 TRACED_FOREACH(Type*, t0, kNumberTypes) {
100 Node* p0 = Parameter(t0, 0);
101 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
102 UndefinedConstant(), p0, context, frame_state,
103 effect, control);
104 Reduction r = Reduce(call);
105
106 ASSERT_TRUE(r.Changed());
107 EXPECT_THAT(r.replacement(), IsNumberAbs(p0));
108 }
109}
110
111TEST_F(JSBuiltinReducerTest, MathAbsWithPlainPrimitive) {
112 Node* function = MathFunction("abs");
113
114 Node* effect = graph()->start();
115 Node* control = graph()->start();
116 Node* context = UndefinedConstant();
117 Node* frame_state = graph()->start();
118 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
119 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
120 UndefinedConstant(), p0, context, frame_state,
121 effect, control);
122 Reduction r = Reduce(call);
123
124 ASSERT_TRUE(r.Changed());
125 EXPECT_THAT(r.replacement(), IsNumberAbs(IsPlainPrimitiveToNumber(p0)));
126}
127
128// -----------------------------------------------------------------------------
129// Math.atan
130
131TEST_F(JSBuiltinReducerTest, MathAtanWithNumber) {
132 Node* function = MathFunction("atan");
133
134 Node* effect = graph()->start();
135 Node* control = graph()->start();
136 Node* context = UndefinedConstant();
137 Node* frame_state = graph()->start();
138 TRACED_FOREACH(Type*, t0, kNumberTypes) {
139 Node* p0 = Parameter(t0, 0);
140 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
141 UndefinedConstant(), p0, context, frame_state,
142 effect, control);
143 Reduction r = Reduce(call);
144
145 ASSERT_TRUE(r.Changed());
146 EXPECT_THAT(r.replacement(), IsNumberAtan(p0));
147 }
148}
149
150TEST_F(JSBuiltinReducerTest, MathAtanWithPlainPrimitive) {
151 Node* function = MathFunction("atan");
152
153 Node* effect = graph()->start();
154 Node* control = graph()->start();
155 Node* context = UndefinedConstant();
156 Node* frame_state = graph()->start();
157 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
158 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
159 UndefinedConstant(), p0, context, frame_state,
160 effect, control);
161 Reduction r = Reduce(call);
162
163 ASSERT_TRUE(r.Changed());
164 EXPECT_THAT(r.replacement(), IsNumberAtan(IsPlainPrimitiveToNumber(p0)));
165}
166
167// -----------------------------------------------------------------------------
168// Math.atan2
169
170TEST_F(JSBuiltinReducerTest, MathAtan2WithNumber) {
171 Node* function = MathFunction("atan2");
172
173 Node* effect = graph()->start();
174 Node* control = graph()->start();
175 Node* context = UndefinedConstant();
176 Node* frame_state = graph()->start();
177 TRACED_FOREACH(Type*, t0, kNumberTypes) {
178 Node* p0 = Parameter(t0, 0);
179 TRACED_FOREACH(Type*, t1, kNumberTypes) {
180 Node* p1 = Parameter(t1, 0);
181 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
182 UndefinedConstant(), p0, p1, context,
183 frame_state, effect, control);
184 Reduction r = Reduce(call);
185
186 ASSERT_TRUE(r.Changed());
187 EXPECT_THAT(r.replacement(), IsNumberAtan2(p0, p1));
188 }
189 }
190}
191
192TEST_F(JSBuiltinReducerTest, MathAtan2WithPlainPrimitive) {
193 Node* function = MathFunction("atan2");
194
195 Node* effect = graph()->start();
196 Node* control = graph()->start();
197 Node* context = UndefinedConstant();
198 Node* frame_state = graph()->start();
199 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
200 Node* p1 = Parameter(Type::PlainPrimitive(), 0);
201 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
202 UndefinedConstant(), p0, p1, context,
203 frame_state, effect, control);
204 Reduction r = Reduce(call);
205
206 ASSERT_TRUE(r.Changed());
207 EXPECT_THAT(r.replacement(), IsNumberAtan2(IsPlainPrimitiveToNumber(p0),
208 IsPlainPrimitiveToNumber(p1)));
209}
210
211// -----------------------------------------------------------------------------
212// Math.ceil
213
214TEST_F(JSBuiltinReducerTest, MathCeilWithNumber) {
215 Node* function = MathFunction("ceil");
216
217 Node* effect = graph()->start();
218 Node* control = graph()->start();
219 Node* context = UndefinedConstant();
220 Node* frame_state = graph()->start();
221 TRACED_FOREACH(Type*, t0, kNumberTypes) {
222 Node* p0 = Parameter(t0, 0);
223 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
224 UndefinedConstant(), p0, context, frame_state,
225 effect, control);
226 Reduction r = Reduce(call);
227
228 ASSERT_TRUE(r.Changed());
229 EXPECT_THAT(r.replacement(), IsNumberCeil(p0));
230 }
231}
232
233TEST_F(JSBuiltinReducerTest, MathCeilWithPlainPrimitive) {
234 Node* function = MathFunction("ceil");
235
236 Node* effect = graph()->start();
237 Node* control = graph()->start();
238 Node* context = UndefinedConstant();
239 Node* frame_state = graph()->start();
240 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
241 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
242 UndefinedConstant(), p0, context, frame_state,
243 effect, control);
244 Reduction r = Reduce(call);
245
246 ASSERT_TRUE(r.Changed());
247 EXPECT_THAT(r.replacement(), IsNumberCeil(IsPlainPrimitiveToNumber(p0)));
248}
249
250// -----------------------------------------------------------------------------
251// Math.clz32
252
253TEST_F(JSBuiltinReducerTest, MathClz32WithUnsigned32) {
254 Node* function = MathFunction("clz32");
255
256 Node* effect = graph()->start();
257 Node* control = graph()->start();
258 Node* context = UndefinedConstant();
259 Node* frame_state = graph()->start();
260 Node* p0 = Parameter(Type::Unsigned32(), 0);
261 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
262 UndefinedConstant(), p0, context, frame_state,
263 effect, control);
264 Reduction r = Reduce(call);
265
266 ASSERT_TRUE(r.Changed());
267 EXPECT_THAT(r.replacement(), IsNumberClz32(p0));
268}
269
270TEST_F(JSBuiltinReducerTest, MathClz32WithNumber) {
271 Node* function = MathFunction("clz32");
272
273 Node* effect = graph()->start();
274 Node* control = graph()->start();
275 Node* context = UndefinedConstant();
276 Node* frame_state = graph()->start();
277 Node* p0 = Parameter(Type::Number(), 0);
278 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
279 UndefinedConstant(), p0, context, frame_state,
280 effect, control);
281 Reduction r = Reduce(call);
282
283 ASSERT_TRUE(r.Changed());
284 EXPECT_THAT(r.replacement(), IsNumberClz32(IsNumberToUint32(p0)));
285}
286
287TEST_F(JSBuiltinReducerTest, MathClz32WithPlainPrimitive) {
288 Node* function = MathFunction("clz32");
289
290 Node* effect = graph()->start();
291 Node* control = graph()->start();
292 Node* context = UndefinedConstant();
293 Node* frame_state = graph()->start();
294 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
295 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
296 UndefinedConstant(), p0, context, frame_state,
297 effect, control);
298 Reduction r = Reduce(call);
299
300 ASSERT_TRUE(r.Changed());
301 EXPECT_THAT(r.replacement(),
302 IsNumberClz32(IsNumberToUint32(IsPlainPrimitiveToNumber(p0))));
303}
304
305// -----------------------------------------------------------------------------
306// Math.cos
307
308TEST_F(JSBuiltinReducerTest, MathCosWithNumber) {
309 Node* function = MathFunction("cos");
310
311 Node* effect = graph()->start();
312 Node* control = graph()->start();
313 Node* context = UndefinedConstant();
314 Node* frame_state = graph()->start();
315 TRACED_FOREACH(Type*, t0, kNumberTypes) {
316 Node* p0 = Parameter(t0, 0);
317 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
318 UndefinedConstant(), p0, context, frame_state,
319 effect, control);
320 Reduction r = Reduce(call);
321
322 ASSERT_TRUE(r.Changed());
323 EXPECT_THAT(r.replacement(), IsNumberCos(p0));
324 }
325}
326
327TEST_F(JSBuiltinReducerTest, MathCosWithPlainPrimitive) {
328 Node* function = MathFunction("cos");
329
330 Node* effect = graph()->start();
331 Node* control = graph()->start();
332 Node* context = UndefinedConstant();
333 Node* frame_state = graph()->start();
334 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
335 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
336 UndefinedConstant(), p0, context, frame_state,
337 effect, control);
338 Reduction r = Reduce(call);
339
340 ASSERT_TRUE(r.Changed());
341 EXPECT_THAT(r.replacement(), IsNumberCos(IsPlainPrimitiveToNumber(p0)));
342}
343
344// -----------------------------------------------------------------------------
345// Math.exp
346
347TEST_F(JSBuiltinReducerTest, MathExpWithNumber) {
348 Node* function = MathFunction("exp");
349
350 Node* effect = graph()->start();
351 Node* control = graph()->start();
352 Node* context = UndefinedConstant();
353 Node* frame_state = graph()->start();
354 TRACED_FOREACH(Type*, t0, kNumberTypes) {
355 Node* p0 = Parameter(t0, 0);
356 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
357 UndefinedConstant(), p0, context, frame_state,
358 effect, control);
359 Reduction r = Reduce(call);
360
361 ASSERT_TRUE(r.Changed());
362 EXPECT_THAT(r.replacement(), IsNumberExp(p0));
363 }
364}
365
366TEST_F(JSBuiltinReducerTest, MathExpWithPlainPrimitive) {
367 Node* function = MathFunction("exp");
368
369 Node* effect = graph()->start();
370 Node* control = graph()->start();
371 Node* context = UndefinedConstant();
372 Node* frame_state = graph()->start();
373 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
374 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
375 UndefinedConstant(), p0, context, frame_state,
376 effect, control);
377 Reduction r = Reduce(call);
378
379 ASSERT_TRUE(r.Changed());
380 EXPECT_THAT(r.replacement(), IsNumberExp(IsPlainPrimitiveToNumber(p0)));
381}
382
383// -----------------------------------------------------------------------------
384// Math.floor
385
386TEST_F(JSBuiltinReducerTest, MathFloorWithNumber) {
387 Node* function = MathFunction("floor");
388
389 Node* effect = graph()->start();
390 Node* control = graph()->start();
391 Node* context = UndefinedConstant();
392 Node* frame_state = graph()->start();
393 TRACED_FOREACH(Type*, t0, kNumberTypes) {
394 Node* p0 = Parameter(t0, 0);
395 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
396 UndefinedConstant(), p0, context, frame_state,
397 effect, control);
398 Reduction r = Reduce(call);
399
400 ASSERT_TRUE(r.Changed());
401 EXPECT_THAT(r.replacement(), IsNumberFloor(p0));
402 }
403}
404
405TEST_F(JSBuiltinReducerTest, MathFloorWithPlainPrimitive) {
406 Node* function = MathFunction("floor");
407
408 Node* effect = graph()->start();
409 Node* control = graph()->start();
410 Node* context = UndefinedConstant();
411 Node* frame_state = graph()->start();
412 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
413 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
414 UndefinedConstant(), p0, context, frame_state,
415 effect, control);
416 Reduction r = Reduce(call);
417
418 ASSERT_TRUE(r.Changed());
419 EXPECT_THAT(r.replacement(), IsNumberFloor(IsPlainPrimitiveToNumber(p0)));
420}
421
422// -----------------------------------------------------------------------------
423// Math.fround
424
425TEST_F(JSBuiltinReducerTest, MathFroundWithNumber) {
426 Node* function = MathFunction("fround");
427
428 Node* effect = graph()->start();
429 Node* control = graph()->start();
430 Node* context = UndefinedConstant();
431 Node* frame_state = graph()->start();
432 TRACED_FOREACH(Type*, t0, kNumberTypes) {
433 Node* p0 = Parameter(t0, 0);
434 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
435 UndefinedConstant(), p0, context, frame_state,
436 effect, control);
437 Reduction r = Reduce(call);
438
439 ASSERT_TRUE(r.Changed());
440 EXPECT_THAT(r.replacement(), IsNumberFround(p0));
441 }
442}
443
444TEST_F(JSBuiltinReducerTest, MathFroundWithPlainPrimitive) {
445 Node* function = MathFunction("fround");
446
447 Node* effect = graph()->start();
448 Node* control = graph()->start();
449 Node* context = UndefinedConstant();
450 Node* frame_state = graph()->start();
451 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
452 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
453 UndefinedConstant(), p0, context, frame_state,
454 effect, control);
455 Reduction r = Reduce(call);
456
457 ASSERT_TRUE(r.Changed());
458 EXPECT_THAT(r.replacement(), IsNumberFround(IsPlainPrimitiveToNumber(p0)));
459}
460
461// -----------------------------------------------------------------------------
462// Math.imul
463
464TEST_F(JSBuiltinReducerTest, MathImulWithUnsigned32) {
465 Node* function = MathFunction("imul");
466
467 Node* effect = graph()->start();
468 Node* control = graph()->start();
469 Node* context = UndefinedConstant();
470 Node* frame_state = graph()->start();
471 Node* p0 = Parameter(Type::Unsigned32(), 0);
472 Node* p1 = Parameter(Type::Unsigned32(), 1);
473 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
474 UndefinedConstant(), p0, p1, context,
475 frame_state, effect, control);
476 Reduction r = Reduce(call);
477
478 ASSERT_TRUE(r.Changed());
479 EXPECT_THAT(r.replacement(), IsNumberImul(p0, p1));
480}
481
482TEST_F(JSBuiltinReducerTest, MathImulWithNumber) {
483 Node* function = MathFunction("imul");
484
485 Node* effect = graph()->start();
486 Node* control = graph()->start();
487 Node* context = UndefinedConstant();
488 Node* frame_state = graph()->start();
489 Node* p0 = Parameter(Type::Number(), 0);
490 Node* p1 = Parameter(Type::Number(), 1);
491 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
492 UndefinedConstant(), p0, p1, context,
493 frame_state, effect, control);
494 Reduction r = Reduce(call);
495
496 ASSERT_TRUE(r.Changed());
497 EXPECT_THAT(r.replacement(),
498 IsNumberImul(IsNumberToUint32(p0), IsNumberToUint32(p1)));
499}
500
501TEST_F(JSBuiltinReducerTest, MathImulWithPlainPrimitive) {
502 Node* function = MathFunction("imul");
503
504 Node* effect = graph()->start();
505 Node* control = graph()->start();
506 Node* context = UndefinedConstant();
507 Node* frame_state = graph()->start();
508 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
509 Node* p1 = Parameter(Type::PlainPrimitive(), 1);
510 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
511 UndefinedConstant(), p0, p1, context,
512 frame_state, effect, control);
513 Reduction r = Reduce(call);
514
515 ASSERT_TRUE(r.Changed());
516 EXPECT_THAT(r.replacement(),
517 IsNumberImul(IsNumberToUint32(IsPlainPrimitiveToNumber(p0)),
518 IsNumberToUint32(IsPlainPrimitiveToNumber(p1))));
519}
520
521// -----------------------------------------------------------------------------
522// Math.log
523
524TEST_F(JSBuiltinReducerTest, MathLogWithNumber) {
525 Node* function = MathFunction("log");
526
527 Node* effect = graph()->start();
528 Node* control = graph()->start();
529 Node* context = UndefinedConstant();
530 Node* frame_state = graph()->start();
531 TRACED_FOREACH(Type*, t0, kNumberTypes) {
532 Node* p0 = Parameter(t0, 0);
533 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
534 UndefinedConstant(), p0, context, frame_state,
535 effect, control);
536 Reduction r = Reduce(call);
537
538 ASSERT_TRUE(r.Changed());
539 EXPECT_THAT(r.replacement(), IsNumberLog(p0));
540 }
541}
542
543TEST_F(JSBuiltinReducerTest, MathLogWithPlainPrimitive) {
544 Node* function = MathFunction("log");
545
546 Node* effect = graph()->start();
547 Node* control = graph()->start();
548 Node* context = UndefinedConstant();
549 Node* frame_state = graph()->start();
550 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
551 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
552 UndefinedConstant(), p0, context, frame_state,
553 effect, control);
554 Reduction r = Reduce(call);
555
556 ASSERT_TRUE(r.Changed());
557 EXPECT_THAT(r.replacement(), IsNumberLog(IsPlainPrimitiveToNumber(p0)));
558}
559
560// -----------------------------------------------------------------------------
561// Math.log1p
562
563TEST_F(JSBuiltinReducerTest, MathLog1pWithNumber) {
564 Node* function = MathFunction("log1p");
565
566 Node* effect = graph()->start();
567 Node* control = graph()->start();
568 Node* context = UndefinedConstant();
569 Node* frame_state = graph()->start();
570 TRACED_FOREACH(Type*, t0, kNumberTypes) {
571 Node* p0 = Parameter(t0, 0);
572 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
573 UndefinedConstant(), p0, context, frame_state,
574 effect, control);
575 Reduction r = Reduce(call);
576
577 ASSERT_TRUE(r.Changed());
578 EXPECT_THAT(r.replacement(), IsNumberLog1p(p0));
579 }
580}
581
582TEST_F(JSBuiltinReducerTest, MathLog1pWithPlainPrimitive) {
583 Node* function = MathFunction("log1p");
584
585 Node* effect = graph()->start();
586 Node* control = graph()->start();
587 Node* context = UndefinedConstant();
588 Node* frame_state = graph()->start();
589 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
590 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
591 UndefinedConstant(), p0, context, frame_state,
592 effect, control);
593 Reduction r = Reduce(call);
594
595 ASSERT_TRUE(r.Changed());
596 EXPECT_THAT(r.replacement(), IsNumberLog1p(IsPlainPrimitiveToNumber(p0)));
597}
598
599// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400600// Math.max
601
Ben Murdoch61f157c2016-09-16 13:49:30 +0100602TEST_F(JSBuiltinReducerTest, MathMaxWithNoArguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 Node* effect = graph()->start();
606 Node* control = graph()->start();
607 Node* context = UndefinedConstant();
608 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100609 Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
610 UndefinedConstant(), context, frame_state,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100611 effect, control);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100612 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400613
Ben Murdoch097c5b22016-05-18 11:27:45 +0100614 ASSERT_TRUE(r.Changed());
615 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400616}
617
Ben Murdoch61f157c2016-09-16 13:49:30 +0100618TEST_F(JSBuiltinReducerTest, MathMaxWithNumber) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000619 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400620
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 Node* effect = graph()->start();
622 Node* control = graph()->start();
623 Node* context = UndefinedConstant();
624 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100625 TRACED_FOREACH(Type*, t0, kNumberTypes) {
626 Node* p0 = Parameter(t0, 0);
627 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
628 UndefinedConstant(), p0, context, frame_state,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100629 effect, control);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100630 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400631
Ben Murdoch097c5b22016-05-18 11:27:45 +0100632 ASSERT_TRUE(r.Changed());
633 EXPECT_THAT(r.replacement(), p0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634 }
635}
636
Ben Murdoch61f157c2016-09-16 13:49:30 +0100637TEST_F(JSBuiltinReducerTest, MathMaxWithPlainPrimitive) {
638 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400639
Ben Murdoch61f157c2016-09-16 13:49:30 +0100640 Node* effect = graph()->start();
641 Node* control = graph()->start();
642 Node* context = UndefinedConstant();
643 Node* frame_state = graph()->start();
644 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
645 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
646 UndefinedConstant(), p0, context, frame_state,
647 effect, control);
648 Reduction r = Reduce(call);
649
650 ASSERT_TRUE(r.Changed());
651 EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(p0));
652}
653
654TEST_F(JSBuiltinReducerTest, MathMaxWithIntegral32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 Node* effect = graph()->start();
658 Node* control = graph()->start();
659 Node* context = UndefinedConstant();
660 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100661 TRACED_FOREACH(Type*, t0, kIntegral32Types) {
662 TRACED_FOREACH(Type*, t1, kIntegral32Types) {
663 Node* p0 = Parameter(t0, 0);
664 Node* p1 = Parameter(t1, 1);
665 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
666 UndefinedConstant(), p0, p1, context,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100667 frame_state, effect, control);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100668 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400669
Ben Murdoch097c5b22016-05-18 11:27:45 +0100670 ASSERT_TRUE(r.Changed());
671 EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
672 IsNumberLessThan(p1, p0), p0, p1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673 }
674 }
675}
676
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400677// -----------------------------------------------------------------------------
Ben Murdoch61f157c2016-09-16 13:49:30 +0100678// Math.min
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400679
Ben Murdoch61f157c2016-09-16 13:49:30 +0100680TEST_F(JSBuiltinReducerTest, MathMinWithNoArguments) {
681 Node* function = MathFunction("min");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 Node* effect = graph()->start();
684 Node* control = graph()->start();
685 Node* context = UndefinedConstant();
686 Node* frame_state = graph()->start();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100687 Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
688 UndefinedConstant(), context, frame_state,
689 effect, control);
690 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400691
Ben Murdoch61f157c2016-09-16 13:49:30 +0100692 ASSERT_TRUE(r.Changed());
693 EXPECT_THAT(r.replacement(), IsNumberConstant(V8_INFINITY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400694}
695
Ben Murdoch61f157c2016-09-16 13:49:30 +0100696TEST_F(JSBuiltinReducerTest, MathMinWithNumber) {
697 Node* function = MathFunction("min");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400698
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 Node* effect = graph()->start();
700 Node* control = graph()->start();
701 Node* context = UndefinedConstant();
702 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100703 TRACED_FOREACH(Type*, t0, kNumberTypes) {
704 Node* p0 = Parameter(t0, 0);
705 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
706 UndefinedConstant(), p0, context, frame_state,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100707 effect, control);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100708 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400709
Ben Murdoch097c5b22016-05-18 11:27:45 +0100710 ASSERT_TRUE(r.Changed());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100711 EXPECT_THAT(r.replacement(), p0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400712 }
713}
714
Ben Murdoch61f157c2016-09-16 13:49:30 +0100715TEST_F(JSBuiltinReducerTest, MathMinWithPlainPrimitive) {
716 Node* function = MathFunction("min");
717
718 Node* effect = graph()->start();
719 Node* control = graph()->start();
720 Node* context = UndefinedConstant();
721 Node* frame_state = graph()->start();
722 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
723 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
724 UndefinedConstant(), p0, context, frame_state,
725 effect, control);
726 Reduction r = Reduce(call);
727
728 ASSERT_TRUE(r.Changed());
729 EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(p0));
730}
731
732TEST_F(JSBuiltinReducerTest, MathMinWithIntegral32) {
733 Node* function = MathFunction("min");
734
735 Node* effect = graph()->start();
736 Node* control = graph()->start();
737 Node* context = UndefinedConstant();
738 Node* frame_state = graph()->start();
739 TRACED_FOREACH(Type*, t0, kIntegral32Types) {
740 TRACED_FOREACH(Type*, t1, kIntegral32Types) {
741 Node* p0 = Parameter(t0, 0);
742 Node* p1 = Parameter(t1, 1);
743 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
744 UndefinedConstant(), p0, p1, context,
745 frame_state, effect, control);
746 Reduction r = Reduce(call);
747
748 ASSERT_TRUE(r.Changed());
749 EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
750 IsNumberLessThan(p1, p0), p1, p0));
751 }
752 }
753}
754
755// -----------------------------------------------------------------------------
756// Math.round
757
758TEST_F(JSBuiltinReducerTest, MathRoundWithNumber) {
759 Node* function = MathFunction("round");
760
761 Node* effect = graph()->start();
762 Node* control = graph()->start();
763 Node* context = UndefinedConstant();
764 Node* frame_state = graph()->start();
765 TRACED_FOREACH(Type*, t0, kNumberTypes) {
766 Node* p0 = Parameter(t0, 0);
767 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
768 UndefinedConstant(), p0, context, frame_state,
769 effect, control);
770 Reduction r = Reduce(call);
771
772 ASSERT_TRUE(r.Changed());
773 EXPECT_THAT(r.replacement(), IsNumberRound(p0));
774 }
775}
776
777TEST_F(JSBuiltinReducerTest, MathRoundWithPlainPrimitive) {
778 Node* function = MathFunction("round");
779
780 Node* effect = graph()->start();
781 Node* control = graph()->start();
782 Node* context = UndefinedConstant();
783 Node* frame_state = graph()->start();
784 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
785 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
786 UndefinedConstant(), p0, context, frame_state,
787 effect, control);
788 Reduction r = Reduce(call);
789
790 ASSERT_TRUE(r.Changed());
791 EXPECT_THAT(r.replacement(), IsNumberRound(IsPlainPrimitiveToNumber(p0)));
792}
793
794// -----------------------------------------------------------------------------
795// Math.sin
796
797TEST_F(JSBuiltinReducerTest, MathSinWithNumber) {
798 Node* function = MathFunction("sin");
799
800 Node* effect = graph()->start();
801 Node* control = graph()->start();
802 Node* context = UndefinedConstant();
803 Node* frame_state = graph()->start();
804 TRACED_FOREACH(Type*, t0, kNumberTypes) {
805 Node* p0 = Parameter(t0, 0);
806 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
807 UndefinedConstant(), p0, context, frame_state,
808 effect, control);
809 Reduction r = Reduce(call);
810
811 ASSERT_TRUE(r.Changed());
812 EXPECT_THAT(r.replacement(), IsNumberSin(p0));
813 }
814}
815
816TEST_F(JSBuiltinReducerTest, MathSinWithPlainPrimitive) {
817 Node* function = MathFunction("sin");
818
819 Node* effect = graph()->start();
820 Node* control = graph()->start();
821 Node* context = UndefinedConstant();
822 Node* frame_state = graph()->start();
823 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
824 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
825 UndefinedConstant(), p0, context, frame_state,
826 effect, control);
827 Reduction r = Reduce(call);
828
829 ASSERT_TRUE(r.Changed());
830 EXPECT_THAT(r.replacement(), IsNumberSin(IsPlainPrimitiveToNumber(p0)));
831}
832
833// -----------------------------------------------------------------------------
834// Math.sqrt
835
836TEST_F(JSBuiltinReducerTest, MathSqrtWithNumber) {
837 Node* function = MathFunction("sqrt");
838
839 Node* effect = graph()->start();
840 Node* control = graph()->start();
841 Node* context = UndefinedConstant();
842 Node* frame_state = graph()->start();
843 TRACED_FOREACH(Type*, t0, kNumberTypes) {
844 Node* p0 = Parameter(t0, 0);
845 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
846 UndefinedConstant(), p0, context, frame_state,
847 effect, control);
848 Reduction r = Reduce(call);
849
850 ASSERT_TRUE(r.Changed());
851 EXPECT_THAT(r.replacement(), IsNumberSqrt(p0));
852 }
853}
854
855TEST_F(JSBuiltinReducerTest, MathSqrtWithPlainPrimitive) {
856 Node* function = MathFunction("sqrt");
857
858 Node* effect = graph()->start();
859 Node* control = graph()->start();
860 Node* context = UndefinedConstant();
861 Node* frame_state = graph()->start();
862 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
863 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
864 UndefinedConstant(), p0, context, frame_state,
865 effect, control);
866 Reduction r = Reduce(call);
867
868 ASSERT_TRUE(r.Changed());
869 EXPECT_THAT(r.replacement(), IsNumberSqrt(IsPlainPrimitiveToNumber(p0)));
870}
871
872// -----------------------------------------------------------------------------
873// Math.tan
874
875TEST_F(JSBuiltinReducerTest, MathTanWithNumber) {
876 Node* function = MathFunction("tan");
877
878 Node* effect = graph()->start();
879 Node* control = graph()->start();
880 Node* context = UndefinedConstant();
881 Node* frame_state = graph()->start();
882 TRACED_FOREACH(Type*, t0, kNumberTypes) {
883 Node* p0 = Parameter(t0, 0);
884 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
885 UndefinedConstant(), p0, context, frame_state,
886 effect, control);
887 Reduction r = Reduce(call);
888
889 ASSERT_TRUE(r.Changed());
890 EXPECT_THAT(r.replacement(), IsNumberTan(p0));
891 }
892}
893
894TEST_F(JSBuiltinReducerTest, MathTanWithPlainPrimitive) {
895 Node* function = MathFunction("tan");
896
897 Node* effect = graph()->start();
898 Node* control = graph()->start();
899 Node* context = UndefinedConstant();
900 Node* frame_state = graph()->start();
901 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
902 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
903 UndefinedConstant(), p0, context, frame_state,
904 effect, control);
905 Reduction r = Reduce(call);
906
907 ASSERT_TRUE(r.Changed());
908 EXPECT_THAT(r.replacement(), IsNumberTan(IsPlainPrimitiveToNumber(p0)));
909}
910
911// -----------------------------------------------------------------------------
912// Math.trunc
913
914TEST_F(JSBuiltinReducerTest, MathTruncWithNumber) {
915 Node* function = MathFunction("trunc");
916
917 Node* effect = graph()->start();
918 Node* control = graph()->start();
919 Node* context = UndefinedConstant();
920 Node* frame_state = graph()->start();
921 TRACED_FOREACH(Type*, t0, kNumberTypes) {
922 Node* p0 = Parameter(t0, 0);
923 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
924 UndefinedConstant(), p0, context, frame_state,
925 effect, control);
926 Reduction r = Reduce(call);
927
928 ASSERT_TRUE(r.Changed());
929 EXPECT_THAT(r.replacement(), IsNumberTrunc(p0));
930 }
931}
932
933TEST_F(JSBuiltinReducerTest, MathTruncWithPlainPrimitive) {
934 Node* function = MathFunction("trunc");
935
936 Node* effect = graph()->start();
937 Node* control = graph()->start();
938 Node* context = UndefinedConstant();
939 Node* frame_state = graph()->start();
940 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
941 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
942 UndefinedConstant(), p0, context, frame_state,
943 effect, control);
944 Reduction r = Reduce(call);
945
946 ASSERT_TRUE(r.Changed());
947 EXPECT_THAT(r.replacement(), IsNumberTrunc(IsPlainPrimitiveToNumber(p0)));
948}
949
950// -----------------------------------------------------------------------------
951// String.fromCharCode
952
953TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithNumber) {
954 Node* function = StringFunction("fromCharCode");
955
956 Node* effect = graph()->start();
957 Node* control = graph()->start();
958 Node* context = UndefinedConstant();
959 Node* frame_state = graph()->start();
960 TRACED_FOREACH(Type*, t0, kNumberTypes) {
961 Node* p0 = Parameter(t0, 0);
962 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
963 UndefinedConstant(), p0, context, frame_state,
964 effect, control);
965 Reduction r = Reduce(call);
966
967 ASSERT_TRUE(r.Changed());
968 EXPECT_THAT(r.replacement(), IsStringFromCharCode(p0));
969 }
970}
971
972TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithPlainPrimitive) {
973 Node* function = StringFunction("fromCharCode");
974
975 Node* effect = graph()->start();
976 Node* control = graph()->start();
977 Node* context = UndefinedConstant();
978 Node* frame_state = graph()->start();
979 Node* p0 = Parameter(Type::PlainPrimitive(), 0);
980 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
981 UndefinedConstant(), p0, context, frame_state,
982 effect, control);
983 Reduction r = Reduce(call);
984
985 ASSERT_TRUE(r.Changed());
986 EXPECT_THAT(r.replacement(),
987 IsStringFromCharCode(IsPlainPrimitiveToNumber(p0)));
988}
989
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400990} // namespace compiler
991} // namespace internal
992} // namespace v8