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/compiler/change-lowering.h" | 5 #include "src/compiler/change-lowering.h" |
6 #include "src/compiler/js-graph.h" | 6 #include "src/compiler/js-graph.h" |
7 #include "src/compiler/node-properties-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
8 #include "src/compiler/simplified-operator.h" | 8 #include "src/compiler/simplified-operator.h" |
9 #include "src/compiler/typer.h" | 9 #include "src/compiler/typer.h" |
10 #include "test/compiler-unittests/graph-unittest.h" | 10 #include "test/compiler-unittests/graph-unittest.h" |
11 #include "testing/gmock-support.h" | 11 #include "testing/gmock-support.h" |
12 | 12 |
13 using testing::_; | 13 using testing::_; |
14 using testing::AllOf; | 14 using testing::AllOf; |
15 using testing::Capture; | 15 using testing::Capture; |
16 using testing::CaptureEq; | 16 using testing::CaptureEq; |
17 | 17 |
18 namespace v8 { | 18 namespace v8 { |
19 namespace internal { | 19 namespace internal { |
20 namespace compiler { | 20 namespace compiler { |
21 | 21 |
22 template <typename T> | 22 // TODO(bmeurer): Find a new home for these functions. |
| 23 inline std::ostream& operator<<(std::ostream& os, const MachineType& type) { |
| 24 OStringStream ost; |
| 25 ost << type; |
| 26 return os << ost.c_str(); |
| 27 } |
| 28 |
| 29 |
23 class ChangeLoweringTest : public GraphTest { | 30 class ChangeLoweringTest : public GraphTest { |
24 public: | 31 public: |
25 static const size_t kPointerSize = sizeof(T); | |
26 static const MachineType kWordRepresentation = | |
27 (kPointerSize == 4) ? kRepWord32 : kRepWord64; | |
28 STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0); | |
29 static const int kHeapNumberValueOffset = static_cast<int>( | |
30 (HeapNumber::kValueOffset / kApiPointerSize) * kPointerSize); | |
31 | |
32 ChangeLoweringTest() : simplified_(zone()) {} | 32 ChangeLoweringTest() : simplified_(zone()) {} |
33 virtual ~ChangeLoweringTest() {} | 33 virtual ~ChangeLoweringTest() {} |
34 | 34 |
| 35 virtual MachineType WordRepresentation() const = 0; |
| 36 |
35 protected: | 37 protected: |
| 38 int HeapNumberValueOffset() const { |
| 39 STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0); |
| 40 return (HeapNumber::kValueOffset / kApiPointerSize) * PointerSize() - |
| 41 kHeapObjectTag; |
| 42 } |
| 43 bool Is32() const { return WordRepresentation() == kRepWord32; } |
| 44 int PointerSize() const { |
| 45 switch (WordRepresentation()) { |
| 46 case kRepWord32: |
| 47 return 4; |
| 48 case kRepWord64: |
| 49 return 8; |
| 50 default: |
| 51 break; |
| 52 } |
| 53 UNREACHABLE(); |
| 54 return 0; |
| 55 } |
| 56 int SmiShiftAmount() const { return kSmiTagSize + SmiShiftSize(); } |
| 57 int SmiShiftSize() const { |
| 58 // TODO(turbofan): Work-around for weird GCC 4.6 linker issue: |
| 59 // src/compiler/change-lowering.cc:46: undefined reference to |
| 60 // `v8::internal::SmiTagging<4u>::kSmiShiftSize' |
| 61 // src/compiler/change-lowering.cc:46: undefined reference to |
| 62 // `v8::internal::SmiTagging<8u>::kSmiShiftSize' |
| 63 STATIC_ASSERT(SmiTagging<4>::kSmiShiftSize == 0); |
| 64 STATIC_ASSERT(SmiTagging<8>::kSmiShiftSize == 31); |
| 65 return Is32() ? 0 : 31; |
| 66 } |
| 67 |
36 Node* Parameter(int32_t index = 0) { | 68 Node* Parameter(int32_t index = 0) { |
37 return graph()->NewNode(common()->Parameter(index), graph()->start()); | 69 return graph()->NewNode(common()->Parameter(index), graph()->start()); |
38 } | 70 } |
39 | 71 |
40 Reduction Reduce(Node* node) { | 72 Reduction Reduce(Node* node) { |
41 Typer typer(zone()); | 73 Typer typer(zone()); |
42 JSGraph jsgraph(graph(), common(), &typer); | 74 JSGraph jsgraph(graph(), common(), &typer); |
43 CompilationInfo info(isolate(), zone()); | 75 CompilationInfo info(isolate(), zone()); |
44 Linkage linkage(&info); | 76 Linkage linkage(&info); |
45 MachineOperatorBuilder machine(zone(), kWordRepresentation); | 77 MachineOperatorBuilder machine(zone(), WordRepresentation()); |
46 ChangeLowering reducer(&jsgraph, &linkage, &machine); | 78 ChangeLowering reducer(&jsgraph, &linkage, &machine); |
47 return reducer.Reduce(node); | 79 return reducer.Reduce(node); |
48 } | 80 } |
49 | 81 |
50 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 82 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
51 | 83 |
52 PrintableUnique<HeapObject> true_unique() { | 84 Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher, |
53 return PrintableUnique<HeapObject>::CreateImmovable( | 85 const Matcher<Node*>& control_matcher) { |
54 zone(), factory()->true_value()); | 86 return IsCall( |
| 87 _, IsHeapConstant(PrintableUnique<HeapObject>::CreateImmovable( |
| 88 zone(), CEntryStub(isolate(), 1).GetCode())), |
| 89 IsExternalConstant(ExternalReference( |
| 90 Runtime::FunctionForId(Runtime::kAllocateHeapNumber), isolate())), |
| 91 IsInt32Constant(0), IsNumberConstant(0.0), effect_matcher, |
| 92 control_matcher); |
55 } | 93 } |
56 PrintableUnique<HeapObject> false_unique() { | 94 Matcher<Node*> IsFalse() { |
57 return PrintableUnique<HeapObject>::CreateImmovable( | 95 return IsHeapConstant(PrintableUnique<HeapObject>::CreateImmovable( |
58 zone(), factory()->false_value()); | 96 zone(), factory()->false_value())); |
| 97 } |
| 98 Matcher<Node*> IsTrue() { |
| 99 return IsHeapConstant(PrintableUnique<HeapObject>::CreateImmovable( |
| 100 zone(), factory()->true_value())); |
| 101 } |
| 102 Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher, |
| 103 const Matcher<Node*>& rhs_matcher) { |
| 104 return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher) |
| 105 : IsWord64Equal(lhs_matcher, rhs_matcher); |
59 } | 106 } |
60 | 107 |
61 private: | 108 private: |
62 SimplifiedOperatorBuilder simplified_; | 109 SimplifiedOperatorBuilder simplified_; |
63 }; | 110 }; |
64 | 111 |
65 | 112 |
66 typedef ::testing::Types<int32_t, int64_t> ChangeLoweringTypes; | 113 // ----------------------------------------------------------------------------- |
67 TYPED_TEST_CASE(ChangeLoweringTest, ChangeLoweringTypes); | 114 // Common. |
| 115 |
| 116 namespace { |
| 117 |
| 118 class Common : public ChangeLoweringTest, |
| 119 public ::testing::WithParamInterface<MachineType> { |
| 120 public: |
| 121 virtual ~Common() {} |
| 122 |
| 123 virtual MachineType WordRepresentation() const V8_FINAL V8_OVERRIDE { |
| 124 return GetParam(); |
| 125 } |
| 126 }; |
68 | 127 |
69 | 128 |
70 TARGET_TYPED_TEST(ChangeLoweringTest, ChangeBitToBool) { | 129 TARGET_TEST_P(Common, ChangeBitToBool) { |
71 Node* val = this->Parameter(0); | 130 Node* val = Parameter(0); |
72 Node* node = | 131 Node* node = graph()->NewNode(simplified()->ChangeBitToBool(), val); |
73 this->graph()->NewNode(this->simplified()->ChangeBitToBool(), val); | 132 Reduction reduction = Reduce(node); |
74 Reduction reduction = this->Reduce(node); | |
75 ASSERT_TRUE(reduction.Changed()); | 133 ASSERT_TRUE(reduction.Changed()); |
76 | 134 |
77 Node* phi = reduction.replacement(); | 135 Node* phi = reduction.replacement(); |
78 Capture<Node*> branch; | 136 Capture<Node*> branch; |
79 EXPECT_THAT( | 137 EXPECT_THAT(phi, |
80 phi, IsPhi(IsHeapConstant(this->true_unique()), | 138 IsPhi(IsTrue(), IsFalse(), |
81 IsHeapConstant(this->false_unique()), | 139 IsMerge(IsIfTrue(AllOf(CaptureEq(&branch), |
82 IsMerge(IsIfTrue(AllOf(CaptureEq(&branch), | 140 IsBranch(val, graph()->start()))), |
83 IsBranch(val, this->graph()->start()))), | 141 IsIfFalse(CaptureEq(&branch))))); |
84 IsIfFalse(CaptureEq(&branch))))); | |
85 } | 142 } |
86 | 143 |
87 | 144 |
88 TARGET_TYPED_TEST(ChangeLoweringTest, StringAdd) { | 145 TARGET_TEST_P(Common, ChangeBoolToBit) { |
89 Node* node = this->graph()->NewNode(this->simplified()->StringAdd(), | |
90 this->Parameter(0), this->Parameter(1)); | |
91 Reduction reduction = this->Reduce(node); | |
92 EXPECT_FALSE(reduction.Changed()); | |
93 } | |
94 | |
95 | |
96 class ChangeLowering32Test : public ChangeLoweringTest<int32_t> { | |
97 public: | |
98 virtual ~ChangeLowering32Test() {} | |
99 }; | |
100 | |
101 | |
102 TARGET_TEST_F(ChangeLowering32Test, ChangeBoolToBit) { | |
103 Node* val = Parameter(0); | 146 Node* val = Parameter(0); |
104 Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val); | 147 Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val); |
105 Reduction reduction = Reduce(node); | 148 Reduction reduction = Reduce(node); |
106 ASSERT_TRUE(reduction.Changed()); | 149 ASSERT_TRUE(reduction.Changed()); |
107 | 150 |
108 EXPECT_THAT(reduction.replacement(), | 151 EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrue())); |
109 IsWord32Equal(val, IsHeapConstant(true_unique()))); | |
110 } | 152 } |
111 | 153 |
112 | 154 |
| 155 TARGET_TEST_P(Common, ChangeFloat64ToTagged) { |
| 156 Node* val = Parameter(0); |
| 157 Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val); |
| 158 Reduction reduction = Reduce(node); |
| 159 ASSERT_TRUE(reduction.Changed()); |
| 160 |
| 161 Node* finish = reduction.replacement(); |
| 162 Capture<Node*> heap_number; |
| 163 EXPECT_THAT( |
| 164 finish, |
| 165 IsFinish( |
| 166 AllOf(CaptureEq(&heap_number), |
| 167 IsAllocateHeapNumber(IsValueEffect(val), graph()->start())), |
| 168 IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), |
| 169 IsInt32Constant(HeapNumberValueOffset()), val, |
| 170 CaptureEq(&heap_number), graph()->start()))); |
| 171 } |
| 172 |
| 173 |
| 174 TARGET_TEST_P(Common, StringAdd) { |
| 175 Node* node = |
| 176 graph()->NewNode(simplified()->StringAdd(), Parameter(0), Parameter(1)); |
| 177 Reduction reduction = Reduce(node); |
| 178 EXPECT_FALSE(reduction.Changed()); |
| 179 } |
| 180 |
| 181 } // namespace |
| 182 |
| 183 |
| 184 INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, Common, |
| 185 ::testing::Values(kRepWord32, kRepWord64)); |
| 186 |
| 187 |
| 188 // ----------------------------------------------------------------------------- |
| 189 // 32-bit |
| 190 |
| 191 |
| 192 class ChangeLowering32Test : public ChangeLoweringTest { |
| 193 public: |
| 194 virtual ~ChangeLowering32Test() {} |
| 195 virtual MachineType WordRepresentation() const V8_FINAL V8_OVERRIDE { |
| 196 return kRepWord32; |
| 197 } |
| 198 }; |
| 199 |
| 200 |
113 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) { | 201 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) { |
114 Node* val = Parameter(0); | 202 Node* val = Parameter(0); |
115 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); | 203 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); |
116 Reduction reduction = Reduce(node); | 204 Reduction reduction = Reduce(node); |
117 ASSERT_TRUE(reduction.Changed()); | 205 ASSERT_TRUE(reduction.Changed()); |
118 | 206 |
119 Node* phi = reduction.replacement(); | 207 Node* phi = reduction.replacement(); |
120 Capture<Node*> add, branch, heap_number, if_true; | 208 Capture<Node*> add, branch, heap_number, if_true; |
121 const int32_t kValueOffset = kHeapNumberValueOffset - kHeapObjectTag; | |
122 EXPECT_THAT( | 209 EXPECT_THAT( |
123 phi, | 210 phi, |
124 IsPhi( | 211 IsPhi(IsFinish( |
125 IsFinish( | 212 AllOf(CaptureEq(&heap_number), |
126 AllOf( | 213 IsAllocateHeapNumber(_, CaptureEq(&if_true))), |
127 CaptureEq(&heap_number), | 214 IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), |
128 IsCall( | 215 IsInt32Constant(HeapNumberValueOffset()), |
129 _, IsHeapConstant( | 216 IsChangeInt32ToFloat64(val), CaptureEq(&heap_number), |
130 PrintableUnique<HeapObject>::CreateImmovable( | 217 CaptureEq(&if_true))), |
131 zone(), CEntryStub(isolate(), 1).GetCode())), | 218 IsProjection( |
132 IsExternalConstant(ExternalReference( | 219 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))), |
133 Runtime::FunctionForId(Runtime::kAllocateHeapNumber), | 220 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
134 isolate())), | 221 IsIfFalse(AllOf(CaptureEq(&branch), |
135 IsInt32Constant(0), IsNumberConstant(0.0), | 222 IsBranch(IsProjection(1, CaptureEq(&add)), |
136 graph()->start(), CaptureEq(&if_true))), | 223 graph()->start())))))); |
137 IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), | |
138 IsInt32Constant(kValueOffset), | |
139 IsChangeInt32ToFloat64(val), CaptureEq(&heap_number), | |
140 CaptureEq(&if_true))), | |
141 IsProjection( | |
142 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))), | |
143 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), | |
144 IsIfFalse(AllOf(CaptureEq(&branch), | |
145 IsBranch(IsProjection(1, CaptureEq(&add)), | |
146 graph()->start())))))); | |
147 } | 224 } |
148 | 225 |
149 | 226 |
150 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) { | 227 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) { |
151 STATIC_ASSERT(kSmiTag == 0); | 228 STATIC_ASSERT(kSmiTag == 0); |
152 STATIC_ASSERT(kSmiTagSize == 1); | 229 STATIC_ASSERT(kSmiTagSize == 1); |
153 | 230 |
154 Node* val = Parameter(0); | 231 Node* val = Parameter(0); |
155 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val); | 232 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val); |
156 Reduction reduction = Reduce(node); | 233 Reduction reduction = Reduce(node); |
157 ASSERT_TRUE(reduction.Changed()); | 234 ASSERT_TRUE(reduction.Changed()); |
158 | 235 |
159 const int32_t kShiftAmount = | |
160 kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize; | |
161 const int32_t kValueOffset = kHeapNumberValueOffset - kHeapObjectTag; | |
162 Node* phi = reduction.replacement(); | 236 Node* phi = reduction.replacement(); |
163 Capture<Node*> branch, if_true; | 237 Capture<Node*> branch, if_true; |
164 EXPECT_THAT( | 238 EXPECT_THAT( |
165 phi, | 239 phi, |
166 IsPhi( | 240 IsPhi( |
167 IsLoad(kMachFloat64, val, IsInt32Constant(kValueOffset), | 241 IsLoad(kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()), |
168 IsControlEffect(CaptureEq(&if_true))), | 242 IsControlEffect(CaptureEq(&if_true))), |
169 IsChangeInt32ToFloat64( | 243 IsChangeInt32ToFloat64( |
170 IsWord32Sar(val, IsInt32Constant(kShiftAmount))), | 244 IsWord32Sar(val, IsInt32Constant(SmiShiftAmount()))), |
171 IsMerge( | 245 IsMerge( |
172 AllOf(CaptureEq(&if_true), | 246 AllOf(CaptureEq(&if_true), |
173 IsIfTrue(AllOf( | 247 IsIfTrue(AllOf( |
174 CaptureEq(&branch), | 248 CaptureEq(&branch), |
175 IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)), | 249 IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)), |
176 graph()->start())))), | 250 graph()->start())))), |
177 IsIfFalse(CaptureEq(&branch))))); | 251 IsIfFalse(CaptureEq(&branch))))); |
178 } | 252 } |
179 | 253 |
180 | 254 |
181 class ChangeLowering64Test : public ChangeLoweringTest<int64_t> { | 255 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) { |
182 public: | 256 STATIC_ASSERT(kSmiTag == 0); |
183 virtual ~ChangeLowering64Test() {} | 257 STATIC_ASSERT(kSmiTagSize == 1); |
184 }; | |
185 | 258 |
186 | |
187 TARGET_TEST_F(ChangeLowering64Test, ChangeBoolToBit) { | |
188 Node* val = Parameter(0); | 259 Node* val = Parameter(0); |
189 Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val); | 260 Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val); |
190 Reduction reduction = Reduce(node); | 261 Reduction reduction = Reduce(node); |
191 ASSERT_TRUE(reduction.Changed()); | 262 ASSERT_TRUE(reduction.Changed()); |
192 | 263 |
193 EXPECT_THAT(reduction.replacement(), | 264 Node* phi = reduction.replacement(); |
194 IsWord64Equal(val, IsHeapConstant(true_unique()))); | 265 Capture<Node*> branch, if_true; |
| 266 EXPECT_THAT( |
| 267 phi, |
| 268 IsPhi(IsChangeFloat64ToInt32(IsLoad( |
| 269 kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()), |
| 270 IsControlEffect(CaptureEq(&if_true)))), |
| 271 IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())), |
| 272 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 273 IsIfFalse(AllOf( |
| 274 CaptureEq(&branch), |
| 275 IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)), |
| 276 graph()->start())))))); |
195 } | 277 } |
196 | 278 |
197 | 279 |
| 280 // ----------------------------------------------------------------------------- |
| 281 // 64-bit |
| 282 |
| 283 |
| 284 class ChangeLowering64Test : public ChangeLoweringTest { |
| 285 public: |
| 286 virtual ~ChangeLowering64Test() {} |
| 287 virtual MachineType WordRepresentation() const V8_FINAL V8_OVERRIDE { |
| 288 return kRepWord64; |
| 289 } |
| 290 }; |
| 291 |
| 292 |
198 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) { | 293 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) { |
199 Node* val = Parameter(0); | 294 Node* val = Parameter(0); |
200 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); | 295 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); |
201 Reduction reduction = Reduce(node); | 296 Reduction reduction = Reduce(node); |
202 ASSERT_TRUE(reduction.Changed()); | 297 ASSERT_TRUE(reduction.Changed()); |
203 | 298 |
204 const int32_t kShiftAmount = | |
205 kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize; | |
206 EXPECT_THAT(reduction.replacement(), | 299 EXPECT_THAT(reduction.replacement(), |
207 IsWord64Shl(val, IsInt32Constant(kShiftAmount))); | 300 IsWord64Shl(val, IsInt32Constant(SmiShiftAmount()))); |
208 } | 301 } |
209 | 302 |
210 | 303 |
211 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) { | 304 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) { |
212 STATIC_ASSERT(kSmiTag == 0); | 305 STATIC_ASSERT(kSmiTag == 0); |
213 STATIC_ASSERT(kSmiTagSize == 1); | 306 STATIC_ASSERT(kSmiTagSize == 1); |
214 | 307 |
215 Node* val = Parameter(0); | 308 Node* val = Parameter(0); |
216 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val); | 309 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val); |
217 Reduction reduction = Reduce(node); | 310 Reduction reduction = Reduce(node); |
218 ASSERT_TRUE(reduction.Changed()); | 311 ASSERT_TRUE(reduction.Changed()); |
219 | 312 |
220 const int32_t kShiftAmount = | |
221 kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize; | |
222 const int32_t kValueOffset = kHeapNumberValueOffset - kHeapObjectTag; | |
223 Node* phi = reduction.replacement(); | 313 Node* phi = reduction.replacement(); |
224 Capture<Node*> branch, if_true; | 314 Capture<Node*> branch, if_true; |
225 EXPECT_THAT( | 315 EXPECT_THAT( |
226 phi, | 316 phi, |
227 IsPhi( | 317 IsPhi( |
228 IsLoad(kMachFloat64, val, IsInt32Constant(kValueOffset), | 318 IsLoad(kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()), |
229 IsControlEffect(CaptureEq(&if_true))), | 319 IsControlEffect(CaptureEq(&if_true))), |
230 IsChangeInt32ToFloat64(IsConvertInt64ToInt32( | 320 IsChangeInt32ToFloat64(IsConvertInt64ToInt32( |
231 IsWord64Sar(val, IsInt32Constant(kShiftAmount)))), | 321 IsWord64Sar(val, IsInt32Constant(SmiShiftAmount())))), |
232 IsMerge( | 322 IsMerge( |
233 AllOf(CaptureEq(&if_true), | 323 AllOf(CaptureEq(&if_true), |
234 IsIfTrue(AllOf( | 324 IsIfTrue(AllOf( |
235 CaptureEq(&branch), | 325 CaptureEq(&branch), |
236 IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)), | 326 IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)), |
237 graph()->start())))), | 327 graph()->start())))), |
238 IsIfFalse(CaptureEq(&branch))))); | 328 IsIfFalse(CaptureEq(&branch))))); |
239 } | 329 } |
240 | 330 |
| 331 |
| 332 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) { |
| 333 STATIC_ASSERT(kSmiTag == 0); |
| 334 STATIC_ASSERT(kSmiTagSize == 1); |
| 335 |
| 336 Node* val = Parameter(0); |
| 337 Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val); |
| 338 Reduction reduction = Reduce(node); |
| 339 ASSERT_TRUE(reduction.Changed()); |
| 340 |
| 341 Node* phi = reduction.replacement(); |
| 342 Capture<Node*> branch, if_true; |
| 343 EXPECT_THAT( |
| 344 phi, |
| 345 IsPhi(IsChangeFloat64ToInt32(IsLoad( |
| 346 kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()), |
| 347 IsControlEffect(CaptureEq(&if_true)))), |
| 348 IsConvertInt64ToInt32( |
| 349 IsWord64Sar(val, IsInt32Constant(SmiShiftAmount()))), |
| 350 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 351 IsIfFalse(AllOf( |
| 352 CaptureEq(&branch), |
| 353 IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)), |
| 354 graph()->start())))))); |
| 355 } |
| 356 |
241 } // namespace compiler | 357 } // namespace compiler |
242 } // namespace internal | 358 } // namespace internal |
243 } // namespace v8 | 359 } // namespace v8 |
OLD | NEW |