Upstream version 10.39.233.0
[platform/framework/web/crosswalk.git] / src / v8 / src / 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/compiler/change-lowering.h"
6 #include "src/compiler/compiler-test-utils.h"
7 #include "src/compiler/graph-unittest.h"
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node-properties-inl.h"
10 #include "src/compiler/simplified-operator.h"
11 #include "src/compiler/typer.h"
12 #include "testing/gmock-support.h"
13
14 using testing::_;
15 using testing::AllOf;
16 using testing::Capture;
17 using testing::CaptureEq;
18
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22
23 // TODO(bmeurer): Find a new home for these functions.
24 inline std::ostream& operator<<(std::ostream& os, const MachineType& type) {
25   OStringStream ost;
26   ost << type;
27   return os << ost.c_str();
28 }
29
30
31 class ChangeLoweringTest : public GraphTest {
32  public:
33   ChangeLoweringTest() : simplified_(zone()) {}
34   virtual ~ChangeLoweringTest() {}
35
36   virtual MachineType WordRepresentation() const = 0;
37
38  protected:
39   int HeapNumberValueOffset() const {
40     STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0);
41     return (HeapNumber::kValueOffset / kApiPointerSize) * PointerSize() -
42            kHeapObjectTag;
43   }
44   bool Is32() const { return WordRepresentation() == kRepWord32; }
45   int PointerSize() const {
46     switch (WordRepresentation()) {
47       case kRepWord32:
48         return 4;
49       case kRepWord64:
50         return 8;
51       default:
52         break;
53     }
54     UNREACHABLE();
55     return 0;
56   }
57   int SmiMaxValue() const { return -(SmiMinValue() + 1); }
58   int SmiMinValue() const {
59     return static_cast<int>(0xffffffffu << (SmiValueSize() - 1));
60   }
61   int SmiShiftAmount() const { return kSmiTagSize + SmiShiftSize(); }
62   int SmiShiftSize() const {
63     return Is32() ? SmiTagging<4>::SmiShiftSize()
64                   : SmiTagging<8>::SmiShiftSize();
65   }
66   int SmiValueSize() const {
67     return Is32() ? SmiTagging<4>::SmiValueSize()
68                   : SmiTagging<8>::SmiValueSize();
69   }
70
71   Node* Parameter(int32_t index = 0) {
72     return graph()->NewNode(common()->Parameter(index), graph()->start());
73   }
74
75   Reduction Reduce(Node* node) {
76     Typer typer(zone());
77     MachineOperatorBuilder machine(WordRepresentation());
78     JSOperatorBuilder javascript(zone());
79     JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
80     CompilationInfo info(isolate(), zone());
81     Linkage linkage(&info);
82     ChangeLowering reducer(&jsgraph, &linkage);
83     return reducer.Reduce(node);
84   }
85
86   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
87
88   Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
89                                       const Matcher<Node*>& control_matcher) {
90     return IsCall(
91         _, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
92                CEntryStub(isolate(), 1).GetCode())),
93         IsExternalConstant(ExternalReference(
94             Runtime::FunctionForId(Runtime::kAllocateHeapNumber), isolate())),
95         IsInt32Constant(0), IsNumberConstant(0.0), effect_matcher,
96         control_matcher);
97   }
98   Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
99                              const Matcher<Node*>& rhs_matcher) {
100     return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
101                   : IsWord64Equal(lhs_matcher, rhs_matcher);
102   }
103
104  private:
105   SimplifiedOperatorBuilder simplified_;
106 };
107
108
109 // -----------------------------------------------------------------------------
110 // Common.
111
112
113 class ChangeLoweringCommonTest
114     : public ChangeLoweringTest,
115       public ::testing::WithParamInterface<MachineType> {
116  public:
117   virtual ~ChangeLoweringCommonTest() {}
118
119   virtual MachineType WordRepresentation() const FINAL OVERRIDE {
120     return GetParam();
121   }
122 };
123
124
125 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
126   Node* val = Parameter(0);
127   Node* node = graph()->NewNode(simplified()->ChangeBitToBool(), val);
128   Reduction reduction = Reduce(node);
129   ASSERT_TRUE(reduction.Changed());
130
131   Node* phi = reduction.replacement();
132   Capture<Node*> branch;
133   EXPECT_THAT(phi,
134               IsPhi(static_cast<MachineType>(kTypeBool | kRepTagged),
135                     IsTrueConstant(), IsFalseConstant(),
136                     IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
137                                            IsBranch(val, graph()->start()))),
138                             IsIfFalse(CaptureEq(&branch)))));
139 }
140
141
142 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
143   Node* val = Parameter(0);
144   Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
145   Reduction reduction = Reduce(node);
146   ASSERT_TRUE(reduction.Changed());
147
148   EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant()));
149 }
150
151
152 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
153   Node* val = Parameter(0);
154   Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val);
155   Reduction reduction = Reduce(node);
156   ASSERT_TRUE(reduction.Changed());
157
158   Node* finish = reduction.replacement();
159   Capture<Node*> heap_number;
160   EXPECT_THAT(
161       finish,
162       IsFinish(
163           AllOf(CaptureEq(&heap_number),
164                 IsAllocateHeapNumber(IsValueEffect(val), graph()->start())),
165           IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
166                   IsInt32Constant(HeapNumberValueOffset()), val,
167                   CaptureEq(&heap_number), graph()->start())));
168 }
169
170
171 TARGET_TEST_P(ChangeLoweringCommonTest, StringAdd) {
172   Node* node =
173       graph()->NewNode(simplified()->StringAdd(), Parameter(0), Parameter(1));
174   Reduction reduction = Reduce(node);
175   EXPECT_FALSE(reduction.Changed());
176 }
177
178
179 INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest,
180                         ::testing::Values(kRepWord32, kRepWord64));
181
182
183 // -----------------------------------------------------------------------------
184 // 32-bit
185
186
187 class ChangeLowering32Test : public ChangeLoweringTest {
188  public:
189   virtual ~ChangeLowering32Test() {}
190   virtual MachineType WordRepresentation() const FINAL OVERRIDE {
191     return kRepWord32;
192   }
193 };
194
195
196 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
197   Node* val = Parameter(0);
198   Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
199   Reduction reduction = Reduce(node);
200   ASSERT_TRUE(reduction.Changed());
201
202   Node* phi = reduction.replacement();
203   Capture<Node*> add, branch, heap_number, if_true;
204   EXPECT_THAT(
205       phi,
206       IsPhi(kMachAnyTagged,
207             IsFinish(
208                 AllOf(CaptureEq(&heap_number),
209                       IsAllocateHeapNumber(_, CaptureEq(&if_true))),
210                 IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
211                         IsInt32Constant(HeapNumberValueOffset()),
212                         IsChangeInt32ToFloat64(val), CaptureEq(&heap_number),
213                         CaptureEq(&if_true))),
214             IsProjection(
215                 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
216             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
217                     IsIfFalse(AllOf(CaptureEq(&branch),
218                                     IsBranch(IsProjection(1, CaptureEq(&add)),
219                                              graph()->start()))))));
220 }
221
222
223 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
224   STATIC_ASSERT(kSmiTag == 0);
225   STATIC_ASSERT(kSmiTagSize == 1);
226
227   Node* val = Parameter(0);
228   Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
229   Reduction reduction = Reduce(node);
230   ASSERT_TRUE(reduction.Changed());
231
232   Node* phi = reduction.replacement();
233   Capture<Node*> branch, if_true;
234   EXPECT_THAT(
235       phi,
236       IsPhi(
237           kMachFloat64,
238           IsLoad(kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
239                  IsControlEffect(CaptureEq(&if_true))),
240           IsChangeInt32ToFloat64(
241               IsWord32Sar(val, IsInt32Constant(SmiShiftAmount()))),
242           IsMerge(
243               AllOf(CaptureEq(&if_true),
244                     IsIfTrue(AllOf(
245                         CaptureEq(&branch),
246                         IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
247                                  graph()->start())))),
248               IsIfFalse(CaptureEq(&branch)))));
249 }
250
251
252 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
253   STATIC_ASSERT(kSmiTag == 0);
254   STATIC_ASSERT(kSmiTagSize == 1);
255
256   Node* val = Parameter(0);
257   Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
258   Reduction reduction = Reduce(node);
259   ASSERT_TRUE(reduction.Changed());
260
261   Node* phi = reduction.replacement();
262   Capture<Node*> branch, if_true;
263   EXPECT_THAT(
264       phi,
265       IsPhi(kMachInt32,
266             IsChangeFloat64ToInt32(IsLoad(
267                 kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
268                 IsControlEffect(CaptureEq(&if_true)))),
269             IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
270             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
271                     IsIfFalse(AllOf(
272                         CaptureEq(&branch),
273                         IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
274                                  graph()->start()))))));
275 }
276
277
278 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
279   STATIC_ASSERT(kSmiTag == 0);
280   STATIC_ASSERT(kSmiTagSize == 1);
281
282   Node* val = Parameter(0);
283   Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
284   Reduction reduction = Reduce(node);
285   ASSERT_TRUE(reduction.Changed());
286
287   Node* phi = reduction.replacement();
288   Capture<Node*> branch, if_true;
289   EXPECT_THAT(
290       phi,
291       IsPhi(kMachUint32,
292             IsChangeFloat64ToUint32(IsLoad(
293                 kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
294                 IsControlEffect(CaptureEq(&if_true)))),
295             IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
296             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
297                     IsIfFalse(AllOf(
298                         CaptureEq(&branch),
299                         IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
300                                  graph()->start()))))));
301 }
302
303
304 TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
305   STATIC_ASSERT(kSmiTag == 0);
306   STATIC_ASSERT(kSmiTagSize == 1);
307
308   Node* val = Parameter(0);
309   Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
310   Reduction reduction = Reduce(node);
311   ASSERT_TRUE(reduction.Changed());
312
313   Node* phi = reduction.replacement();
314   Capture<Node*> branch, heap_number, if_false;
315   EXPECT_THAT(
316       phi,
317       IsPhi(
318           kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())),
319           IsFinish(
320               AllOf(CaptureEq(&heap_number),
321                     IsAllocateHeapNumber(_, CaptureEq(&if_false))),
322               IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
323                       IsInt32Constant(HeapNumberValueOffset()),
324                       IsChangeUint32ToFloat64(val), CaptureEq(&heap_number),
325                       CaptureEq(&if_false))),
326           IsMerge(
327               IsIfTrue(AllOf(CaptureEq(&branch),
328                              IsBranch(IsUint32LessThanOrEqual(
329                                           val, IsInt32Constant(SmiMaxValue())),
330                                       graph()->start()))),
331               AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
332 }
333
334
335 // -----------------------------------------------------------------------------
336 // 64-bit
337
338
339 class ChangeLowering64Test : public ChangeLoweringTest {
340  public:
341   virtual ~ChangeLowering64Test() {}
342   virtual MachineType WordRepresentation() const FINAL OVERRIDE {
343     return kRepWord64;
344   }
345 };
346
347
348 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
349   Node* val = Parameter(0);
350   Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
351   Reduction reduction = Reduce(node);
352   ASSERT_TRUE(reduction.Changed());
353
354   EXPECT_THAT(reduction.replacement(),
355               IsWord64Shl(IsChangeInt32ToInt64(val),
356                           IsInt32Constant(SmiShiftAmount())));
357 }
358
359
360 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
361   STATIC_ASSERT(kSmiTag == 0);
362   STATIC_ASSERT(kSmiTagSize == 1);
363
364   Node* val = Parameter(0);
365   Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
366   Reduction reduction = Reduce(node);
367   ASSERT_TRUE(reduction.Changed());
368
369   Node* phi = reduction.replacement();
370   Capture<Node*> branch, if_true;
371   EXPECT_THAT(
372       phi,
373       IsPhi(
374           kMachFloat64,
375           IsLoad(kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
376                  IsControlEffect(CaptureEq(&if_true))),
377           IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(
378               IsWord64Sar(val, IsInt32Constant(SmiShiftAmount())))),
379           IsMerge(
380               AllOf(CaptureEq(&if_true),
381                     IsIfTrue(AllOf(
382                         CaptureEq(&branch),
383                         IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)),
384                                  graph()->start())))),
385               IsIfFalse(CaptureEq(&branch)))));
386 }
387
388
389 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
390   STATIC_ASSERT(kSmiTag == 0);
391   STATIC_ASSERT(kSmiTagSize == 1);
392
393   Node* val = Parameter(0);
394   Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
395   Reduction reduction = Reduce(node);
396   ASSERT_TRUE(reduction.Changed());
397
398   Node* phi = reduction.replacement();
399   Capture<Node*> branch, if_true;
400   EXPECT_THAT(
401       phi,
402       IsPhi(kMachInt32,
403             IsChangeFloat64ToInt32(IsLoad(
404                 kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
405                 IsControlEffect(CaptureEq(&if_true)))),
406             IsTruncateInt64ToInt32(
407                 IsWord64Sar(val, IsInt32Constant(SmiShiftAmount()))),
408             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
409                     IsIfFalse(AllOf(
410                         CaptureEq(&branch),
411                         IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)),
412                                  graph()->start()))))));
413 }
414
415
416 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
417   STATIC_ASSERT(kSmiTag == 0);
418   STATIC_ASSERT(kSmiTagSize == 1);
419
420   Node* val = Parameter(0);
421   Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
422   Reduction reduction = Reduce(node);
423   ASSERT_TRUE(reduction.Changed());
424
425   Node* phi = reduction.replacement();
426   Capture<Node*> branch, if_true;
427   EXPECT_THAT(
428       phi,
429       IsPhi(kMachUint32,
430             IsChangeFloat64ToUint32(IsLoad(
431                 kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
432                 IsControlEffect(CaptureEq(&if_true)))),
433             IsTruncateInt64ToInt32(
434                 IsWord64Sar(val, IsInt32Constant(SmiShiftAmount()))),
435             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
436                     IsIfFalse(AllOf(
437                         CaptureEq(&branch),
438                         IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)),
439                                  graph()->start()))))));
440 }
441
442
443 TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
444   STATIC_ASSERT(kSmiTag == 0);
445   STATIC_ASSERT(kSmiTagSize == 1);
446
447   Node* val = Parameter(0);
448   Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
449   Reduction reduction = Reduce(node);
450   ASSERT_TRUE(reduction.Changed());
451
452   Node* phi = reduction.replacement();
453   Capture<Node*> branch, heap_number, if_false;
454   EXPECT_THAT(
455       phi,
456       IsPhi(
457           kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val),
458                                       IsInt32Constant(SmiShiftAmount())),
459           IsFinish(
460               AllOf(CaptureEq(&heap_number),
461                     IsAllocateHeapNumber(_, CaptureEq(&if_false))),
462               IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
463                       IsInt32Constant(HeapNumberValueOffset()),
464                       IsChangeUint32ToFloat64(val), CaptureEq(&heap_number),
465                       CaptureEq(&if_false))),
466           IsMerge(
467               IsIfTrue(AllOf(CaptureEq(&branch),
468                              IsBranch(IsUint32LessThanOrEqual(
469                                           val, IsInt32Constant(SmiMaxValue())),
470                                       graph()->start()))),
471               AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
472 }
473
474 }  // namespace compiler
475 }  // namespace internal
476 }  // namespace v8