blob: 78e9253a1717257385fb6ee1c5c670c265877f0c [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(
46 JSObject::GetProperty(
47 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
67const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
68
69
Emily Bernierd0a1eb72015-03-24 16:35:39 -040070// TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
71Type* const kNumberTypes[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
73 Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
74 Type::Integral32(), Type::MinusZero(), Type::NaN(),
75 Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076
77} // namespace
78
79
80// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -040081// Math.max
82
83
84TEST_F(JSBuiltinReducerTest, MathMax0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 Node* effect = graph()->start();
88 Node* control = graph()->start();
89 Node* context = UndefinedConstant();
90 Node* frame_state = graph()->start();
91 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
92 Node* call = graph()->NewNode(javascript()->CallFunction(2, language_mode),
93 function, UndefinedConstant(), context,
94 frame_state, frame_state, effect, control);
95 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 ASSERT_TRUE(r.Changed());
98 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
99 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400100}
101
102
103TEST_F(JSBuiltinReducerTest, MathMax1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 Node* effect = graph()->start();
107 Node* control = graph()->start();
108 Node* context = UndefinedConstant();
109 Node* frame_state = graph()->start();
110 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
111 TRACED_FOREACH(Type*, t0, kNumberTypes) {
112 Node* p0 = Parameter(t0, 0);
113 Node* call =
114 graph()->NewNode(javascript()->CallFunction(3, language_mode),
115 function, UndefinedConstant(), p0, context,
116 frame_state, frame_state, effect, control);
117 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 ASSERT_TRUE(r.Changed());
120 EXPECT_THAT(r.replacement(), p0);
121 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122 }
123}
124
125
126TEST_F(JSBuiltinReducerTest, MathMax2) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 Node* function = MathFunction("max");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 Node* effect = graph()->start();
130 Node* control = graph()->start();
131 Node* context = UndefinedConstant();
132 Node* frame_state = graph()->start();
133 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
134 TRACED_FOREACH(Type*, t0, kIntegral32Types) {
135 TRACED_FOREACH(Type*, t1, kIntegral32Types) {
136 Node* p0 = Parameter(t0, 0);
137 Node* p1 = Parameter(t1, 1);
138 Node* call =
139 graph()->NewNode(javascript()->CallFunction(4, language_mode),
140 function, UndefinedConstant(), p0, p1, context,
141 frame_state, frame_state, effect, control);
142 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400143
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144 ASSERT_TRUE(r.Changed());
145 EXPECT_THAT(r.replacement(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 IsSelect(MachineRepresentation::kNone,
147 IsNumberLessThan(p1, p0), p0, p1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400148 }
149 }
150 }
151}
152
153
154// -----------------------------------------------------------------------------
155// Math.imul
156
157
158TEST_F(JSBuiltinReducerTest, MathImul) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 Node* function = MathFunction("imul");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400160
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 Node* effect = graph()->start();
162 Node* control = graph()->start();
163 Node* context = UndefinedConstant();
164 Node* frame_state = graph()->start();
165 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
166 TRACED_FOREACH(Type*, t0, kIntegral32Types) {
167 TRACED_FOREACH(Type*, t1, kIntegral32Types) {
168 Node* p0 = Parameter(t0, 0);
169 Node* p1 = Parameter(t1, 1);
170 Node* call =
171 graph()->NewNode(javascript()->CallFunction(4, language_mode),
172 function, UndefinedConstant(), p0, p1, context,
173 frame_state, frame_state, effect, control);
174 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400176 ASSERT_TRUE(r.Changed());
177 EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178 }
179 }
180 }
181}
182
183
184// -----------------------------------------------------------------------------
185// Math.fround
186
187
188TEST_F(JSBuiltinReducerTest, MathFround) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 Node* function = MathFunction("fround");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 Node* effect = graph()->start();
192 Node* control = graph()->start();
193 Node* context = UndefinedConstant();
194 Node* frame_state = graph()->start();
195 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
196 TRACED_FOREACH(Type*, t0, kNumberTypes) {
197 Node* p0 = Parameter(t0, 0);
198 Node* call =
199 graph()->NewNode(javascript()->CallFunction(3, language_mode),
200 function, UndefinedConstant(), p0, context,
201 frame_state, frame_state, effect, control);
202 Reduction r = Reduce(call);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 ASSERT_TRUE(r.Changed());
205 EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
206 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207 }
208}
209
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400210} // namespace compiler
211} // namespace internal
212} // namespace v8