OLD | NEW |
| (Empty) |
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 "src/compiler/graph-unittest.h" | |
6 #include "src/compiler/js-builtin-reducer.h" | |
7 #include "src/compiler/js-graph.h" | |
8 #include "src/compiler/node-properties-inl.h" | |
9 #include "src/compiler/typer.h" | |
10 #include "testing/gmock-support.h" | |
11 | |
12 using testing::Capture; | |
13 | |
14 namespace v8 { | |
15 namespace internal { | |
16 namespace compiler { | |
17 | |
18 class JSBuiltinReducerTest : public GraphTest { | |
19 public: | |
20 JSBuiltinReducerTest() : javascript_(zone()) {} | |
21 | |
22 protected: | |
23 Reduction Reduce(Node* node) { | |
24 Typer typer(zone()); | |
25 MachineOperatorBuilder machine; | |
26 JSGraph jsgraph(graph(), common(), javascript(), &typer, &machine); | |
27 JSBuiltinReducer reducer(&jsgraph); | |
28 return reducer.Reduce(node); | |
29 } | |
30 | |
31 Node* Parameter(Type* t, int32_t index = 0) { | |
32 Node* n = graph()->NewNode(common()->Parameter(index), graph()->start()); | |
33 NodeProperties::SetBounds(n, Bounds(Type::None(), t)); | |
34 return n; | |
35 } | |
36 | |
37 Node* UndefinedConstant() { | |
38 return HeapConstant( | |
39 Unique<HeapObject>::CreateImmovable(factory()->undefined_value())); | |
40 } | |
41 | |
42 JSOperatorBuilder* javascript() { return &javascript_; } | |
43 | |
44 private: | |
45 JSOperatorBuilder javascript_; | |
46 }; | |
47 | |
48 | |
49 namespace { | |
50 | |
51 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering. | |
52 Type* const kNumberTypes[] = { | |
53 Type::UnsignedSmall(), Type::OtherSignedSmall(), Type::OtherUnsigned31(), | |
54 Type::OtherUnsigned32(), Type::OtherSigned32(), Type::SignedSmall(), | |
55 Type::Signed32(), Type::Unsigned32(), Type::Integral32(), | |
56 Type::MinusZero(), Type::NaN(), Type::OtherNumber(), | |
57 Type::OrderedNumber(), Type::Number()}; | |
58 | |
59 } // namespace | |
60 | |
61 | |
62 // ----------------------------------------------------------------------------- | |
63 // Math.abs | |
64 | |
65 | |
66 TEST_F(JSBuiltinReducerTest, MathAbs) { | |
67 Handle<JSFunction> f(isolate()->context()->math_abs_fun()); | |
68 | |
69 TRACED_FOREACH(Type*, t0, kNumberTypes) { | |
70 Node* p0 = Parameter(t0, 0); | |
71 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
72 Node* call = | |
73 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | |
74 fun, UndefinedConstant(), p0); | |
75 Reduction r = Reduce(call); | |
76 | |
77 if (t0->Is(Type::Unsigned32())) { | |
78 ASSERT_TRUE(r.Changed()); | |
79 EXPECT_THAT(r.replacement(), p0); | |
80 } else { | |
81 Capture<Node*> branch; | |
82 ASSERT_TRUE(r.Changed()); | |
83 EXPECT_THAT( | |
84 r.replacement(), | |
85 IsPhi(kMachNone, p0, IsNumberSubtract(IsNumberConstant(0), p0), | |
86 IsMerge(IsIfTrue(CaptureEq(&branch)), | |
87 IsIfFalse(AllOf( | |
88 CaptureEq(&branch), | |
89 IsBranch(IsNumberLessThan(IsNumberConstant(0), p0), | |
90 graph()->start())))))); | |
91 } | |
92 } | |
93 } | |
94 | |
95 | |
96 // ----------------------------------------------------------------------------- | |
97 // Math.sqrt | |
98 | |
99 | |
100 TEST_F(JSBuiltinReducerTest, MathSqrt) { | |
101 Handle<JSFunction> f(isolate()->context()->math_sqrt_fun()); | |
102 | |
103 TRACED_FOREACH(Type*, t0, kNumberTypes) { | |
104 Node* p0 = Parameter(t0, 0); | |
105 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
106 Node* call = | |
107 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | |
108 fun, UndefinedConstant(), p0); | |
109 Reduction r = Reduce(call); | |
110 | |
111 ASSERT_TRUE(r.Changed()); | |
112 EXPECT_THAT(r.replacement(), IsFloat64Sqrt(p0)); | |
113 } | |
114 } | |
115 | |
116 | |
117 // ----------------------------------------------------------------------------- | |
118 // Math.max | |
119 | |
120 | |
121 TEST_F(JSBuiltinReducerTest, MathMax0) { | |
122 Handle<JSFunction> f(isolate()->context()->math_max_fun()); | |
123 | |
124 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
125 Node* call = | |
126 graph()->NewNode(javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS), | |
127 fun, UndefinedConstant()); | |
128 Reduction r = Reduce(call); | |
129 | |
130 ASSERT_TRUE(r.Changed()); | |
131 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY)); | |
132 } | |
133 | |
134 | |
135 TEST_F(JSBuiltinReducerTest, MathMax1) { | |
136 Handle<JSFunction> f(isolate()->context()->math_max_fun()); | |
137 | |
138 TRACED_FOREACH(Type*, t0, kNumberTypes) { | |
139 Node* p0 = Parameter(t0, 0); | |
140 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
141 Node* call = | |
142 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | |
143 fun, UndefinedConstant(), p0); | |
144 Reduction r = Reduce(call); | |
145 | |
146 ASSERT_TRUE(r.Changed()); | |
147 EXPECT_THAT(r.replacement(), p0); | |
148 } | |
149 } | |
150 | |
151 | |
152 TEST_F(JSBuiltinReducerTest, MathMax2) { | |
153 Handle<JSFunction> f(isolate()->context()->math_max_fun()); | |
154 | |
155 TRACED_FOREACH(Type*, t0, kNumberTypes) { | |
156 TRACED_FOREACH(Type*, t1, kNumberTypes) { | |
157 Node* p0 = Parameter(t0, 0); | |
158 Node* p1 = Parameter(t1, 1); | |
159 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
160 Node* call = graph()->NewNode( | |
161 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun, | |
162 UndefinedConstant(), p0, p1); | |
163 Reduction r = Reduce(call); | |
164 | |
165 if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) { | |
166 Capture<Node*> branch; | |
167 ASSERT_TRUE(r.Changed()); | |
168 EXPECT_THAT( | |
169 r.replacement(), | |
170 IsPhi(kMachNone, p1, p0, | |
171 IsMerge(IsIfTrue(CaptureEq(&branch)), | |
172 IsIfFalse(AllOf(CaptureEq(&branch), | |
173 IsBranch(IsNumberLessThan(p0, p1), | |
174 graph()->start())))))); | |
175 } else { | |
176 ASSERT_FALSE(r.Changed()); | |
177 EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode()); | |
178 } | |
179 } | |
180 } | |
181 } | |
182 | |
183 | |
184 // ----------------------------------------------------------------------------- | |
185 // Math.imul | |
186 | |
187 | |
188 TEST_F(JSBuiltinReducerTest, MathImul) { | |
189 Handle<JSFunction> f(isolate()->context()->math_imul_fun()); | |
190 | |
191 TRACED_FOREACH(Type*, t0, kNumberTypes) { | |
192 TRACED_FOREACH(Type*, t1, kNumberTypes) { | |
193 Node* p0 = Parameter(t0, 0); | |
194 Node* p1 = Parameter(t1, 1); | |
195 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
196 Node* call = graph()->NewNode( | |
197 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun, | |
198 UndefinedConstant(), p0, p1); | |
199 Reduction r = Reduce(call); | |
200 | |
201 if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) { | |
202 ASSERT_TRUE(r.Changed()); | |
203 EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1)); | |
204 } else { | |
205 ASSERT_FALSE(r.Changed()); | |
206 EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode()); | |
207 } | |
208 } | |
209 } | |
210 } | |
211 | |
212 | |
213 // ----------------------------------------------------------------------------- | |
214 // Math.fround | |
215 | |
216 | |
217 TEST_F(JSBuiltinReducerTest, MathFround) { | |
218 Handle<Object> m = | |
219 JSObject::GetProperty(isolate()->global_object(), | |
220 isolate()->factory()->NewStringFromAsciiChecked( | |
221 "Math")).ToHandleChecked(); | |
222 Handle<JSFunction> f = Handle<JSFunction>::cast( | |
223 JSObject::GetProperty(m, isolate()->factory()->NewStringFromAsciiChecked( | |
224 "fround")).ToHandleChecked()); | |
225 | |
226 TRACED_FOREACH(Type*, t0, kNumberTypes) { | |
227 Node* p0 = Parameter(t0, 0); | |
228 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | |
229 Node* call = | |
230 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | |
231 fun, UndefinedConstant(), p0); | |
232 Reduction r = Reduce(call); | |
233 | |
234 ASSERT_TRUE(r.Changed()); | |
235 EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0)); | |
236 } | |
237 } | |
238 | |
239 } // namespace compiler | |
240 } // namespace internal | |
241 } // namespace v8 | |
OLD | NEW |