| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 // Both are words less than or equal to 32-bits. | 135 // Both are words less than or equal to 32-bits. |
| 136 // Since loads of integers from memory implicitly sign or zero extend the | 136 // Since loads of integers from memory implicitly sign or zero extend the |
| 137 // value to the full machine word size and stores implicitly truncate, | 137 // value to the full machine word size and stores implicitly truncate, |
| 138 // no representation change is necessary. | 138 // no representation change is necessary. |
| 139 return node; | 139 return node; |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 | 142 |
| 143 switch (use_info.representation()) { | 143 switch (use_info.representation()) { |
| 144 case MachineRepresentation::kTaggedSigned: | 144 case MachineRepresentation::kTaggedSigned: |
| 145 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 146 return GetTaggedSignedRepresentationFor(node, output_rep, output_type); |
| 145 case MachineRepresentation::kTaggedPointer: | 147 case MachineRepresentation::kTaggedPointer: |
| 148 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 149 return GetTaggedPointerRepresentationFor(node, output_rep, output_type); |
| 146 case MachineRepresentation::kTagged: | 150 case MachineRepresentation::kTagged: |
| 147 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 151 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 148 return GetTaggedRepresentationFor(node, output_rep, output_type); | 152 return GetTaggedRepresentationFor(node, output_rep, output_type); |
| 149 case MachineRepresentation::kFloat32: | 153 case MachineRepresentation::kFloat32: |
| 150 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 154 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 151 return GetFloat32RepresentationFor(node, output_rep, output_type, | 155 return GetFloat32RepresentationFor(node, output_rep, output_type, |
| 152 use_info.truncation()); | 156 use_info.truncation()); |
| 153 case MachineRepresentation::kFloat64: | 157 case MachineRepresentation::kFloat64: |
| 154 return GetFloat64RepresentationFor(node, output_rep, output_type, | 158 return GetFloat64RepresentationFor(node, output_rep, output_type, |
| 155 use_node, use_info); | 159 use_node, use_info); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 167 case MachineRepresentation::kSimd128: // Fall through. | 171 case MachineRepresentation::kSimd128: // Fall through. |
| 168 // TODO(bbudge) Handle conversions between tagged and untagged. | 172 // TODO(bbudge) Handle conversions between tagged and untagged. |
| 169 break; | 173 break; |
| 170 case MachineRepresentation::kNone: | 174 case MachineRepresentation::kNone: |
| 171 return node; | 175 return node; |
| 172 } | 176 } |
| 173 UNREACHABLE(); | 177 UNREACHABLE(); |
| 174 return nullptr; | 178 return nullptr; |
| 175 } | 179 } |
| 176 | 180 |
| 181 Node* RepresentationChanger::GetTaggedSignedRepresentationFor( |
| 182 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 183 // Eagerly fold representation changes for constants. |
| 184 switch (node->opcode()) { |
| 185 case IrOpcode::kNumberConstant: { |
| 186 int32_t value = OpParameter<int32_t>(node); |
| 187 if (Smi::IsValid(value)) { |
| 188 return jsgraph()->Constant(value); |
| 189 } |
| 190 return TypeError(node, output_rep, output_type, |
| 191 MachineRepresentation::kTaggedSigned); |
| 192 } |
| 193 case IrOpcode::kHeapConstant: |
| 194 return TypeError(node, output_rep, output_type, |
| 195 MachineRepresentation::kTaggedSigned); |
| 196 case IrOpcode::kInt32Constant: |
| 197 if (output_type->Is(Type::SignedSmall())) { |
| 198 int32_t value = OpParameter<int32_t>(node); |
| 199 return jsgraph()->Constant(value); |
| 200 } else { |
| 201 return TypeError(node, output_rep, output_type, |
| 202 MachineRepresentation::kTaggedSigned); |
| 203 } |
| 204 case IrOpcode::kFloat64Constant: |
| 205 case IrOpcode::kFloat32Constant: |
| 206 return TypeError(node, output_rep, output_type, |
| 207 MachineRepresentation::kTaggedSigned); |
| 208 default: |
| 209 break; |
| 210 } |
| 211 // Select the correct X -> Tagged operator. |
| 212 const Operator* op; |
| 213 if (output_type->Is(Type::None())) { |
| 214 // This is an impossible value; it should not be used at runtime. |
| 215 // We just provide a dummy value here. |
| 216 return jsgraph()->Constant(0); |
| 217 } else if (IsWord(output_rep)) { |
| 218 if (output_type->Is(Type::Signed31())) { |
| 219 op = simplified()->ChangeInt31ToTaggedSigned(); |
| 220 } else if (machine()->Is64() && output_type->Is(Type::Signed32())) { |
| 221 op = simplified()->ChangeInt32ToTagged(); |
| 222 } else { |
| 223 return TypeError(node, output_rep, output_type, |
| 224 MachineRepresentation::kTaggedSigned); |
| 225 } |
| 226 } else { |
| 227 return TypeError(node, output_rep, output_type, |
| 228 MachineRepresentation::kTaggedSigned); |
| 229 } |
| 230 return jsgraph()->graph()->NewNode(op, node); |
| 231 } |
| 232 |
| 233 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( |
| 234 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 235 // Eagerly fold representation changes for constants. |
| 236 switch (node->opcode()) { |
| 237 case IrOpcode::kHeapConstant: |
| 238 return node; // No change necessary. |
| 239 case IrOpcode::kInt32Constant: |
| 240 if (output_type->Is(Type::Boolean())) { |
| 241 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant() |
| 242 : jsgraph()->TrueConstant(); |
| 243 } else { |
| 244 return TypeError(node, output_rep, output_type, |
| 245 MachineRepresentation::kTaggedPointer); |
| 246 } |
| 247 case IrOpcode::kFloat64Constant: |
| 248 case IrOpcode::kFloat32Constant: |
| 249 return TypeError(node, output_rep, output_type, |
| 250 MachineRepresentation::kTaggedPointer); |
| 251 default: |
| 252 break; |
| 253 } |
| 254 // Select the correct X -> Tagged operator. |
| 255 if (output_type->Is(Type::None())) { |
| 256 // This is an impossible value; it should not be used at runtime. |
| 257 // We just provide a dummy value here. |
| 258 return jsgraph()->TheHoleConstant(); |
| 259 } |
| 260 return TypeError(node, output_rep, output_type, |
| 261 MachineRepresentation::kTaggedPointer); |
| 262 } |
| 263 |
| 177 Node* RepresentationChanger::GetTaggedRepresentationFor( | 264 Node* RepresentationChanger::GetTaggedRepresentationFor( |
| 178 Node* node, MachineRepresentation output_rep, Type* output_type) { | 265 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 179 // Eagerly fold representation changes for constants. | 266 // Eagerly fold representation changes for constants. |
| 180 switch (node->opcode()) { | 267 switch (node->opcode()) { |
| 181 case IrOpcode::kNumberConstant: | 268 case IrOpcode::kNumberConstant: |
| 182 case IrOpcode::kHeapConstant: | 269 case IrOpcode::kHeapConstant: |
| 183 return node; // No change necessary. | 270 return node; // No change necessary. |
| 184 case IrOpcode::kInt32Constant: | 271 case IrOpcode::kInt32Constant: |
| 185 if (output_type->Is(Type::Signed32())) { | 272 if (output_type->Is(Type::Signed32())) { |
| 186 int32_t value = OpParameter<int32_t>(node); | 273 int32_t value = OpParameter<int32_t>(node); |
| 187 return jsgraph()->Constant(value); | 274 return jsgraph()->Constant(value); |
| 188 } else if (output_type->Is(Type::Unsigned32())) { | 275 } else if (output_type->Is(Type::Unsigned32())) { |
| 189 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); | 276 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); |
| 190 return jsgraph()->Constant(static_cast<double>(value)); | 277 return jsgraph()->Constant(static_cast<double>(value)); |
| 191 } else if (output_type->Is(Type::Boolean())) { | 278 } else if (output_type->Is(Type::Boolean())) { |
| 192 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant() | 279 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant() |
| 193 : jsgraph()->TrueConstant(); | 280 : jsgraph()->TrueConstant(); |
| 194 } else { | 281 } else { |
| 195 return TypeError(node, output_rep, output_type, | 282 return TypeError(node, output_rep, output_type, |
| 196 MachineRepresentation::kTagged); | 283 MachineRepresentation::kTagged); |
| 197 } | 284 } |
| 198 case IrOpcode::kFloat64Constant: | 285 case IrOpcode::kFloat64Constant: |
| 199 return jsgraph()->Constant(OpParameter<double>(node)); | 286 return jsgraph()->Constant(OpParameter<double>(node)); |
| 200 case IrOpcode::kFloat32Constant: | 287 case IrOpcode::kFloat32Constant: |
| 201 return jsgraph()->Constant(OpParameter<float>(node)); | 288 return jsgraph()->Constant(OpParameter<float>(node)); |
| 202 default: | 289 default: |
| 203 break; | 290 break; |
| 204 } | 291 } |
| 292 if (output_rep == MachineRepresentation::kTaggedSigned || |
| 293 output_rep == MachineRepresentation::kTaggedPointer) { |
| 294 // this is a no-op. |
| 295 return node; |
| 296 } |
| 205 // Select the correct X -> Tagged operator. | 297 // Select the correct X -> Tagged operator. |
| 206 const Operator* op; | 298 const Operator* op; |
| 207 if (output_type->Is(Type::None())) { | 299 if (output_type->Is(Type::None())) { |
| 208 // This is an impossible value; it should not be used at runtime. | 300 // This is an impossible value; it should not be used at runtime. |
| 209 // We just provide a dummy value here. | 301 // We just provide a dummy value here. |
| 210 return jsgraph()->TheHoleConstant(); | 302 return jsgraph()->TheHoleConstant(); |
| 211 } else if (output_rep == MachineRepresentation::kBit) { | 303 } else if (output_rep == MachineRepresentation::kBit) { |
| 212 if (output_type->Is(Type::Boolean())) { | 304 if (output_type->Is(Type::Boolean())) { |
| 213 op = simplified()->ChangeBitToTagged(); | 305 op = simplified()->ChangeBitToTagged(); |
| 214 } else { | 306 } else { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 } else if (output_type->Is(Type::Unsigned32()) || | 388 } else if (output_type->Is(Type::Unsigned32()) || |
| 297 truncation.IsUsedAsWord32()) { | 389 truncation.IsUsedAsWord32()) { |
| 298 // Either the output is uint32 or the uses only care about the | 390 // Either the output is uint32 or the uses only care about the |
| 299 // low 32 bits (so we can pick uint32 safely). | 391 // low 32 bits (so we can pick uint32 safely). |
| 300 | 392 |
| 301 // uint32 -> float64 -> float32 | 393 // uint32 -> float64 -> float32 |
| 302 op = machine()->ChangeUint32ToFloat64(); | 394 op = machine()->ChangeUint32ToFloat64(); |
| 303 node = jsgraph()->graph()->NewNode(op, node); | 395 node = jsgraph()->graph()->NewNode(op, node); |
| 304 op = machine()->TruncateFloat64ToFloat32(); | 396 op = machine()->TruncateFloat64ToFloat32(); |
| 305 } | 397 } |
| 306 } else if (output_rep == MachineRepresentation::kTagged) { | 398 } else if (output_rep == MachineRepresentation::kTagged || |
| 399 output_rep == MachineRepresentation::kTaggedPointer) { |
| 307 if (output_type->Is(Type::NumberOrOddball())) { | 400 if (output_type->Is(Type::NumberOrOddball())) { |
| 308 // tagged -> float64 -> float32 | 401 // tagged -> float64 -> float32 |
| 309 if (output_type->Is(Type::Number())) { | 402 if (output_type->Is(Type::Number())) { |
| 310 op = simplified()->ChangeTaggedToFloat64(); | 403 op = simplified()->ChangeTaggedToFloat64(); |
| 311 } else { | 404 } else { |
| 312 op = simplified()->TruncateTaggedToFloat64(); | 405 op = simplified()->TruncateTaggedToFloat64(); |
| 313 } | 406 } |
| 314 node = jsgraph()->graph()->NewNode(op, node); | 407 node = jsgraph()->graph()->NewNode(op, node); |
| 315 op = machine()->TruncateFloat64ToFloat32(); | 408 op = machine()->TruncateFloat64ToFloat32(); |
| 316 } | 409 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 if (output_type->Is(Type::Signed32())) { | 453 if (output_type->Is(Type::Signed32())) { |
| 361 op = machine()->ChangeInt32ToFloat64(); | 454 op = machine()->ChangeInt32ToFloat64(); |
| 362 } else if (output_type->Is(Type::Unsigned32()) || | 455 } else if (output_type->Is(Type::Unsigned32()) || |
| 363 use_info.truncation().IsUsedAsWord32()) { | 456 use_info.truncation().IsUsedAsWord32()) { |
| 364 // Either the output is uint32 or the uses only care about the | 457 // Either the output is uint32 or the uses only care about the |
| 365 // low 32 bits (so we can pick uint32 safely). | 458 // low 32 bits (so we can pick uint32 safely). |
| 366 op = machine()->ChangeUint32ToFloat64(); | 459 op = machine()->ChangeUint32ToFloat64(); |
| 367 } | 460 } |
| 368 } else if (output_rep == MachineRepresentation::kBit) { | 461 } else if (output_rep == MachineRepresentation::kBit) { |
| 369 op = machine()->ChangeUint32ToFloat64(); | 462 op = machine()->ChangeUint32ToFloat64(); |
| 370 } else if (output_rep == MachineRepresentation::kTagged) { | 463 } else if (output_rep == MachineRepresentation::kTagged || |
| 464 output_rep == MachineRepresentation::kTaggedSigned || |
| 465 output_rep == MachineRepresentation::kTaggedPointer) { |
| 371 if (output_type->Is(Type::Undefined())) { | 466 if (output_type->Is(Type::Undefined())) { |
| 372 return jsgraph()->Float64Constant( | 467 return jsgraph()->Float64Constant( |
| 373 std::numeric_limits<double>::quiet_NaN()); | 468 std::numeric_limits<double>::quiet_NaN()); |
| 374 } else if (output_type->Is(Type::TaggedSigned())) { | 469 } else if (output_type->Is(Type::TaggedSigned())) { |
| 375 node = InsertChangeTaggedSignedToInt32(node); | 470 node = InsertChangeTaggedSignedToInt32(node); |
| 376 op = machine()->ChangeInt32ToFloat64(); | 471 op = machine()->ChangeInt32ToFloat64(); |
| 377 } else if (output_type->Is(Type::Number())) { | 472 } else if (output_type->Is(Type::Number())) { |
| 378 op = simplified()->ChangeTaggedToFloat64(); | 473 op = simplified()->ChangeTaggedToFloat64(); |
| 379 } else if (output_type->Is(Type::NumberOrOddball())) { | 474 } else if (output_type->Is(Type::NumberOrOddball())) { |
| 380 // TODO(jarin) Here we should check that truncation is Number. | 475 // TODO(jarin) Here we should check that truncation is Number. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 op = machine()->ChangeFloat64ToInt32(); | 558 op = machine()->ChangeFloat64ToInt32(); |
| 464 } else if (use_info.truncation().IsUsedAsWord32()) { | 559 } else if (use_info.truncation().IsUsedAsWord32()) { |
| 465 op = machine()->TruncateFloat64ToWord32(); | 560 op = machine()->TruncateFloat64ToWord32(); |
| 466 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || | 561 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || |
| 467 use_info.type_check() == TypeCheckKind::kSigned32) { | 562 use_info.type_check() == TypeCheckKind::kSigned32) { |
| 468 op = simplified()->CheckedFloat64ToInt32( | 563 op = simplified()->CheckedFloat64ToInt32( |
| 469 output_type->Maybe(Type::MinusZero()) | 564 output_type->Maybe(Type::MinusZero()) |
| 470 ? CheckForMinusZeroMode::kCheckForMinusZero | 565 ? CheckForMinusZeroMode::kCheckForMinusZero |
| 471 : CheckForMinusZeroMode::kDontCheckForMinusZero); | 566 : CheckForMinusZeroMode::kDontCheckForMinusZero); |
| 472 } | 567 } |
| 473 } else if (output_rep == MachineRepresentation::kTagged) { | 568 } else if (output_rep == MachineRepresentation::kTaggedSigned) { |
| 474 if (output_type->Is(Type::TaggedSigned())) { | 569 if (output_type->Is(Type::Signed32())) { |
| 475 op = simplified()->ChangeTaggedSignedToInt32(); | 570 op = simplified()->ChangeTaggedSignedToInt32(); |
| 476 } else if (output_type->Is(Type::Unsigned32())) { | 571 } else if (use_info.truncation().IsUsedAsWord32()) { |
| 572 if (use_info.type_check() != TypeCheckKind::kNone) { |
| 573 op = simplified()->CheckedTruncateTaggedToWord32(); |
| 574 } else { |
| 575 op = simplified()->TruncateTaggedToWord32(); |
| 576 } |
| 577 } |
| 578 } else if (output_rep == MachineRepresentation::kTagged || |
| 579 output_rep == MachineRepresentation::kTaggedPointer) { |
| 580 if (output_type->Is(Type::Unsigned32())) { |
| 477 op = simplified()->ChangeTaggedToUint32(); | 581 op = simplified()->ChangeTaggedToUint32(); |
| 478 } else if (output_type->Is(Type::Signed32())) { | 582 } else if (output_type->Is(Type::Signed32())) { |
| 479 op = simplified()->ChangeTaggedToInt32(); | 583 op = simplified()->ChangeTaggedToInt32(); |
| 480 } else if (use_info.truncation().IsUsedAsWord32()) { | 584 } else if (use_info.truncation().IsUsedAsWord32()) { |
| 481 if (use_info.type_check() != TypeCheckKind::kNone) { | 585 if (use_info.type_check() != TypeCheckKind::kNone) { |
| 482 op = simplified()->CheckedTruncateTaggedToWord32(); | 586 op = simplified()->CheckedTruncateTaggedToWord32(); |
| 483 } else { | 587 } else { |
| 484 op = simplified()->TruncateTaggedToWord32(); | 588 op = simplified()->TruncateTaggedToWord32(); |
| 485 } | 589 } |
| 486 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { | 590 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 } | 652 } |
| 549 default: | 653 default: |
| 550 break; | 654 break; |
| 551 } | 655 } |
| 552 // Select the correct X -> Bit operator. | 656 // Select the correct X -> Bit operator. |
| 553 const Operator* op; | 657 const Operator* op; |
| 554 if (output_type->Is(Type::None())) { | 658 if (output_type->Is(Type::None())) { |
| 555 // This is an impossible value; it should not be used at runtime. | 659 // This is an impossible value; it should not be used at runtime. |
| 556 // We just provide a dummy value here. | 660 // We just provide a dummy value here. |
| 557 return jsgraph()->Int32Constant(0); | 661 return jsgraph()->Int32Constant(0); |
| 558 } else if (output_rep == MachineRepresentation::kTagged) { | 662 } else if (output_rep == MachineRepresentation::kTagged || |
| 663 output_rep == MachineRepresentation::kTaggedSigned || |
| 664 output_rep == MachineRepresentation::kTaggedPointer) { |
| 559 op = simplified()->ChangeTaggedToBit(); | 665 op = simplified()->ChangeTaggedToBit(); |
| 560 } else { | 666 } else { |
| 561 return TypeError(node, output_rep, output_type, | 667 return TypeError(node, output_rep, output_type, |
| 562 MachineRepresentation::kBit); | 668 MachineRepresentation::kBit); |
| 563 } | 669 } |
| 564 return jsgraph()->graph()->NewNode(op, node); | 670 return jsgraph()->graph()->NewNode(op, node); |
| 565 } | 671 } |
| 566 | 672 |
| 567 Node* RepresentationChanger::GetWord64RepresentationFor( | 673 Node* RepresentationChanger::GetWord64RepresentationFor( |
| 568 Node* node, MachineRepresentation output_rep, Type* output_type) { | 674 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 } | 927 } |
| 822 | 928 |
| 823 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 929 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
| 824 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 930 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
| 825 node); | 931 node); |
| 826 } | 932 } |
| 827 | 933 |
| 828 } // namespace compiler | 934 } // namespace compiler |
| 829 } // namespace internal | 935 } // namespace internal |
| 830 } // namespace v8 | 936 } // namespace v8 |
| OLD | NEW |