deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / unittests / compiler / change-lowering-unittest.cc
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:
28   ChangeLoweringTest() : simplified_(zone()) {}
29
30   virtual MachineType WordRepresentation() const = 0;
31
32  protected:
33   bool Is32() const { return WordRepresentation() == kRepWord32; }
34   bool Is64() const { return WordRepresentation() == kRepWord64; }
35
36   Reduction Reduce(Node* node) {
37     MachineOperatorBuilder machine(zone(), WordRepresentation());
38     JSOperatorBuilder javascript(zone());
39     JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
40     ChangeLowering reducer(&jsgraph);
41     return reducer.Reduce(node);
42   }
43
44   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
45
46   Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
47                                       const Matcher<Node*>& control_matcher) {
48     return IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
49                          AllocateHeapNumberStub(isolate()).GetCode())),
50                   IsNumberConstant(BitEq(0.0)), effect_matcher,
51                   control_matcher);
52   }
53   Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) {
54     return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher),
55                                 IsSmiShiftBitsConstant())
56                   : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
57   }
58   Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) {
59     return Is64() ? IsTruncateInt64ToInt32(
60                         IsWord64Sar(value_matcher, IsSmiShiftBitsConstant()))
61                   : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant());
62   }
63   Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) {
64     return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher),
65                                 IsSmiShiftBitsConstant())
66                   : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
67   }
68   Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
69                                   const Matcher<Node*>& control_matcher) {
70     return IsLoad(kMachFloat64, value_matcher,
71                   IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
72                   graph()->start(), control_matcher);
73   }
74   Matcher<Node*> IsIntPtrConstant(int value) {
75     return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
76   }
77   Matcher<Node*> IsSmiShiftBitsConstant() {
78     return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize);
79   }
80   Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
81                              const Matcher<Node*>& rhs_matcher) {
82     return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
83                   : IsWord64Equal(lhs_matcher, rhs_matcher);
84   }
85
86  private:
87   SimplifiedOperatorBuilder simplified_;
88 };
89
90
91 // -----------------------------------------------------------------------------
92 // Common.
93
94
95 class ChangeLoweringCommonTest
96     : public ChangeLoweringTest,
97       public ::testing::WithParamInterface<MachineType> {
98  public:
99   ~ChangeLoweringCommonTest() OVERRIDE {}
100
101   MachineType WordRepresentation() const FINAL { return GetParam(); }
102 };
103
104
105 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
106   Node* value = Parameter(Type::Boolean());
107   Reduction r =
108       Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value));
109   ASSERT_TRUE(r.Changed());
110   EXPECT_THAT(r.replacement(), IsSelect(kMachAnyTagged, value, IsTrueConstant(),
111                                         IsFalseConstant()));
112 }
113
114
115 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
116   Node* value = Parameter(Type::Number());
117   Reduction r =
118       Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value));
119   ASSERT_TRUE(r.Changed());
120   EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant()));
121 }
122
123
124 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
125   Node* value = Parameter(Type::Number());
126   Reduction r =
127       Reduce(graph()->NewNode(simplified()->ChangeFloat64ToTagged(), value));
128   ASSERT_TRUE(r.Changed());
129   Capture<Node*> heap_number;
130   EXPECT_THAT(
131       r.replacement(),
132       IsFinish(
133           AllOf(CaptureEq(&heap_number),
134                 IsAllocateHeapNumber(IsValueEffect(value), graph()->start())),
135           IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
136                   CaptureEq(&heap_number),
137                   IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
138                   value, CaptureEq(&heap_number), graph()->start())));
139 }
140
141
142 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
143   Node* value = Parameter(Type::SignedSmall());
144   Reduction r =
145       Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value));
146   ASSERT_TRUE(r.Changed());
147   EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
148 }
149
150
151 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) {
152   Node* value = Parameter(Type::UnsignedSmall());
153   Reduction r =
154       Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value));
155   ASSERT_TRUE(r.Changed());
156   EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value));
157 }
158
159
160 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) {
161   Node* value = Parameter(Type::TaggedSigned());
162   Reduction r =
163       Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
164   ASSERT_TRUE(r.Changed());
165   EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
166 }
167
168
169 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) {
170   Node* value = Parameter(Type::TaggedPointer());
171   Reduction r =
172       Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
173   ASSERT_TRUE(r.Changed());
174   EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32(
175                                    IsLoadHeapNumber(value, graph()->start())));
176 }
177
178
179 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) {
180   Node* value = Parameter(Type::TaggedSigned());
181   Reduction r =
182       Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
183   ASSERT_TRUE(r.Changed());
184   EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
185 }
186
187
188 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) {
189   Node* value = Parameter(Type::TaggedPointer());
190   Reduction r =
191       Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
192   ASSERT_TRUE(r.Changed());
193   EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32(
194                                    IsLoadHeapNumber(value, graph()->start())));
195 }
196
197
198 INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest,
199                         ::testing::Values(kRepWord32, kRepWord64));
200
201
202 // -----------------------------------------------------------------------------
203 // 32-bit
204
205
206 class ChangeLowering32Test : public ChangeLoweringTest {
207  public:
208   ~ChangeLowering32Test() OVERRIDE {}
209   MachineType WordRepresentation() const FINAL { return kRepWord32; }
210 };
211
212
213 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
214   Node* value = Parameter(Type::Integral32());
215   Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
216   Reduction r = Reduce(node);
217   ASSERT_TRUE(r.Changed());
218   Capture<Node*> add, branch, heap_number, if_true;
219   EXPECT_THAT(
220       r.replacement(),
221       IsPhi(kMachAnyTagged,
222             IsFinish(AllOf(CaptureEq(&heap_number),
223                            IsAllocateHeapNumber(_, CaptureEq(&if_true))),
224                      IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
225                              CaptureEq(&heap_number),
226                              IsIntPtrConstant(HeapNumber::kValueOffset -
227                                               kHeapObjectTag),
228                              IsChangeInt32ToFloat64(value),
229                              CaptureEq(&heap_number), CaptureEq(&if_true))),
230             IsProjection(0, AllOf(CaptureEq(&add),
231                                   IsInt32AddWithOverflow(value, value))),
232             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
233                     IsIfFalse(AllOf(CaptureEq(&branch),
234                                     IsBranch(IsProjection(1, CaptureEq(&add)),
235                                              graph()->start()))))));
236 }
237
238
239 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
240   STATIC_ASSERT(kSmiTag == 0);
241   STATIC_ASSERT(kSmiTagSize == 1);
242
243   Node* value = Parameter(Type::Number());
244   Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
245   Reduction r = Reduce(node);
246   ASSERT_TRUE(r.Changed());
247   Capture<Node*> branch, if_true;
248   EXPECT_THAT(
249       r.replacement(),
250       IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)),
251             IsChangeInt32ToFloat64(IsWord32Sar(
252                 value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))),
253             IsMerge(AllOf(CaptureEq(&if_true),
254                           IsIfTrue(AllOf(
255                               CaptureEq(&branch),
256                               IsBranch(IsWord32And(
257                                            value, IsInt32Constant(kSmiTagMask)),
258                                        graph()->start())))),
259                     IsIfFalse(CaptureEq(&branch)))));
260 }
261
262
263 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
264   STATIC_ASSERT(kSmiTag == 0);
265   STATIC_ASSERT(kSmiTagSize == 1);
266
267   Node* value = Parameter(Type::Signed32());
268   Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
269   Reduction r = Reduce(node);
270   ASSERT_TRUE(r.Changed());
271   Capture<Node*> branch, if_true;
272   EXPECT_THAT(
273       r.replacement(),
274       IsPhi(
275           kMachInt32,
276           IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
277           IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
278           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
279                   IsIfFalse(AllOf(
280                       CaptureEq(&branch),
281                       IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
282                                graph()->start()))))));
283 }
284
285
286 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
287   STATIC_ASSERT(kSmiTag == 0);
288   STATIC_ASSERT(kSmiTagSize == 1);
289
290   Node* value = Parameter(Type::Unsigned32());
291   Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
292   Reduction r = Reduce(node);
293   ASSERT_TRUE(r.Changed());
294   Capture<Node*> branch, if_true;
295   EXPECT_THAT(
296       r.replacement(),
297       IsPhi(
298           kMachUint32,
299           IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
300           IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
301           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
302                   IsIfFalse(AllOf(
303                       CaptureEq(&branch),
304                       IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
305                                graph()->start()))))));
306 }
307
308
309 TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
310   STATIC_ASSERT(kSmiTag == 0);
311   STATIC_ASSERT(kSmiTagSize == 1);
312
313   Node* value = Parameter(Type::Number());
314   Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
315   Reduction r = Reduce(node);
316   ASSERT_TRUE(r.Changed());
317   Capture<Node*> branch, heap_number, if_false;
318   EXPECT_THAT(
319       r.replacement(),
320       IsPhi(
321           kMachAnyTagged,
322           IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
323           IsFinish(AllOf(CaptureEq(&heap_number),
324                          IsAllocateHeapNumber(_, CaptureEq(&if_false))),
325                    IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
326                            CaptureEq(&heap_number),
327                            IsInt32Constant(HeapNumber::kValueOffset -
328                                            kHeapObjectTag),
329                            IsChangeUint32ToFloat64(value),
330                            CaptureEq(&heap_number), CaptureEq(&if_false))),
331           IsMerge(IsIfTrue(AllOf(
332                       CaptureEq(&branch),
333                       IsBranch(IsUint32LessThanOrEqual(
334                                    value, IsInt32Constant(Smi::kMaxValue)),
335                                graph()->start()))),
336                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
337 }
338
339
340 // -----------------------------------------------------------------------------
341 // 64-bit
342
343
344 class ChangeLowering64Test : public ChangeLoweringTest {
345  public:
346   ~ChangeLowering64Test() OVERRIDE {}
347   MachineType WordRepresentation() const FINAL { return kRepWord64; }
348 };
349
350
351 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
352   Node* value = Parameter(Type::Signed32());
353   Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
354   Reduction r = Reduce(node);
355   ASSERT_TRUE(r.Changed());
356   EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
357 }
358
359
360 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
361   STATIC_ASSERT(kSmiTag == 0);
362   STATIC_ASSERT(kSmiTagSize == 1);
363
364   Node* value = Parameter(Type::Number());
365   Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
366   Reduction r = Reduce(node);
367   ASSERT_TRUE(r.Changed());
368   Capture<Node*> branch, if_true;
369   EXPECT_THAT(
370       r.replacement(),
371       IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)),
372             IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar(
373                 value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))),
374             IsMerge(AllOf(CaptureEq(&if_true),
375                           IsIfTrue(AllOf(
376                               CaptureEq(&branch),
377                               IsBranch(IsWord64And(
378                                            value, IsInt64Constant(kSmiTagMask)),
379                                        graph()->start())))),
380                     IsIfFalse(CaptureEq(&branch)))));
381 }
382
383
384 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
385   STATIC_ASSERT(kSmiTag == 0);
386   STATIC_ASSERT(kSmiTagSize == 1);
387
388   Node* value = Parameter(Type::Signed32());
389   Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
390   Reduction r = Reduce(node);
391   ASSERT_TRUE(r.Changed());
392   Capture<Node*> branch, if_true;
393   EXPECT_THAT(
394       r.replacement(),
395       IsPhi(
396           kMachInt32,
397           IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
398           IsTruncateInt64ToInt32(
399               IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
400           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
401                   IsIfFalse(AllOf(
402                       CaptureEq(&branch),
403                       IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
404                                graph()->start()))))));
405 }
406
407
408 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
409   STATIC_ASSERT(kSmiTag == 0);
410   STATIC_ASSERT(kSmiTagSize == 1);
411
412   Node* value = Parameter(Type::Unsigned32());
413   Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
414   Reduction r = Reduce(node);
415   ASSERT_TRUE(r.Changed());
416   Capture<Node*> branch, if_true;
417   EXPECT_THAT(
418       r.replacement(),
419       IsPhi(
420           kMachUint32,
421           IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
422           IsTruncateInt64ToInt32(
423               IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
424           IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
425                   IsIfFalse(AllOf(
426                       CaptureEq(&branch),
427                       IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
428                                graph()->start()))))));
429 }
430
431
432 TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
433   STATIC_ASSERT(kSmiTag == 0);
434   STATIC_ASSERT(kSmiTagSize == 1);
435
436   Node* value = Parameter(Type::Number());
437   Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
438   Reduction r = Reduce(node);
439   ASSERT_TRUE(r.Changed());
440   Capture<Node*> branch, heap_number, if_false;
441   EXPECT_THAT(
442       r.replacement(),
443       IsPhi(
444           kMachAnyTagged,
445           IsWord64Shl(IsChangeUint32ToUint64(value),
446                       IsInt64Constant(kSmiTagSize + kSmiShiftSize)),
447           IsFinish(AllOf(CaptureEq(&heap_number),
448                          IsAllocateHeapNumber(_, CaptureEq(&if_false))),
449                    IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
450                            CaptureEq(&heap_number),
451                            IsInt64Constant(HeapNumber::kValueOffset -
452                                            kHeapObjectTag),
453                            IsChangeUint32ToFloat64(value),
454                            CaptureEq(&heap_number), CaptureEq(&if_false))),
455           IsMerge(IsIfTrue(AllOf(
456                       CaptureEq(&branch),
457                       IsBranch(IsUint32LessThanOrEqual(
458                                    value, IsInt32Constant(Smi::kMaxValue)),
459                                graph()->start()))),
460                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
461 }
462
463 }  // namespace compiler
464 }  // namespace internal
465 }  // namespace v8