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 3 // found in the LICENSE file. 4 5 #include "src/compiler/representation-change.h" 6 7 #include <sstream> 8 9 #include "src/base/bits.h" 10 #include "src/code-factory.h" 11 #include "src/compiler/machine-operator.h" 12 13 namespace v8 { 14 namespace internal { 15 namespace compiler { 16 17 const char* Truncation::description() const { 18 switch (kind()) { 19 case TruncationKind::kNone: 20 return "no-value-use"; 21 case TruncationKind::kBool: 22 return "truncate-to-bool"; 23 case TruncationKind::kWord32: 24 return "truncate-to-word32"; 25 case TruncationKind::kWord64: 26 return "truncate-to-word64"; 27 case TruncationKind::kFloat64: 28 return "truncate-to-float64"; 29 case TruncationKind::kAny: 30 return "no-truncation"; 31 } 32 UNREACHABLE(); 33 return nullptr; 34 } 35 36 37 // Partial order for truncations: 38 // 39 // kWord64 kAny 40 // ^ ^ 41 // \ | 42 // \ kFloat64 <--+ 43 // \ ^ | 44 // \ / | 45 // kWord32 kBool 46 // ^ ^ 47 // \ / 48 // \ / 49 // \ / 50 // \ / 51 // \ / 52 // kNone 53 54 // static 55 Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1, 56 TruncationKind rep2) { 57 if (LessGeneral(rep1, rep2)) return rep2; 58 if (LessGeneral(rep2, rep1)) return rep1; 59 // Handle the generalization of float64-representable values. 60 if (LessGeneral(rep1, TruncationKind::kFloat64) && 61 LessGeneral(rep2, TruncationKind::kFloat64)) { 62 return TruncationKind::kFloat64; 63 } 64 // Handle the generalization of any-representable values. 65 if (LessGeneral(rep1, TruncationKind::kAny) && 66 LessGeneral(rep2, TruncationKind::kAny)) { 67 return TruncationKind::kAny; 68 } 69 // All other combinations are illegal. 70 FATAL("Tried to combine incompatible truncations"); 71 return TruncationKind::kNone; 72 } 73 74 75 // static 76 bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) { 77 switch (rep1) { 78 case TruncationKind::kNone: 79 return true; 80 case TruncationKind::kBool: 81 return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny; 82 case TruncationKind::kWord32: 83 return rep2 == TruncationKind::kWord32 || 84 rep2 == TruncationKind::kWord64 || 85 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny; 86 case TruncationKind::kWord64: 87 return rep2 == TruncationKind::kWord64; 88 case TruncationKind::kFloat64: 89 return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny; 90 case TruncationKind::kAny: 91 return rep2 == TruncationKind::kAny; 92 } 93 UNREACHABLE(); 94 return false; 95 } 96 97 98 namespace { 99 100 bool IsWord(MachineRepresentation rep) { 101 return rep == MachineRepresentation::kWord8 || 102 rep == MachineRepresentation::kWord16 || 103 rep == MachineRepresentation::kWord32; 104 } 105 106 } // namespace 107 108 // Changes representation from {output_rep} to {use_rep}. The {truncation} 109 // parameter is only used for sanity checking - if the changer cannot figure 110 // out signedness for the word32->float64 conversion, then we check that the 111 // uses truncate to word32 (so they do not care about signedness). 112 Node* RepresentationChanger::GetRepresentationFor( 113 Node* node, MachineRepresentation output_rep, Type* output_type, 114 Node* use_node, UseInfo use_info) { 115 if (output_rep == MachineRepresentation::kNone && 116 output_type->IsInhabited()) { 117 // The output representation should be set if the type is inhabited (i.e., 118 // if the value is possible). 119 return TypeError(node, output_rep, output_type, use_info.representation()); 120 } 121 122 // Handle the no-op shortcuts when no checking is necessary. 123 if (use_info.type_check() == TypeCheckKind::kNone || 124 output_rep != MachineRepresentation::kWord32) { 125 if (use_info.representation() == output_rep) { 126 // Representations are the same. That's a no-op. 127 return node; 128 } 129 if (IsWord(use_info.representation()) && IsWord(output_rep)) { 130 // Both are words less than or equal to 32-bits. 131 // Since loads of integers from memory implicitly sign or zero extend the 132 // value to the full machine word size and stores implicitly truncate, 133 // no representation change is necessary. 134 return node; 135 } 136 } 137 138 switch (use_info.representation()) { 139 case MachineRepresentation::kTaggedSigned: 140 DCHECK(use_info.type_check() == TypeCheckKind::kNone || 141 use_info.type_check() == TypeCheckKind::kSignedSmall); 142 return GetTaggedSignedRepresentationFor(node, output_rep, output_type, 143 use_node, use_info); 144 case MachineRepresentation::kTaggedPointer: 145 DCHECK(use_info.type_check() == TypeCheckKind::kNone || 146 use_info.type_check() == TypeCheckKind::kHeapObject); 147 return GetTaggedPointerRepresentationFor(node, output_rep, output_type, 148 use_node, use_info); 149 case MachineRepresentation::kTagged: 150 DCHECK(use_info.type_check() == TypeCheckKind::kNone); 151 return GetTaggedRepresentationFor(node, output_rep, output_type, 152 use_info.truncation()); 153 case MachineRepresentation::kFloat32: 154 DCHECK(use_info.type_check() == TypeCheckKind::kNone); 155 return GetFloat32RepresentationFor(node, output_rep, output_type, 156 use_info.truncation()); 157 case MachineRepresentation::kFloat64: 158 return GetFloat64RepresentationFor(node, output_rep, output_type, 159 use_node, use_info); 160 case MachineRepresentation::kBit: 161 DCHECK(use_info.type_check() == TypeCheckKind::kNone); 162 return GetBitRepresentationFor(node, output_rep, output_type); 163 case MachineRepresentation::kWord8: 164 case MachineRepresentation::kWord16: 165 case MachineRepresentation::kWord32: 166 return GetWord32RepresentationFor(node, output_rep, output_type, use_node, 167 use_info); 168 case MachineRepresentation::kWord64: 169 DCHECK(use_info.type_check() == TypeCheckKind::kNone); 170 return GetWord64RepresentationFor(node, output_rep, output_type); 171 case MachineRepresentation::kSimd128: // Fall through. 172 // TODO(bbudge) Handle conversions between tagged and untagged. 173 break; 174 case MachineRepresentation::kNone: 175 return node; 176 } 177 UNREACHABLE(); 178 return nullptr; 179 } 180 181 Node* RepresentationChanger::GetTaggedSignedRepresentationFor( 182 Node* node, MachineRepresentation output_rep, Type* output_type, 183 Node* use_node, UseInfo use_info) { 184 // Eagerly fold representation changes for constants. 185 switch (node->opcode()) { 186 case IrOpcode::kNumberConstant: 187 if (output_type->Is(Type::SignedSmall())) { 188 return node; 189 } 190 break; 191 default: 192 break; 193 } 194 // Select the correct X -> Tagged operator. 195 const Operator* op; 196 if (output_type->Is(Type::None())) { 197 // This is an impossible value; it should not be used at runtime. 198 // We just provide a dummy value here. 199 return jsgraph()->Constant(0); 200 } else if (IsWord(output_rep)) { 201 if (output_type->Is(Type::Signed31())) { 202 op = simplified()->ChangeInt31ToTaggedSigned(); 203 } else if (output_type->Is(Type::Signed32())) { 204 if (SmiValuesAre32Bits()) { 205 op = simplified()->ChangeInt32ToTagged(); 206 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { 207 op = simplified()->CheckedInt32ToTaggedSigned(); 208 } else { 209 return TypeError(node, output_rep, output_type, 210 MachineRepresentation::kTaggedSigned); 211 } 212 } else if (output_type->Is(Type::Unsigned32()) && 213 use_info.type_check() == TypeCheckKind::kSignedSmall) { 214 op = simplified()->CheckedUint32ToTaggedSigned(); 215 } else { 216 return TypeError(node, output_rep, output_type, 217 MachineRepresentation::kTaggedSigned); 218 } 219 } else if (output_rep == MachineRepresentation::kFloat64) { 220 if (output_type->Is(Type::Signed31())) { 221 // float64 -> int32 -> tagged signed 222 node = InsertChangeFloat64ToInt32(node); 223 op = simplified()->ChangeInt31ToTaggedSigned(); 224 } else if (output_type->Is(Type::Signed32())) { 225 // float64 -> int32 -> tagged signed 226 node = InsertChangeFloat64ToInt32(node); 227 if (SmiValuesAre32Bits()) { 228 op = simplified()->ChangeInt32ToTagged(); 229 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { 230 op = simplified()->CheckedInt32ToTaggedSigned(); 231 } else { 232 return TypeError(node, output_rep, output_type, 233 MachineRepresentation::kTaggedSigned); 234 } 235 } else if (output_type->Is(Type::Unsigned32()) && 236 use_info.type_check() == TypeCheckKind::kSignedSmall) { 237 // float64 -> uint32 -> tagged signed 238 node = InsertChangeFloat64ToUint32(node); 239 op = simplified()->CheckedUint32ToTaggedSigned(); 240 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { 241 op = simplified()->CheckedFloat64ToInt32( 242 output_type->Maybe(Type::MinusZero()) 243 ? CheckForMinusZeroMode::kCheckForMinusZero 244 : CheckForMinusZeroMode::kDontCheckForMinusZero); 245 node = InsertConversion(node, op, use_node); 246 if (SmiValuesAre32Bits()) { 247 op = simplified()->ChangeInt32ToTagged(); 248 } else { 249 op = simplified()->CheckedInt32ToTaggedSigned(); 250 } 251 } else { 252 return TypeError(node, output_rep, output_type, 253 MachineRepresentation::kTaggedSigned); 254 } 255 } else if (output_rep == MachineRepresentation::kFloat32) { 256 if (use_info.type_check() == TypeCheckKind::kSignedSmall) { 257 op = machine()->ChangeFloat32ToFloat64(); 258 node = InsertConversion(node, op, use_node); 259 op = simplified()->CheckedFloat64ToInt32( 260 output_type->Maybe(Type::MinusZero()) 261 ? CheckForMinusZeroMode::kCheckForMinusZero 262 : CheckForMinusZeroMode::kDontCheckForMinusZero); 263 node = InsertConversion(node, op, use_node); 264 if (SmiValuesAre32Bits()) { 265 op = simplified()->ChangeInt32ToTagged(); 266 } else { 267 op = simplified()->CheckedInt32ToTaggedSigned(); 268 } 269 } else { 270 return TypeError(node, output_rep, output_type, 271 MachineRepresentation::kTaggedSigned); 272 } 273 } else if (CanBeTaggedPointer(output_rep) && 274 use_info.type_check() == TypeCheckKind::kSignedSmall) { 275 op = simplified()->CheckedTaggedToTaggedSigned(); 276 } else if (output_rep == MachineRepresentation::kBit && 277 use_info.type_check() == TypeCheckKind::kSignedSmall) { 278 // TODO(turbofan): Consider adding a Bailout operator that just deopts. 279 // Also use that for MachineRepresentation::kPointer case above. 280 node = InsertChangeBitToTagged(node); 281 op = simplified()->CheckedTaggedToTaggedSigned(); 282 } else { 283 return TypeError(node, output_rep, output_type, 284 MachineRepresentation::kTaggedSigned); 285 } 286 return InsertConversion(node, op, use_node); 287 } 288 289 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( 290 Node* node, MachineRepresentation output_rep, Type* output_type, 291 Node* use_node, UseInfo use_info) { 292 // Eagerly fold representation changes for constants. 293 switch (node->opcode()) { 294 case IrOpcode::kHeapConstant: 295 return node; // No change necessary. 296 case IrOpcode::kInt32Constant: 297 case IrOpcode::kFloat64Constant: 298 case IrOpcode::kFloat32Constant: 299 UNREACHABLE(); 300 default: 301 break; 302 } 303 // Select the correct X -> TaggedPointer operator. 304 Operator const* op; 305 if (output_type->Is(Type::None())) { 306 // This is an impossible value; it should not be used at runtime. 307 // We just provide a dummy value here. 308 return jsgraph()->TheHoleConstant(); 309 } else if (output_rep == MachineRepresentation::kBit) { 310 return node; 311 } else if (IsWord(output_rep)) { 312 if (output_type->Is(Type::Unsigned32())) { 313 // uint32 -> float64 -> tagged 314 node = InsertChangeUint32ToFloat64(node); 315 } else if (output_type->Is(Type::Signed32())) { 316 // int32 -> float64 -> tagged 317 node = InsertChangeInt32ToFloat64(node); 318 } else { 319 return TypeError(node, output_rep, output_type, 320 MachineRepresentation::kTaggedPointer); 321 } 322 op = simplified()->ChangeFloat64ToTaggedPointer(); 323 } else if (output_rep == MachineRepresentation::kFloat32) { 324 // float32 -> float64 -> tagged 325 node = InsertChangeFloat32ToFloat64(node); 326 op = simplified()->ChangeFloat64ToTaggedPointer(); 327 } else if (output_rep == MachineRepresentation::kFloat64) { 328 // float64 -> tagged 329 op = simplified()->ChangeFloat64ToTaggedPointer(); 330 } else if (CanBeTaggedSigned(output_rep) && 331 use_info.type_check() == TypeCheckKind::kHeapObject) { 332 if (!output_type->Maybe(Type::SignedSmall())) { 333 return node; 334 } 335 // TODO(turbofan): Consider adding a Bailout operator that just deopts 336 // for TaggedSigned output representation. 337 op = simplified()->CheckedTaggedToTaggedPointer(); 338 } else { 339 return TypeError(node, output_rep, output_type, 340 MachineRepresentation::kTaggedPointer); 341 } 342 return InsertConversion(node, op, use_node); 343 } 344 345 Node* RepresentationChanger::GetTaggedRepresentationFor( 346 Node* node, MachineRepresentation output_rep, Type* output_type, 347 Truncation truncation) { 348 // Eagerly fold representation changes for constants. 349 switch (node->opcode()) { 350 case IrOpcode::kNumberConstant: 351 case IrOpcode::kHeapConstant: 352 return node; // No change necessary. 353 case IrOpcode::kInt32Constant: 354 case IrOpcode::kFloat64Constant: 355 case IrOpcode::kFloat32Constant: 356 UNREACHABLE(); 357 break; 358 default: 359 break; 360 } 361 if (output_rep == MachineRepresentation::kTaggedSigned || 362 output_rep == MachineRepresentation::kTaggedPointer) { 363 // this is a no-op. 364 return node; 365 } 366 // Select the correct X -> Tagged operator. 367 const Operator* op; 368 if (output_type->Is(Type::None())) { 369 // This is an impossible value; it should not be used at runtime. 370 // We just provide a dummy value here. 371 return jsgraph()->TheHoleConstant(); 372 } else if (output_rep == MachineRepresentation::kBit) { 373 if (output_type->Is(Type::Boolean())) { 374 op = simplified()->ChangeBitToTagged(); 375 } else { 376 return TypeError(node, output_rep, output_type, 377 MachineRepresentation::kTagged); 378 } 379 } else if (IsWord(output_rep)) { 380 if (output_type->Is(Type::Signed31())) { 381 op = simplified()->ChangeInt31ToTaggedSigned(); 382 } else if (output_type->Is(Type::Signed32())) { 383 op = simplified()->ChangeInt32ToTagged(); 384 } else if (output_type->Is(Type::Unsigned32()) || 385 truncation.IsUsedAsWord32()) { 386 // Either the output is uint32 or the uses only care about the 387 // low 32 bits (so we can pick uint32 safely). 388 op = simplified()->ChangeUint32ToTagged(); 389 } else { 390 return TypeError(node, output_rep, output_type, 391 MachineRepresentation::kTagged); 392 } 393 } else if (output_rep == 394 MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged 395 node = InsertChangeFloat32ToFloat64(node); 396 op = simplified()->ChangeFloat64ToTagged(); 397 } else if (output_rep == MachineRepresentation::kFloat64) { 398 if (output_type->Is(Type::Signed31())) { // float64 -> int32 -> tagged 399 node = InsertChangeFloat64ToInt32(node); 400 op = simplified()->ChangeInt31ToTaggedSigned(); 401 } else if (output_type->Is( 402 Type::Signed32())) { // float64 -> int32 -> tagged 403 node = InsertChangeFloat64ToInt32(node); 404 op = simplified()->ChangeInt32ToTagged(); 405 } else if (output_type->Is( 406 Type::Unsigned32())) { // float64 -> uint32 -> tagged 407 node = InsertChangeFloat64ToUint32(node); 408 op = simplified()->ChangeUint32ToTagged(); 409 } else { 410 op = simplified()->ChangeFloat64ToTagged(); 411 } 412 } else { 413 return TypeError(node, output_rep, output_type, 414 MachineRepresentation::kTagged); 415 } 416 return jsgraph()->graph()->NewNode(op, node); 417 } 418 419 420 Node* RepresentationChanger::GetFloat32RepresentationFor( 421 Node* node, MachineRepresentation output_rep, Type* output_type, 422 Truncation truncation) { 423 // Eagerly fold representation changes for constants. 424 switch (node->opcode()) { 425 case IrOpcode::kNumberConstant: 426 return jsgraph()->Float32Constant( 427 DoubleToFloat32(OpParameter<double>(node))); 428 case IrOpcode::kInt32Constant: 429 case IrOpcode::kFloat64Constant: 430 case IrOpcode::kFloat32Constant: 431 UNREACHABLE(); 432 break; 433 default: 434 break; 435 } 436 // Select the correct X -> Float32 operator. 437 const Operator* op = nullptr; 438 if (output_type->Is(Type::None())) { 439 // This is an impossible value; it should not be used at runtime. 440 // We just provide a dummy value here. 441 return jsgraph()->Float32Constant(0.0f); 442 } else if (IsWord(output_rep)) { 443 if (output_type->Is(Type::Signed32())) { 444 // int32 -> float64 -> float32 445 op = machine()->ChangeInt32ToFloat64(); 446 node = jsgraph()->graph()->NewNode(op, node); 447 op = machine()->TruncateFloat64ToFloat32(); 448 } else if (output_type->Is(Type::Unsigned32()) || 449 truncation.IsUsedAsWord32()) { 450 // Either the output is uint32 or the uses only care about the 451 // low 32 bits (so we can pick uint32 safely). 452 453 // uint32 -> float64 -> float32 454 op = machine()->ChangeUint32ToFloat64(); 455 node = jsgraph()->graph()->NewNode(op, node); 456 op = machine()->TruncateFloat64ToFloat32(); 457 } 458 } else if (output_rep == MachineRepresentation::kTagged || 459 output_rep == MachineRepresentation::kTaggedPointer) { 460 if (output_type->Is(Type::NumberOrOddball())) { 461 // tagged -> float64 -> float32 462 if (output_type->Is(Type::Number())) { 463 op = simplified()->ChangeTaggedToFloat64(); 464 } else { 465 op = simplified()->TruncateTaggedToFloat64(); 466 } 467 node = jsgraph()->graph()->NewNode(op, node); 468 op = machine()->TruncateFloat64ToFloat32(); 469 } 470 } else if (output_rep == MachineRepresentation::kFloat64) { 471 op = machine()->TruncateFloat64ToFloat32(); 472 } 473 if (op == nullptr) { 474 return TypeError(node, output_rep, output_type, 475 MachineRepresentation::kFloat32); 476 } 477 return jsgraph()->graph()->NewNode(op, node); 478 } 479 480 Node* RepresentationChanger::GetFloat64RepresentationFor( 481 Node* node, MachineRepresentation output_rep, Type* output_type, 482 Node* use_node, UseInfo use_info) { 483 // Eagerly fold representation changes for constants. 484 if ((use_info.type_check() == TypeCheckKind::kNone)) { 485 // TODO(jarin) Handle checked constant conversions. 486 switch (node->opcode()) { 487 case IrOpcode::kNumberConstant: 488 return jsgraph()->Float64Constant(OpParameter<double>(node)); 489 case IrOpcode::kInt32Constant: 490 case IrOpcode::kFloat64Constant: 491 case IrOpcode::kFloat32Constant: 492 UNREACHABLE(); 493 break; 494 default: 495 break; 496 } 497 } 498 // Select the correct X -> Float64 operator. 499 const Operator* op = nullptr; 500 if (output_type->Is(Type::None())) { 501 // This is an impossible value; it should not be used at runtime. 502 // We just provide a dummy value here. 503 return jsgraph()->Float64Constant(0.0); 504 } else if (IsWord(output_rep)) { 505 if (output_type->Is(Type::Signed32())) { 506 op = machine()->ChangeInt32ToFloat64(); 507 } else if (output_type->Is(Type::Unsigned32()) || 508 use_info.truncation().IsUsedAsWord32()) { 509 // Either the output is uint32 or the uses only care about the 510 // low 32 bits (so we can pick uint32 safely). 511 op = machine()->ChangeUint32ToFloat64(); 512 } 513 } else if (output_rep == MachineRepresentation::kBit) { 514 op = machine()->ChangeUint32ToFloat64(); 515 } else if (output_rep == MachineRepresentation::kTagged || 516 output_rep == MachineRepresentation::kTaggedSigned || 517 output_rep == MachineRepresentation::kTaggedPointer) { 518 if (output_type->Is(Type::Undefined())) { 519 return jsgraph()->Float64Constant( 520 std::numeric_limits<double>::quiet_NaN()); 521 522 } else if (output_rep == MachineRepresentation::kTaggedSigned) { 523 node = InsertChangeTaggedSignedToInt32(node); 524 op = machine()->ChangeInt32ToFloat64(); 525 } else if (output_type->Is(Type::Number())) { 526 op = simplified()->ChangeTaggedToFloat64(); 527 } else if (output_type->Is(Type::NumberOrOddball())) { 528 // TODO(jarin) Here we should check that truncation is Number. 529 op = simplified()->TruncateTaggedToFloat64(); 530 } else if (use_info.type_check() == TypeCheckKind::kNumber || 531 (use_info.type_check() == TypeCheckKind::kNumberOrOddball && 532 !output_type->Maybe(Type::BooleanOrNullOrNumber()))) { 533 op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber); 534 } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) { 535 op = simplified()->CheckedTaggedToFloat64( 536 CheckTaggedInputMode::kNumberOrOddball); 537 } 538 } else if (output_rep == MachineRepresentation::kFloat32) { 539 op = machine()->ChangeFloat32ToFloat64(); 540 } 541 if (op == nullptr) { 542 return TypeError(node, output_rep, output_type, 543 MachineRepresentation::kFloat64); 544 } 545 return InsertConversion(node, op, use_node); 546 } 547 548 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { 549 return jsgraph()->Int32Constant(DoubleToInt32(value)); 550 } 551 552 Node* RepresentationChanger::GetWord32RepresentationFor( 553 Node* node, MachineRepresentation output_rep, Type* output_type, 554 Node* use_node, UseInfo use_info) { 555 // Eagerly fold representation changes for constants. 556 switch (node->opcode()) { 557 case IrOpcode::kInt32Constant: 558 case IrOpcode::kFloat32Constant: 559 case IrOpcode::kFloat64Constant: 560 UNREACHABLE(); 561 break; 562 case IrOpcode::kNumberConstant: { 563 double const fv = OpParameter<double>(node); 564 if (use_info.type_check() == TypeCheckKind::kNone || 565 ((use_info.type_check() == TypeCheckKind::kSignedSmall || 566 use_info.type_check() == TypeCheckKind::kSigned32) && 567 IsInt32Double(fv))) { 568 return MakeTruncatedInt32Constant(fv); 569 } 570 break; 571 } 572 default: 573 break; 574 } 575 576 // Select the correct X -> Word32 operator. 577 const Operator* op = nullptr; 578 if (output_type->Is(Type::None())) { 579 // This is an impossible value; it should not be used at runtime. 580 // We just provide a dummy value here. 581 return jsgraph()->Int32Constant(0); 582 } else if (output_rep == MachineRepresentation::kBit) { 583 return node; // Sloppy comparison -> word32 584 } else if (output_rep == MachineRepresentation::kFloat64) { 585 if (output_type->Is(Type::Unsigned32())) { 586 op = machine()->ChangeFloat64ToUint32(); 587 } else if (output_type->Is(Type::Signed32())) { 588 op = machine()->ChangeFloat64ToInt32(); 589 } else if (use_info.truncation().IsUsedAsWord32()) { 590 op = machine()->TruncateFloat64ToWord32(); 591 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || 592 use_info.type_check() == TypeCheckKind::kSigned32) { 593 op = simplified()->CheckedFloat64ToInt32( 594 output_type->Maybe(Type::MinusZero()) 595 ? use_info.minus_zero_check() 596 : CheckForMinusZeroMode::kDontCheckForMinusZero); 597 } 598 } else if (output_rep == MachineRepresentation::kFloat32) { 599 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 600 if (output_type->Is(Type::Unsigned32())) { 601 op = machine()->ChangeFloat64ToUint32(); 602 } else if (output_type->Is(Type::Signed32())) { 603 op = machine()->ChangeFloat64ToInt32(); 604 } else if (use_info.truncation().IsUsedAsWord32()) { 605 op = machine()->TruncateFloat64ToWord32(); 606 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || 607 use_info.type_check() == TypeCheckKind::kSigned32) { 608 op = simplified()->CheckedFloat64ToInt32( 609 output_type->Maybe(Type::MinusZero()) 610 ? CheckForMinusZeroMode::kCheckForMinusZero 611 : CheckForMinusZeroMode::kDontCheckForMinusZero); 612 } 613 } else if (output_rep == MachineRepresentation::kTaggedSigned) { 614 if (output_type->Is(Type::Signed32())) { 615 op = simplified()->ChangeTaggedSignedToInt32(); 616 } else if (use_info.truncation().IsUsedAsWord32()) { 617 if (use_info.type_check() != TypeCheckKind::kNone) { 618 op = simplified()->CheckedTruncateTaggedToWord32(); 619 } else { 620 op = simplified()->TruncateTaggedToWord32(); 621 } 622 } 623 } else if (output_rep == MachineRepresentation::kTagged || 624 output_rep == MachineRepresentation::kTaggedPointer) { 625 if (output_type->Is(Type::Unsigned32())) { 626 op = simplified()->ChangeTaggedToUint32(); 627 } else if (output_type->Is(Type::Signed32())) { 628 op = simplified()->ChangeTaggedToInt32(); 629 } else if (use_info.truncation().IsUsedAsWord32()) { 630 if (use_info.type_check() != TypeCheckKind::kNone) { 631 op = simplified()->CheckedTruncateTaggedToWord32(); 632 } else { 633 op = simplified()->TruncateTaggedToWord32(); 634 } 635 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { 636 op = simplified()->CheckedTaggedSignedToInt32(); 637 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { 638 op = simplified()->CheckedTaggedToInt32( 639 output_type->Maybe(Type::MinusZero()) 640 ? CheckForMinusZeroMode::kCheckForMinusZero 641 : CheckForMinusZeroMode::kDontCheckForMinusZero); 642 } 643 } else if (output_rep == MachineRepresentation::kWord32) { 644 // Only the checked case should get here, the non-checked case is 645 // handled in GetRepresentationFor. 646 if (use_info.type_check() == TypeCheckKind::kSignedSmall || 647 use_info.type_check() == TypeCheckKind::kSigned32) { 648 if (output_type->Is(Type::Signed32())) { 649 return node; 650 } else if (output_type->Is(Type::Unsigned32())) { 651 op = simplified()->CheckedUint32ToInt32(); 652 } 653 } else { 654 DCHECK_EQ(TypeCheckKind::kNumberOrOddball, use_info.type_check()); 655 return node; 656 } 657 } else if (output_rep == MachineRepresentation::kWord8 || 658 output_rep == MachineRepresentation::kWord16) { 659 DCHECK(use_info.representation() == MachineRepresentation::kWord32); 660 DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall || 661 use_info.type_check() == TypeCheckKind::kSigned32); 662 return node; 663 } 664 665 if (op == nullptr) { 666 return TypeError(node, output_rep, output_type, 667 MachineRepresentation::kWord32); 668 } 669 return InsertConversion(node, op, use_node); 670 } 671 672 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op, 673 Node* use_node) { 674 if (op->ControlInputCount() > 0) { 675 // If the operator can deoptimize (which means it has control 676 // input), we need to connect it to the effect and control chains. 677 Node* effect = NodeProperties::GetEffectInput(use_node); 678 Node* control = NodeProperties::GetControlInput(use_node); 679 Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control); 680 NodeProperties::ReplaceEffectInput(use_node, conversion); 681 return conversion; 682 } 683 return jsgraph()->graph()->NewNode(op, node); 684 } 685 686 687 Node* RepresentationChanger::GetBitRepresentationFor( 688 Node* node, MachineRepresentation output_rep, Type* output_type) { 689 // Eagerly fold representation changes for constants. 690 switch (node->opcode()) { 691 case IrOpcode::kHeapConstant: { 692 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); 693 return jsgraph()->Int32Constant(value->BooleanValue() ? 1 : 0); 694 } 695 default: 696 break; 697 } 698 // Select the correct X -> Bit operator. 699 const Operator* op; 700 if (output_type->Is(Type::None())) { 701 // This is an impossible value; it should not be used at runtime. 702 // We just provide a dummy value here. 703 return jsgraph()->Int32Constant(0); 704 } else if (output_rep == MachineRepresentation::kTagged || 705 output_rep == MachineRepresentation::kTaggedPointer) { 706 if (output_type->Is(Type::BooleanOrNullOrUndefined())) { 707 // true is the only trueish Oddball. 708 op = simplified()->ChangeTaggedToBit(); 709 } else { 710 op = simplified()->TruncateTaggedToBit(); 711 } 712 } else if (output_rep == MachineRepresentation::kTaggedSigned) { 713 node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node, 714 jsgraph()->IntPtrConstant(0)); 715 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node, 716 jsgraph()->Int32Constant(0)); 717 } else if (IsWord(output_rep)) { 718 node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node, 719 jsgraph()->Int32Constant(0)); 720 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node, 721 jsgraph()->Int32Constant(0)); 722 } else if (output_rep == MachineRepresentation::kFloat32) { 723 node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node); 724 return jsgraph()->graph()->NewNode(machine()->Float32LessThan(), 725 jsgraph()->Float32Constant(0.0), node); 726 } else if (output_rep == MachineRepresentation::kFloat64) { 727 node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node); 728 return jsgraph()->graph()->NewNode(machine()->Float64LessThan(), 729 jsgraph()->Float64Constant(0.0), node); 730 } else { 731 return TypeError(node, output_rep, output_type, 732 MachineRepresentation::kBit); 733 } 734 return jsgraph()->graph()->NewNode(op, node); 735 } 736 737 Node* RepresentationChanger::GetWord64RepresentationFor( 738 Node* node, MachineRepresentation output_rep, Type* output_type) { 739 if (output_type->Is(Type::None())) { 740 // This is an impossible value; it should not be used at runtime. 741 // We just provide a dummy value here. 742 return jsgraph()->Int64Constant(0); 743 } else if (output_rep == MachineRepresentation::kBit) { 744 return node; // Sloppy comparison -> word64 745 } 746 // Can't really convert Word64 to anything else. Purported to be internal. 747 return TypeError(node, output_rep, output_type, 748 MachineRepresentation::kWord64); 749 } 750 751 const Operator* RepresentationChanger::Int32OperatorFor( 752 IrOpcode::Value opcode) { 753 switch (opcode) { 754 case IrOpcode::kSpeculativeNumberAdd: // Fall through. 755 case IrOpcode::kNumberAdd: 756 return machine()->Int32Add(); 757 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. 758 case IrOpcode::kNumberSubtract: 759 return machine()->Int32Sub(); 760 case IrOpcode::kSpeculativeNumberMultiply: 761 case IrOpcode::kNumberMultiply: 762 return machine()->Int32Mul(); 763 case IrOpcode::kSpeculativeNumberDivide: 764 case IrOpcode::kNumberDivide: 765 return machine()->Int32Div(); 766 case IrOpcode::kSpeculativeNumberModulus: 767 case IrOpcode::kNumberModulus: 768 return machine()->Int32Mod(); 769 case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through. 770 case IrOpcode::kNumberBitwiseOr: 771 return machine()->Word32Or(); 772 case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through. 773 case IrOpcode::kNumberBitwiseXor: 774 return machine()->Word32Xor(); 775 case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through. 776 case IrOpcode::kNumberBitwiseAnd: 777 return machine()->Word32And(); 778 case IrOpcode::kNumberEqual: 779 case IrOpcode::kSpeculativeNumberEqual: 780 return machine()->Word32Equal(); 781 case IrOpcode::kNumberLessThan: 782 case IrOpcode::kSpeculativeNumberLessThan: 783 return machine()->Int32LessThan(); 784 case IrOpcode::kNumberLessThanOrEqual: 785 case IrOpcode::kSpeculativeNumberLessThanOrEqual: 786 return machine()->Int32LessThanOrEqual(); 787 default: 788 UNREACHABLE(); 789 return nullptr; 790 } 791 } 792 793 const Operator* RepresentationChanger::Int32OverflowOperatorFor( 794 IrOpcode::Value opcode) { 795 switch (opcode) { 796 case IrOpcode::kSpeculativeNumberAdd: 797 return simplified()->CheckedInt32Add(); 798 case IrOpcode::kSpeculativeNumberSubtract: 799 return simplified()->CheckedInt32Sub(); 800 case IrOpcode::kSpeculativeNumberDivide: 801 return simplified()->CheckedInt32Div(); 802 case IrOpcode::kSpeculativeNumberModulus: 803 return simplified()->CheckedInt32Mod(); 804 default: 805 UNREACHABLE(); 806 return nullptr; 807 } 808 } 809 810 const Operator* RepresentationChanger::Uint32OperatorFor( 811 IrOpcode::Value opcode) { 812 switch (opcode) { 813 case IrOpcode::kNumberAdd: 814 return machine()->Int32Add(); 815 case IrOpcode::kNumberSubtract: 816 return machine()->Int32Sub(); 817 case IrOpcode::kSpeculativeNumberMultiply: 818 case IrOpcode::kNumberMultiply: 819 return machine()->Int32Mul(); 820 case IrOpcode::kSpeculativeNumberDivide: 821 case IrOpcode::kNumberDivide: 822 return machine()->Uint32Div(); 823 case IrOpcode::kSpeculativeNumberModulus: 824 case IrOpcode::kNumberModulus: 825 return machine()->Uint32Mod(); 826 case IrOpcode::kNumberEqual: 827 case IrOpcode::kSpeculativeNumberEqual: 828 return machine()->Word32Equal(); 829 case IrOpcode::kNumberLessThan: 830 case IrOpcode::kSpeculativeNumberLessThan: 831 return machine()->Uint32LessThan(); 832 case IrOpcode::kNumberLessThanOrEqual: 833 case IrOpcode::kSpeculativeNumberLessThanOrEqual: 834 return machine()->Uint32LessThanOrEqual(); 835 case IrOpcode::kNumberClz32: 836 return machine()->Word32Clz(); 837 case IrOpcode::kNumberImul: 838 return machine()->Int32Mul(); 839 default: 840 UNREACHABLE(); 841 return nullptr; 842 } 843 } 844 845 const Operator* RepresentationChanger::Uint32OverflowOperatorFor( 846 IrOpcode::Value opcode) { 847 switch (opcode) { 848 case IrOpcode::kSpeculativeNumberDivide: 849 return simplified()->CheckedUint32Div(); 850 case IrOpcode::kSpeculativeNumberModulus: 851 return simplified()->CheckedUint32Mod(); 852 default: 853 UNREACHABLE(); 854 return nullptr; 855 } 856 } 857 858 const Operator* RepresentationChanger::Float64OperatorFor( 859 IrOpcode::Value opcode) { 860 switch (opcode) { 861 case IrOpcode::kSpeculativeNumberAdd: 862 case IrOpcode::kNumberAdd: 863 return machine()->Float64Add(); 864 case IrOpcode::kSpeculativeNumberSubtract: 865 case IrOpcode::kNumberSubtract: 866 return machine()->Float64Sub(); 867 case IrOpcode::kSpeculativeNumberMultiply: 868 case IrOpcode::kNumberMultiply: 869 return machine()->Float64Mul(); 870 case IrOpcode::kSpeculativeNumberDivide: 871 case IrOpcode::kNumberDivide: 872 return machine()->Float64Div(); 873 case IrOpcode::kSpeculativeNumberModulus: 874 case IrOpcode::kNumberModulus: 875 return machine()->Float64Mod(); 876 case IrOpcode::kNumberEqual: 877 case IrOpcode::kSpeculativeNumberEqual: 878 return machine()->Float64Equal(); 879 case IrOpcode::kNumberLessThan: 880 case IrOpcode::kSpeculativeNumberLessThan: 881 return machine()->Float64LessThan(); 882 case IrOpcode::kNumberLessThanOrEqual: 883 case IrOpcode::kSpeculativeNumberLessThanOrEqual: 884 return machine()->Float64LessThanOrEqual(); 885 case IrOpcode::kNumberAbs: 886 return machine()->Float64Abs(); 887 case IrOpcode::kNumberAcos: 888 return machine()->Float64Acos(); 889 case IrOpcode::kNumberAcosh: 890 return machine()->Float64Acosh(); 891 case IrOpcode::kNumberAsin: 892 return machine()->Float64Asin(); 893 case IrOpcode::kNumberAsinh: 894 return machine()->Float64Asinh(); 895 case IrOpcode::kNumberAtan: 896 return machine()->Float64Atan(); 897 case IrOpcode::kNumberAtanh: 898 return machine()->Float64Atanh(); 899 case IrOpcode::kNumberAtan2: 900 return machine()->Float64Atan2(); 901 case IrOpcode::kNumberCbrt: 902 return machine()->Float64Cbrt(); 903 case IrOpcode::kNumberCeil: 904 return machine()->Float64RoundUp().placeholder(); 905 case IrOpcode::kNumberCos: 906 return machine()->Float64Cos(); 907 case IrOpcode::kNumberCosh: 908 return machine()->Float64Cosh(); 909 case IrOpcode::kNumberExp: 910 return machine()->Float64Exp(); 911 case IrOpcode::kNumberExpm1: 912 return machine()->Float64Expm1(); 913 case IrOpcode::kNumberFloor: 914 return machine()->Float64RoundDown().placeholder(); 915 case IrOpcode::kNumberFround: 916 return machine()->TruncateFloat64ToFloat32(); 917 case IrOpcode::kNumberLog: 918 return machine()->Float64Log(); 919 case IrOpcode::kNumberLog1p: 920 return machine()->Float64Log1p(); 921 case IrOpcode::kNumberLog2: 922 return machine()->Float64Log2(); 923 case IrOpcode::kNumberLog10: 924 return machine()->Float64Log10(); 925 case IrOpcode::kNumberMax: 926 return machine()->Float64Max(); 927 case IrOpcode::kNumberMin: 928 return machine()->Float64Min(); 929 case IrOpcode::kNumberPow: 930 return machine()->Float64Pow(); 931 case IrOpcode::kNumberSin: 932 return machine()->Float64Sin(); 933 case IrOpcode::kNumberSinh: 934 return machine()->Float64Sinh(); 935 case IrOpcode::kNumberSqrt: 936 return machine()->Float64Sqrt(); 937 case IrOpcode::kNumberTan: 938 return machine()->Float64Tan(); 939 case IrOpcode::kNumberTanh: 940 return machine()->Float64Tanh(); 941 case IrOpcode::kNumberTrunc: 942 return machine()->Float64RoundTruncate().placeholder(); 943 case IrOpcode::kNumberSilenceNaN: 944 return machine()->Float64SilenceNaN(); 945 default: 946 UNREACHABLE(); 947 return nullptr; 948 } 949 } 950 951 952 Node* RepresentationChanger::TypeError(Node* node, 953 MachineRepresentation output_rep, 954 Type* output_type, 955 MachineRepresentation use) { 956 type_error_ = true; 957 if (!testing_type_errors_) { 958 std::ostringstream out_str; 959 out_str << output_rep << " ("; 960 output_type->PrintTo(out_str); 961 out_str << ")"; 962 963 std::ostringstream use_str; 964 use_str << use; 965 966 V8_Fatal(__FILE__, __LINE__, 967 "RepresentationChangerError: node #%d:%s of " 968 "%s cannot be changed to %s", 969 node->id(), node->op()->mnemonic(), out_str.str().c_str(), 970 use_str.str().c_str()); 971 } 972 return node; 973 } 974 975 Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) { 976 return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node); 977 } 978 979 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) { 980 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); 981 } 982 983 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) { 984 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node); 985 } 986 987 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) { 988 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node); 989 } 990 991 Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) { 992 return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node); 993 } 994 995 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) { 996 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), 997 node); 998 } 999 1000 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { 1001 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), 1002 node); 1003 } 1004 1005 Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) { 1006 return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node); 1007 } 1008 1009 } // namespace compiler 1010 } // namespace internal 1011 } // namespace v8 1012