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