blob: 0f8eed7958587baf4ff6445d1f2fc0caa9557261 [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
52 JSOperatorBuilder* javascript() { return &javascript_; }
53
54 private:
55 JSOperatorBuilder javascript_;
56};
57
58
59namespace {
60
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061Type* const kIntegral32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
62 Type::Unsigned31(), Type::SignedSmall(),
63 Type::Signed32(), Type::Unsigned32(),
64 Type::Integral32()};
65
66
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067Type* const kNumberTypes[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
69 Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
70 Type::Integral32(), Type::MinusZero(), Type::NaN(),
71 Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072
73} // namespace
74
75
76// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -040077// Math.max
78
79
80TEST_F(JSBuiltinReducerTest, MathMax0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 Node* effect = graph()->start();
84 Node* control = graph()->start();
85 Node* context = UndefinedConstant();
86 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +010087 Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
88 UndefinedConstant(), context, frame_state,
89 frame_state, effect, control);
90 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091
Ben Murdoch097c5b22016-05-18 11:27:45 +010092 ASSERT_TRUE(r.Changed());
93 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040094}
95
96
97TEST_F(JSBuiltinReducerTest, MathMax1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100 Node* effect = graph()->start();
101 Node* control = graph()->start();
102 Node* context = UndefinedConstant();
103 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100104 TRACED_FOREACH(Type*, t0, kNumberTypes) {
105 Node* p0 = Parameter(t0, 0);
106 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
107 UndefinedConstant(), p0, context, frame_state,
108 frame_state, effect, control);
109 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 ASSERT_TRUE(r.Changed());
112 EXPECT_THAT(r.replacement(), p0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400113 }
114}
115
116
117TEST_F(JSBuiltinReducerTest, MathMax2) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 Node* effect = graph()->start();
121 Node* control = graph()->start();
122 Node* context = UndefinedConstant();
123 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100124 TRACED_FOREACH(Type*, t0, kIntegral32Types) {
125 TRACED_FOREACH(Type*, t1, kIntegral32Types) {
126 Node* p0 = Parameter(t0, 0);
127 Node* p1 = Parameter(t1, 1);
128 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
129 UndefinedConstant(), p0, p1, context,
130 frame_state, frame_state, effect, control);
131 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400132
Ben Murdoch097c5b22016-05-18 11:27:45 +0100133 ASSERT_TRUE(r.Changed());
134 EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
135 IsNumberLessThan(p1, p0), p0, p1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400136 }
137 }
138}
139
140
141// -----------------------------------------------------------------------------
142// Math.imul
143
144
145TEST_F(JSBuiltinReducerTest, MathImul) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 Node* function = MathFunction("imul");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 Node* effect = graph()->start();
149 Node* control = graph()->start();
150 Node* context = UndefinedConstant();
151 Node* frame_state = graph()->start();
Ben Murdochda12d292016-06-02 14:46:10 +0100152 TRACED_FOREACH(Type*, t0, kNumberTypes) {
153 TRACED_FOREACH(Type*, t1, kNumberTypes) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100154 Node* p0 = Parameter(t0, 0);
155 Node* p1 = Parameter(t1, 1);
156 Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
157 UndefinedConstant(), p0, p1, context,
158 frame_state, frame_state, effect, control);
159 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400160
Ben Murdoch097c5b22016-05-18 11:27:45 +0100161 ASSERT_TRUE(r.Changed());
Ben Murdochda12d292016-06-02 14:46:10 +0100162 EXPECT_THAT(r.replacement(),
163 IsNumberImul(IsNumberToUint32(p0), IsNumberToUint32(p1)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164 }
165 }
166}
167
168
169// -----------------------------------------------------------------------------
170// Math.fround
171
172
173TEST_F(JSBuiltinReducerTest, MathFround) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 Node* function = MathFunction("fround");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 Node* effect = graph()->start();
177 Node* control = graph()->start();
178 Node* context = UndefinedConstant();
179 Node* frame_state = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100180 TRACED_FOREACH(Type*, t0, kNumberTypes) {
181 Node* p0 = Parameter(t0, 0);
182 Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
183 UndefinedConstant(), p0, context, frame_state,
184 frame_state, effect, control);
185 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186
Ben Murdoch097c5b22016-05-18 11:27:45 +0100187 ASSERT_TRUE(r.Changed());
188 EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400189 }
190}
191
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192} // namespace compiler
193} // namespace internal
194} // namespace v8