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/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some | 49 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some |
50 // operators for some nodes, expanding some nodes to multiple nodes, or | 50 // operators for some nodes, expanding some nodes to multiple nodes, or |
51 // removing some (redundant) nodes. | 51 // removing some (redundant) nodes. |
52 // During this phase, use the {RepresentationChanger} to insert | 52 // During this phase, use the {RepresentationChanger} to insert |
53 // representation changes between uses that demand a particular | 53 // representation changes between uses that demand a particular |
54 // representation and nodes that produce a different representation. | 54 // representation and nodes that produce a different representation. |
55 LOWER | 55 LOWER |
56 }; | 56 }; |
57 | 57 |
58 | 58 |
| 59 namespace { |
| 60 |
| 61 // The {UseInfo} class is used to describe a use of an input of a node. |
| 62 // |
| 63 // This information is used in two different ways, based on the phase: |
| 64 // |
| 65 // 1. During propagation, the use info is used to inform the input node |
| 66 // about what part of the input is used (we call this truncation) and what |
| 67 // is the preferred representation. |
| 68 // |
| 69 // 2. During lowering, the use info is used to properly convert the input |
| 70 // to the preferred representation. The preferred representation might be |
| 71 // insufficient to do the conversion (e.g. word32->float64 conv), so we also |
| 72 // need the signedness information to produce the correct value. |
| 73 class UseInfo { |
| 74 public: |
| 75 // Constructors |
| 76 // ================================================================ |
| 77 |
| 78 // Uses truncating to the preferred representation. |
| 79 static UseInfo TruncatingWord32() { |
| 80 return UseInfo(kTypeInt32 | kTypeUint32 | kRepWord32); |
| 81 } |
| 82 static UseInfo TruncatingWord64() { |
| 83 return UseInfo(kTypeInt64 | kTypeUint64 | kRepWord64); |
| 84 } |
| 85 static UseInfo Bool() { return UseInfo(kMachBool); } |
| 86 static UseInfo Float32() { return UseInfo(kMachFloat32); } |
| 87 static UseInfo Float64() { return UseInfo(kMachFloat64); } |
| 88 static UseInfo PointerInt() { |
| 89 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64(); |
| 90 } |
| 91 |
| 92 // Non-truncating uses. |
| 93 static UseInfo AnyTagged() { return UseInfo(kMachAnyTagged); } |
| 94 static UseInfo Any() { return UseInfo(kTypeAny); } |
| 95 |
| 96 // Ignored-value 'use'. |
| 97 static UseInfo None() { return UseInfo(kMachNone); } |
| 98 |
| 99 // Truncating to a representation that is smaller than the preferred |
| 100 // one. |
| 101 static UseInfo Float64TruncatingToWord32() { |
| 102 return UseInfo(kRepFloat64 | kTypeInt32 | kTypeUint32); |
| 103 } |
| 104 static UseInfo Word64TruncatingToWord32() { |
| 105 return UseInfo(kRepWord64 | kTypeInt32 | kTypeUint32); |
| 106 } |
| 107 static UseInfo AnyTruncatingToBool() { return UseInfo(kTypeBool); } |
| 108 |
| 109 UseInfo(MachineTypeUnion representation, MachineTypeUnion truncation) |
| 110 : type_(representation | truncation) { |
| 111 DCHECK(base::bits::CountPopulation32(representation & kRepMask) == 1); |
| 112 DCHECK((representation & kTypeMask) == 0); |
| 113 DCHECK((truncation & kRepMask) == 0); |
| 114 // TODO(jarin) Check/normalize truncation? |
| 115 } |
| 116 |
| 117 // Queries |
| 118 // ================================================================ |
| 119 MachineType GetRepresentation() const { |
| 120 return static_cast<MachineType>(type_ & kRepMask); |
| 121 } |
| 122 |
| 123 // This should only be used by the Enqueue method. |
| 124 MachineTypeUnion machine_type() const { return type_; } |
| 125 |
| 126 private: |
| 127 explicit UseInfo(MachineTypeUnion type) : type_(type) {} |
| 128 |
| 129 MachineTypeUnion type_; |
| 130 }; |
| 131 |
| 132 |
| 133 UseInfo UseInfoFromRepresentation(MachineTypeUnion rep) { |
| 134 DCHECK((rep & kTypeMask) == 0); |
| 135 if (rep & kRepTagged) return UseInfo::AnyTagged(); |
| 136 if (rep & kRepFloat64) { |
| 137 DCHECK((rep & kRepWord64) == 0); |
| 138 return UseInfo::Float64(); |
| 139 } |
| 140 if (rep & kRepFloat32) { |
| 141 if (rep == kRepFloat32) return UseInfo::Float32(); |
| 142 return UseInfo::AnyTagged(); |
| 143 } |
| 144 if (rep & kRepWord64) { |
| 145 return UseInfo::TruncatingWord64(); |
| 146 } |
| 147 if (rep & (kRepWord32 | kRepWord16 | kRepWord8)) { |
| 148 CHECK(!(rep & kRepBit)); |
| 149 return UseInfo::TruncatingWord32(); |
| 150 } |
| 151 DCHECK(rep & kRepBit); |
| 152 return UseInfo::Bool(); |
| 153 } |
| 154 |
| 155 |
| 156 UseInfo UseInfoFromMachineType(MachineType type) { |
| 157 return UseInfoFromRepresentation(RepresentationOf(type)); |
| 158 } |
| 159 |
| 160 |
| 161 UseInfo UseInfoForBasePointer(const FieldAccess& access) { |
| 162 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); |
| 163 } |
| 164 |
| 165 |
| 166 UseInfo UseInfoForBasePointer(const ElementAccess& access) { |
| 167 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); |
| 168 } |
| 169 |
| 170 } // namespace |
| 171 |
| 172 |
59 class RepresentationSelector { | 173 class RepresentationSelector { |
60 public: | 174 public: |
61 // Information for each node tracked during the fixpoint. | 175 // Information for each node tracked during the fixpoint. |
62 struct NodeInfo { | 176 struct NodeInfo { |
63 MachineTypeUnion use : 15; // Union of all usages for the node. | 177 MachineTypeUnion use : 15; // Union of all usages for the node. |
64 bool queued : 1; // Bookkeeping for the traversal. | 178 bool queued : 1; // Bookkeeping for the traversal. |
65 bool visited : 1; // Bookkeeping for the traversal. | 179 bool visited : 1; // Bookkeeping for the traversal. |
66 MachineTypeUnion output : 15; // Output type of the node. | 180 MachineTypeUnion output : 15; // Output type of the node. |
67 }; | 181 }; |
68 | 182 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // We also need to replace the node in the rest of the vector. | 238 // We also need to replace the node in the rest of the vector. |
125 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { | 239 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { |
126 ++j; | 240 ++j; |
127 if (*j == node) *j = replacement; | 241 if (*j == node) *j = replacement; |
128 } | 242 } |
129 } | 243 } |
130 } | 244 } |
131 | 245 |
132 // Enqueue {node} if the {use} contains new information for that node. | 246 // Enqueue {node} if the {use} contains new information for that node. |
133 // Add {node} to {nodes_} if this is the first time it's been visited. | 247 // Add {node} to {nodes_} if this is the first time it's been visited. |
134 void Enqueue(Node* node, MachineTypeUnion use = 0) { | 248 void Enqueue(Node* node, UseInfo use_info = UseInfo::None()) { |
| 249 MachineTypeUnion use = use_info.machine_type(); |
| 250 |
135 if (phase_ != PROPAGATE) return; | 251 if (phase_ != PROPAGATE) return; |
136 NodeInfo* info = GetInfo(node); | 252 NodeInfo* info = GetInfo(node); |
137 if (!info->visited) { | 253 if (!info->visited) { |
138 // First visit of this node. | 254 // First visit of this node. |
139 info->visited = true; | 255 info->visited = true; |
140 info->queued = true; | 256 info->queued = true; |
141 nodes_.push_back(node); | 257 nodes_.push_back(node); |
142 queue_.push(node); | 258 queue_.push(node); |
143 TRACE(" initial: "); | 259 TRACE(" initial: "); |
144 info->use |= use; | 260 info->use |= use; |
(...skipping 11 matching lines...) Expand all Loading... |
156 } else { | 272 } else { |
157 TRACE(" inqueue: "); | 273 TRACE(" inqueue: "); |
158 } | 274 } |
159 info->use |= use; | 275 info->use |= use; |
160 PrintUseInfo(node); | 276 PrintUseInfo(node); |
161 } | 277 } |
162 } | 278 } |
163 | 279 |
164 bool lower() { return phase_ == LOWER; } | 280 bool lower() { return phase_ == LOWER; } |
165 | 281 |
166 void Enqueue(Node* node, MachineType use) { | |
167 Enqueue(node, static_cast<MachineTypeUnion>(use)); | |
168 } | |
169 | |
170 void SetOutput(Node* node, MachineTypeUnion output) { | 282 void SetOutput(Node* node, MachineTypeUnion output) { |
171 // Every node should have at most one output representation. Note that | 283 // Every node should have at most one output representation. Note that |
172 // phis can have 0, if they have not been used in a representation-inducing | 284 // phis can have 0, if they have not been used in a representation-inducing |
173 // instruction. | 285 // instruction. |
174 DCHECK((output & kRepMask) == 0 || | 286 DCHECK((output & kRepMask) == 0 || |
175 base::bits::IsPowerOfTwo32(output & kRepMask)); | 287 base::bits::IsPowerOfTwo32(output & kRepMask)); |
176 GetInfo(node)->output = output; | 288 GetInfo(node)->output = output; |
177 } | 289 } |
178 | 290 |
179 bool BothInputsAre(Node* node, Type* type) { | 291 bool BothInputsAre(Node* node, Type* type) { |
180 DCHECK_EQ(2, node->InputCount()); | 292 DCHECK_EQ(2, node->InputCount()); |
181 return NodeProperties::GetType(node->InputAt(0))->Is(type) && | 293 return NodeProperties::GetType(node->InputAt(0))->Is(type) && |
182 NodeProperties::GetType(node->InputAt(1))->Is(type); | 294 NodeProperties::GetType(node->InputAt(1))->Is(type); |
183 } | 295 } |
184 | 296 |
185 void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) { | 297 void ProcessTruncateWord32Input(Node* node, int index) { |
186 Node* input = node->InputAt(index); | 298 Node* input = node->InputAt(index); |
187 if (phase_ == PROPAGATE) { | 299 if (phase_ == PROPAGATE) { |
188 // In the propagate phase, propagate the usage information backward. | 300 // In the propagate phase, propagate the usage information backward. |
189 Enqueue(input, use); | 301 Enqueue(input, UseInfo::TruncatingWord32()); |
190 } else { | 302 } else { |
191 // In the change phase, insert a change before the use if necessary. | 303 // In the change phase, insert a change before the use if necessary. |
192 MachineTypeUnion output = GetInfo(input)->output; | 304 MachineTypeUnion output = GetInfo(input)->output; |
193 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { | 305 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { |
194 // Output representation doesn't match usage. | 306 // Output representation doesn't match usage. |
195 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), | 307 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), |
196 node->op()->mnemonic(), index, input->id(), | 308 node->op()->mnemonic(), index, input->id(), |
197 input->op()->mnemonic()); | 309 input->op()->mnemonic()); |
198 TRACE(" from "); | 310 TRACE(" from "); |
199 PrintInfo(output); | 311 PrintInfo(output); |
200 TRACE(" to "); | |
201 PrintInfo(use); | |
202 TRACE("\n"); | 312 TRACE("\n"); |
203 Node* n = changer_->GetTruncatedWord32For(input, output); | 313 Node* n = changer_->GetTruncatedWord32For(input, output); |
204 node->ReplaceInput(index, n); | 314 node->ReplaceInput(index, n); |
205 } | 315 } |
206 } | 316 } |
207 } | 317 } |
208 | 318 |
209 void ProcessInput(Node* node, int index, MachineTypeUnion use) { | 319 void EnqueueInputUse(Node* node, int index, UseInfo use) { |
| 320 Enqueue(node->InputAt(index), use); |
| 321 } |
| 322 |
| 323 void ConvertInput(Node* node, int index, UseInfo use) { |
210 Node* input = node->InputAt(index); | 324 Node* input = node->InputAt(index); |
211 if (phase_ == PROPAGATE) { | 325 // In the change phase, insert a change before the use if necessary. |
212 // In the propagate phase, propagate the usage information backward. | 326 if (use.GetRepresentation() == kMachNone) |
213 Enqueue(input, use); | 327 return; // No input requirement on the use. |
214 } else { | 328 MachineTypeUnion output = GetInfo(input)->output; |
215 // In the change phase, insert a change before the use if necessary. | 329 if ((output & kRepMask) != use.GetRepresentation()) { |
216 if ((use & kRepMask) == 0) return; // No input requirement on the use. | 330 // Output representation doesn't match usage. |
217 MachineTypeUnion output = GetInfo(input)->output; | 331 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), |
218 if ((output & kRepMask & use) == 0) { | 332 index, input->id(), input->op()->mnemonic()); |
219 // Output representation doesn't match usage. | 333 TRACE(" from "); |
220 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), | 334 PrintInfo(output); |
221 node->op()->mnemonic(), index, input->id(), | 335 TRACE(" to "); |
222 input->op()->mnemonic()); | 336 PrintUseInfo(use); |
223 TRACE(" from "); | 337 TRACE("\n"); |
224 PrintInfo(output); | 338 Node* n = |
225 TRACE(" to "); | 339 changer_->GetRepresentationFor(input, output, use.machine_type()); |
226 PrintInfo(use); | 340 node->ReplaceInput(index, n); |
227 TRACE("\n"); | |
228 Node* n = changer_->GetRepresentationFor(input, output, use); | |
229 node->ReplaceInput(index, n); | |
230 } | |
231 } | 341 } |
232 } | 342 } |
233 | 343 |
| 344 void ProcessInput(Node* node, int index, UseInfo use) { |
| 345 if (phase_ == PROPAGATE) { |
| 346 EnqueueInputUse(node, index, use); |
| 347 } else { |
| 348 ConvertInput(node, index, use); |
| 349 } |
| 350 } |
| 351 |
234 void ProcessRemainingInputs(Node* node, int index) { | 352 void ProcessRemainingInputs(Node* node, int index) { |
235 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); | 353 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); |
236 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); | 354 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); |
237 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); | 355 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); |
238 i < NodeProperties::PastEffectIndex(node); ++i) { | 356 i < NodeProperties::PastEffectIndex(node); ++i) { |
239 Enqueue(node->InputAt(i)); // Effect inputs: just visit | 357 Enqueue(node->InputAt(i)); // Effect inputs: just visit |
240 } | 358 } |
241 for (int i = std::max(index, NodeProperties::FirstControlIndex(node)); | 359 for (int i = std::max(index, NodeProperties::FirstControlIndex(node)); |
242 i < NodeProperties::PastControlIndex(node); ++i) { | 360 i < NodeProperties::PastControlIndex(node); ++i) { |
243 Enqueue(node->InputAt(i)); // Control inputs: just visit | 361 Enqueue(node->InputAt(i)); // Control inputs: just visit |
244 } | 362 } |
245 } | 363 } |
246 | 364 |
247 // The default, most general visitation case. For {node}, process all value, | 365 // The default, most general visitation case. For {node}, process all value, |
248 // context, frame state, effect, and control inputs, assuming that value | 366 // context, frame state, effect, and control inputs, assuming that value |
249 // inputs should have {kRepTagged} representation and can observe all output | 367 // inputs should have {kRepTagged} representation and can observe all output |
250 // values {kTypeAny}. | 368 // values {kTypeAny}. |
251 void VisitInputs(Node* node) { | 369 void VisitInputs(Node* node) { |
252 int tagged_count = node->op()->ValueInputCount() + | 370 int tagged_count = node->op()->ValueInputCount() + |
253 OperatorProperties::GetContextInputCount(node->op()); | 371 OperatorProperties::GetContextInputCount(node->op()); |
254 // Visit value and context inputs as tagged. | 372 // Visit value and context inputs as tagged. |
255 for (int i = 0; i < tagged_count; i++) { | 373 for (int i = 0; i < tagged_count; i++) { |
256 ProcessInput(node, i, kMachAnyTagged); | 374 ProcessInput(node, i, UseInfo::AnyTagged()); |
257 } | 375 } |
258 // Only enqueue other inputs (framestates, effects, control). | 376 // Only enqueue other inputs (framestates, effects, control). |
259 for (int i = tagged_count; i < node->InputCount(); i++) { | 377 for (int i = tagged_count; i < node->InputCount(); i++) { |
260 Enqueue(node->InputAt(i)); | 378 Enqueue(node->InputAt(i)); |
261 } | 379 } |
262 // Assume the output is tagged. | 380 // Assume the output is tagged. |
263 SetOutput(node, kMachAnyTagged); | 381 SetOutput(node, kMachAnyTagged); |
264 } | 382 } |
265 | 383 |
266 // Helper for binops of the R x L -> O variety. | 384 // Helper for binops of the R x L -> O variety. |
267 void VisitBinop(Node* node, MachineTypeUnion left_use, | 385 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, |
268 MachineTypeUnion right_use, MachineTypeUnion output) { | 386 MachineTypeUnion output) { |
269 DCHECK_EQ(2, node->op()->ValueInputCount()); | 387 DCHECK_EQ(2, node->op()->ValueInputCount()); |
270 ProcessInput(node, 0, left_use); | 388 ProcessInput(node, 0, left_use); |
271 ProcessInput(node, 1, right_use); | 389 ProcessInput(node, 1, right_use); |
272 for (int i = 2; i < node->InputCount(); i++) { | 390 for (int i = 2; i < node->InputCount(); i++) { |
273 Enqueue(node->InputAt(i)); | 391 Enqueue(node->InputAt(i)); |
274 } | 392 } |
275 SetOutput(node, output); | 393 SetOutput(node, output); |
276 } | 394 } |
277 | 395 |
278 // Helper for binops of the I x I -> O variety. | 396 // Helper for binops of the I x I -> O variety. |
279 void VisitBinop(Node* node, MachineTypeUnion input_use, | 397 void VisitBinop(Node* node, UseInfo input_use, MachineTypeUnion output) { |
280 MachineTypeUnion output) { | |
281 VisitBinop(node, input_use, input_use, output); | 398 VisitBinop(node, input_use, input_use, output); |
282 } | 399 } |
283 | 400 |
284 // Helper for unops of the I -> O variety. | 401 // Helper for unops of the I -> O variety. |
285 void VisitUnop(Node* node, MachineTypeUnion input_use, | 402 void VisitUnop(Node* node, UseInfo input_use, MachineTypeUnion output) { |
286 MachineTypeUnion output) { | |
287 DCHECK_EQ(1, node->InputCount()); | 403 DCHECK_EQ(1, node->InputCount()); |
288 ProcessInput(node, 0, input_use); | 404 ProcessInput(node, 0, input_use); |
289 SetOutput(node, output); | 405 SetOutput(node, output); |
290 } | 406 } |
291 | 407 |
292 // Helper for leaf nodes. | 408 // Helper for leaf nodes. |
293 void VisitLeaf(Node* node, MachineTypeUnion output) { | 409 void VisitLeaf(Node* node, MachineTypeUnion output) { |
294 DCHECK_EQ(0, node->InputCount()); | 410 DCHECK_EQ(0, node->InputCount()); |
295 SetOutput(node, output); | 411 SetOutput(node, output); |
296 } | 412 } |
297 | 413 |
298 // Helpers for specific types of binops. | 414 // Helpers for specific types of binops. |
299 void VisitFloat64Binop(Node* node) { | 415 void VisitFloat64Binop(Node* node) { |
300 VisitBinop(node, kMachFloat64, kMachFloat64); | 416 VisitBinop(node, UseInfo::Float64(), kMachFloat64); |
301 } | 417 } |
302 void VisitInt32Binop(Node* node) { VisitBinop(node, kMachInt32, kMachInt32); } | 418 void VisitInt32Binop(Node* node) { |
| 419 VisitBinop(node, UseInfo::TruncatingWord32(), kMachInt32); |
| 420 } |
303 void VisitUint32Binop(Node* node) { | 421 void VisitUint32Binop(Node* node) { |
304 VisitBinop(node, kMachUint32, kMachUint32); | 422 VisitBinop(node, UseInfo::TruncatingWord32(), kMachUint32); |
305 } | 423 } |
306 void VisitInt64Binop(Node* node) { VisitBinop(node, kMachInt64, kMachInt64); } | 424 void VisitInt64Binop(Node* node) { |
| 425 VisitBinop(node, UseInfo::TruncatingWord64(), kMachInt64); |
| 426 } |
307 void VisitUint64Binop(Node* node) { | 427 void VisitUint64Binop(Node* node) { |
308 VisitBinop(node, kMachUint64, kMachUint64); | 428 VisitBinop(node, UseInfo::TruncatingWord64(), kMachUint64); |
309 } | 429 } |
310 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } | 430 void VisitFloat64Cmp(Node* node) { |
311 void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } | 431 VisitBinop(node, UseInfo::Float64(), kMachBool); |
312 void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } | 432 } |
313 void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } | 433 void VisitInt32Cmp(Node* node) { |
314 void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } | 434 VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
| 435 } |
| 436 void VisitUint32Cmp(Node* node) { |
| 437 VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
| 438 } |
| 439 void VisitInt64Cmp(Node* node) { |
| 440 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
| 441 } |
| 442 void VisitUint64Cmp(Node* node) { |
| 443 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
| 444 } |
315 | 445 |
316 // Infer representation for phi-like nodes. | 446 // Infer representation for phi-like nodes. |
317 MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { | 447 static MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { |
318 // Phis adapt to the output representation their uses demand. | 448 // Phis adapt to the output representation their uses demand. |
319 Type* upper = NodeProperties::GetType(node); | 449 Type* upper = NodeProperties::GetType(node); |
320 if ((use & kRepMask) == kRepFloat32) { | 450 if ((use & kRepMask) == kRepFloat32) { |
321 // only float32 uses. | 451 // only float32 uses. |
322 return kRepFloat32; | 452 return kRepFloat32; |
323 } else if ((use & kRepMask) == kRepFloat64) { | 453 } else if ((use & kRepMask) == kRepFloat64) { |
324 // only float64 uses. | 454 // only float64 uses. |
325 return kRepFloat64; | 455 return kRepFloat64; |
326 } else if ((use & kRepMask) == kRepTagged) { | 456 } else if ((use & kRepMask) == kRepTagged) { |
327 // only tagged uses. | 457 // only tagged uses. |
328 return kRepTagged; | 458 return kRepTagged; |
329 } else if (upper->Is(Type::Integral32())) { | 459 } else if (upper->Is(Type::Integral32())) { |
330 // Integer within [-2^31, 2^32[ range. | 460 // Integer within [-2^31, 2^32[ range. |
331 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { | 461 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { |
332 // multiple uses, but we are within 32 bits range => pick kRepWord32. | 462 // multiple uses, but we are within 32 bits range => pick kRepWord32. |
333 return kRepWord32; | 463 return kRepWord32; |
334 } else if ((use & kTypeMask) == kTypeInt32 || | 464 } else if (!CanObserveNonWord32(use)) { |
335 (use & kTypeMask) == kTypeUint32) { | 465 // We only use 32 bits. |
336 // We only use 32 bits or we use the result consistently. | |
337 return kRepWord32; | 466 return kRepWord32; |
338 } else { | 467 } else { |
339 return kRepFloat64; | 468 return kRepFloat64; |
340 } | 469 } |
341 } else if (upper->Is(Type::Boolean())) { | 470 } else if (upper->Is(Type::Boolean())) { |
342 // multiple uses => pick kRepBit. | 471 // multiple uses => pick kRepBit. |
343 return kRepBit; | 472 return kRepBit; |
344 } else if (upper->Is(Type::Number())) { | 473 } else if (upper->Is(Type::Number())) { |
345 // multiple uses => pick kRepFloat64. | 474 // multiple uses => pick kRepFloat64. |
346 return kRepFloat64; | 475 return kRepFloat64; |
347 } else if (upper->Is(Type::Internal())) { | 476 } else if (upper->Is(Type::Internal())) { |
348 return kMachPtr; | 477 return kMachPtr; |
349 } | 478 } |
350 return kRepTagged; | 479 return kRepTagged; |
351 } | 480 } |
352 | 481 |
353 // Helper for handling selects. | 482 // Helper for handling selects. |
354 void VisitSelect(Node* node, MachineTypeUnion use, | 483 void VisitSelect(Node* node, MachineTypeUnion use, |
355 SimplifiedLowering* lowering) { | 484 SimplifiedLowering* lowering) { |
356 ProcessInput(node, 0, kRepBit); | 485 ProcessInput(node, 0, UseInfo::Bool()); |
357 MachineType output = GetRepresentationForPhi(node, use); | 486 MachineType output = GetRepresentationForPhi(node, use); |
358 | 487 |
359 Type* upper = NodeProperties::GetType(node); | 488 Type* upper = NodeProperties::GetType(node); |
360 MachineType output_type = | 489 MachineType output_type = |
361 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 490 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
362 SetOutput(node, output_type); | 491 SetOutput(node, output_type); |
363 | 492 |
364 if (lower()) { | 493 if (lower()) { |
365 // Update the select operator. | 494 // Update the select operator. |
366 SelectParameters p = SelectParametersOf(node->op()); | 495 SelectParameters p = SelectParametersOf(node->op()); |
367 MachineType type = static_cast<MachineType>(output_type); | 496 MachineType type = static_cast<MachineType>(output_type); |
368 if (type != p.type()) { | 497 if (type != p.type()) { |
369 NodeProperties::ChangeOp(node, | 498 NodeProperties::ChangeOp(node, |
370 lowering->common()->Select(type, p.hint())); | 499 lowering->common()->Select(type, p.hint())); |
371 } | 500 } |
372 | |
373 // Convert inputs to the output representation of this select. | |
374 ProcessInput(node, 1, output_type); | |
375 ProcessInput(node, 2, output_type); | |
376 } else { | |
377 // Propagate {use} of the select to value inputs. | |
378 MachineType use_type = | |
379 static_cast<MachineType>((use & kTypeMask) | output); | |
380 ProcessInput(node, 1, use_type); | |
381 ProcessInput(node, 2, use_type); | |
382 } | 501 } |
| 502 // Convert inputs to the output representation of this phi, pass the |
| 503 // use truncation along. |
| 504 UseInfo input_use(output, use & kTypeMask); |
| 505 ProcessInput(node, 1, input_use); |
| 506 ProcessInput(node, 2, input_use); |
383 } | 507 } |
384 | 508 |
385 // Helper for handling phis. | 509 // Helper for handling phis. |
386 void VisitPhi(Node* node, MachineTypeUnion use, | 510 void VisitPhi(Node* node, MachineTypeUnion use, |
387 SimplifiedLowering* lowering) { | 511 SimplifiedLowering* lowering) { |
388 MachineType output = GetRepresentationForPhi(node, use); | 512 MachineType output = GetRepresentationForPhi(node, use); |
389 | 513 |
390 Type* upper = NodeProperties::GetType(node); | 514 Type* upper = NodeProperties::GetType(node); |
391 MachineType output_type = | 515 MachineType output_type = |
392 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 516 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
393 SetOutput(node, output_type); | 517 SetOutput(node, output_type); |
394 | 518 |
395 int values = node->op()->ValueInputCount(); | 519 int values = node->op()->ValueInputCount(); |
396 | 520 |
397 if (lower()) { | 521 if (lower()) { |
398 // Update the phi operator. | 522 // Update the phi operator. |
399 MachineType type = static_cast<MachineType>(output_type); | 523 MachineType type = static_cast<MachineType>(output_type); |
400 if (type != OpParameter<MachineType>(node)) { | 524 if (type != OpParameter<MachineType>(node)) { |
401 NodeProperties::ChangeOp(node, lowering->common()->Phi(type, values)); | 525 NodeProperties::ChangeOp(node, lowering->common()->Phi(type, values)); |
402 } | 526 } |
403 } | 527 } |
404 | 528 |
405 // Convert inputs to the output representation of this phi, pass the | 529 // Convert inputs to the output representation of this phi, pass the |
406 // use truncation along. | 530 // use truncation along. |
407 MachineType use_type = static_cast<MachineType>((use & kTypeMask) | output); | 531 UseInfo input_use(output, use & kTypeMask); |
408 for (int i = 0; i < node->InputCount(); i++) { | 532 for (int i = 0; i < node->InputCount(); i++) { |
409 ProcessInput(node, i, i < values ? use_type : 0); | 533 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); |
410 } | 534 } |
411 } | 535 } |
412 | 536 |
413 void VisitCall(Node* node, SimplifiedLowering* lowering) { | 537 void VisitCall(Node* node, SimplifiedLowering* lowering) { |
414 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); | 538 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); |
415 const MachineSignature* sig = desc->GetMachineSignature(); | 539 const MachineSignature* sig = desc->GetMachineSignature(); |
416 int params = static_cast<int>(sig->parameter_count()); | 540 int params = static_cast<int>(sig->parameter_count()); |
417 // Propagate representation information from call descriptor. | 541 // Propagate representation information from call descriptor. |
418 for (int i = 0; i < node->InputCount(); i++) { | 542 for (int i = 0; i < node->InputCount(); i++) { |
419 if (i == 0) { | 543 if (i == 0) { |
420 // The target of the call. | 544 // The target of the call. |
421 ProcessInput(node, i, 0); | 545 ProcessInput(node, i, UseInfo::None()); |
422 } else if ((i - 1) < params) { | 546 } else if ((i - 1) < params) { |
423 ProcessInput(node, i, sig->GetParam(i - 1)); | 547 ProcessInput(node, i, UseInfoFromMachineType(sig->GetParam(i - 1))); |
424 } else { | 548 } else { |
425 ProcessInput(node, i, 0); | 549 ProcessInput(node, i, UseInfo::None()); |
426 } | 550 } |
427 } | 551 } |
428 | 552 |
429 if (sig->return_count() > 0) { | 553 if (sig->return_count() > 0) { |
430 SetOutput(node, desc->GetMachineSignature()->GetReturn()); | 554 SetOutput(node, desc->GetMachineSignature()->GetReturn()); |
431 } else { | 555 } else { |
432 SetOutput(node, kMachAnyTagged); | 556 SetOutput(node, kMachAnyTagged); |
433 } | 557 } |
434 } | 558 } |
435 | 559 |
436 void VisitStateValues(Node* node) { | 560 void VisitStateValues(Node* node) { |
437 if (phase_ == PROPAGATE) { | 561 if (phase_ == PROPAGATE) { |
438 for (int i = 0; i < node->InputCount(); i++) { | 562 for (int i = 0; i < node->InputCount(); i++) { |
439 Enqueue(node->InputAt(i), kTypeAny); | 563 Enqueue(node->InputAt(i), UseInfo::Any()); |
440 } | 564 } |
441 } else { | 565 } else { |
442 Zone* zone = jsgraph_->zone(); | 566 Zone* zone = jsgraph_->zone(); |
443 ZoneVector<MachineType>* types = | 567 ZoneVector<MachineType>* types = |
444 new (zone->New(sizeof(ZoneVector<MachineType>))) | 568 new (zone->New(sizeof(ZoneVector<MachineType>))) |
445 ZoneVector<MachineType>(node->InputCount(), zone); | 569 ZoneVector<MachineType>(node->InputCount(), zone); |
446 for (int i = 0; i < node->InputCount(); i++) { | 570 for (int i = 0; i < node->InputCount(); i++) { |
447 MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output; | 571 MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output; |
448 (*types)[i] = static_cast<MachineType>(input_type); | 572 (*types)[i] = static_cast<MachineType>(input_type); |
449 } | 573 } |
(...skipping 25 matching lines...) Expand all Loading... |
475 return BothInputsAre(node, safe_int_additive_range_) && | 599 return BothInputsAre(node, safe_int_additive_range_) && |
476 !CanObserveNonWord32(use); | 600 !CanObserveNonWord32(use); |
477 } | 601 } |
478 | 602 |
479 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { | 603 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { |
480 return BothInputsAre(node, Type::Unsigned32()) && | 604 return BothInputsAre(node, Type::Unsigned32()) && |
481 (!CanObserveNonWord32(use) || | 605 (!CanObserveNonWord32(use) || |
482 NodeProperties::GetType(node)->Is(Type::Unsigned32())); | 606 NodeProperties::GetType(node)->Is(Type::Unsigned32())); |
483 } | 607 } |
484 | 608 |
485 bool CanObserveNonWord32(MachineTypeUnion use) { | 609 static bool CanObserveNonWord32(MachineTypeUnion use) { |
486 return (use & kTypeMask & ~(kTypeInt32 | kTypeUint32)) != 0; | 610 return (use & kTypeMask & ~(kTypeInt32 | kTypeUint32)) != 0; |
487 } | 611 } |
488 | 612 |
489 bool CanObserveNaN(MachineTypeUnion use) { | 613 static bool CanObserveNaN(MachineTypeUnion use) { |
490 return (use & (kTypeNumber | kTypeAny)) != 0; | 614 return (use & (kTypeNumber | kTypeAny)) != 0; |
491 } | 615 } |
492 | 616 |
493 // Dispatching routine for visiting the node {node} with the usage {use}. | 617 // Dispatching routine for visiting the node {node} with the usage {use}. |
494 // Depending on the operator, propagate new usage info to the inputs. | 618 // Depending on the operator, propagate new usage info to the inputs. |
495 void VisitNode(Node* node, MachineTypeUnion use, | 619 void VisitNode(Node* node, MachineTypeUnion use, |
496 SimplifiedLowering* lowering) { | 620 SimplifiedLowering* lowering) { |
497 switch (node->opcode()) { | 621 switch (node->opcode()) { |
498 //------------------------------------------------------------------ | 622 //------------------------------------------------------------------ |
499 // Common operators. | 623 // Common operators. |
500 //------------------------------------------------------------------ | 624 //------------------------------------------------------------------ |
501 case IrOpcode::kStart: | 625 case IrOpcode::kStart: |
502 case IrOpcode::kDead: | 626 case IrOpcode::kDead: |
503 return VisitLeaf(node, 0); | 627 return VisitLeaf(node, 0); |
504 case IrOpcode::kParameter: { | 628 case IrOpcode::kParameter: { |
505 // TODO(titzer): use representation from linkage. | 629 // TODO(titzer): use representation from linkage. |
506 Type* upper = NodeProperties::GetType(node); | 630 Type* upper = NodeProperties::GetType(node); |
507 ProcessInput(node, 0, 0); | 631 ProcessInput(node, 0, UseInfo::None()); |
508 SetOutput(node, kRepTagged | changer_->TypeFromUpperBound(upper)); | 632 SetOutput(node, kRepTagged | changer_->TypeFromUpperBound(upper)); |
509 return; | 633 return; |
510 } | 634 } |
511 case IrOpcode::kInt32Constant: | 635 case IrOpcode::kInt32Constant: |
512 return VisitLeaf(node, kRepWord32); | 636 return VisitLeaf(node, kRepWord32); |
513 case IrOpcode::kInt64Constant: | 637 case IrOpcode::kInt64Constant: |
514 return VisitLeaf(node, kRepWord64); | 638 return VisitLeaf(node, kRepWord64); |
515 case IrOpcode::kFloat32Constant: | 639 case IrOpcode::kFloat32Constant: |
516 return VisitLeaf(node, kRepFloat32); | 640 return VisitLeaf(node, kRepFloat32); |
517 case IrOpcode::kFloat64Constant: | 641 case IrOpcode::kFloat64Constant: |
518 return VisitLeaf(node, kRepFloat64); | 642 return VisitLeaf(node, kRepFloat64); |
519 case IrOpcode::kExternalConstant: | 643 case IrOpcode::kExternalConstant: |
520 return VisitLeaf(node, kMachPtr); | 644 return VisitLeaf(node, kMachPtr); |
521 case IrOpcode::kNumberConstant: | 645 case IrOpcode::kNumberConstant: |
522 return VisitLeaf(node, kRepTagged); | 646 return VisitLeaf(node, kRepTagged); |
523 case IrOpcode::kHeapConstant: | 647 case IrOpcode::kHeapConstant: |
524 return VisitLeaf(node, kRepTagged); | 648 return VisitLeaf(node, kRepTagged); |
525 | 649 |
526 case IrOpcode::kBranch: | 650 case IrOpcode::kBranch: |
527 ProcessInput(node, 0, kRepBit); | 651 ProcessInput(node, 0, UseInfo::Bool()); |
528 Enqueue(NodeProperties::GetControlInput(node, 0)); | 652 Enqueue(NodeProperties::GetControlInput(node, 0)); |
529 break; | 653 break; |
530 case IrOpcode::kSwitch: | 654 case IrOpcode::kSwitch: |
531 ProcessInput(node, 0, kRepWord32); | 655 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
532 Enqueue(NodeProperties::GetControlInput(node, 0)); | 656 Enqueue(NodeProperties::GetControlInput(node, 0)); |
533 break; | 657 break; |
534 case IrOpcode::kSelect: | 658 case IrOpcode::kSelect: |
535 return VisitSelect(node, use, lowering); | 659 return VisitSelect(node, use, lowering); |
536 case IrOpcode::kPhi: | 660 case IrOpcode::kPhi: |
537 return VisitPhi(node, use, lowering); | 661 return VisitPhi(node, use, lowering); |
538 case IrOpcode::kCall: | 662 case IrOpcode::kCall: |
539 return VisitCall(node, lowering); | 663 return VisitCall(node, lowering); |
540 | 664 |
541 //------------------------------------------------------------------ | 665 //------------------------------------------------------------------ |
(...skipping 20 matching lines...) Expand all Loading... |
562 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) | 686 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) |
563 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); | 687 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); |
564 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); | 688 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); |
565 } else { | 689 } else { |
566 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) | 690 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) |
567 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); | 691 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); |
568 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 692 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
569 } | 693 } |
570 } else { | 694 } else { |
571 // No input representation requirement; adapt during lowering. | 695 // No input representation requirement; adapt during lowering. |
572 ProcessInput(node, 0, kTypeBool); | 696 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
573 SetOutput(node, kRepBit); | 697 SetOutput(node, kRepBit); |
574 } | 698 } |
575 break; | 699 break; |
576 } | 700 } |
577 case IrOpcode::kBooleanToNumber: { | 701 case IrOpcode::kBooleanToNumber: { |
578 if (lower()) { | 702 if (lower()) { |
579 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; | 703 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; |
580 if (input & kRepBit) { | 704 if (input & kRepBit) { |
581 // BooleanToNumber(x: kRepBit) => x | 705 // BooleanToNumber(x: kRepBit) => x |
582 DeferReplacement(node, node->InputAt(0)); | 706 DeferReplacement(node, node->InputAt(0)); |
583 } else { | 707 } else { |
584 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) | 708 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) |
585 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); | 709 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); |
586 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 710 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
587 } | 711 } |
588 } else { | 712 } else { |
589 // No input representation requirement; adapt during lowering. | 713 // No input representation requirement; adapt during lowering. |
590 ProcessInput(node, 0, kTypeBool); | 714 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
591 SetOutput(node, kMachInt32); | 715 SetOutput(node, kMachInt32); |
592 } | 716 } |
593 break; | 717 break; |
594 } | 718 } |
595 case IrOpcode::kNumberEqual: | 719 case IrOpcode::kNumberEqual: |
596 case IrOpcode::kNumberLessThan: | 720 case IrOpcode::kNumberLessThan: |
597 case IrOpcode::kNumberLessThanOrEqual: { | 721 case IrOpcode::kNumberLessThanOrEqual: { |
598 // Number comparisons reduce to integer comparisons for integer inputs. | 722 // Number comparisons reduce to integer comparisons for integer inputs. |
599 if (BothInputsAre(node, Type::Signed32())) { | 723 if (BothInputsAre(node, Type::Signed32())) { |
600 // => signed Int32Cmp | 724 // => signed Int32Cmp |
(...skipping 17 matching lines...) Expand all Loading... |
618 if (CanLowerToInt32Binop(node, use)) { | 742 if (CanLowerToInt32Binop(node, use)) { |
619 // => signed Int32Add/Sub | 743 // => signed Int32Add/Sub |
620 VisitInt32Binop(node); | 744 VisitInt32Binop(node); |
621 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 745 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
622 } else if (CanLowerToUint32Binop(node, use)) { | 746 } else if (CanLowerToUint32Binop(node, use)) { |
623 // => unsigned Int32Add/Sub | 747 // => unsigned Int32Add/Sub |
624 VisitUint32Binop(node); | 748 VisitUint32Binop(node); |
625 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); | 749 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
626 } else if (CanLowerToWord32AdditiveBinop(node, use)) { | 750 } else if (CanLowerToWord32AdditiveBinop(node, use)) { |
627 // => signed Int32Add/Sub, truncating inputs | 751 // => signed Int32Add/Sub, truncating inputs |
628 ProcessTruncateWord32Input(node, 0, kTypeInt32); | 752 ProcessTruncateWord32Input(node, 0); |
629 ProcessTruncateWord32Input(node, 1, kTypeInt32); | 753 ProcessTruncateWord32Input(node, 1); |
630 SetOutput(node, kMachInt32); | 754 SetOutput(node, kMachInt32); |
631 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 755 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
632 } else { | 756 } else { |
633 // => Float64Add/Sub | 757 // => Float64Add/Sub |
634 VisitFloat64Binop(node); | 758 VisitFloat64Binop(node); |
635 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 759 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
636 } | 760 } |
637 break; | 761 break; |
638 } | 762 } |
639 case IrOpcode::kNumberMultiply: { | 763 case IrOpcode::kNumberMultiply: { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 break; | 812 break; |
689 } | 813 } |
690 case IrOpcode::kNumberBitwiseOr: | 814 case IrOpcode::kNumberBitwiseOr: |
691 case IrOpcode::kNumberBitwiseXor: | 815 case IrOpcode::kNumberBitwiseXor: |
692 case IrOpcode::kNumberBitwiseAnd: { | 816 case IrOpcode::kNumberBitwiseAnd: { |
693 VisitInt32Binop(node); | 817 VisitInt32Binop(node); |
694 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 818 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
695 break; | 819 break; |
696 } | 820 } |
697 case IrOpcode::kNumberShiftLeft: { | 821 case IrOpcode::kNumberShiftLeft: { |
698 VisitBinop(node, kMachInt32, kMachUint32, kMachInt32); | 822 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 823 UseInfo::TruncatingWord32(), kMachInt32); |
699 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl()); | 824 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl()); |
700 break; | 825 break; |
701 } | 826 } |
702 case IrOpcode::kNumberShiftRight: { | 827 case IrOpcode::kNumberShiftRight: { |
703 VisitBinop(node, kMachInt32, kMachUint32, kMachInt32); | 828 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 829 UseInfo::TruncatingWord32(), kMachInt32); |
704 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar()); | 830 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar()); |
705 break; | 831 break; |
706 } | 832 } |
707 case IrOpcode::kNumberShiftRightLogical: { | 833 case IrOpcode::kNumberShiftRightLogical: { |
708 VisitBinop(node, kMachUint32, kMachUint32, kMachUint32); | 834 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 835 UseInfo::TruncatingWord32(), kMachUint32); |
709 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr()); | 836 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr()); |
710 break; | 837 break; |
711 } | 838 } |
712 case IrOpcode::kNumberToInt32: { | 839 case IrOpcode::kNumberToInt32: { |
713 MachineTypeUnion use_rep = use & kRepMask; | 840 MachineTypeUnion use_rep = use & kRepMask; |
714 Node* input = node->InputAt(0); | 841 Node* input = node->InputAt(0); |
715 Type* in_upper = NodeProperties::GetType(input); | 842 Type* in_upper = NodeProperties::GetType(input); |
716 MachineTypeUnion in = GetInfo(input)->output; | 843 MachineTypeUnion in = GetInfo(input)->output; |
717 if (in_upper->Is(Type::Signed32())) { | 844 if (in_upper->Is(Type::Signed32())) { |
718 // If the input has type int32, pass through representation. | 845 // If the input has type int32, pass through representation. |
719 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); | 846 VisitUnop(node, UseInfoFromRepresentation(use_rep), |
| 847 kTypeInt32 | use_rep); |
720 if (lower()) DeferReplacement(node, node->InputAt(0)); | 848 if (lower()) DeferReplacement(node, node->InputAt(0)); |
721 } else if ((in & kTypeMask) == kTypeUint32 || | 849 } else if ((in & kTypeMask) == kTypeUint32 || |
722 in_upper->Is(Type::Unsigned32())) { | 850 in_upper->Is(Type::Unsigned32())) { |
723 // Just change representation if necessary. | 851 // Just change representation if necessary. |
724 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeInt32 | kRepWord32); | 852 VisitUnop(node, UseInfo::TruncatingWord32(), kTypeInt32 | kRepWord32); |
725 if (lower()) DeferReplacement(node, node->InputAt(0)); | 853 if (lower()) DeferReplacement(node, node->InputAt(0)); |
726 } else if ((in & kTypeMask) == kTypeInt32 || | 854 } else if ((in & kTypeMask) == kTypeInt32 || |
727 (in & kRepMask) == kRepWord32) { | 855 (in & kRepMask) == kRepWord32) { |
728 // Just change representation if necessary. | 856 // Just change representation if necessary. |
729 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); | 857 VisitUnop(node, UseInfo::TruncatingWord32(), kTypeInt32 | kRepWord32); |
730 if (lower()) DeferReplacement(node, node->InputAt(0)); | 858 if (lower()) DeferReplacement(node, node->InputAt(0)); |
731 } else { | 859 } else { |
732 // Require the input in float64 format and perform truncation. | 860 // Require the input in float64 format and perform truncation. |
733 // TODO(turbofan): avoid a truncation with a smi check. | 861 // TODO(turbofan): avoid a truncation with a smi check. |
734 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); | 862 VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
| 863 kTypeInt32 | kRepWord32); |
735 if (lower()) { | 864 if (lower()) { |
736 NodeProperties::ChangeOp( | 865 NodeProperties::ChangeOp( |
737 node, lowering->machine()->TruncateFloat64ToInt32( | 866 node, lowering->machine()->TruncateFloat64ToInt32( |
738 TruncationMode::kJavaScript)); | 867 TruncationMode::kJavaScript)); |
739 } | 868 } |
740 } | 869 } |
741 break; | 870 break; |
742 } | 871 } |
743 case IrOpcode::kNumberToUint32: { | 872 case IrOpcode::kNumberToUint32: { |
744 MachineTypeUnion use_rep = use & kRepMask; | 873 MachineTypeUnion use_rep = use & kRepMask; |
745 Node* input = node->InputAt(0); | 874 Node* input = node->InputAt(0); |
746 Type* in_upper = NodeProperties::GetType(input); | 875 Type* in_upper = NodeProperties::GetType(input); |
747 MachineTypeUnion in = GetInfo(input)->output; | 876 MachineTypeUnion in = GetInfo(input)->output; |
748 if (in_upper->Is(Type::Unsigned32())) { | 877 if (in_upper->Is(Type::Unsigned32())) { |
749 // If the input has type uint32, pass through representation. | 878 // If the input has type uint32, pass through representation. |
750 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); | 879 VisitUnop(node, UseInfoFromRepresentation(use_rep), |
| 880 kTypeUint32 | use_rep); |
751 if (lower()) DeferReplacement(node, node->InputAt(0)); | 881 if (lower()) DeferReplacement(node, node->InputAt(0)); |
752 } else if ((in & kTypeMask) == kTypeInt32 || | 882 } else if ((in & kTypeMask) == kTypeInt32 || |
753 in_upper->Is(Type::Signed32())) { | 883 in_upper->Is(Type::Signed32())) { |
754 // Just change representation if necessary. | 884 // Just change representation if necessary. |
755 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeUint32 | kRepWord32); | 885 VisitUnop(node, UseInfo::TruncatingWord32(), |
| 886 kTypeUint32 | kRepWord32); |
756 if (lower()) DeferReplacement(node, node->InputAt(0)); | 887 if (lower()) DeferReplacement(node, node->InputAt(0)); |
757 } else if ((in & kTypeMask) == kTypeUint32 || | 888 } else if ((in & kTypeMask) == kTypeUint32 || |
758 (in & kRepMask) == kRepWord32) { | 889 (in & kRepMask) == kRepWord32) { |
759 // Just change representation if necessary. | 890 // Just change representation if necessary. |
760 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); | 891 VisitUnop(node, UseInfo::TruncatingWord32(), |
| 892 kTypeUint32 | kRepWord32); |
761 if (lower()) DeferReplacement(node, node->InputAt(0)); | 893 if (lower()) DeferReplacement(node, node->InputAt(0)); |
762 } else { | 894 } else { |
763 // Require the input in float64 format and perform truncation. | 895 // Require the input in float64 format and perform truncation. |
764 // TODO(turbofan): avoid a truncation with a smi check. | 896 // TODO(turbofan): avoid a truncation with a smi check. |
765 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); | 897 VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
| 898 kTypeUint32 | kRepWord32); |
766 if (lower()) { | 899 if (lower()) { |
767 NodeProperties::ChangeOp( | 900 NodeProperties::ChangeOp( |
768 node, lowering->machine()->TruncateFloat64ToInt32( | 901 node, lowering->machine()->TruncateFloat64ToInt32( |
769 TruncationMode::kJavaScript)); | 902 TruncationMode::kJavaScript)); |
770 } | 903 } |
771 } | 904 } |
772 break; | 905 break; |
773 } | 906 } |
774 case IrOpcode::kNumberIsHoleNaN: { | 907 case IrOpcode::kNumberIsHoleNaN: { |
775 VisitUnop(node, kMachFloat64, kMachBool); | 908 VisitUnop(node, UseInfo::Float64(), kMachBool); |
776 if (lower()) { | 909 if (lower()) { |
777 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), | 910 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), |
778 // #HoleNaNLower32) | 911 // #HoleNaNLower32) |
779 node->ReplaceInput(0, | 912 node->ReplaceInput(0, |
780 jsgraph_->graph()->NewNode( | 913 jsgraph_->graph()->NewNode( |
781 lowering->machine()->Float64ExtractLowWord32(), | 914 lowering->machine()->Float64ExtractLowWord32(), |
782 node->InputAt(0))); | 915 node->InputAt(0))); |
783 node->AppendInput(jsgraph_->zone(), | 916 node->AppendInput(jsgraph_->zone(), |
784 jsgraph_->Int32Constant(kHoleNanLower32)); | 917 jsgraph_->Int32Constant(kHoleNanLower32)); |
785 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); | 918 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); |
786 } | 919 } |
787 break; | 920 break; |
788 } | 921 } |
789 case IrOpcode::kPlainPrimitiveToNumber: { | 922 case IrOpcode::kPlainPrimitiveToNumber: { |
790 VisitUnop(node, kMachAnyTagged, kTypeNumber | kRepTagged); | 923 VisitUnop(node, UseInfo::AnyTagged(), kTypeNumber | kRepTagged); |
791 if (lower()) { | 924 if (lower()) { |
792 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context) | 925 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context) |
793 Operator::Properties properties = node->op()->properties(); | 926 Operator::Properties properties = node->op()->properties(); |
794 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate()); | 927 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate()); |
795 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 928 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
796 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 929 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
797 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, | 930 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, |
798 flags, properties); | 931 flags, properties); |
799 node->InsertInput(jsgraph_->zone(), 0, | 932 node->InsertInput(jsgraph_->zone(), 0, |
800 jsgraph_->HeapConstant(callable.code())); | 933 jsgraph_->HeapConstant(callable.code())); |
801 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); | 934 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
802 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); | 935 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); |
803 } | 936 } |
804 break; | 937 break; |
805 } | 938 } |
806 case IrOpcode::kReferenceEqual: { | 939 case IrOpcode::kReferenceEqual: { |
807 VisitBinop(node, kMachAnyTagged, kRepBit); | 940 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
808 if (lower()) { | 941 if (lower()) { |
809 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 942 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
810 } | 943 } |
811 break; | 944 break; |
812 } | 945 } |
813 case IrOpcode::kStringEqual: { | 946 case IrOpcode::kStringEqual: { |
814 VisitBinop(node, kMachAnyTagged, kRepBit); | 947 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
815 if (lower()) lowering->DoStringEqual(node); | 948 if (lower()) lowering->DoStringEqual(node); |
816 break; | 949 break; |
817 } | 950 } |
818 case IrOpcode::kStringLessThan: { | 951 case IrOpcode::kStringLessThan: { |
819 VisitBinop(node, kMachAnyTagged, kRepBit); | 952 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
820 if (lower()) lowering->DoStringLessThan(node); | 953 if (lower()) lowering->DoStringLessThan(node); |
821 break; | 954 break; |
822 } | 955 } |
823 case IrOpcode::kStringLessThanOrEqual: { | 956 case IrOpcode::kStringLessThanOrEqual: { |
824 VisitBinop(node, kMachAnyTagged, kRepBit); | 957 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
825 if (lower()) lowering->DoStringLessThanOrEqual(node); | 958 if (lower()) lowering->DoStringLessThanOrEqual(node); |
826 break; | 959 break; |
827 } | 960 } |
828 case IrOpcode::kAllocate: { | 961 case IrOpcode::kAllocate: { |
829 ProcessInput(node, 0, kMachAnyTagged); | 962 ProcessInput(node, 0, UseInfo::AnyTagged()); |
830 ProcessRemainingInputs(node, 1); | 963 ProcessRemainingInputs(node, 1); |
831 SetOutput(node, kMachAnyTagged); | 964 SetOutput(node, kMachAnyTagged); |
832 break; | 965 break; |
833 } | 966 } |
834 case IrOpcode::kLoadField: { | 967 case IrOpcode::kLoadField: { |
835 FieldAccess access = FieldAccessOf(node->op()); | 968 FieldAccess access = FieldAccessOf(node->op()); |
836 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 969 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
837 ProcessRemainingInputs(node, 1); | 970 ProcessRemainingInputs(node, 1); |
838 SetOutput(node, access.machine_type); | 971 SetOutput(node, access.machine_type); |
839 break; | 972 break; |
840 } | 973 } |
841 case IrOpcode::kStoreField: { | 974 case IrOpcode::kStoreField: { |
842 FieldAccess access = FieldAccessOf(node->op()); | 975 FieldAccess access = FieldAccessOf(node->op()); |
843 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 976 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
844 ProcessInput(node, 1, access.machine_type); | 977 ProcessInput(node, 1, UseInfoFromMachineType(access.machine_type)); |
845 ProcessRemainingInputs(node, 2); | 978 ProcessRemainingInputs(node, 2); |
846 SetOutput(node, 0); | 979 SetOutput(node, 0); |
847 break; | 980 break; |
848 } | 981 } |
849 case IrOpcode::kLoadBuffer: { | 982 case IrOpcode::kLoadBuffer: { |
850 BufferAccess access = BufferAccessOf(node->op()); | 983 BufferAccess access = BufferAccessOf(node->op()); |
851 ProcessInput(node, 0, kMachPtr); // buffer | 984 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
852 ProcessInput(node, 1, kMachInt32); // offset | 985 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
853 ProcessInput(node, 2, kMachInt32); // length | 986 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
854 ProcessRemainingInputs(node, 3); | 987 ProcessRemainingInputs(node, 3); |
855 // Tagged overrides everything if we have to do a typed array bounds | 988 // Tagged overrides everything if we have to do a typed array bounds |
856 // check, because we may need to return undefined then. | 989 // check, because we may need to return undefined then. |
857 MachineType output_type; | 990 MachineType output_type; |
858 if (use & kRepTagged) { | 991 if (use & kRepTagged) { |
859 output_type = kMachAnyTagged; | 992 output_type = kMachAnyTagged; |
860 } else if (use & kRepFloat64) { | 993 } else if (use & kRepFloat64) { |
861 if (access.machine_type() & kRepFloat32) { | 994 if (access.machine_type() & kRepFloat32) { |
862 output_type = access.machine_type(); | 995 output_type = access.machine_type(); |
863 } else { | 996 } else { |
864 output_type = kMachFloat64; | 997 output_type = kMachFloat64; |
865 } | 998 } |
866 } else if (use & kRepFloat32) { | 999 } else if (use & kRepFloat32) { |
867 output_type = kMachFloat32; | 1000 output_type = kMachFloat32; |
868 } else { | 1001 } else { |
869 output_type = access.machine_type(); | 1002 output_type = access.machine_type(); |
870 } | 1003 } |
871 SetOutput(node, output_type); | 1004 SetOutput(node, output_type); |
872 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); | 1005 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); |
873 break; | 1006 break; |
874 } | 1007 } |
875 case IrOpcode::kStoreBuffer: { | 1008 case IrOpcode::kStoreBuffer: { |
876 BufferAccess access = BufferAccessOf(node->op()); | 1009 BufferAccess access = BufferAccessOf(node->op()); |
877 ProcessInput(node, 0, kMachPtr); // buffer | 1010 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
878 ProcessInput(node, 1, kMachInt32); // offset | 1011 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
879 ProcessInput(node, 2, kMachInt32); // length | 1012 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
880 ProcessInput(node, 3, access.machine_type()); // value | 1013 ProcessInput(node, 3, |
| 1014 UseInfoFromMachineType(access.machine_type())); // value |
881 ProcessRemainingInputs(node, 4); | 1015 ProcessRemainingInputs(node, 4); |
882 SetOutput(node, 0); | 1016 SetOutput(node, 0); |
883 if (lower()) lowering->DoStoreBuffer(node); | 1017 if (lower()) lowering->DoStoreBuffer(node); |
884 break; | 1018 break; |
885 } | 1019 } |
886 case IrOpcode::kLoadElement: { | 1020 case IrOpcode::kLoadElement: { |
887 ElementAccess access = ElementAccessOf(node->op()); | 1021 ElementAccess access = ElementAccessOf(node->op()); |
888 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base | 1022 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
889 ProcessInput(node, 1, kMachInt32); // index | 1023 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
890 ProcessRemainingInputs(node, 2); | 1024 ProcessRemainingInputs(node, 2); |
891 SetOutput(node, access.machine_type); | 1025 SetOutput(node, access.machine_type); |
892 break; | 1026 break; |
893 } | 1027 } |
894 case IrOpcode::kStoreElement: { | 1028 case IrOpcode::kStoreElement: { |
895 ElementAccess access = ElementAccessOf(node->op()); | 1029 ElementAccess access = ElementAccessOf(node->op()); |
896 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base | 1030 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
897 ProcessInput(node, 1, kMachInt32); // index | 1031 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
898 ProcessInput(node, 2, access.machine_type); // value | 1032 ProcessInput(node, 2, |
| 1033 UseInfoFromMachineType(access.machine_type)); // value |
899 ProcessRemainingInputs(node, 3); | 1034 ProcessRemainingInputs(node, 3); |
900 SetOutput(node, 0); | 1035 SetOutput(node, 0); |
901 break; | 1036 break; |
902 } | 1037 } |
903 case IrOpcode::kObjectIsNumber: { | 1038 case IrOpcode::kObjectIsNumber: { |
904 ProcessInput(node, 0, kMachAnyTagged); | 1039 ProcessInput(node, 0, UseInfo::AnyTagged()); |
905 SetOutput(node, kRepBit | kTypeBool); | 1040 SetOutput(node, kMachBool); |
906 if (lower()) lowering->DoObjectIsNumber(node); | 1041 if (lower()) lowering->DoObjectIsNumber(node); |
907 break; | 1042 break; |
908 } | 1043 } |
909 case IrOpcode::kObjectIsSmi: { | 1044 case IrOpcode::kObjectIsSmi: { |
910 ProcessInput(node, 0, kMachAnyTagged); | 1045 ProcessInput(node, 0, UseInfo::AnyTagged()); |
911 SetOutput(node, kRepBit | kTypeBool); | 1046 SetOutput(node, kMachBool); |
912 if (lower()) lowering->DoObjectIsSmi(node); | 1047 if (lower()) lowering->DoObjectIsSmi(node); |
913 break; | 1048 break; |
914 } | 1049 } |
915 | 1050 |
916 //------------------------------------------------------------------ | 1051 //------------------------------------------------------------------ |
917 // Machine-level operators. | 1052 // Machine-level operators. |
918 //------------------------------------------------------------------ | 1053 //------------------------------------------------------------------ |
919 case IrOpcode::kLoad: { | 1054 case IrOpcode::kLoad: { |
920 // TODO(titzer): machine loads/stores need to know BaseTaggedness!? | 1055 // TODO(jarin) Eventually, we should get rid of all machine stores |
921 MachineTypeUnion tBase = kRepTagged | kMachPtr; | 1056 // from the high-level phases, then this becomes UNREACHABLE. |
922 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); | 1057 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); |
923 ProcessInput(node, 0, tBase); // pointer or object | 1058 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
924 ProcessInput(node, 1, kMachIntPtr); // index | 1059 ProcessInput(node, 1, UseInfo::PointerInt()); // index |
925 ProcessRemainingInputs(node, 2); | 1060 ProcessRemainingInputs(node, 2); |
926 SetOutput(node, rep); | 1061 SetOutput(node, rep); |
927 break; | 1062 break; |
928 } | 1063 } |
929 case IrOpcode::kStore: { | 1064 case IrOpcode::kStore: { |
930 // TODO(titzer): machine loads/stores need to know BaseTaggedness!? | 1065 // TODO(jarin) Eventually, we should get rid of all machine stores |
931 MachineTypeUnion tBase = kRepTagged | kMachPtr; | 1066 // from the high-level phases, then this becomes UNREACHABLE. |
932 StoreRepresentation rep = OpParameter<StoreRepresentation>(node); | 1067 StoreRepresentation rep = OpParameter<StoreRepresentation>(node); |
933 ProcessInput(node, 0, tBase); // pointer or object | 1068 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
934 ProcessInput(node, 1, kMachIntPtr); // index | 1069 ProcessInput(node, 1, UseInfo::PointerInt()); // index |
935 ProcessInput(node, 2, rep.machine_type()); | 1070 ProcessInput(node, 2, UseInfoFromMachineType(rep.machine_type())); |
936 ProcessRemainingInputs(node, 3); | 1071 ProcessRemainingInputs(node, 3); |
937 SetOutput(node, 0); | 1072 SetOutput(node, 0); |
938 break; | 1073 break; |
939 } | 1074 } |
940 case IrOpcode::kWord32Shr: | 1075 case IrOpcode::kWord32Shr: |
941 // We output unsigned int32 for shift right because JavaScript. | 1076 // We output unsigned int32 for shift right because JavaScript. |
942 return VisitBinop(node, kMachUint32, kMachUint32); | 1077 return VisitBinop(node, UseInfo::TruncatingWord32(), kMachUint32); |
943 case IrOpcode::kWord32And: | 1078 case IrOpcode::kWord32And: |
944 case IrOpcode::kWord32Or: | 1079 case IrOpcode::kWord32Or: |
945 case IrOpcode::kWord32Xor: | 1080 case IrOpcode::kWord32Xor: |
946 case IrOpcode::kWord32Shl: | 1081 case IrOpcode::kWord32Shl: |
947 case IrOpcode::kWord32Sar: | 1082 case IrOpcode::kWord32Sar: |
948 // We use signed int32 as the output type for these word32 operations, | 1083 // We use signed int32 as the output type for these word32 operations, |
949 // though the machine bits are the same for either signed or unsigned, | 1084 // though the machine bits are the same for either signed or unsigned, |
950 // because JavaScript considers the result from these operations signed. | 1085 // because JavaScript considers the result from these operations signed. |
951 return VisitBinop(node, kRepWord32, kRepWord32 | kTypeInt32); | 1086 return VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1087 kRepWord32 | kTypeInt32); |
952 case IrOpcode::kWord32Equal: | 1088 case IrOpcode::kWord32Equal: |
953 return VisitBinop(node, kRepWord32, kRepBit); | 1089 return VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
954 | 1090 |
955 case IrOpcode::kWord32Clz: | 1091 case IrOpcode::kWord32Clz: |
956 return VisitUnop(node, kMachUint32, kMachUint32); | 1092 return VisitUnop(node, UseInfo::TruncatingWord32(), kMachUint32); |
957 | 1093 |
958 case IrOpcode::kInt32Add: | 1094 case IrOpcode::kInt32Add: |
959 case IrOpcode::kInt32Sub: | 1095 case IrOpcode::kInt32Sub: |
960 case IrOpcode::kInt32Mul: | 1096 case IrOpcode::kInt32Mul: |
961 case IrOpcode::kInt32MulHigh: | 1097 case IrOpcode::kInt32MulHigh: |
962 case IrOpcode::kInt32Div: | 1098 case IrOpcode::kInt32Div: |
963 case IrOpcode::kInt32Mod: | 1099 case IrOpcode::kInt32Mod: |
964 return VisitInt32Binop(node); | 1100 return VisitInt32Binop(node); |
965 case IrOpcode::kUint32Div: | 1101 case IrOpcode::kUint32Div: |
966 case IrOpcode::kUint32Mod: | 1102 case IrOpcode::kUint32Mod: |
(...skipping 23 matching lines...) Expand all Loading... |
990 case IrOpcode::kUint64Div: | 1126 case IrOpcode::kUint64Div: |
991 case IrOpcode::kUint64Mod: | 1127 case IrOpcode::kUint64Mod: |
992 return VisitUint64Binop(node); | 1128 return VisitUint64Binop(node); |
993 | 1129 |
994 case IrOpcode::kWord64And: | 1130 case IrOpcode::kWord64And: |
995 case IrOpcode::kWord64Or: | 1131 case IrOpcode::kWord64Or: |
996 case IrOpcode::kWord64Xor: | 1132 case IrOpcode::kWord64Xor: |
997 case IrOpcode::kWord64Shl: | 1133 case IrOpcode::kWord64Shl: |
998 case IrOpcode::kWord64Shr: | 1134 case IrOpcode::kWord64Shr: |
999 case IrOpcode::kWord64Sar: | 1135 case IrOpcode::kWord64Sar: |
1000 return VisitBinop(node, kRepWord64, kRepWord64); | 1136 return VisitBinop(node, UseInfo::TruncatingWord64(), kRepWord64); |
1001 case IrOpcode::kWord64Equal: | 1137 case IrOpcode::kWord64Equal: |
1002 return VisitBinop(node, kRepWord64, kRepBit); | 1138 return VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
1003 | 1139 |
1004 case IrOpcode::kChangeInt32ToInt64: | 1140 case IrOpcode::kChangeInt32ToInt64: |
1005 return VisitUnop(node, kTypeInt32 | kRepWord32, | 1141 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1006 kTypeInt32 | kRepWord64); | 1142 kTypeInt32 | kRepWord64); |
1007 case IrOpcode::kChangeUint32ToUint64: | 1143 case IrOpcode::kChangeUint32ToUint64: |
1008 return VisitUnop(node, kTypeUint32 | kRepWord32, | 1144 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1009 kTypeUint32 | kRepWord64); | 1145 kTypeUint32 | kRepWord64); |
1010 case IrOpcode::kTruncateFloat64ToFloat32: | 1146 case IrOpcode::kTruncateFloat64ToFloat32: |
1011 return VisitUnop(node, kTypeNumber | kRepFloat64, | 1147 return VisitUnop(node, UseInfo::Float64(), kTypeNumber | kRepFloat32); |
1012 kTypeNumber | kRepFloat32); | |
1013 case IrOpcode::kTruncateFloat64ToInt32: | 1148 case IrOpcode::kTruncateFloat64ToInt32: |
1014 return VisitUnop(node, kTypeNumber | kRepFloat64, | 1149 return VisitUnop(node, UseInfo::Float64(), kTypeInt32 | kRepWord32); |
1015 kTypeInt32 | kRepWord32); | |
1016 case IrOpcode::kTruncateInt64ToInt32: | 1150 case IrOpcode::kTruncateInt64ToInt32: |
1017 // TODO(titzer): Is kTypeInt32 correct here? | 1151 // TODO(titzer): Is kTypeInt32 correct here? |
1018 return VisitUnop(node, kTypeInt32 | kRepWord64, | 1152 return VisitUnop(node, UseInfo::Word64TruncatingToWord32(), |
1019 kTypeInt32 | kRepWord32); | 1153 kTypeInt32 | kRepWord32); |
1020 | 1154 |
1021 case IrOpcode::kChangeFloat32ToFloat64: | 1155 case IrOpcode::kChangeFloat32ToFloat64: |
1022 return VisitUnop(node, kTypeNumber | kRepFloat32, | 1156 return VisitUnop(node, UseInfo::Float32(), kTypeNumber | kRepFloat64); |
1023 kTypeNumber | kRepFloat64); | |
1024 case IrOpcode::kChangeInt32ToFloat64: | 1157 case IrOpcode::kChangeInt32ToFloat64: |
1025 return VisitUnop(node, kTypeInt32 | kRepWord32, | 1158 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1026 kTypeInt32 | kRepFloat64); | 1159 kTypeInt32 | kRepFloat64); |
1027 case IrOpcode::kChangeUint32ToFloat64: | 1160 case IrOpcode::kChangeUint32ToFloat64: |
1028 return VisitUnop(node, kTypeUint32 | kRepWord32, | 1161 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1029 kTypeUint32 | kRepFloat64); | 1162 kTypeUint32 | kRepFloat64); |
1030 case IrOpcode::kChangeFloat64ToInt32: | 1163 case IrOpcode::kChangeFloat64ToInt32: |
1031 return VisitUnop(node, kTypeInt32 | kRepFloat64, | 1164 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
1032 kTypeInt32 | kRepWord32); | 1165 kTypeInt32 | kRepWord32); |
1033 case IrOpcode::kChangeFloat64ToUint32: | 1166 case IrOpcode::kChangeFloat64ToUint32: |
1034 return VisitUnop(node, kTypeUint32 | kRepFloat64, | 1167 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
1035 kTypeUint32 | kRepWord32); | 1168 kTypeUint32 | kRepWord32); |
1036 | 1169 |
1037 case IrOpcode::kFloat64Add: | 1170 case IrOpcode::kFloat64Add: |
1038 case IrOpcode::kFloat64Sub: | 1171 case IrOpcode::kFloat64Sub: |
1039 case IrOpcode::kFloat64Mul: | 1172 case IrOpcode::kFloat64Mul: |
1040 case IrOpcode::kFloat64Div: | 1173 case IrOpcode::kFloat64Div: |
1041 case IrOpcode::kFloat64Mod: | 1174 case IrOpcode::kFloat64Mod: |
1042 case IrOpcode::kFloat64Min: | 1175 case IrOpcode::kFloat64Min: |
1043 return VisitFloat64Binop(node); | 1176 return VisitFloat64Binop(node); |
1044 case IrOpcode::kFloat64Abs: | 1177 case IrOpcode::kFloat64Abs: |
1045 case IrOpcode::kFloat64Sqrt: | 1178 case IrOpcode::kFloat64Sqrt: |
1046 case IrOpcode::kFloat64RoundDown: | 1179 case IrOpcode::kFloat64RoundDown: |
1047 case IrOpcode::kFloat64RoundTruncate: | 1180 case IrOpcode::kFloat64RoundTruncate: |
1048 case IrOpcode::kFloat64RoundTiesAway: | 1181 case IrOpcode::kFloat64RoundTiesAway: |
1049 return VisitUnop(node, kMachFloat64, kMachFloat64); | 1182 return VisitUnop(node, UseInfo::Float64(), kMachFloat64); |
1050 case IrOpcode::kFloat64Equal: | 1183 case IrOpcode::kFloat64Equal: |
1051 case IrOpcode::kFloat64LessThan: | 1184 case IrOpcode::kFloat64LessThan: |
1052 case IrOpcode::kFloat64LessThanOrEqual: | 1185 case IrOpcode::kFloat64LessThanOrEqual: |
1053 return VisitFloat64Cmp(node); | 1186 return VisitFloat64Cmp(node); |
1054 case IrOpcode::kFloat64ExtractLowWord32: | 1187 case IrOpcode::kFloat64ExtractLowWord32: |
1055 case IrOpcode::kFloat64ExtractHighWord32: | 1188 case IrOpcode::kFloat64ExtractHighWord32: |
1056 return VisitUnop(node, kMachFloat64, kMachInt32); | 1189 return VisitUnop(node, UseInfo::Float64(), kMachInt32); |
1057 case IrOpcode::kFloat64InsertLowWord32: | 1190 case IrOpcode::kFloat64InsertLowWord32: |
1058 case IrOpcode::kFloat64InsertHighWord32: | 1191 case IrOpcode::kFloat64InsertHighWord32: |
1059 return VisitBinop(node, kMachFloat64, kMachInt32, kMachFloat64); | 1192 return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(), |
| 1193 kMachFloat64); |
1060 case IrOpcode::kLoadStackPointer: | 1194 case IrOpcode::kLoadStackPointer: |
1061 case IrOpcode::kLoadFramePointer: | 1195 case IrOpcode::kLoadFramePointer: |
1062 return VisitLeaf(node, kMachPtr); | 1196 return VisitLeaf(node, kMachPtr); |
1063 case IrOpcode::kStateValues: | 1197 case IrOpcode::kStateValues: |
1064 VisitStateValues(node); | 1198 VisitStateValues(node); |
1065 break; | 1199 break; |
1066 default: | 1200 default: |
1067 VisitInputs(node); | 1201 VisitInputs(node); |
1068 break; | 1202 break; |
1069 } | 1203 } |
(...skipping 26 matching lines...) Expand all Loading... |
1096 TRACE("\n"); | 1230 TRACE("\n"); |
1097 } | 1231 } |
1098 | 1232 |
1099 void PrintInfo(MachineTypeUnion info) { | 1233 void PrintInfo(MachineTypeUnion info) { |
1100 if (FLAG_trace_representation) { | 1234 if (FLAG_trace_representation) { |
1101 OFStream os(stdout); | 1235 OFStream os(stdout); |
1102 os << static_cast<MachineType>(info); | 1236 os << static_cast<MachineType>(info); |
1103 } | 1237 } |
1104 } | 1238 } |
1105 | 1239 |
| 1240 void PrintUseInfo(UseInfo info) { |
| 1241 if (FLAG_trace_representation) { |
| 1242 OFStream os(stdout); |
| 1243 os << static_cast<MachineType>(info.machine_type()); |
| 1244 } |
| 1245 } |
| 1246 |
1106 private: | 1247 private: |
1107 JSGraph* jsgraph_; | 1248 JSGraph* jsgraph_; |
1108 size_t const count_; // number of nodes in the graph | 1249 size_t const count_; // number of nodes in the graph |
1109 NodeInfo* info_; // node id -> usage information | 1250 NodeInfo* info_; // node id -> usage information |
1110 NodeVector nodes_; // collected nodes | 1251 NodeVector nodes_; // collected nodes |
1111 NodeVector replacements_; // replacements to be done after lowering | 1252 NodeVector replacements_; // replacements to be done after lowering |
1112 Phase phase_; // current phase of algorithm | 1253 Phase phase_; // current phase of algorithm |
1113 RepresentationChanger* changer_; // for inserting representation changes | 1254 RepresentationChanger* changer_; // for inserting representation changes |
1114 ZoneQueue<Node*> queue_; // queue for traversing the graph | 1255 ZoneQueue<Node*> queue_; // queue for traversing the graph |
1115 // TODO(danno): RepresentationSelector shouldn't know anything about the | 1256 // TODO(danno): RepresentationSelector shouldn't know anything about the |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 ReplaceEffectUses(node, comparison); | 1705 ReplaceEffectUses(node, comparison); |
1565 node->ReplaceInput(0, comparison); | 1706 node->ReplaceInput(0, comparison); |
1566 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1707 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
1567 node->TrimInputCount(2); | 1708 node->TrimInputCount(2); |
1568 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); | 1709 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); |
1569 } | 1710 } |
1570 | 1711 |
1571 } // namespace compiler | 1712 } // namespace compiler |
1572 } // namespace internal | 1713 } // namespace internal |
1573 } // namespace v8 | 1714 } // namespace v8 |
OLD | NEW |