Line data Source code
1 : // Copyright 2016 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/int64-lowering.h"
6 : #include "src/compiler/common-operator.h"
7 : #include "src/compiler/linkage.h"
8 : #include "src/compiler/machine-operator.h"
9 : #include "src/compiler/node.h"
10 : #include "src/compiler/wasm-compiler.h"
11 :
12 : #include "src/compiler/node-properties.h"
13 :
14 : #include "src/objects-inl.h"
15 : #include "src/signature.h"
16 :
17 : #include "src/wasm/wasm-module.h"
18 :
19 : #include "test/unittests/compiler/graph-unittest.h"
20 : #include "test/unittests/compiler/node-test-utils.h"
21 : #include "testing/gmock-support.h"
22 :
23 : using testing::AllOf;
24 : using testing::Capture;
25 : using testing::CaptureEq;
26 :
27 : namespace v8 {
28 : namespace internal {
29 : namespace compiler {
30 :
31 45 : class Int64LoweringTest : public GraphTest {
32 : public:
33 45 : Int64LoweringTest()
34 : : GraphTest(),
35 : machine_(zone(), MachineRepresentation::kWord32,
36 90 : MachineOperatorBuilder::Flag::kAllOptionalOps) {
37 45 : value_[0] = 0x1234567890abcdef;
38 45 : value_[1] = 0x1edcba098765432f;
39 45 : value_[2] = 0x1133557799886644;
40 45 : }
41 :
42 : MachineOperatorBuilder* machine() { return &machine_; }
43 :
44 42 : void LowerGraph(Node* node, Signature<MachineRepresentation>* signature) {
45 42 : Node* zero = graph()->NewNode(common()->Int32Constant(0));
46 : Node* ret = graph()->NewNode(common()->Return(), zero, node,
47 42 : graph()->start(), graph()->start());
48 42 : NodeProperties::MergeControlToEnd(graph(), common(), ret);
49 :
50 42 : Int64Lowering lowering(graph(), machine(), common(), zone(), signature);
51 42 : lowering.LowerGraph();
52 42 : }
53 :
54 41 : void LowerGraph(Node* node, MachineRepresentation return_type,
55 : MachineRepresentation rep = MachineRepresentation::kWord32,
56 : int num_params = 0) {
57 : Signature<MachineRepresentation>::Builder sig_builder(zone(), 1,
58 41 : num_params);
59 : sig_builder.AddReturn(return_type);
60 43 : for (int i = 0; i < num_params; i++) {
61 : sig_builder.AddParam(rep);
62 : }
63 41 : LowerGraph(node, sig_builder.Build());
64 41 : }
65 :
66 : void CompareCallDescriptors(const CallDescriptor* lhs,
67 : const CallDescriptor* rhs) {
68 : EXPECT_THAT(lhs->CalleeSavedFPRegisters(), rhs->CalleeSavedFPRegisters());
69 : EXPECT_THAT(lhs->CalleeSavedRegisters(), rhs->CalleeSavedRegisters());
70 : EXPECT_THAT(lhs->FrameStateCount(), rhs->FrameStateCount());
71 : EXPECT_THAT(lhs->InputCount(), rhs->InputCount());
72 : for (size_t i = 0; i < lhs->InputCount(); i++) {
73 : EXPECT_THAT(lhs->GetInputLocation(i), rhs->GetInputLocation(i));
74 : EXPECT_THAT(lhs->GetInputType(i), rhs->GetInputType(i));
75 : }
76 : EXPECT_THAT(lhs->ReturnCount(), rhs->ReturnCount());
77 : for (size_t i = 0; i < lhs->ReturnCount(); i++) {
78 : EXPECT_THAT(lhs->GetReturnLocation(i), rhs->GetReturnLocation(i));
79 : EXPECT_THAT(lhs->GetReturnType(i), rhs->GetReturnType(i));
80 : }
81 : EXPECT_THAT(lhs->flags(), rhs->flags());
82 : EXPECT_THAT(lhs->kind(), rhs->kind());
83 : }
84 :
85 57 : int64_t value(int i) { return value_[i]; }
86 :
87 : int32_t low_word_value(int i) {
88 59 : return static_cast<int32_t>(value_[i] & 0xffffffff);
89 : }
90 :
91 : int32_t high_word_value(int i) {
92 53 : return static_cast<int32_t>(value_[i] >> 32);
93 : }
94 :
95 4 : void TestComparison(
96 : const Operator* op,
97 : Matcher<Node*> (*high_word_matcher)(const Matcher<Node*>& lhs_matcher,
98 : const Matcher<Node*>& rhs_matcher),
99 : Matcher<Node*> (*low_word_matcher)(const Matcher<Node*>& lhs_matcher,
100 : const Matcher<Node*>& rhs_matcher)) {
101 : LowerGraph(
102 : graph()->NewNode(op, Int64Constant(value(0)), Int64Constant(value(1))),
103 12 : MachineRepresentation::kWord32);
104 124 : EXPECT_THAT(
105 : graph()->end()->InputAt(1),
106 : IsReturn(IsWord32Or(
107 : high_word_matcher(IsInt32Constant(high_word_value(0)),
108 : IsInt32Constant(high_word_value(1))),
109 : IsWord32And(
110 : IsWord32Equal(IsInt32Constant(high_word_value(0)),
111 : IsInt32Constant(high_word_value(1))),
112 : low_word_matcher(IsInt32Constant(low_word_value(0)),
113 : IsInt32Constant(low_word_value(1))))),
114 0 : start(), start()));
115 4 : }
116 :
117 : private:
118 : MachineOperatorBuilder machine_;
119 : int64_t value_[3];
120 : };
121 :
122 13160 : TEST_F(Int64LoweringTest, Int64Constant) {
123 1 : LowerGraph(Int64Constant(value(0)), MachineRepresentation::kWord64);
124 14 : EXPECT_THAT(graph()->end()->InputAt(1),
125 : IsReturn2(IsInt32Constant(low_word_value(0)),
126 0 : IsInt32Constant(high_word_value(0)), start(), start()));
127 1 : }
128 :
129 : #if defined(V8_TARGET_LITTLE_ENDIAN)
130 : #define LOAD_VERIFY(kLoad) \
131 : Matcher<Node*> high_word_load_matcher = \
132 : Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
133 : IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), \
134 : start(), start()); \
135 : \
136 : EXPECT_THAT( \
137 : graph()->end()->InputAt(1), \
138 : IsReturn2( \
139 : Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
140 : IsInt32Constant(index), \
141 : AllOf(CaptureEq(&high_word_load), high_word_load_matcher), \
142 : start()), \
143 : AllOf(CaptureEq(&high_word_load), high_word_load_matcher), start(), \
144 : start()));
145 : #elif defined(V8_TARGET_BIG_ENDIAN)
146 : #define LOAD_VERIFY(kLoad) \
147 : Matcher<Node*> high_word_load_matcher = \
148 : Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
149 : IsInt32Constant(index), start(), start()); \
150 : \
151 : EXPECT_THAT( \
152 : graph()->end()->InputAt(1), \
153 : IsReturn2( \
154 : Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
155 : IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), \
156 : AllOf(CaptureEq(&high_word_load), high_word_load_matcher), \
157 : start()), \
158 : AllOf(CaptureEq(&high_word_load), high_word_load_matcher), start(), \
159 : start()));
160 : #endif
161 :
162 : #define INT64_LOAD_LOWERING(kLoad) \
163 : int32_t base = 0x1234; \
164 : int32_t index = 0x5678; \
165 : \
166 : LowerGraph(graph()->NewNode(machine()->kLoad(MachineType::Int64()), \
167 : Int32Constant(base), Int32Constant(index), \
168 : start(), start()), \
169 : MachineRepresentation::kWord64); \
170 : \
171 : Capture<Node*> high_word_load; \
172 : LOAD_VERIFY(kLoad)
173 :
174 13198 : TEST_F(Int64LoweringTest, Int64Load) { INT64_LOAD_LOWERING(Load); }
175 :
176 13160 : TEST_F(Int64LoweringTest, UnalignedInt64Load) {
177 37 : INT64_LOAD_LOWERING(UnalignedLoad);
178 1 : }
179 :
180 : #if defined(V8_TARGET_LITTLE_ENDIAN)
181 : #define STORE_VERIFY(kStore, kRep) \
182 : EXPECT_THAT( \
183 : graph()->end()->InputAt(1), \
184 : IsReturn(IsInt32Constant(return_value), \
185 : Is##kStore( \
186 : kRep, IsInt32Constant(base), IsInt32Constant(index), \
187 : IsInt32Constant(low_word_value(0)), \
188 : Is##kStore( \
189 : kRep, IsInt32Constant(base), \
190 : IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)), \
191 : IsInt32Constant(high_word_value(0)), start(), start()), \
192 : start()), \
193 : start()));
194 : #elif defined(V8_TARGET_BIG_ENDIAN)
195 : #define STORE_VERIFY(kStore, kRep) \
196 : EXPECT_THAT( \
197 : graph()->end()->InputAt(1), \
198 : IsReturn(IsInt32Constant(return_value), \
199 : Is##kStore( \
200 : kRep, IsInt32Constant(base), \
201 : IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)), \
202 : IsInt32Constant(low_word_value(0)), \
203 : Is##kStore( \
204 : kRep, IsInt32Constant(base), IsInt32Constant(index), \
205 : IsInt32Constant(high_word_value(0)), start(), start()), \
206 : start()), \
207 : start()));
208 : #endif
209 :
210 : #define INT64_STORE_LOWERING(kStore, kRep32, kRep64) \
211 : int32_t base = 1111; \
212 : int32_t index = 2222; \
213 : int32_t return_value = 0x5555; \
214 : \
215 : Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0); \
216 : sig_builder.AddReturn(MachineRepresentation::kWord32); \
217 : \
218 : Node* store = graph()->NewNode(machine()->kStore(kRep64), \
219 : Int32Constant(base), Int32Constant(index), \
220 : Int64Constant(value(0)), start(), start()); \
221 : \
222 : Node* zero = graph()->NewNode(common()->Int32Constant(0)); \
223 : Node* ret = graph()->NewNode(common()->Return(), zero, \
224 : Int32Constant(return_value), store, start()); \
225 : \
226 : NodeProperties::MergeControlToEnd(graph(), common(), ret); \
227 : \
228 : Int64Lowering lowering(graph(), machine(), common(), zone(), \
229 : sig_builder.Build()); \
230 : lowering.LowerGraph(); \
231 : \
232 : STORE_VERIFY(kStore, kRep32)
233 :
234 13160 : TEST_F(Int64LoweringTest, Int64Store) {
235 : const StoreRepresentation rep64(MachineRepresentation::kWord64,
236 : WriteBarrierKind::kNoWriteBarrier);
237 : const StoreRepresentation rep32(MachineRepresentation::kWord32,
238 : WriteBarrierKind::kNoWriteBarrier);
239 39 : INT64_STORE_LOWERING(Store, rep32, rep64);
240 1 : }
241 :
242 13160 : TEST_F(Int64LoweringTest, Int32Store) {
243 : const StoreRepresentation rep32(MachineRepresentation::kWord32,
244 : WriteBarrierKind::kNoWriteBarrier);
245 : int32_t base = 1111;
246 : int32_t index = 2222;
247 : int32_t return_value = 0x5555;
248 :
249 1 : Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
250 : sig_builder.AddReturn(MachineRepresentation::kWord32);
251 :
252 : Node* store = graph()->NewNode(machine()->Store(rep32), Int32Constant(base),
253 : Int32Constant(index), Int64Constant(value(0)),
254 1 : start(), start());
255 :
256 1 : Node* zero = graph()->NewNode(common()->Int32Constant(0));
257 : Node* ret = graph()->NewNode(common()->Return(), zero,
258 1 : Int32Constant(return_value), store, start());
259 :
260 1 : NodeProperties::MergeControlToEnd(graph(), common(), ret);
261 :
262 : Int64Lowering lowering(graph(), machine(), common(), zone(),
263 1 : sig_builder.Build());
264 1 : lowering.LowerGraph();
265 :
266 21 : EXPECT_THAT(
267 : graph()->end()->InputAt(1),
268 : IsReturn(IsInt32Constant(return_value),
269 : IsStore(rep32, IsInt32Constant(base), IsInt32Constant(index),
270 : IsInt32Constant(low_word_value(0)), start(), start()),
271 0 : start()));
272 1 : }
273 :
274 13160 : TEST_F(Int64LoweringTest, Int64UnalignedStore) {
275 : const UnalignedStoreRepresentation rep64(MachineRepresentation::kWord64);
276 : const UnalignedStoreRepresentation rep32(MachineRepresentation::kWord32);
277 39 : INT64_STORE_LOWERING(UnalignedStore, rep32, rep64);
278 1 : }
279 :
280 13160 : TEST_F(Int64LoweringTest, Int64And) {
281 : LowerGraph(graph()->NewNode(machine()->Word64And(), Int64Constant(value(0)),
282 : Int64Constant(value(1))),
283 3 : MachineRepresentation::kWord64);
284 22 : EXPECT_THAT(graph()->end()->InputAt(1),
285 : IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
286 : IsInt32Constant(low_word_value(1))),
287 : IsWord32And(IsInt32Constant(high_word_value(0)),
288 : IsInt32Constant(high_word_value(1))),
289 0 : start(), start()));
290 1 : }
291 :
292 13160 : TEST_F(Int64LoweringTest, TruncateInt64ToInt32) {
293 : LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
294 : Int64Constant(value(0))),
295 2 : MachineRepresentation::kWord32);
296 11 : EXPECT_THAT(graph()->end()->InputAt(1),
297 0 : IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
298 1 : }
299 :
300 13160 : TEST_F(Int64LoweringTest, Parameter) {
301 : LowerGraph(Parameter(1), MachineRepresentation::kWord64,
302 1 : MachineRepresentation::kWord64, 1);
303 :
304 12 : EXPECT_THAT(graph()->end()->InputAt(1),
305 0 : IsReturn2(IsParameter(1), IsParameter(2), start(), start()));
306 1 : }
307 :
308 13160 : TEST_F(Int64LoweringTest, Parameter2) {
309 1 : Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 5);
310 : sig_builder.AddReturn(MachineRepresentation::kWord32);
311 :
312 : sig_builder.AddParam(MachineRepresentation::kWord32);
313 : sig_builder.AddParam(MachineRepresentation::kWord64);
314 : sig_builder.AddParam(MachineRepresentation::kFloat64);
315 : sig_builder.AddParam(MachineRepresentation::kWord64);
316 : sig_builder.AddParam(MachineRepresentation::kWord32);
317 :
318 1 : int start_parameter = start()->op()->ValueOutputCount();
319 1 : LowerGraph(Parameter(5), sig_builder.Build());
320 :
321 10 : EXPECT_THAT(graph()->end()->InputAt(1),
322 0 : IsReturn(IsParameter(7), start(), start()));
323 : // The parameter of the start node should increase by 2, because we lowered
324 : // two parameter nodes.
325 2 : EXPECT_THAT(start()->op()->ValueOutputCount(), start_parameter + 2);
326 1 : }
327 :
328 : // The following tests assume that pointers are 32 bit and therefore pointers do
329 : // not get lowered. This assumption does not hold on 64 bit platforms, which
330 : // invalidates these tests.
331 : // TODO(wasm): We can find an alternative to re-activate these tests.
332 : #if V8_TARGET_ARCH_32_BIT
333 : TEST_F(Int64LoweringTest, CallI64Return) {
334 : int32_t function = 0x9999;
335 : Node* context_address = Int32Constant(0);
336 :
337 : Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
338 : sig_builder.AddReturn(MachineRepresentation::kWord64);
339 :
340 : compiler::CallDescriptor* desc =
341 : compiler::GetWasmCallDescriptor(zone(), sig_builder.Build());
342 :
343 : LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
344 : context_address, start(), start()),
345 : MachineRepresentation::kWord64);
346 :
347 : Capture<Node*> call;
348 : Matcher<Node*> call_matcher =
349 : IsCall(testing::_, IsInt32Constant(function), start(), start());
350 :
351 : EXPECT_THAT(graph()->end()->InputAt(1),
352 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&call), call_matcher)),
353 : IsProjection(1, AllOf(CaptureEq(&call), call_matcher)),
354 : start(), start()));
355 :
356 : CompareCallDescriptors(
357 : OpParameter<const CallDescriptor*>(
358 : graph()->end()->InputAt(1)->InputAt(1)->InputAt(0)),
359 : compiler::GetI32WasmCallDescriptor(zone(), desc));
360 : }
361 :
362 : TEST_F(Int64LoweringTest, CallI64Parameter) {
363 : int32_t function = 0x9999;
364 : Node* context_address = Int32Constant(0);
365 :
366 : Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 3);
367 : sig_builder.AddReturn(MachineRepresentation::kWord32);
368 : sig_builder.AddParam(MachineRepresentation::kWord64);
369 : sig_builder.AddParam(MachineRepresentation::kWord32);
370 : sig_builder.AddParam(MachineRepresentation::kWord64);
371 :
372 : compiler::CallDescriptor* desc =
373 : compiler::GetWasmCallDescriptor(zone(), sig_builder.Build());
374 :
375 : LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
376 : context_address, Int64Constant(value(0)),
377 : Int32Constant(low_word_value(1)),
378 : Int64Constant(value(2)), start(), start()),
379 : MachineRepresentation::kWord32);
380 :
381 : EXPECT_THAT(
382 : graph()->end()->InputAt(1),
383 : IsReturn(IsCall(testing::_, IsInt32Constant(function), context_address,
384 : IsInt32Constant(low_word_value(0)),
385 : IsInt32Constant(high_word_value(0)),
386 : IsInt32Constant(low_word_value(1)),
387 : IsInt32Constant(low_word_value(2)),
388 : IsInt32Constant(high_word_value(2)), start(), start()),
389 : start(), start()));
390 :
391 : CompareCallDescriptors(OpParameter<const CallDescriptor*>(
392 : graph()->end()->InputAt(1)->InputAt(1)),
393 : compiler::GetI32WasmCallDescriptor(zone(), desc));
394 : }
395 :
396 : TEST_F(Int64LoweringTest, Int64Add) {
397 : LowerGraph(graph()->NewNode(machine()->Int64Add(), Int64Constant(value(0)),
398 : Int64Constant(value(1))),
399 : MachineRepresentation::kWord64);
400 :
401 : Capture<Node*> add;
402 : Matcher<Node*> add_matcher = IsInt32PairAdd(
403 : IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
404 : IsInt32Constant(low_word_value(1)), IsInt32Constant(high_word_value(1)));
405 :
406 : EXPECT_THAT(graph()->end()->InputAt(1),
407 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&add), add_matcher)),
408 : IsProjection(1, AllOf(CaptureEq(&add), add_matcher)),
409 : start(), start()));
410 : }
411 : #endif
412 :
413 13160 : TEST_F(Int64LoweringTest, Int64Sub) {
414 : LowerGraph(graph()->NewNode(machine()->Int64Sub(), Int64Constant(value(0)),
415 : Int64Constant(value(1))),
416 3 : MachineRepresentation::kWord64);
417 :
418 : Capture<Node*> sub;
419 : Matcher<Node*> sub_matcher = IsInt32PairSub(
420 : IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
421 12 : IsInt32Constant(low_word_value(1)), IsInt32Constant(high_word_value(1)));
422 :
423 20 : EXPECT_THAT(graph()->end()->InputAt(1),
424 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&sub), sub_matcher)),
425 : IsProjection(1, AllOf(CaptureEq(&sub), sub_matcher)),
426 0 : start(), start()));
427 1 : }
428 :
429 13160 : TEST_F(Int64LoweringTest, Int64Mul) {
430 : LowerGraph(graph()->NewNode(machine()->Int64Mul(), Int64Constant(value(0)),
431 : Int64Constant(value(1))),
432 3 : MachineRepresentation::kWord64);
433 :
434 : Capture<Node*> mul_capture;
435 : Matcher<Node*> mul_matcher = IsInt32PairMul(
436 : IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
437 12 : IsInt32Constant(low_word_value(1)), IsInt32Constant(high_word_value(1)));
438 :
439 20 : EXPECT_THAT(
440 : graph()->end()->InputAt(1),
441 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&mul_capture), mul_matcher)),
442 : IsProjection(1, AllOf(CaptureEq(&mul_capture), mul_matcher)),
443 0 : start(), start()));
444 1 : }
445 :
446 13160 : TEST_F(Int64LoweringTest, Int64Ior) {
447 : LowerGraph(graph()->NewNode(machine()->Word64Or(), Int64Constant(value(0)),
448 : Int64Constant(value(1))),
449 3 : MachineRepresentation::kWord64);
450 22 : EXPECT_THAT(graph()->end()->InputAt(1),
451 : IsReturn2(IsWord32Or(IsInt32Constant(low_word_value(0)),
452 : IsInt32Constant(low_word_value(1))),
453 : IsWord32Or(IsInt32Constant(high_word_value(0)),
454 : IsInt32Constant(high_word_value(1))),
455 0 : start(), start()));
456 1 : }
457 :
458 13160 : TEST_F(Int64LoweringTest, Int64Xor) {
459 : LowerGraph(graph()->NewNode(machine()->Word64Xor(), Int64Constant(value(0)),
460 : Int64Constant(value(1))),
461 3 : MachineRepresentation::kWord64);
462 22 : EXPECT_THAT(graph()->end()->InputAt(1),
463 : IsReturn2(IsWord32Xor(IsInt32Constant(low_word_value(0)),
464 : IsInt32Constant(low_word_value(1))),
465 : IsWord32Xor(IsInt32Constant(high_word_value(0)),
466 : IsInt32Constant(high_word_value(1))),
467 0 : start(), start()));
468 1 : }
469 :
470 13160 : TEST_F(Int64LoweringTest, Int64Shl) {
471 : LowerGraph(graph()->NewNode(machine()->Word64Shl(), Int64Constant(value(0)),
472 : Int64Constant(value(1))),
473 3 : MachineRepresentation::kWord64);
474 :
475 : Capture<Node*> shl;
476 : Matcher<Node*> shl_matcher = IsWord32PairShl(
477 : IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
478 9 : IsInt32Constant(low_word_value(1)));
479 :
480 20 : EXPECT_THAT(graph()->end()->InputAt(1),
481 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&shl), shl_matcher)),
482 : IsProjection(1, AllOf(CaptureEq(&shl), shl_matcher)),
483 0 : start(), start()));
484 1 : }
485 :
486 13160 : TEST_F(Int64LoweringTest, Int64ShrU) {
487 : LowerGraph(graph()->NewNode(machine()->Word64Shr(), Int64Constant(value(0)),
488 : Int64Constant(value(1))),
489 3 : MachineRepresentation::kWord64);
490 :
491 : Capture<Node*> shr;
492 : Matcher<Node*> shr_matcher = IsWord32PairShr(
493 : IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
494 9 : IsInt32Constant(low_word_value(1)));
495 :
496 20 : EXPECT_THAT(graph()->end()->InputAt(1),
497 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&shr), shr_matcher)),
498 : IsProjection(1, AllOf(CaptureEq(&shr), shr_matcher)),
499 0 : start(), start()));
500 1 : }
501 :
502 13160 : TEST_F(Int64LoweringTest, Int64ShrS) {
503 : LowerGraph(graph()->NewNode(machine()->Word64Sar(), Int64Constant(value(0)),
504 : Int64Constant(value(1))),
505 3 : MachineRepresentation::kWord64);
506 :
507 : Capture<Node*> sar;
508 : Matcher<Node*> sar_matcher = IsWord32PairSar(
509 : IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
510 9 : IsInt32Constant(low_word_value(1)));
511 :
512 20 : EXPECT_THAT(graph()->end()->InputAt(1),
513 : IsReturn2(IsProjection(0, AllOf(CaptureEq(&sar), sar_matcher)),
514 : IsProjection(1, AllOf(CaptureEq(&sar), sar_matcher)),
515 0 : start(), start()));
516 1 : }
517 :
518 13160 : TEST_F(Int64LoweringTest, Int64Eq) {
519 : LowerGraph(graph()->NewNode(machine()->Word64Equal(), Int64Constant(value(0)),
520 : Int64Constant(value(1))),
521 3 : MachineRepresentation::kWord32);
522 26 : EXPECT_THAT(
523 : graph()->end()->InputAt(1),
524 : IsReturn(IsWord32Equal(
525 : IsWord32Or(IsWord32Xor(IsInt32Constant(low_word_value(0)),
526 : IsInt32Constant(low_word_value(1))),
527 : IsWord32Xor(IsInt32Constant(high_word_value(0)),
528 : IsInt32Constant(high_word_value(1)))),
529 : IsInt32Constant(0)),
530 0 : start(), start()));
531 1 : }
532 :
533 13160 : TEST_F(Int64LoweringTest, Int64LtS) {
534 1 : TestComparison(machine()->Int64LessThan(), IsInt32LessThan, IsUint32LessThan);
535 1 : }
536 :
537 13160 : TEST_F(Int64LoweringTest, Int64LeS) {
538 : TestComparison(machine()->Int64LessThanOrEqual(), IsInt32LessThan,
539 1 : IsUint32LessThanOrEqual);
540 1 : }
541 :
542 13160 : TEST_F(Int64LoweringTest, Int64LtU) {
543 : TestComparison(machine()->Uint64LessThan(), IsUint32LessThan,
544 1 : IsUint32LessThan);
545 1 : }
546 :
547 13160 : TEST_F(Int64LoweringTest, Int64LeU) {
548 : TestComparison(machine()->Uint64LessThanOrEqual(), IsUint32LessThan,
549 1 : IsUint32LessThanOrEqual);
550 1 : }
551 :
552 13160 : TEST_F(Int64LoweringTest, I32ConvertI64) {
553 : LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
554 : Int64Constant(value(0))),
555 2 : MachineRepresentation::kWord32);
556 11 : EXPECT_THAT(graph()->end()->InputAt(1),
557 0 : IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
558 1 : }
559 :
560 13160 : TEST_F(Int64LoweringTest, I64SConvertI32) {
561 : LowerGraph(graph()->NewNode(machine()->ChangeInt32ToInt64(),
562 : Int32Constant(low_word_value(0))),
563 2 : MachineRepresentation::kWord64);
564 :
565 17 : EXPECT_THAT(graph()->end()->InputAt(1),
566 : IsReturn2(IsInt32Constant(low_word_value(0)),
567 : IsWord32Sar(IsInt32Constant(low_word_value(0)),
568 : IsInt32Constant(31)),
569 0 : start(), start()));
570 1 : }
571 :
572 13160 : TEST_F(Int64LoweringTest, I64SConvertI32_2) {
573 : LowerGraph(
574 : graph()->NewNode(machine()->ChangeInt32ToInt64(),
575 : graph()->NewNode(machine()->TruncateInt64ToInt32(),
576 : Int64Constant(value(0)))),
577 3 : MachineRepresentation::kWord64);
578 :
579 17 : EXPECT_THAT(graph()->end()->InputAt(1),
580 : IsReturn2(IsInt32Constant(low_word_value(0)),
581 : IsWord32Sar(IsInt32Constant(low_word_value(0)),
582 : IsInt32Constant(31)),
583 0 : start(), start()));
584 1 : }
585 :
586 13160 : TEST_F(Int64LoweringTest, I64UConvertI32) {
587 : LowerGraph(graph()->NewNode(machine()->ChangeUint32ToUint64(),
588 : Int32Constant(low_word_value(0))),
589 2 : MachineRepresentation::kWord64);
590 :
591 13 : EXPECT_THAT(graph()->end()->InputAt(1),
592 : IsReturn2(IsInt32Constant(low_word_value(0)), IsInt32Constant(0),
593 0 : start(), start()));
594 1 : }
595 :
596 13160 : TEST_F(Int64LoweringTest, I64UConvertI32_2) {
597 : LowerGraph(
598 : graph()->NewNode(machine()->ChangeUint32ToUint64(),
599 : graph()->NewNode(machine()->TruncateInt64ToInt32(),
600 : Int64Constant(value(0)))),
601 3 : MachineRepresentation::kWord64);
602 :
603 13 : EXPECT_THAT(graph()->end()->InputAt(1),
604 : IsReturn2(IsInt32Constant(low_word_value(0)), IsInt32Constant(0),
605 0 : start(), start()));
606 1 : }
607 :
608 13160 : TEST_F(Int64LoweringTest, F64ReinterpretI64) {
609 : LowerGraph(graph()->NewNode(machine()->BitcastInt64ToFloat64(),
610 : Int64Constant(value(0))),
611 2 : MachineRepresentation::kFloat64);
612 :
613 : Capture<Node*> stack_slot_capture;
614 : Matcher<Node*> stack_slot_matcher =
615 2 : IsStackSlot(StackSlotRepresentation(sizeof(int64_t), 0));
616 :
617 : Capture<Node*> store_capture;
618 : Matcher<Node*> store_matcher =
619 : IsStore(StoreRepresentation(MachineRepresentation::kWord32,
620 : WriteBarrierKind::kNoWriteBarrier),
621 : AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
622 : IsInt32Constant(kInt64LowerHalfMemoryOffset),
623 : IsInt32Constant(low_word_value(0)),
624 : IsStore(StoreRepresentation(MachineRepresentation::kWord32,
625 : WriteBarrierKind::kNoWriteBarrier),
626 : AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
627 : IsInt32Constant(kInt64UpperHalfMemoryOffset),
628 : IsInt32Constant(high_word_value(0)), start(), start()),
629 29 : start());
630 :
631 22 : EXPECT_THAT(
632 : graph()->end()->InputAt(1),
633 : IsReturn(IsLoad(MachineType::Float64(),
634 : AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
635 : IsInt32Constant(0),
636 : AllOf(CaptureEq(&store_capture), store_matcher), start()),
637 0 : start(), start()));
638 1 : }
639 :
640 13160 : TEST_F(Int64LoweringTest, I64ReinterpretF64) {
641 : LowerGraph(graph()->NewNode(machine()->BitcastFloat64ToInt64(),
642 : Float64Constant(bit_cast<double>(value(0)))),
643 2 : MachineRepresentation::kWord64);
644 :
645 : Capture<Node*> stack_slot;
646 : Matcher<Node*> stack_slot_matcher =
647 2 : IsStackSlot(StackSlotRepresentation(sizeof(int64_t), 0));
648 :
649 : Capture<Node*> store;
650 : Matcher<Node*> store_matcher = IsStore(
651 : StoreRepresentation(MachineRepresentation::kFloat64,
652 : WriteBarrierKind::kNoWriteBarrier),
653 : AllOf(CaptureEq(&stack_slot), stack_slot_matcher), IsInt32Constant(0),
654 15 : IsFloat64Constant(bit_cast<double>(value(0))), start(), start());
655 :
656 36 : EXPECT_THAT(
657 : graph()->end()->InputAt(1),
658 : IsReturn2(IsLoad(MachineType::Int32(),
659 : AllOf(CaptureEq(&stack_slot), stack_slot_matcher),
660 : IsInt32Constant(kInt64LowerHalfMemoryOffset),
661 : AllOf(CaptureEq(&store), store_matcher), start()),
662 : IsLoad(MachineType::Int32(),
663 : AllOf(CaptureEq(&stack_slot), stack_slot_matcher),
664 : IsInt32Constant(kInt64UpperHalfMemoryOffset),
665 : AllOf(CaptureEq(&store), store_matcher), start()),
666 0 : start(), start()));
667 1 : }
668 :
669 13160 : TEST_F(Int64LoweringTest, I64Clz) {
670 : LowerGraph(graph()->NewNode(machine()->Word64Clz(), Int64Constant(value(0))),
671 2 : MachineRepresentation::kWord64);
672 :
673 : Capture<Node*> branch_capture;
674 : Matcher<Node*> branch_matcher = IsBranch(
675 : IsWord32Equal(IsInt32Constant(high_word_value(0)), IsInt32Constant(0)),
676 8 : start());
677 :
678 34 : EXPECT_THAT(
679 : graph()->end()->InputAt(1),
680 : IsReturn2(
681 : IsPhi(MachineRepresentation::kWord32,
682 : IsInt32Add(IsWord32Clz(IsInt32Constant(low_word_value(0))),
683 : IsInt32Constant(32)),
684 : IsWord32Clz(IsInt32Constant(high_word_value(0))),
685 : IsMerge(
686 : IsIfTrue(AllOf(CaptureEq(&branch_capture), branch_matcher)),
687 : IsIfFalse(
688 : AllOf(CaptureEq(&branch_capture), branch_matcher)))),
689 0 : IsInt32Constant(0), start(), start()));
690 1 : }
691 :
692 13160 : TEST_F(Int64LoweringTest, I64Ctz) {
693 1 : LowerGraph(graph()->NewNode(machine()->Word64Ctz().placeholder(),
694 : Int64Constant(value(0))),
695 3 : MachineRepresentation::kWord64);
696 : Capture<Node*> branch_capture;
697 : Matcher<Node*> branch_matcher = IsBranch(
698 : IsWord32Equal(IsInt32Constant(low_word_value(0)), IsInt32Constant(0)),
699 8 : start());
700 34 : EXPECT_THAT(
701 : graph()->end()->InputAt(1),
702 : IsReturn2(
703 : IsPhi(MachineRepresentation::kWord32,
704 : IsInt32Add(IsWord32Ctz(IsInt32Constant(high_word_value(0))),
705 : IsInt32Constant(32)),
706 : IsWord32Ctz(IsInt32Constant(low_word_value(0))),
707 : IsMerge(
708 : IsIfTrue(AllOf(CaptureEq(&branch_capture), branch_matcher)),
709 : IsIfFalse(
710 : AllOf(CaptureEq(&branch_capture), branch_matcher)))),
711 0 : IsInt32Constant(0), start(), start()));
712 1 : }
713 :
714 13160 : TEST_F(Int64LoweringTest, Dfs) {
715 1 : Node* common = Int64Constant(value(0));
716 : LowerGraph(graph()->NewNode(machine()->Word64And(), common,
717 : graph()->NewNode(machine()->Word64And(), common,
718 : Int64Constant(value(1)))),
719 3 : MachineRepresentation::kWord64);
720 :
721 30 : EXPECT_THAT(
722 : graph()->end()->InputAt(1),
723 : IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
724 : IsWord32And(IsInt32Constant(low_word_value(0)),
725 : IsInt32Constant(low_word_value(1)))),
726 : IsWord32And(IsInt32Constant(high_word_value(0)),
727 : IsWord32And(IsInt32Constant(high_word_value(0)),
728 : IsInt32Constant(high_word_value(1)))),
729 0 : start(), start()));
730 1 : }
731 :
732 13160 : TEST_F(Int64LoweringTest, I64Popcnt) {
733 1 : LowerGraph(graph()->NewNode(machine()->Word64Popcnt().placeholder(),
734 : Int64Constant(value(0))),
735 3 : MachineRepresentation::kWord64);
736 :
737 19 : EXPECT_THAT(
738 : graph()->end()->InputAt(1),
739 : IsReturn2(IsInt32Add(IsWord32Popcnt(IsInt32Constant(low_word_value(0))),
740 : IsWord32Popcnt(IsInt32Constant(high_word_value(0)))),
741 0 : IsInt32Constant(0), start(), start()));
742 1 : }
743 :
744 13160 : TEST_F(Int64LoweringTest, I64Ror) {
745 : LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
746 : Parameter(0)),
747 3 : MachineRepresentation::kWord64, MachineRepresentation::kWord64, 1);
748 :
749 : Matcher<Node*> branch_lt32_matcher =
750 7 : IsBranch(IsInt32LessThan(IsParameter(0), IsInt32Constant(32)), start());
751 :
752 : Matcher<Node*> low_input_matcher = IsPhi(
753 : MachineRepresentation::kWord32, IsInt32Constant(low_word_value(0)),
754 : IsInt32Constant(high_word_value(0)),
755 11 : IsMerge(IsIfTrue(branch_lt32_matcher), IsIfFalse(branch_lt32_matcher)));
756 :
757 : Matcher<Node*> high_input_matcher = IsPhi(
758 : MachineRepresentation::kWord32, IsInt32Constant(high_word_value(0)),
759 : IsInt32Constant(low_word_value(0)),
760 11 : IsMerge(IsIfTrue(branch_lt32_matcher), IsIfFalse(branch_lt32_matcher)));
761 :
762 : Matcher<Node*> shift_matcher =
763 5 : IsWord32And(IsParameter(0), IsInt32Constant(0x1f));
764 :
765 : Matcher<Node*> bit_mask_matcher = IsWord32Shl(
766 : IsWord32Sar(IsInt32Constant(std::numeric_limits<int32_t>::min()),
767 : shift_matcher),
768 6 : IsInt32Constant(1));
769 :
770 : Matcher<Node*> inv_mask_matcher =
771 3 : IsWord32Xor(bit_mask_matcher, IsInt32Constant(-1));
772 :
773 18 : EXPECT_THAT(
774 : graph()->end()->InputAt(1),
775 : IsReturn2(
776 : IsWord32Or(IsWord32And(IsWord32Ror(low_input_matcher, shift_matcher),
777 : inv_mask_matcher),
778 : IsWord32And(IsWord32Ror(high_input_matcher, shift_matcher),
779 : bit_mask_matcher)),
780 : IsWord32Or(IsWord32And(IsWord32Ror(high_input_matcher, shift_matcher),
781 : inv_mask_matcher),
782 : IsWord32And(IsWord32Ror(low_input_matcher, shift_matcher),
783 : bit_mask_matcher)),
784 0 : start(), start()));
785 1 : }
786 :
787 13160 : TEST_F(Int64LoweringTest, I64Ror_0) {
788 : LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
789 : Int32Constant(0)),
790 3 : MachineRepresentation::kWord64);
791 :
792 14 : EXPECT_THAT(graph()->end()->InputAt(1),
793 : IsReturn2(IsInt32Constant(low_word_value(0)),
794 0 : IsInt32Constant(high_word_value(0)), start(), start()));
795 1 : }
796 :
797 13160 : TEST_F(Int64LoweringTest, I64Ror_32) {
798 : LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
799 : Int32Constant(32)),
800 3 : MachineRepresentation::kWord64);
801 :
802 14 : EXPECT_THAT(graph()->end()->InputAt(1),
803 : IsReturn2(IsInt32Constant(high_word_value(0)),
804 0 : IsInt32Constant(low_word_value(0)), start(), start()));
805 1 : }
806 :
807 13160 : TEST_F(Int64LoweringTest, I64Ror_11) {
808 : LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
809 : Int32Constant(11)),
810 3 : MachineRepresentation::kWord64);
811 :
812 34 : EXPECT_THAT(
813 : graph()->end()->InputAt(1),
814 : IsReturn2(IsWord32Or(IsWord32Shr(IsInt32Constant(low_word_value(0)),
815 : IsInt32Constant(11)),
816 : IsWord32Shl(IsInt32Constant(high_word_value(0)),
817 : IsInt32Constant(21))),
818 : IsWord32Or(IsWord32Shr(IsInt32Constant(high_word_value(0)),
819 : IsInt32Constant(11)),
820 : IsWord32Shl(IsInt32Constant(low_word_value(0)),
821 : IsInt32Constant(21))),
822 0 : start(), start()));
823 1 : }
824 :
825 13160 : TEST_F(Int64LoweringTest, I64Ror_43) {
826 : LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
827 : Int32Constant(43)),
828 3 : MachineRepresentation::kWord64);
829 :
830 34 : EXPECT_THAT(
831 : graph()->end()->InputAt(1),
832 : IsReturn2(IsWord32Or(IsWord32Shr(IsInt32Constant(high_word_value(0)),
833 : IsInt32Constant(11)),
834 : IsWord32Shl(IsInt32Constant(low_word_value(0)),
835 : IsInt32Constant(21))),
836 : IsWord32Or(IsWord32Shr(IsInt32Constant(low_word_value(0)),
837 : IsInt32Constant(11)),
838 : IsWord32Shl(IsInt32Constant(high_word_value(0)),
839 : IsInt32Constant(21))),
840 0 : start(), start()));
841 1 : }
842 :
843 13160 : TEST_F(Int64LoweringTest, I64PhiWord64) {
844 : LowerGraph(graph()->NewNode(common()->Phi(MachineRepresentation::kWord64, 2),
845 : Int64Constant(value(0)), Int64Constant(value(1)),
846 : start()),
847 3 : MachineRepresentation::kWord64);
848 :
849 28 : EXPECT_THAT(graph()->end()->InputAt(1),
850 : IsReturn2(IsPhi(MachineRepresentation::kWord32,
851 : IsInt32Constant(low_word_value(0)),
852 : IsInt32Constant(low_word_value(1)), start()),
853 : IsPhi(MachineRepresentation::kWord32,
854 : IsInt32Constant(high_word_value(0)),
855 : IsInt32Constant(high_word_value(1)), start()),
856 0 : start(), start()));
857 1 : }
858 :
859 3 : void TestPhi(Int64LoweringTest* test, MachineRepresentation rep, Node* v1,
860 : Node* v2) {
861 : test->LowerGraph(test->graph()->NewNode(test->common()->Phi(rep, 2), v1, v2,
862 : test->start()),
863 6 : rep);
864 :
865 42 : EXPECT_THAT(test->graph()->end()->InputAt(1),
866 : IsReturn(IsPhi(rep, v1, v2, test->start()), test->start(),
867 0 : test->start()));
868 3 : }
869 :
870 13160 : TEST_F(Int64LoweringTest, I64PhiFloat32) {
871 : TestPhi(this, MachineRepresentation::kFloat32, Float32Constant(1.5),
872 1 : Float32Constant(2.5));
873 1 : }
874 :
875 13160 : TEST_F(Int64LoweringTest, I64PhiFloat64) {
876 : TestPhi(this, MachineRepresentation::kFloat64, Float32Constant(1.5),
877 1 : Float32Constant(2.5));
878 1 : }
879 :
880 13160 : TEST_F(Int64LoweringTest, I64PhiWord32) {
881 : TestPhi(this, MachineRepresentation::kWord32, Float32Constant(1),
882 1 : Float32Constant(2));
883 1 : }
884 :
885 13160 : TEST_F(Int64LoweringTest, I64ReverseBytes) {
886 1 : LowerGraph(graph()->NewNode(machine()->Word64ReverseBytes().placeholder(),
887 : Int64Constant(value(0))),
888 3 : MachineRepresentation::kWord64);
889 16 : EXPECT_THAT(
890 : graph()->end()->InputAt(1),
891 : IsReturn2(IsWord32ReverseBytes(IsInt32Constant(high_word_value(0))),
892 : IsWord32ReverseBytes(IsInt32Constant(low_word_value(0))),
893 0 : start(), start()));
894 1 : }
895 :
896 13160 : TEST_F(Int64LoweringTest, EffectPhiLoop) {
897 : // Construct a cycle consisting of an EffectPhi, a Store, and a Load.
898 1 : Node* eff_phi = graph()->NewNode(common()->EffectPhi(1), graph()->start(),
899 1 : graph()->start());
900 :
901 : StoreRepresentation store_rep(MachineRepresentation::kWord64,
902 : WriteBarrierKind::kNoWriteBarrier);
903 1 : LoadRepresentation load_rep(MachineType::Int64());
904 :
905 : Node* load =
906 : graph()->NewNode(machine()->Load(load_rep), Int64Constant(value(0)),
907 3 : Int64Constant(value(1)), eff_phi, graph()->start());
908 :
909 : Node* store =
910 : graph()->NewNode(machine()->Store(store_rep), Int64Constant(value(0)),
911 3 : Int64Constant(value(1)), load, load, graph()->start());
912 :
913 1 : eff_phi->InsertInput(zone(), 1, store);
914 : NodeProperties::ChangeOp(eff_phi,
915 1 : common()->ResizeMergeOrPhi(eff_phi->op(), 2));
916 :
917 1 : LowerGraph(load, MachineRepresentation::kWord64);
918 1 : }
919 :
920 13160 : TEST_F(Int64LoweringTest, LoopCycle) {
921 : // New node with two placeholders.
922 : Node* compare = graph()->NewNode(machine()->Word64Equal(), Int64Constant(0),
923 1 : Int64Constant(value(0)));
924 :
925 : Node* load = graph()->NewNode(
926 : machine()->Load(MachineType::Int64()), Int64Constant(value(1)),
927 : Int64Constant(value(2)), graph()->start(),
928 : graph()->NewNode(
929 : common()->Loop(2), graph()->start(),
930 : graph()->NewNode(common()->IfFalse(),
931 : graph()->NewNode(common()->Branch(), compare,
932 6 : graph()->start()))));
933 :
934 1 : NodeProperties::ReplaceValueInput(compare, load, 0);
935 :
936 1 : LowerGraph(load, MachineRepresentation::kWord64);
937 1 : }
938 : } // namespace compiler
939 : } // namespace internal
940 7893 : } // namespace v8
|