OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/representation-change.h" | 5 #include "src/compiler/representation-change.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 namespace { | 98 namespace { |
99 | 99 |
100 bool IsWord(MachineRepresentation rep) { | 100 bool IsWord(MachineRepresentation rep) { |
101 return rep == MachineRepresentation::kWord8 || | 101 return rep == MachineRepresentation::kWord8 || |
102 rep == MachineRepresentation::kWord16 || | 102 rep == MachineRepresentation::kWord16 || |
103 rep == MachineRepresentation::kWord32; | 103 rep == MachineRepresentation::kWord32; |
104 } | 104 } |
105 | 105 |
106 } // namespace | 106 } // namespace |
107 | 107 |
108 | |
109 // Changes representation from {output_rep} to {use_rep}. The {truncation} | 108 // Changes representation from {output_rep} to {use_rep}. The {truncation} |
110 // parameter is only used for sanity checking - if the changer cannot figure | 109 // parameter is only used for sanity checking - if the changer cannot figure |
111 // out signedness for the word32->float64 conversion, then we check that the | 110 // out signedness for the word32->float64 conversion, then we check that the |
112 // uses truncate to word32 (so they do not care about signedness). | 111 // uses truncate to word32 (so they do not care about signedness). |
113 Node* RepresentationChanger::GetRepresentationFor( | 112 Node* RepresentationChanger::GetRepresentationFor( |
114 Node* node, MachineRepresentation output_rep, Type* output_type, | 113 Node* node, MachineRepresentation output_rep, Type* output_type, |
115 MachineRepresentation use_rep, Truncation truncation) { | 114 Node* use_node, UseInfo use_info) { |
116 if (output_rep == MachineRepresentation::kNone) { | 115 if (output_rep == MachineRepresentation::kNone) { |
117 // The output representation should be set. | 116 // The output representation should be set. |
118 return TypeError(node, output_rep, output_type, use_rep); | 117 return TypeError(node, output_rep, output_type, use_info.representation()); |
119 } | 118 } |
120 if (use_rep == output_rep) { | 119 |
121 // Representations are the same. That's a no-op. | 120 // Handle the no-op shortcuts when no checking is necessary. |
122 return node; | 121 if (use_info.type_check() == TypeCheckKind::kNone || |
| 122 output_rep != MachineRepresentation::kWord32) { |
| 123 if (use_info.representation() == output_rep) { |
| 124 // Representations are the same. That's a no-op. |
| 125 return node; |
| 126 } |
| 127 if (IsWord(use_info.representation()) && IsWord(output_rep)) { |
| 128 // Both are words less than or equal to 32-bits. |
| 129 // Since loads of integers from memory implicitly sign or zero extend the |
| 130 // value to the full machine word size and stores implicitly truncate, |
| 131 // no representation change is necessary. |
| 132 return node; |
| 133 } |
123 } | 134 } |
124 if (IsWord(use_rep) && IsWord(output_rep)) { | 135 |
125 // Both are words less than or equal to 32-bits. | 136 switch (use_info.representation()) { |
126 // Since loads of integers from memory implicitly sign or zero extend the | |
127 // value to the full machine word size and stores implicitly truncate, | |
128 // no representation change is necessary. | |
129 return node; | |
130 } | |
131 switch (use_rep) { | |
132 case MachineRepresentation::kTagged: | 137 case MachineRepresentation::kTagged: |
| 138 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
133 return GetTaggedRepresentationFor(node, output_rep, output_type); | 139 return GetTaggedRepresentationFor(node, output_rep, output_type); |
134 case MachineRepresentation::kFloat32: | 140 case MachineRepresentation::kFloat32: |
| 141 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
135 return GetFloat32RepresentationFor(node, output_rep, output_type, | 142 return GetFloat32RepresentationFor(node, output_rep, output_type, |
136 truncation); | 143 use_info.truncation()); |
137 case MachineRepresentation::kFloat64: | 144 case MachineRepresentation::kFloat64: |
138 return GetFloat64RepresentationFor(node, output_rep, output_type, | 145 return GetFloat64RepresentationFor(node, output_rep, output_type, |
139 truncation); | 146 use_node, use_info); |
140 case MachineRepresentation::kBit: | 147 case MachineRepresentation::kBit: |
| 148 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
141 return GetBitRepresentationFor(node, output_rep, output_type); | 149 return GetBitRepresentationFor(node, output_rep, output_type); |
142 case MachineRepresentation::kWord8: | 150 case MachineRepresentation::kWord8: |
143 case MachineRepresentation::kWord16: | 151 case MachineRepresentation::kWord16: |
144 case MachineRepresentation::kWord32: | 152 case MachineRepresentation::kWord32: |
145 return GetWord32RepresentationFor(node, output_rep, output_type, | 153 return GetWord32RepresentationFor(node, output_rep, output_type, use_node, |
146 truncation); | 154 use_info); |
147 case MachineRepresentation::kWord64: | 155 case MachineRepresentation::kWord64: |
| 156 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
148 return GetWord64RepresentationFor(node, output_rep, output_type); | 157 return GetWord64RepresentationFor(node, output_rep, output_type); |
149 case MachineRepresentation::kSimd128: // Fall through. | 158 case MachineRepresentation::kSimd128: // Fall through. |
150 // TODO(bbudge) Handle conversions between tagged and untagged. | 159 // TODO(bbudge) Handle conversions between tagged and untagged. |
151 break; | 160 break; |
152 case MachineRepresentation::kNone: | 161 case MachineRepresentation::kNone: |
153 return node; | 162 return node; |
154 } | 163 } |
155 UNREACHABLE(); | 164 UNREACHABLE(); |
156 return nullptr; | 165 return nullptr; |
157 } | 166 } |
158 | 167 |
159 | |
160 Node* RepresentationChanger::GetTaggedRepresentationFor( | 168 Node* RepresentationChanger::GetTaggedRepresentationFor( |
161 Node* node, MachineRepresentation output_rep, Type* output_type) { | 169 Node* node, MachineRepresentation output_rep, Type* output_type) { |
162 // Eagerly fold representation changes for constants. | 170 // Eagerly fold representation changes for constants. |
163 switch (node->opcode()) { | 171 switch (node->opcode()) { |
164 case IrOpcode::kNumberConstant: | 172 case IrOpcode::kNumberConstant: |
165 case IrOpcode::kHeapConstant: | 173 case IrOpcode::kHeapConstant: |
166 return node; // No change necessary. | 174 return node; // No change necessary. |
167 case IrOpcode::kInt32Constant: | 175 case IrOpcode::kInt32Constant: |
168 if (output_type->Is(Type::Signed32())) { | 176 if (output_type->Is(Type::Signed32())) { |
169 int32_t value = OpParameter<int32_t>(node); | 177 int32_t value = OpParameter<int32_t>(node); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 } else if (output_rep == MachineRepresentation::kFloat64) { | 291 } else if (output_rep == MachineRepresentation::kFloat64) { |
284 op = machine()->TruncateFloat64ToFloat32(); | 292 op = machine()->TruncateFloat64ToFloat32(); |
285 } | 293 } |
286 if (op == nullptr) { | 294 if (op == nullptr) { |
287 return TypeError(node, output_rep, output_type, | 295 return TypeError(node, output_rep, output_type, |
288 MachineRepresentation::kFloat32); | 296 MachineRepresentation::kFloat32); |
289 } | 297 } |
290 return jsgraph()->graph()->NewNode(op, node); | 298 return jsgraph()->graph()->NewNode(op, node); |
291 } | 299 } |
292 | 300 |
293 | |
294 Node* RepresentationChanger::GetFloat64RepresentationFor( | 301 Node* RepresentationChanger::GetFloat64RepresentationFor( |
295 Node* node, MachineRepresentation output_rep, Type* output_type, | 302 Node* node, MachineRepresentation output_rep, Type* output_type, |
296 Truncation truncation) { | 303 Node* use_node, UseInfo use_info) { |
297 // Eagerly fold representation changes for constants. | 304 // Eagerly fold representation changes for constants. |
298 switch (node->opcode()) { | 305 if ((use_info.type_check() == TypeCheckKind::kNone)) { |
299 case IrOpcode::kNumberConstant: | 306 // TODO(jarin) Handle checked constant conversions. |
300 return jsgraph()->Float64Constant(OpParameter<double>(node)); | 307 switch (node->opcode()) { |
301 case IrOpcode::kInt32Constant: | 308 case IrOpcode::kNumberConstant: |
302 if (output_type->Is(Type::Signed32())) { | 309 return jsgraph()->Float64Constant(OpParameter<double>(node)); |
303 int32_t value = OpParameter<int32_t>(node); | 310 case IrOpcode::kInt32Constant: |
304 return jsgraph()->Float64Constant(value); | 311 if (output_type->Is(Type::Signed32())) { |
305 } else { | 312 int32_t value = OpParameter<int32_t>(node); |
306 DCHECK(output_type->Is(Type::Unsigned32())); | 313 return jsgraph()->Float64Constant(value); |
307 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); | 314 } else { |
308 return jsgraph()->Float64Constant(static_cast<double>(value)); | 315 DCHECK(output_type->Is(Type::Unsigned32())); |
309 } | 316 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); |
310 case IrOpcode::kFloat64Constant: | 317 return jsgraph()->Float64Constant(static_cast<double>(value)); |
311 return node; // No change necessary. | 318 } |
312 case IrOpcode::kFloat32Constant: | 319 case IrOpcode::kFloat64Constant: |
313 return jsgraph()->Float64Constant(OpParameter<float>(node)); | 320 return node; // No change necessary. |
314 default: | 321 case IrOpcode::kFloat32Constant: |
315 break; | 322 return jsgraph()->Float64Constant(OpParameter<float>(node)); |
| 323 default: |
| 324 break; |
| 325 } |
316 } | 326 } |
317 // Select the correct X -> Float64 operator. | 327 // Select the correct X -> Float64 operator. |
318 const Operator* op = nullptr; | 328 const Operator* op = nullptr; |
319 if (IsWord(output_rep)) { | 329 if (IsWord(output_rep)) { |
320 if (output_type->Is(Type::Signed32())) { | 330 if (output_type->Is(Type::Signed32())) { |
321 op = machine()->ChangeInt32ToFloat64(); | 331 op = machine()->ChangeInt32ToFloat64(); |
322 } else if (output_type->Is(Type::Unsigned32()) || | 332 } else if (output_type->Is(Type::Unsigned32()) || |
323 truncation.TruncatesToWord32()) { | 333 use_info.truncation().TruncatesToWord32()) { |
324 // Either the output is uint32 or the uses only care about the | 334 // Either the output is uint32 or the uses only care about the |
325 // low 32 bits (so we can pick uint32 safely). | 335 // low 32 bits (so we can pick uint32 safely). |
326 op = machine()->ChangeUint32ToFloat64(); | 336 op = machine()->ChangeUint32ToFloat64(); |
327 } | 337 } |
328 } else if (output_rep == MachineRepresentation::kTagged) { | 338 } else if (output_rep == MachineRepresentation::kTagged) { |
329 if (output_type->Is(Type::Undefined())) { | 339 if (output_type->Is(Type::Undefined())) { |
330 return jsgraph()->Float64Constant( | 340 return jsgraph()->Float64Constant( |
331 std::numeric_limits<double>::quiet_NaN()); | 341 std::numeric_limits<double>::quiet_NaN()); |
332 } else if (output_type->Is(Type::TaggedSigned())) { | 342 } else if (output_type->Is(Type::TaggedSigned())) { |
333 node = InsertChangeTaggedSignedToInt32(node); | 343 node = InsertChangeTaggedSignedToInt32(node); |
334 op = machine()->ChangeInt32ToFloat64(); | 344 op = machine()->ChangeInt32ToFloat64(); |
335 } else if (output_type->Is(Type::Number())) { | 345 } else if (output_type->Is(Type::Number())) { |
336 op = simplified()->ChangeTaggedToFloat64(); | 346 op = simplified()->ChangeTaggedToFloat64(); |
337 } else if (output_type->Is(Type::NumberOrUndefined())) { | 347 } else if (output_type->Is(Type::NumberOrUndefined())) { |
| 348 // TODO(jarin) Here we should check that truncation is Number. |
338 op = simplified()->TruncateTaggedToFloat64(); | 349 op = simplified()->TruncateTaggedToFloat64(); |
| 350 } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) { |
| 351 op = simplified()->CheckedTaggedToFloat64(); |
339 } | 352 } |
340 } else if (output_rep == MachineRepresentation::kFloat32) { | 353 } else if (output_rep == MachineRepresentation::kFloat32) { |
341 op = machine()->ChangeFloat32ToFloat64(); | 354 op = machine()->ChangeFloat32ToFloat64(); |
342 } | 355 } |
343 if (op == nullptr) { | 356 if (op == nullptr) { |
344 return TypeError(node, output_rep, output_type, | 357 return TypeError(node, output_rep, output_type, |
345 MachineRepresentation::kFloat64); | 358 MachineRepresentation::kFloat64); |
346 } | 359 } |
347 return jsgraph()->graph()->NewNode(op, node); | 360 return InsertConversion(node, op, use_node); |
348 } | 361 } |
349 | 362 |
350 | |
351 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { | 363 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { |
352 return jsgraph()->Int32Constant(DoubleToInt32(value)); | 364 return jsgraph()->Int32Constant(DoubleToInt32(value)); |
353 } | 365 } |
354 | 366 |
355 Node* RepresentationChanger::GetWord32RepresentationFor( | 367 Node* RepresentationChanger::GetWord32RepresentationFor( |
356 Node* node, MachineRepresentation output_rep, Type* output_type, | 368 Node* node, MachineRepresentation output_rep, Type* output_type, |
357 Truncation truncation) { | 369 Node* use_node, UseInfo use_info) { |
358 // Eagerly fold representation changes for constants. | 370 // Eagerly fold representation changes for constants. |
359 switch (node->opcode()) { | 371 // TODO(jarin) Properly fold constants in presence of type check. |
360 case IrOpcode::kInt32Constant: | 372 if (use_info.type_check() == TypeCheckKind::kNone) { |
361 return node; // No change necessary. | 373 switch (node->opcode()) { |
362 case IrOpcode::kFloat32Constant: | 374 case IrOpcode::kInt32Constant: |
363 return MakeTruncatedInt32Constant(OpParameter<float>(node)); | 375 return node; // No change necessary. |
364 case IrOpcode::kNumberConstant: | 376 case IrOpcode::kFloat32Constant: |
365 case IrOpcode::kFloat64Constant: | 377 return MakeTruncatedInt32Constant(OpParameter<float>(node)); |
366 return MakeTruncatedInt32Constant(OpParameter<double>(node)); | 378 case IrOpcode::kNumberConstant: |
367 default: | 379 case IrOpcode::kFloat64Constant: |
368 break; | 380 return MakeTruncatedInt32Constant(OpParameter<double>(node)); |
| 381 default: |
| 382 break; |
| 383 } |
369 } | 384 } |
| 385 |
370 // Select the correct X -> Word32 operator. | 386 // Select the correct X -> Word32 operator. |
371 const Operator* op = nullptr; | 387 const Operator* op = nullptr; |
372 if (output_rep == MachineRepresentation::kBit) { | 388 if (output_rep == MachineRepresentation::kBit) { |
373 return node; // Sloppy comparison -> word32 | 389 return node; // Sloppy comparison -> word32 |
374 } else if (output_rep == MachineRepresentation::kFloat64) { | 390 } else if (output_rep == MachineRepresentation::kFloat64) { |
375 if (output_type->Is(Type::Unsigned32())) { | 391 if (output_type->Is(Type::Unsigned32())) { |
376 op = machine()->ChangeFloat64ToUint32(); | 392 op = machine()->ChangeFloat64ToUint32(); |
377 } else if (output_type->Is(Type::Signed32())) { | 393 } else if (output_type->Is(Type::Signed32())) { |
378 op = machine()->ChangeFloat64ToInt32(); | 394 op = machine()->ChangeFloat64ToInt32(); |
379 } else if (truncation.TruncatesToWord32()) { | 395 } else if (use_info.truncation().TruncatesToWord32()) { |
380 op = machine()->TruncateFloat64ToWord32(); | 396 op = machine()->TruncateFloat64ToWord32(); |
| 397 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
| 398 op = simplified()->CheckedFloat64ToInt32(); |
381 } | 399 } |
382 } else if (output_rep == MachineRepresentation::kFloat32) { | 400 } else if (output_rep == MachineRepresentation::kFloat32) { |
383 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | 401 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 |
384 if (output_type->Is(Type::Unsigned32())) { | 402 if (output_type->Is(Type::Unsigned32())) { |
385 op = machine()->ChangeFloat64ToUint32(); | 403 op = machine()->ChangeFloat64ToUint32(); |
386 } else if (output_type->Is(Type::Signed32())) { | 404 } else if (output_type->Is(Type::Signed32())) { |
387 op = machine()->ChangeFloat64ToInt32(); | 405 op = machine()->ChangeFloat64ToInt32(); |
388 } else if (truncation.TruncatesToWord32()) { | 406 } else if (use_info.truncation().TruncatesToWord32()) { |
389 op = machine()->TruncateFloat64ToWord32(); | 407 op = machine()->TruncateFloat64ToWord32(); |
| 408 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
| 409 op = simplified()->CheckedFloat64ToInt32(); |
390 } | 410 } |
391 } else if (output_rep == MachineRepresentation::kTagged) { | 411 } else if (output_rep == MachineRepresentation::kTagged) { |
392 if (output_type->Is(Type::TaggedSigned())) { | 412 if (output_type->Is(Type::TaggedSigned())) { |
393 op = simplified()->ChangeTaggedSignedToInt32(); | 413 op = simplified()->ChangeTaggedSignedToInt32(); |
394 } else if (output_type->Is(Type::Unsigned32())) { | 414 } else if (output_type->Is(Type::Unsigned32())) { |
395 op = simplified()->ChangeTaggedToUint32(); | 415 op = simplified()->ChangeTaggedToUint32(); |
396 } else if (output_type->Is(Type::Signed32())) { | 416 } else if (output_type->Is(Type::Signed32())) { |
397 op = simplified()->ChangeTaggedToInt32(); | 417 op = simplified()->ChangeTaggedToInt32(); |
398 } else if (truncation.TruncatesToWord32()) { | 418 } else if (use_info.truncation().TruncatesToWord32()) { |
399 op = simplified()->TruncateTaggedToWord32(); | 419 op = simplified()->TruncateTaggedToWord32(); |
| 420 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
| 421 op = simplified()->CheckedTaggedToInt32(); |
400 } | 422 } |
| 423 } else if (output_rep == MachineRepresentation::kWord32) { |
| 424 // Only the checked case should get here, the non-checked case is |
| 425 // handled in GetRepresentationFor. |
| 426 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); |
| 427 if (output_type->Is(Type::Signed32())) { |
| 428 return node; |
| 429 } else if (output_type->Is(Type::Unsigned32())) { |
| 430 op = simplified()->CheckedUint32ToInt32(); |
| 431 } |
| 432 } else if (output_rep == MachineRepresentation::kWord8 || |
| 433 output_rep == MachineRepresentation::kWord16) { |
| 434 DCHECK(use_info.representation() == MachineRepresentation::kWord32); |
| 435 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); |
| 436 return node; |
401 } | 437 } |
| 438 |
402 if (op == nullptr) { | 439 if (op == nullptr) { |
403 return TypeError(node, output_rep, output_type, | 440 return TypeError(node, output_rep, output_type, |
404 MachineRepresentation::kWord32); | 441 MachineRepresentation::kWord32); |
405 } | 442 } |
| 443 return InsertConversion(node, op, use_node); |
| 444 } |
| 445 |
| 446 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op, |
| 447 Node* use_node) { |
| 448 if (op->ControlInputCount() > 0) { |
| 449 // If the operator can deoptimize (which means it has control |
| 450 // input), we need to connect it to the effect and control chains |
| 451 // and also provide it with a frame state. |
| 452 Node* effect = NodeProperties::GetEffectInput(use_node); |
| 453 Node* control = NodeProperties::GetControlInput(use_node); |
| 454 Node* frame_state = NodeProperties::GetFrameStateInput(use_node, 0); |
| 455 Node* conversion = |
| 456 jsgraph()->graph()->NewNode(op, node, frame_state, effect, control); |
| 457 NodeProperties::ReplaceControlInput(use_node, control); |
| 458 NodeProperties::ReplaceEffectInput(use_node, effect); |
| 459 return conversion; |
| 460 } |
406 return jsgraph()->graph()->NewNode(op, node); | 461 return jsgraph()->graph()->NewNode(op, node); |
407 } | 462 } |
408 | 463 |
409 | 464 |
410 Node* RepresentationChanger::GetBitRepresentationFor( | 465 Node* RepresentationChanger::GetBitRepresentationFor( |
411 Node* node, MachineRepresentation output_rep, Type* output_type) { | 466 Node* node, MachineRepresentation output_rep, Type* output_type) { |
412 // Eagerly fold representation changes for constants. | 467 // Eagerly fold representation changes for constants. |
413 switch (node->opcode()) { | 468 switch (node->opcode()) { |
414 case IrOpcode::kHeapConstant: { | 469 case IrOpcode::kHeapConstant: { |
415 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); | 470 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); |
416 DCHECK(value.is_identical_to(factory()->true_value()) || | 471 DCHECK(value.is_identical_to(factory()->true_value()) || |
417 value.is_identical_to(factory()->false_value())); | 472 value.is_identical_to(factory()->false_value())); |
418 return jsgraph()->Int32Constant( | 473 return jsgraph()->Int32Constant( |
419 value.is_identical_to(factory()->true_value()) ? 1 : 0); | 474 value.is_identical_to(factory()->true_value()) ? 1 : 0); |
420 } | 475 } |
421 default: | 476 default: |
422 break; | 477 break; |
423 } | 478 } |
424 // Select the correct X -> Bit operator. | 479 // Select the correct X -> Bit operator. |
425 const Operator* op; | 480 const Operator* op; |
426 if (output_rep == MachineRepresentation::kTagged) { | 481 if (output_rep == MachineRepresentation::kTagged) { |
427 op = simplified()->ChangeTaggedToBit(); | 482 op = simplified()->ChangeTaggedToBit(); |
428 } else { | 483 } else { |
429 return TypeError(node, output_rep, output_type, | 484 return TypeError(node, output_rep, output_type, |
430 MachineRepresentation::kBit); | 485 MachineRepresentation::kBit); |
431 } | 486 } |
432 return jsgraph()->graph()->NewNode(op, node); | 487 return jsgraph()->graph()->NewNode(op, node); |
433 } | 488 } |
434 | 489 |
435 | |
436 Node* RepresentationChanger::GetWord64RepresentationFor( | 490 Node* RepresentationChanger::GetWord64RepresentationFor( |
437 Node* node, MachineRepresentation output_rep, Type* output_type) { | 491 Node* node, MachineRepresentation output_rep, Type* output_type) { |
438 if (output_rep == MachineRepresentation::kBit) { | 492 if (output_rep == MachineRepresentation::kBit) { |
439 return node; // Sloppy comparison -> word64 | 493 return node; // Sloppy comparison -> word64 |
440 } | 494 } |
441 // Can't really convert Word64 to anything else. Purported to be internal. | 495 // Can't really convert Word64 to anything else. Purported to be internal. |
442 return TypeError(node, output_rep, output_type, | 496 return TypeError(node, output_rep, output_type, |
443 MachineRepresentation::kWord64); | 497 MachineRepresentation::kWord64); |
444 } | 498 } |
445 | 499 |
| 500 Node* RepresentationChanger::GetCheckedWord32RepresentationFor( |
| 501 Node* node, MachineRepresentation output_rep, Type* output_type, |
| 502 Node* use_node, Truncation truncation, TypeCheckKind check) { |
| 503 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant |
| 504 // does not pass the check). |
| 505 |
| 506 // If the input is already Signed32 in Word32 representation, we do not |
| 507 // have to do anything. (We could fold this into the big if below, but |
| 508 // it feels nicer to have the shortcut return first). |
| 509 if (output_rep == MachineRepresentation::kWord32 || |
| 510 output_type->Is(Type::Signed32())) { |
| 511 return node; |
| 512 } |
| 513 |
| 514 // Select the correct X -> Word32 operator. |
| 515 const Operator* op = nullptr; |
| 516 if (output_rep == MachineRepresentation::kWord32) { |
| 517 if (output_type->Is(Type::Unsigned32())) { |
| 518 op = simplified()->CheckedUint32ToInt32(); |
| 519 } |
| 520 } else if (output_rep == MachineRepresentation::kBit) { |
| 521 return node; // Sloppy comparison -> word32 |
| 522 } else if (output_rep == MachineRepresentation::kFloat64) { |
| 523 if (output_type->Is(Type::Unsigned32())) { |
| 524 op = machine()->ChangeFloat64ToUint32(); |
| 525 } else if (output_type->Is(Type::Signed32())) { |
| 526 op = machine()->ChangeFloat64ToInt32(); |
| 527 } else if (truncation.TruncatesToWord32()) { |
| 528 op = machine()->TruncateFloat64ToWord32(); |
| 529 } else if (check == TypeCheckKind::kSigned32) { |
| 530 op = simplified()->CheckedFloat64ToInt32(); |
| 531 } |
| 532 } else if (output_rep == MachineRepresentation::kFloat32) { |
| 533 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 |
| 534 if (output_type->Is(Type::Unsigned32())) { |
| 535 op = machine()->ChangeFloat64ToUint32(); |
| 536 } else if (output_type->Is(Type::Signed32())) { |
| 537 op = machine()->ChangeFloat64ToInt32(); |
| 538 } else if (truncation.TruncatesToWord32()) { |
| 539 op = machine()->TruncateFloat64ToWord32(); |
| 540 } else if (check == TypeCheckKind::kSigned32) { |
| 541 op = simplified()->CheckedFloat64ToInt32(); |
| 542 } |
| 543 } else if (output_rep == MachineRepresentation::kTagged) { |
| 544 if (output_type->Is(Type::TaggedSigned())) { |
| 545 op = simplified()->ChangeTaggedSignedToInt32(); |
| 546 } else if (output_type->Is(Type::Unsigned32())) { |
| 547 op = simplified()->ChangeTaggedToUint32(); |
| 548 } else if (output_type->Is(Type::Signed32())) { |
| 549 op = simplified()->ChangeTaggedToInt32(); |
| 550 } else if (truncation.TruncatesToWord32()) { |
| 551 op = simplified()->TruncateTaggedToWord32(); |
| 552 } else if (check == TypeCheckKind::kSigned32) { |
| 553 op = simplified()->CheckedTaggedToInt32(); |
| 554 } |
| 555 } |
| 556 if (op == nullptr) { |
| 557 return TypeError(node, output_rep, output_type, |
| 558 MachineRepresentation::kWord32); |
| 559 } |
| 560 if (op->ControlInputCount() > 0) { |
| 561 // If the operator can deoptimize (which means it has control |
| 562 // input), we need to connect it to the effect and control chains |
| 563 // and also provide it with a frame state. |
| 564 UNIMPLEMENTED(); |
| 565 } |
| 566 return jsgraph()->graph()->NewNode(op, node); |
| 567 } |
446 | 568 |
447 const Operator* RepresentationChanger::Int32OperatorFor( | 569 const Operator* RepresentationChanger::Int32OperatorFor( |
448 IrOpcode::Value opcode) { | 570 IrOpcode::Value opcode) { |
449 switch (opcode) { | 571 switch (opcode) { |
| 572 case IrOpcode::kSpeculativeNumberAdd: // Fall through. |
450 case IrOpcode::kNumberAdd: | 573 case IrOpcode::kNumberAdd: |
451 return machine()->Int32Add(); | 574 return machine()->Int32Add(); |
| 575 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. |
452 case IrOpcode::kNumberSubtract: | 576 case IrOpcode::kNumberSubtract: |
453 return machine()->Int32Sub(); | 577 return machine()->Int32Sub(); |
454 case IrOpcode::kNumberMultiply: | 578 case IrOpcode::kNumberMultiply: |
455 return machine()->Int32Mul(); | 579 return machine()->Int32Mul(); |
456 case IrOpcode::kNumberDivide: | 580 case IrOpcode::kNumberDivide: |
457 return machine()->Int32Div(); | 581 return machine()->Int32Div(); |
458 case IrOpcode::kNumberModulus: | 582 case IrOpcode::kNumberModulus: |
459 return machine()->Int32Mod(); | 583 return machine()->Int32Mod(); |
460 case IrOpcode::kNumberBitwiseOr: | 584 case IrOpcode::kNumberBitwiseOr: |
461 return machine()->Word32Or(); | 585 return machine()->Word32Or(); |
462 case IrOpcode::kNumberBitwiseXor: | 586 case IrOpcode::kNumberBitwiseXor: |
463 return machine()->Word32Xor(); | 587 return machine()->Word32Xor(); |
464 case IrOpcode::kNumberBitwiseAnd: | 588 case IrOpcode::kNumberBitwiseAnd: |
465 return machine()->Word32And(); | 589 return machine()->Word32And(); |
466 case IrOpcode::kNumberEqual: | 590 case IrOpcode::kNumberEqual: |
467 return machine()->Word32Equal(); | 591 return machine()->Word32Equal(); |
468 case IrOpcode::kNumberLessThan: | 592 case IrOpcode::kNumberLessThan: |
469 return machine()->Int32LessThan(); | 593 return machine()->Int32LessThan(); |
470 case IrOpcode::kNumberLessThanOrEqual: | 594 case IrOpcode::kNumberLessThanOrEqual: |
471 return machine()->Int32LessThanOrEqual(); | 595 return machine()->Int32LessThanOrEqual(); |
472 default: | 596 default: |
473 UNREACHABLE(); | 597 UNREACHABLE(); |
474 return nullptr; | 598 return nullptr; |
475 } | 599 } |
476 } | 600 } |
477 | 601 |
| 602 const Operator* RepresentationChanger::Int32OverflowOperatorFor( |
| 603 IrOpcode::Value opcode) { |
| 604 switch (opcode) { |
| 605 case IrOpcode::kSpeculativeNumberAdd: // Fall through. |
| 606 return machine()->Int32AddWithOverflow(); |
| 607 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. |
| 608 return machine()->Int32SubWithOverflow(); |
| 609 default: |
| 610 UNREACHABLE(); |
| 611 return nullptr; |
| 612 } |
| 613 } |
478 | 614 |
479 const Operator* RepresentationChanger::Uint32OperatorFor( | 615 const Operator* RepresentationChanger::Uint32OperatorFor( |
480 IrOpcode::Value opcode) { | 616 IrOpcode::Value opcode) { |
481 switch (opcode) { | 617 switch (opcode) { |
482 case IrOpcode::kNumberAdd: | 618 case IrOpcode::kNumberAdd: |
483 return machine()->Int32Add(); | 619 return machine()->Int32Add(); |
484 case IrOpcode::kNumberSubtract: | 620 case IrOpcode::kNumberSubtract: |
485 return machine()->Int32Sub(); | 621 return machine()->Int32Sub(); |
486 case IrOpcode::kNumberMultiply: | 622 case IrOpcode::kNumberMultiply: |
487 return machine()->Int32Mul(); | 623 return machine()->Int32Mul(); |
(...skipping 14 matching lines...) Expand all Loading... |
502 default: | 638 default: |
503 UNREACHABLE(); | 639 UNREACHABLE(); |
504 return nullptr; | 640 return nullptr; |
505 } | 641 } |
506 } | 642 } |
507 | 643 |
508 | 644 |
509 const Operator* RepresentationChanger::Float64OperatorFor( | 645 const Operator* RepresentationChanger::Float64OperatorFor( |
510 IrOpcode::Value opcode) { | 646 IrOpcode::Value opcode) { |
511 switch (opcode) { | 647 switch (opcode) { |
| 648 case IrOpcode::kSpeculativeNumberAdd: |
512 case IrOpcode::kNumberAdd: | 649 case IrOpcode::kNumberAdd: |
513 return machine()->Float64Add(); | 650 return machine()->Float64Add(); |
| 651 case IrOpcode::kSpeculativeNumberSubtract: |
514 case IrOpcode::kNumberSubtract: | 652 case IrOpcode::kNumberSubtract: |
515 return machine()->Float64Sub(); | 653 return machine()->Float64Sub(); |
516 case IrOpcode::kNumberMultiply: | 654 case IrOpcode::kNumberMultiply: |
517 return machine()->Float64Mul(); | 655 return machine()->Float64Mul(); |
518 case IrOpcode::kNumberDivide: | 656 case IrOpcode::kNumberDivide: |
519 return machine()->Float64Div(); | 657 return machine()->Float64Div(); |
520 case IrOpcode::kNumberModulus: | 658 case IrOpcode::kNumberModulus: |
521 return machine()->Float64Mod(); | 659 return machine()->Float64Mod(); |
522 case IrOpcode::kNumberEqual: | 660 case IrOpcode::kNumberEqual: |
523 return machine()->Float64Equal(); | 661 return machine()->Float64Equal(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 } | 712 } |
575 | 713 |
576 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 714 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
577 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 715 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
578 node); | 716 node); |
579 } | 717 } |
580 | 718 |
581 } // namespace compiler | 719 } // namespace compiler |
582 } // namespace internal | 720 } // namespace internal |
583 } // namespace v8 | 721 } // namespace v8 |
OLD | NEW |