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.
5 #include "src/compiler/js-builtin-reducer.h"
6 #include "src/compiler/js-graph.h"
7 #include "src/compiler/node-properties.h"
8 #include "src/compiler/typer.h"
9 #include "test/unittests/compiler/graph-unittest.h"
10 #include "test/unittests/compiler/node-test-utils.h"
11 #include "testing/gmock-support.h"
14 using testing::Capture;
20 class JSBuiltinReducerTest : public TypedGraphTest {
22 JSBuiltinReducerTest() : javascript_(zone()) {}
25 Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
26 MachineOperatorBuilder::Flag::kNoFlags) {
27 MachineOperatorBuilder machine(zone(), kMachPtr, flags);
28 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
29 JSBuiltinReducer reducer(&jsgraph);
30 return reducer.Reduce(node);
33 Handle<JSFunction> MathFunction(const char* name) {
35 JSObject::GetProperty(isolate()->global_object(),
36 isolate()->factory()->NewStringFromAsciiChecked(
37 "Math")).ToHandleChecked();
38 Handle<JSFunction> f = Handle<JSFunction>::cast(
39 JSObject::GetProperty(
40 m, isolate()->factory()->NewStringFromAsciiChecked(name))
45 JSOperatorBuilder* javascript() { return &javascript_; }
48 JSOperatorBuilder javascript_;
54 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
55 Type* const kNumberTypes[] = {
56 Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
57 Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
58 Type::Integral32(), Type::MinusZero(), Type::NaN(),
59 Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
64 // -----------------------------------------------------------------------------
68 TEST_F(JSBuiltinReducerTest, MathMax0) {
69 Handle<JSFunction> f = MathFunction("max");
71 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
73 graph()->NewNode(javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS),
74 fun, UndefinedConstant());
75 Reduction r = Reduce(call);
77 ASSERT_TRUE(r.Changed());
78 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
82 TEST_F(JSBuiltinReducerTest, MathMax1) {
83 Handle<JSFunction> f = MathFunction("max");
85 TRACED_FOREACH(Type*, t0, kNumberTypes) {
86 Node* p0 = Parameter(t0, 0);
87 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
89 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
90 fun, UndefinedConstant(), p0);
91 Reduction r = Reduce(call);
93 ASSERT_TRUE(r.Changed());
94 EXPECT_THAT(r.replacement(), p0);
99 TEST_F(JSBuiltinReducerTest, MathMax2) {
100 Handle<JSFunction> f = MathFunction("max");
102 TRACED_FOREACH(Type*, t0, kNumberTypes) {
103 TRACED_FOREACH(Type*, t1, kNumberTypes) {
104 Node* p0 = Parameter(t0, 0);
105 Node* p1 = Parameter(t1, 1);
106 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
107 Node* call = graph()->NewNode(
108 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun,
109 UndefinedConstant(), p0, p1);
110 Reduction r = Reduce(call);
112 if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
113 ASSERT_TRUE(r.Changed());
114 EXPECT_THAT(r.replacement(),
115 IsSelect(kMachNone, IsNumberLessThan(p1, p0), p0, p1));
117 ASSERT_FALSE(r.Changed());
118 EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode());
125 // -----------------------------------------------------------------------------
129 TEST_F(JSBuiltinReducerTest, MathImul) {
130 Handle<JSFunction> f = MathFunction("imul");
132 TRACED_FOREACH(Type*, t0, kNumberTypes) {
133 TRACED_FOREACH(Type*, t1, kNumberTypes) {
134 Node* p0 = Parameter(t0, 0);
135 Node* p1 = Parameter(t1, 1);
136 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
137 Node* call = graph()->NewNode(
138 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun,
139 UndefinedConstant(), p0, p1);
140 Reduction r = Reduce(call);
142 if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
143 ASSERT_TRUE(r.Changed());
144 EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
146 ASSERT_FALSE(r.Changed());
147 EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode());
154 // -----------------------------------------------------------------------------
158 TEST_F(JSBuiltinReducerTest, MathFround) {
159 Handle<JSFunction> f = MathFunction("fround");
161 TRACED_FOREACH(Type*, t0, kNumberTypes) {
162 Node* p0 = Parameter(t0, 0);
163 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
165 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
166 fun, UndefinedConstant(), p0);
167 Reduction r = Reduce(call);
169 ASSERT_TRUE(r.Changed());
170 EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
174 } // namespace compiler
175 } // namespace internal