Home | History | Annotate | Download | only in compiler
      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