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