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/code-stubs.h"
6 #include "src/compiler/change-lowering.h"
7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/linkage.h"
9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h"
11 #include "test/unittests/compiler/compiler-test-utils.h"
12 #include "test/unittests/compiler/graph-unittest.h"
13 #include "test/unittests/compiler/node-test-utils.h"
14 #include "testing/gmock-support.h"
15 
16 using testing::_;
17 using testing::AllOf;
18 using testing::BitEq;
19 using testing::Capture;
20 using testing::CaptureEq;
21 
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25 
26 class ChangeLoweringTest : public TypedGraphTest {
27  public:
ChangeLoweringTest()28   ChangeLoweringTest() : simplified_(zone()) {}
29 
30   virtual MachineRepresentation WordRepresentation() const = 0;
31 
32  protected:
Is32() const33   bool Is32() const {
34     return WordRepresentation() == MachineRepresentation::kWord32;
35   }
Is64() const36   bool Is64() const {
37     return WordRepresentation() == MachineRepresentation::kWord64;
38   }
39 
Reduce(Node * node)40   Reduction Reduce(Node* node) {
41     MachineOperatorBuilder machine(zone(), WordRepresentation());
42     JSOperatorBuilder javascript(zone());
43     JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
44                     &machine);
45     ChangeLowering reducer(&jsgraph);
46     return reducer.Reduce(node);
47   }
48 
simplified()49   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
50 
IsAllocateHeapNumber(const Matcher<Node * > & effect_matcher,const Matcher<Node * > & control_matcher)51   Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
52                                       const Matcher<Node*>& control_matcher) {
53     return IsCall(
54         _, IsHeapConstant(AllocateHeapNumberStub(isolate()).GetCode()),
55         IsNumberConstant(BitEq(0.0)), effect_matcher, control_matcher);
56   }
IsChangeInt32ToSmi(const Matcher<Node * > & value_matcher)57   Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) {
58     return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher),
59                                 IsSmiShiftBitsConstant())
60                   : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
61   }
IsChangeSmiToInt32(const Matcher<Node * > & value_matcher)62   Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) {
63     return Is64() ? IsTruncateInt64ToInt32(
64                         IsWord64Sar(value_matcher, IsSmiShiftBitsConstant()))
65                   : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant());
66   }
IsChangeUint32ToSmi(const Matcher<Node * > & value_matcher)67   Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) {
68     return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher),
69                                 IsSmiShiftBitsConstant())
70                   : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
71   }
IsLoadHeapNumber(const Matcher<Node * > & value_matcher,const Matcher<Node * > & control_matcher)72   Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
73                                   const Matcher<Node*>& control_matcher) {
74     return IsLoad(MachineType::Float64(), value_matcher,
75                   IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
76                   graph()->start(), control_matcher);
77   }
IsIntPtrConstant(int value)78   Matcher<Node*> IsIntPtrConstant(int value) {
79     return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
80   }
IsSmiShiftBitsConstant()81   Matcher<Node*> IsSmiShiftBitsConstant() {
82     return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize);
83   }
IsWordEqual(const Matcher<Node * > & lhs_matcher,const Matcher<Node * > & rhs_matcher)84   Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
85                              const Matcher<Node*>& rhs_matcher) {
86     return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
87                   : IsWord64Equal(lhs_matcher, rhs_matcher);
88   }
89 
90  private:
91   SimplifiedOperatorBuilder simplified_;
92 };
93 
94 
95 // -----------------------------------------------------------------------------
96 // Common.
97 
98 
99 class ChangeLoweringCommonTest
100     : public ChangeLoweringTest,
101       public ::testing::WithParamInterface<MachineRepresentation> {
102  public:
~ChangeLoweringCommonTest()103   ~ChangeLoweringCommonTest() override {}
104 
WordRepresentation() const105   MachineRepresentation WordRepresentation() const final { return GetParam(); }
106 };
107 
108 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeBitToBool)109 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
110   Node* value = Parameter(Type::Boolean());
111   Reduction r =
112       Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value));
113   ASSERT_TRUE(r.Changed());
114   EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kTagged, value,
115                                         IsTrueConstant(), IsFalseConstant()));
116 }
117 
118 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeBoolToBit)119 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
120   Node* value = Parameter(Type::Number());
121   Reduction r =
122       Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value));
123   ASSERT_TRUE(r.Changed());
124   EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant()));
125 }
126 
127 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeInt32ToTaggedWithSignedSmall)128 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
129   Node* value = Parameter(Type::SignedSmall());
130   Reduction r =
131       Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value));
132   ASSERT_TRUE(r.Changed());
133   EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
134 }
135 
136 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeUint32ToTaggedWithUnsignedSmall)137 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) {
138   Node* value = Parameter(Type::UnsignedSmall());
139   Reduction r =
140       Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value));
141   ASSERT_TRUE(r.Changed());
142   EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value));
143 }
144 
145 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeTaggedToInt32WithTaggedSigned)146 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) {
147   Node* value = Parameter(Type::TaggedSigned());
148   Reduction r =
149       Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
150   ASSERT_TRUE(r.Changed());
151   EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
152 }
153 
154 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeTaggedToInt32WithTaggedPointer)155 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) {
156   Node* value = Parameter(Type::TaggedPointer());
157   Reduction r =
158       Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
159   ASSERT_TRUE(r.Changed());
160   EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32(
161                                    IsLoadHeapNumber(value, graph()->start())));
162 }
163 
164 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeTaggedToUint32WithTaggedSigned)165 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) {
166   Node* value = Parameter(Type::TaggedSigned());
167   Reduction r =
168       Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
169   ASSERT_TRUE(r.Changed());
170   EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
171 }
172 
173 
TARGET_TEST_P(ChangeLoweringCommonTest,ChangeTaggedToUint32WithTaggedPointer)174 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) {
175   Node* value = Parameter(Type::TaggedPointer());
176   Reduction r =
177       Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
178   ASSERT_TRUE(r.Changed());
179   EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32(
180                                    IsLoadHeapNumber(value, graph()->start())));
181 }
182 
183 
TARGET_TEST_P(ChangeLoweringCommonTest,StoreFieldSmi)184 TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldSmi) {
185   FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
186                         Handle<Name>::null(), Type::Any(),
187                         MachineType::AnyTagged()};
188   Node* p0 = Parameter(Type::TaggedPointer());
189   Node* p1 = Parameter(Type::TaggedSigned());
190   Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1,
191                                  graph()->start(), graph()->start());
192   Reduction r = Reduce(store);
193 
194   ASSERT_TRUE(r.Changed());
195   EXPECT_THAT(r.replacement(),
196               IsStore(StoreRepresentation(MachineRepresentation::kTagged,
197                                           kNoWriteBarrier),
198                       p0, IsIntPtrConstant(access.offset - access.tag()), p1,
199                       graph()->start(), graph()->start()));
200 }
201 
202 
TARGET_TEST_P(ChangeLoweringCommonTest,StoreFieldTagged)203 TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldTagged) {
204   FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
205                         Handle<Name>::null(), Type::Any(),
206                         MachineType::AnyTagged()};
207   Node* p0 = Parameter(Type::TaggedPointer());
208   Node* p1 = Parameter(Type::Tagged());
209   Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1,
210                                  graph()->start(), graph()->start());
211   Reduction r = Reduce(store);
212 
213   ASSERT_TRUE(r.Changed());
214   EXPECT_THAT(r.replacement(),
215               IsStore(StoreRepresentation(MachineRepresentation::kTagged,
216                                           kFullWriteBarrier),
217                       p0, IsIntPtrConstant(access.offset - access.tag()), p1,
218                       graph()->start(), graph()->start()));
219 }
220 
221 
TARGET_TEST_P(ChangeLoweringCommonTest,LoadField)222 TARGET_TEST_P(ChangeLoweringCommonTest, LoadField) {
223   FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
224                         Handle<Name>::null(), Type::Any(),
225                         MachineType::AnyTagged()};
226   Node* p0 = Parameter(Type::TaggedPointer());
227   Node* load = graph()->NewNode(simplified()->LoadField(access), p0,
228                                 graph()->start(), graph()->start());
229   Reduction r = Reduce(load);
230 
231   ASSERT_TRUE(r.Changed());
232   Matcher<Node*> index_match = IsIntPtrConstant(access.offset - access.tag());
233   EXPECT_THAT(r.replacement(),
234               IsLoad(MachineType::AnyTagged(), p0,
235                      IsIntPtrConstant(access.offset - access.tag()),
236                      graph()->start(), graph()->start()));
237 }
238 
239 
TARGET_TEST_P(ChangeLoweringCommonTest,StoreElementTagged)240 TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementTagged) {
241   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
242                           MachineType::AnyTagged()};
243   Node* p0 = Parameter(Type::TaggedPointer());
244   Node* p1 = Parameter(Type::Signed32());
245   Node* p2 = Parameter(Type::Tagged());
246   Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2,
247                                  graph()->start(), graph()->start());
248   Reduction r = Reduce(store);
249 
250   const int element_size_shift =
251       ElementSizeLog2Of(access.machine_type.representation());
252   ASSERT_TRUE(r.Changed());
253   Matcher<Node*> index_match =
254       IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)),
255                  IsInt32Constant(access.header_size - access.tag()));
256   if (!Is32()) {
257     index_match = IsChangeUint32ToUint64(index_match);
258   }
259 
260   EXPECT_THAT(r.replacement(),
261               IsStore(StoreRepresentation(MachineRepresentation::kTagged,
262                                           kFullWriteBarrier),
263                       p0, index_match, p2, graph()->start(), graph()->start()));
264 }
265 
266 
TARGET_TEST_P(ChangeLoweringCommonTest,StoreElementUint8)267 TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementUint8) {
268   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
269                           Type::Signed32(), MachineType::Uint8()};
270   Node* p0 = Parameter(Type::TaggedPointer());
271   Node* p1 = Parameter(Type::Signed32());
272   Node* p2 = Parameter(Type::Signed32());
273   Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2,
274                                  graph()->start(), graph()->start());
275   Reduction r = Reduce(store);
276 
277   ASSERT_TRUE(r.Changed());
278   Matcher<Node*> index_match =
279       IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag()));
280   if (!Is32()) {
281     index_match = IsChangeUint32ToUint64(index_match);
282   }
283 
284   EXPECT_THAT(r.replacement(),
285               IsStore(StoreRepresentation(MachineRepresentation::kWord8,
286                                           kNoWriteBarrier),
287                       p0, index_match, p2, graph()->start(), graph()->start()));
288 }
289 
290 
TARGET_TEST_P(ChangeLoweringCommonTest,LoadElementTagged)291 TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementTagged) {
292   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
293                           MachineType::AnyTagged()};
294   Node* p0 = Parameter(Type::TaggedPointer());
295   Node* p1 = Parameter(Type::Signed32());
296   Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1,
297                                 graph()->start(), graph()->start());
298   Reduction r = Reduce(load);
299 
300   const int element_size_shift =
301       ElementSizeLog2Of(access.machine_type.representation());
302   ASSERT_TRUE(r.Changed());
303   Matcher<Node*> index_match =
304       IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)),
305                  IsInt32Constant(access.header_size - access.tag()));
306   if (!Is32()) {
307     index_match = IsChangeUint32ToUint64(index_match);
308   }
309 
310   EXPECT_THAT(r.replacement(), IsLoad(MachineType::AnyTagged(), p0, index_match,
311                                       graph()->start(), graph()->start()));
312 }
313 
314 
TARGET_TEST_P(ChangeLoweringCommonTest,LoadElementInt8)315 TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementInt8) {
316   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
317                           Type::Signed32(), MachineType::Int8()};
318   Node* p0 = Parameter(Type::TaggedPointer());
319   Node* p1 = Parameter(Type::Signed32());
320   Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1,
321                                 graph()->start(), graph()->start());
322   Reduction r = Reduce(load);
323 
324   ASSERT_TRUE(r.Changed());
325   Matcher<Node*> index_match =
326       IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag()));
327   if (!Is32()) {
328     index_match = IsChangeUint32ToUint64(index_match);
329   }
330 
331   EXPECT_THAT(r.replacement(), IsLoad(MachineType::Int8(), p0, index_match,
332                                       graph()->start(), graph()->start()));
333 }
334 
335 
TARGET_TEST_P(ChangeLoweringCommonTest,Allocate)336 TARGET_TEST_P(ChangeLoweringCommonTest, Allocate) {
337   Node* p0 = Parameter(Type::Signed32());
338   Node* alloc = graph()->NewNode(simplified()->Allocate(TENURED), p0,
339                                  graph()->start(), graph()->start());
340   Reduction r = Reduce(alloc);
341 
342   // Only check that we lowered, but do not specify the exact form since
343   // this is subject to change.
344   ASSERT_TRUE(r.Changed());
345 }
346 
347 
348 INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest,
349                         ::testing::Values(MachineRepresentation::kWord32,
350                                           MachineRepresentation::kWord64));
351 
352 
353 // -----------------------------------------------------------------------------
354 // 32-bit
355 
356 
357 class ChangeLowering32Test : public ChangeLoweringTest {
358  public:
~ChangeLowering32Test()359   ~ChangeLowering32Test() override {}
WordRepresentation() const360   MachineRepresentation WordRepresentation() const final {
361     return MachineRepresentation::kWord32;
362   }
363 };
364 
365 
TARGET_TEST_F(ChangeLowering32Test,ChangeInt32ToTagged)366 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
367   Node* value = Parameter(Type::Integral32());
368   Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
369   Reduction r = Reduce(node);
370   ASSERT_TRUE(r.Changed());
371   Capture<Node*> add, branch, heap_number, if_true;
372   EXPECT_THAT(
373       r.replacement(),
374       IsPhi(MachineRepresentation::kTagged,
375             IsFinishRegion(
376                 AllOf(CaptureEq(&heap_number),
377                       IsAllocateHeapNumber(_, CaptureEq(&if_true))),
378                 IsStore(
379                     StoreRepresentation(MachineRepresentation::kFloat64,
380                                         kNoWriteBarrier),
381                     CaptureEq(&heap_number),
382                     IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
383                     IsChangeInt32ToFloat64(value), CaptureEq(&heap_number),
384                     CaptureEq(&if_true))),
385             IsProjection(0, AllOf(CaptureEq(&add),
386                                   IsInt32AddWithOverflow(value, value))),
387             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
388                     IsIfFalse(AllOf(CaptureEq(&branch),
389                                     IsBranch(IsProjection(1, CaptureEq(&add)),
390                                              graph()->start()))))));
391 }
392 
393 
TARGET_TEST_F(ChangeLowering32Test,ChangeTaggedToFloat64)394 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
395   STATIC_ASSERT(kSmiTag == 0);
396   STATIC_ASSERT(kSmiTagSize == 1);
397 
398   Node* value = Parameter(Type::Number());
399   Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
400   Reduction r = Reduce(node);
401   ASSERT_TRUE(r.Changed());
402   Capture<Node*> branch, if_true;
403   EXPECT_THAT(
404       r.replacement(),
405       IsPhi(MachineRepresentation::kFloat64,
406             IsLoadHeapNumber(value, CaptureEq(&if_true)),
407             IsChangeInt32ToFloat64(IsWord32Sar(
408                 value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))),
409             IsMerge(AllOf(CaptureEq(&if_true),
410                           IsIfTrue(AllOf(
411                               CaptureEq(&branch),
412                               IsBranch(IsWord32And(
413                                            value, IsInt32Constant(kSmiTagMask)),
414                                        graph()->start())))),
415                     IsIfFalse(CaptureEq(&branch)))));
416 }
417 
418 
TARGET_TEST_F(ChangeLowering32Test,ChangeTaggedToInt32)419 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
420   STATIC_ASSERT(kSmiTag == 0);
421   STATIC_ASSERT(kSmiTagSize == 1);
422 
423   Node* value = Parameter(Type::Signed32());
424   Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
425   Reduction r = Reduce(node);
426   ASSERT_TRUE(r.Changed());
427   Capture<Node*> branch, if_true;
428   EXPECT_THAT(
429       r.replacement(),
430       IsPhi(
431           MachineRepresentation::kWord32,
432           IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
433           IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
434           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
435                   IsIfFalse(AllOf(
436                       CaptureEq(&branch),
437                       IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
438                                graph()->start()))))));
439 }
440 
441 
TARGET_TEST_F(ChangeLowering32Test,ChangeTaggedToUint32)442 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
443   STATIC_ASSERT(kSmiTag == 0);
444   STATIC_ASSERT(kSmiTagSize == 1);
445 
446   Node* value = Parameter(Type::Unsigned32());
447   Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
448   Reduction r = Reduce(node);
449   ASSERT_TRUE(r.Changed());
450   Capture<Node*> branch, if_true;
451   EXPECT_THAT(
452       r.replacement(),
453       IsPhi(
454           MachineRepresentation::kWord32,
455           IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
456           IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
457           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
458                   IsIfFalse(AllOf(
459                       CaptureEq(&branch),
460                       IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
461                                graph()->start()))))));
462 }
463 
464 
TARGET_TEST_F(ChangeLowering32Test,ChangeUint32ToTagged)465 TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
466   STATIC_ASSERT(kSmiTag == 0);
467   STATIC_ASSERT(kSmiTagSize == 1);
468 
469   Node* value = Parameter(Type::Number());
470   Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
471   Reduction r = Reduce(node);
472   ASSERT_TRUE(r.Changed());
473   Capture<Node*> branch, heap_number, if_false;
474   EXPECT_THAT(
475       r.replacement(),
476       IsPhi(
477           MachineRepresentation::kTagged,
478           IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
479           IsFinishRegion(
480               AllOf(CaptureEq(&heap_number),
481                     IsAllocateHeapNumber(_, CaptureEq(&if_false))),
482               IsStore(
483                   StoreRepresentation(MachineRepresentation::kFloat64,
484                                       kNoWriteBarrier),
485                   CaptureEq(&heap_number),
486                   IsInt32Constant(HeapNumber::kValueOffset - kHeapObjectTag),
487                   IsChangeUint32ToFloat64(value), CaptureEq(&heap_number),
488                   CaptureEq(&if_false))),
489           IsMerge(IsIfTrue(AllOf(
490                       CaptureEq(&branch),
491                       IsBranch(IsUint32LessThanOrEqual(
492                                    value, IsInt32Constant(Smi::kMaxValue)),
493                                graph()->start()))),
494                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
495 }
496 
497 
498 // -----------------------------------------------------------------------------
499 // 64-bit
500 
501 
502 class ChangeLowering64Test : public ChangeLoweringTest {
503  public:
~ChangeLowering64Test()504   ~ChangeLowering64Test() override {}
WordRepresentation() const505   MachineRepresentation WordRepresentation() const final {
506     return MachineRepresentation::kWord64;
507   }
508 };
509 
510 
TARGET_TEST_F(ChangeLowering64Test,ChangeInt32ToTagged)511 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
512   Node* value = Parameter(Type::Signed32());
513   Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
514   Reduction r = Reduce(node);
515   ASSERT_TRUE(r.Changed());
516   EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
517 }
518 
519 
TARGET_TEST_F(ChangeLowering64Test,ChangeTaggedToFloat64)520 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
521   STATIC_ASSERT(kSmiTag == 0);
522   STATIC_ASSERT(kSmiTagSize == 1);
523 
524   Node* value = Parameter(Type::Number());
525   Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
526   Reduction r = Reduce(node);
527   ASSERT_TRUE(r.Changed());
528   Capture<Node*> branch, if_true;
529   EXPECT_THAT(
530       r.replacement(),
531       IsPhi(MachineRepresentation::kFloat64,
532             IsLoadHeapNumber(value, CaptureEq(&if_true)),
533             IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar(
534                 value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))),
535             IsMerge(AllOf(CaptureEq(&if_true),
536                           IsIfTrue(AllOf(
537                               CaptureEq(&branch),
538                               IsBranch(IsWord64And(
539                                            value, IsInt64Constant(kSmiTagMask)),
540                                        graph()->start())))),
541                     IsIfFalse(CaptureEq(&branch)))));
542 }
543 
544 
TARGET_TEST_F(ChangeLowering64Test,ChangeTaggedToInt32)545 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
546   STATIC_ASSERT(kSmiTag == 0);
547   STATIC_ASSERT(kSmiTagSize == 1);
548 
549   Node* value = Parameter(Type::Signed32());
550   Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
551   Reduction r = Reduce(node);
552   ASSERT_TRUE(r.Changed());
553   Capture<Node*> branch, if_true;
554   EXPECT_THAT(
555       r.replacement(),
556       IsPhi(
557           MachineRepresentation::kWord32,
558           IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
559           IsTruncateInt64ToInt32(
560               IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
561           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
562                   IsIfFalse(AllOf(
563                       CaptureEq(&branch),
564                       IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
565                                graph()->start()))))));
566 }
567 
568 
TARGET_TEST_F(ChangeLowering64Test,ChangeTaggedToUint32)569 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
570   STATIC_ASSERT(kSmiTag == 0);
571   STATIC_ASSERT(kSmiTagSize == 1);
572 
573   Node* value = Parameter(Type::Unsigned32());
574   Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
575   Reduction r = Reduce(node);
576   ASSERT_TRUE(r.Changed());
577   Capture<Node*> branch, if_true;
578   EXPECT_THAT(
579       r.replacement(),
580       IsPhi(
581           MachineRepresentation::kWord32,
582           IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
583           IsTruncateInt64ToInt32(
584               IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
585           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
586                   IsIfFalse(AllOf(
587                       CaptureEq(&branch),
588                       IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
589                                graph()->start()))))));
590 }
591 
592 
TARGET_TEST_F(ChangeLowering64Test,ChangeUint32ToTagged)593 TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
594   STATIC_ASSERT(kSmiTag == 0);
595   STATIC_ASSERT(kSmiTagSize == 1);
596 
597   Node* value = Parameter(Type::Number());
598   Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
599   Reduction r = Reduce(node);
600   ASSERT_TRUE(r.Changed());
601   Capture<Node*> branch, heap_number, if_false;
602   EXPECT_THAT(
603       r.replacement(),
604       IsPhi(
605           MachineRepresentation::kTagged,
606           IsWord64Shl(IsChangeUint32ToUint64(value),
607                       IsInt64Constant(kSmiTagSize + kSmiShiftSize)),
608           IsFinishRegion(
609               AllOf(CaptureEq(&heap_number),
610                     IsAllocateHeapNumber(_, CaptureEq(&if_false))),
611               IsStore(
612                   StoreRepresentation(MachineRepresentation::kFloat64,
613                                       kNoWriteBarrier),
614                   CaptureEq(&heap_number),
615                   IsInt64Constant(HeapNumber::kValueOffset - kHeapObjectTag),
616                   IsChangeUint32ToFloat64(value), CaptureEq(&heap_number),
617                   CaptureEq(&if_false))),
618           IsMerge(IsIfTrue(AllOf(
619                       CaptureEq(&branch),
620                       IsBranch(IsUint32LessThanOrEqual(
621                                    value, IsInt32Constant(Smi::kMaxValue)),
622                                graph()->start()))),
623                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
624 }
625 
626 }  // namespace compiler
627 }  // namespace internal
628 }  // namespace v8
629