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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 110 |
111 } // namespace | 111 } // namespace |
112 | 112 |
113 // Changes representation from {output_rep} to {use_rep}. The {truncation} | 113 // Changes representation from {output_rep} to {use_rep}. The {truncation} |
114 // parameter is only used for sanity checking - if the changer cannot figure | 114 // parameter is only used for sanity checking - if the changer cannot figure |
115 // out signedness for the word32->float64 conversion, then we check that the | 115 // out signedness for the word32->float64 conversion, then we check that the |
116 // uses truncate to word32 (so they do not care about signedness). | 116 // uses truncate to word32 (so they do not care about signedness). |
117 Node* RepresentationChanger::GetRepresentationFor( | 117 Node* RepresentationChanger::GetRepresentationFor( |
118 Node* node, MachineRepresentation output_rep, Type* output_type, | 118 Node* node, MachineRepresentation output_rep, Type* output_type, |
119 Node* use_node, UseInfo use_info) { | 119 Node* use_node, UseInfo use_info) { |
120 if (output_rep == MachineRepresentation::kNone) { | 120 if (output_rep == MachineRepresentation::kNone && |
121 // The output representation should be set. | 121 output_type->IsInhabited()) { |
| 122 // The output representation should be set if the type is inhabited (i.e., |
| 123 // if the value is possible). |
122 return TypeError(node, output_rep, output_type, use_info.representation()); | 124 return TypeError(node, output_rep, output_type, use_info.representation()); |
123 } | 125 } |
124 | 126 |
125 // Handle the no-op shortcuts when no checking is necessary. | 127 // Handle the no-op shortcuts when no checking is necessary. |
126 if (use_info.type_check() == TypeCheckKind::kNone || | 128 if (use_info.type_check() == TypeCheckKind::kNone || |
127 output_rep != MachineRepresentation::kWord32) { | 129 output_rep != MachineRepresentation::kWord32) { |
128 if (use_info.representation() == output_rep) { | 130 if (use_info.representation() == output_rep) { |
129 // Representations are the same. That's a no-op. | 131 // Representations are the same. That's a no-op. |
130 return node; | 132 return node; |
131 } | 133 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } | 195 } |
194 case IrOpcode::kFloat64Constant: | 196 case IrOpcode::kFloat64Constant: |
195 return jsgraph()->Constant(OpParameter<double>(node)); | 197 return jsgraph()->Constant(OpParameter<double>(node)); |
196 case IrOpcode::kFloat32Constant: | 198 case IrOpcode::kFloat32Constant: |
197 return jsgraph()->Constant(OpParameter<float>(node)); | 199 return jsgraph()->Constant(OpParameter<float>(node)); |
198 default: | 200 default: |
199 break; | 201 break; |
200 } | 202 } |
201 // Select the correct X -> Tagged operator. | 203 // Select the correct X -> Tagged operator. |
202 const Operator* op; | 204 const Operator* op; |
203 if (output_rep == MachineRepresentation::kBit) { | 205 if (output_rep == MachineRepresentation::kNone) { |
| 206 // We should only asisgn this representation if the type is empty. |
| 207 CHECK(!output_type->IsInhabited()); |
| 208 op = machine()->ImpossibleToTagged(); |
| 209 } else if (output_rep == MachineRepresentation::kBit) { |
204 if (output_type->Is(Type::Boolean())) { | 210 if (output_type->Is(Type::Boolean())) { |
205 op = simplified()->ChangeBitToTagged(); | 211 op = simplified()->ChangeBitToTagged(); |
206 } else { | 212 } else { |
207 return TypeError(node, output_rep, output_type, | 213 return TypeError(node, output_rep, output_type, |
208 MachineRepresentation::kTagged); | 214 MachineRepresentation::kTagged); |
209 } | 215 } |
210 } else if (IsWord(output_rep)) { | 216 } else if (IsWord(output_rep)) { |
211 if (output_type->Is(Type::Signed31())) { | 217 if (output_type->Is(Type::Signed31())) { |
212 op = simplified()->ChangeInt31ToTaggedSigned(); | 218 op = simplified()->ChangeInt31ToTaggedSigned(); |
213 } else if (output_type->Is(Type::Signed32())) { | 219 } else if (output_type->Is(Type::Signed32())) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 int32_t value = OpParameter<int32_t>(node); | 270 int32_t value = OpParameter<int32_t>(node); |
265 return jsgraph()->Float32Constant(static_cast<float>(value)); | 271 return jsgraph()->Float32Constant(static_cast<float>(value)); |
266 } | 272 } |
267 case IrOpcode::kFloat32Constant: | 273 case IrOpcode::kFloat32Constant: |
268 return node; // No change necessary. | 274 return node; // No change necessary. |
269 default: | 275 default: |
270 break; | 276 break; |
271 } | 277 } |
272 // Select the correct X -> Float32 operator. | 278 // Select the correct X -> Float32 operator. |
273 const Operator* op = nullptr; | 279 const Operator* op = nullptr; |
274 if (IsWord(output_rep)) { | 280 if (output_rep == MachineRepresentation::kNone) { |
| 281 // We should only use kNone representation if the type is empty. |
| 282 CHECK(!output_type->IsInhabited()); |
| 283 op = machine()->ImpossibleToFloat32(); |
| 284 } else if (IsWord(output_rep)) { |
275 if (output_type->Is(Type::Signed32())) { | 285 if (output_type->Is(Type::Signed32())) { |
276 // int32 -> float64 -> float32 | 286 // int32 -> float64 -> float32 |
277 op = machine()->ChangeInt32ToFloat64(); | 287 op = machine()->ChangeInt32ToFloat64(); |
278 node = jsgraph()->graph()->NewNode(op, node); | 288 node = jsgraph()->graph()->NewNode(op, node); |
279 op = machine()->TruncateFloat64ToFloat32(); | 289 op = machine()->TruncateFloat64ToFloat32(); |
280 } else if (output_type->Is(Type::Unsigned32()) || | 290 } else if (output_type->Is(Type::Unsigned32()) || |
281 truncation.IsUsedAsWord32()) { | 291 truncation.IsUsedAsWord32()) { |
282 // Either the output is uint32 or the uses only care about the | 292 // Either the output is uint32 or the uses only care about the |
283 // low 32 bits (so we can pick uint32 safely). | 293 // low 32 bits (so we can pick uint32 safely). |
284 | 294 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 case IrOpcode::kFloat64Constant: | 339 case IrOpcode::kFloat64Constant: |
330 return node; // No change necessary. | 340 return node; // No change necessary. |
331 case IrOpcode::kFloat32Constant: | 341 case IrOpcode::kFloat32Constant: |
332 return jsgraph()->Float64Constant(OpParameter<float>(node)); | 342 return jsgraph()->Float64Constant(OpParameter<float>(node)); |
333 default: | 343 default: |
334 break; | 344 break; |
335 } | 345 } |
336 } | 346 } |
337 // Select the correct X -> Float64 operator. | 347 // Select the correct X -> Float64 operator. |
338 const Operator* op = nullptr; | 348 const Operator* op = nullptr; |
339 if (IsWord(output_rep)) { | 349 if (output_rep == MachineRepresentation::kNone) { |
| 350 // We should only use kNone representation if the type is empty. |
| 351 CHECK(!output_type->IsInhabited()); |
| 352 op = machine()->ImpossibleToFloat64(); |
| 353 } else if (IsWord(output_rep)) { |
340 if (output_type->Is(Type::Signed32())) { | 354 if (output_type->Is(Type::Signed32())) { |
341 op = machine()->ChangeInt32ToFloat64(); | 355 op = machine()->ChangeInt32ToFloat64(); |
342 } else if (output_type->Is(Type::Unsigned32()) || | 356 } else if (output_type->Is(Type::Unsigned32()) || |
343 use_info.truncation().IsUsedAsWord32()) { | 357 use_info.truncation().IsUsedAsWord32()) { |
344 // Either the output is uint32 or the uses only care about the | 358 // Either the output is uint32 or the uses only care about the |
345 // low 32 bits (so we can pick uint32 safely). | 359 // low 32 bits (so we can pick uint32 safely). |
346 op = machine()->ChangeUint32ToFloat64(); | 360 op = machine()->ChangeUint32ToFloat64(); |
347 } | 361 } |
348 } else if (output_rep == MachineRepresentation::kBit) { | 362 } else if (output_rep == MachineRepresentation::kBit) { |
349 op = machine()->ChangeUint32ToFloat64(); | 363 op = machine()->ChangeUint32ToFloat64(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 return MakeTruncatedInt32Constant(fv); | 415 return MakeTruncatedInt32Constant(fv); |
402 } | 416 } |
403 break; | 417 break; |
404 } | 418 } |
405 default: | 419 default: |
406 break; | 420 break; |
407 } | 421 } |
408 | 422 |
409 // Select the correct X -> Word32 operator. | 423 // Select the correct X -> Word32 operator. |
410 const Operator* op = nullptr; | 424 const Operator* op = nullptr; |
411 if (output_rep == MachineRepresentation::kBit) { | 425 if (output_rep == MachineRepresentation::kNone) { |
| 426 // We should only use kNone representation if the type is empty. |
| 427 CHECK(!output_type->IsInhabited()); |
| 428 op = machine()->ImpossibleToWord32(); |
| 429 } else if (output_rep == MachineRepresentation::kBit) { |
412 return node; // Sloppy comparison -> word32 | 430 return node; // Sloppy comparison -> word32 |
413 } else if (output_rep == MachineRepresentation::kFloat64) { | 431 } else if (output_rep == MachineRepresentation::kFloat64) { |
414 if (output_type->Is(Type::Unsigned32())) { | 432 if (output_type->Is(Type::Unsigned32())) { |
415 op = machine()->ChangeFloat64ToUint32(); | 433 op = machine()->ChangeFloat64ToUint32(); |
416 } else if (output_type->Is(Type::Signed32())) { | 434 } else if (output_type->Is(Type::Signed32())) { |
417 op = machine()->ChangeFloat64ToInt32(); | 435 op = machine()->ChangeFloat64ToInt32(); |
418 } else if (use_info.truncation().IsUsedAsWord32()) { | 436 } else if (use_info.truncation().IsUsedAsWord32()) { |
419 op = machine()->TruncateFloat64ToWord32(); | 437 op = machine()->TruncateFloat64ToWord32(); |
420 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { | 438 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
421 op = simplified()->CheckedFloat64ToInt32(); | 439 op = simplified()->CheckedFloat64ToInt32(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 DCHECK(value.is_identical_to(factory()->true_value()) || | 508 DCHECK(value.is_identical_to(factory()->true_value()) || |
491 value.is_identical_to(factory()->false_value())); | 509 value.is_identical_to(factory()->false_value())); |
492 return jsgraph()->Int32Constant( | 510 return jsgraph()->Int32Constant( |
493 value.is_identical_to(factory()->true_value()) ? 1 : 0); | 511 value.is_identical_to(factory()->true_value()) ? 1 : 0); |
494 } | 512 } |
495 default: | 513 default: |
496 break; | 514 break; |
497 } | 515 } |
498 // Select the correct X -> Bit operator. | 516 // Select the correct X -> Bit operator. |
499 const Operator* op; | 517 const Operator* op; |
500 if (output_rep == MachineRepresentation::kTagged) { | 518 if (output_rep == MachineRepresentation::kNone) { |
| 519 // We should only use kNone representation if the type is empty. |
| 520 CHECK(!output_type->IsInhabited()); |
| 521 op = machine()->ImpossibleToBit(); |
| 522 } else if (output_rep == MachineRepresentation::kTagged) { |
501 op = simplified()->ChangeTaggedToBit(); | 523 op = simplified()->ChangeTaggedToBit(); |
502 } else { | 524 } else { |
503 return TypeError(node, output_rep, output_type, | 525 return TypeError(node, output_rep, output_type, |
504 MachineRepresentation::kBit); | 526 MachineRepresentation::kBit); |
505 } | 527 } |
506 return jsgraph()->graph()->NewNode(op, node); | 528 return jsgraph()->graph()->NewNode(op, node); |
507 } | 529 } |
508 | 530 |
509 Node* RepresentationChanger::GetWord64RepresentationFor( | 531 Node* RepresentationChanger::GetWord64RepresentationFor( |
510 Node* node, MachineRepresentation output_rep, Type* output_type) { | 532 Node* node, MachineRepresentation output_rep, Type* output_type) { |
511 if (output_rep == MachineRepresentation::kBit) { | 533 if (output_rep == MachineRepresentation::kNone) { |
| 534 // We should only use kNone representation if the type is empty. |
| 535 CHECK(!output_type->IsInhabited()); |
| 536 return jsgraph()->graph()->NewNode(machine()->ImpossibleToFloat64(), node); |
| 537 } else if (output_rep == MachineRepresentation::kBit) { |
512 return node; // Sloppy comparison -> word64 | 538 return node; // Sloppy comparison -> word64 |
513 } | 539 } |
514 // Can't really convert Word64 to anything else. Purported to be internal. | 540 // Can't really convert Word64 to anything else. Purported to be internal. |
515 return TypeError(node, output_rep, output_type, | 541 return TypeError(node, output_rep, output_type, |
516 MachineRepresentation::kWord64); | 542 MachineRepresentation::kWord64); |
517 } | 543 } |
518 | 544 |
519 Node* RepresentationChanger::GetCheckedWord32RepresentationFor( | 545 Node* RepresentationChanger::GetCheckedWord32RepresentationFor( |
520 Node* node, MachineRepresentation output_rep, Type* output_type, | 546 Node* node, MachineRepresentation output_rep, Type* output_type, |
521 Node* use_node, Truncation truncation, TypeCheckKind check) { | 547 Node* use_node, Truncation truncation, TypeCheckKind check) { |
522 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant | 548 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant |
523 // does not pass the check). | 549 // does not pass the check). |
524 | 550 |
525 // If the input is already Signed32 in Word32 representation, we do not | 551 // If the input is already Signed32 in Word32 representation, we do not |
526 // have to do anything. (We could fold this into the big if below, but | 552 // have to do anything. (We could fold this into the big if below, but |
527 // it feels nicer to have the shortcut return first). | 553 // it feels nicer to have the shortcut return first). |
528 if (output_rep == MachineRepresentation::kWord32 || | 554 if (output_rep == MachineRepresentation::kWord32 || |
529 output_type->Is(Type::Signed32())) { | 555 output_type->Is(Type::Signed32())) { |
530 return node; | 556 return node; |
531 } | 557 } |
532 | 558 |
533 // Select the correct X -> Word32 operator. | 559 // Select the correct X -> Word32 operator. |
534 const Operator* op = nullptr; | 560 const Operator* op = nullptr; |
535 if (output_rep == MachineRepresentation::kWord32) { | 561 if (output_rep == MachineRepresentation::kNone) { |
| 562 // We should only use kNone representation if the type is empty. |
| 563 CHECK(!output_type->IsInhabited()); |
| 564 op = machine()->ImpossibleToWord32(); |
| 565 } else if (output_rep == MachineRepresentation::kWord32) { |
536 if (output_type->Is(Type::Unsigned32())) { | 566 if (output_type->Is(Type::Unsigned32())) { |
537 op = simplified()->CheckedUint32ToInt32(); | 567 op = simplified()->CheckedUint32ToInt32(); |
538 } | 568 } |
539 } else if (output_rep == MachineRepresentation::kBit) { | 569 } else if (output_rep == MachineRepresentation::kBit) { |
540 return node; // Sloppy comparison -> word32 | 570 return node; // Sloppy comparison -> word32 |
541 } else if (output_rep == MachineRepresentation::kFloat64) { | 571 } else if (output_rep == MachineRepresentation::kFloat64) { |
542 if (output_type->Is(Type::Unsigned32())) { | 572 if (output_type->Is(Type::Unsigned32())) { |
543 op = machine()->ChangeFloat64ToUint32(); | 573 op = machine()->ChangeFloat64ToUint32(); |
544 } else if (output_type->Is(Type::Signed32())) { | 574 } else if (output_type->Is(Type::Signed32())) { |
545 op = machine()->ChangeFloat64ToInt32(); | 575 op = machine()->ChangeFloat64ToInt32(); |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 } | 844 } |
815 | 845 |
816 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 846 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
817 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 847 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
818 node); | 848 node); |
819 } | 849 } |
820 | 850 |
821 } // namespace compiler | 851 } // namespace compiler |
822 } // namespace internal | 852 } // namespace internal |
823 } // namespace v8 | 853 } // namespace v8 |
OLD | NEW |