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