Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 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 <limits>
      6 
      7 #include "test/cctest/cctest.h"
      8 #include "test/cctest/compiler/codegen-tester.h"
      9 #include "test/cctest/compiler/graph-builder-tester.h"
     10 #include "test/cctest/compiler/value-helper.h"
     11 
     12 #include "src/compiler/node-matchers.h"
     13 #include "src/compiler/representation-change.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 namespace compiler {
     18 
     19 class RepresentationChangerTester : public HandleAndZoneScope,
     20                                     public GraphAndBuilders {
     21  public:
     22   explicit RepresentationChangerTester(int num_parameters = 0)
     23       : GraphAndBuilders(main_zone()),
     24         javascript_(main_zone()),
     25         jsgraph_(main_isolate(), main_graph_, &main_common_, &javascript_,
     26                  &main_simplified_, &main_machine_),
     27         changer_(&jsgraph_, main_isolate()) {
     28     Node* s = graph()->NewNode(common()->Start(num_parameters));
     29     graph()->SetStart(s);
     30   }
     31 
     32   JSOperatorBuilder javascript_;
     33   JSGraph jsgraph_;
     34   RepresentationChanger changer_;
     35 
     36   Isolate* isolate() { return main_isolate(); }
     37   Graph* graph() { return main_graph_; }
     38   CommonOperatorBuilder* common() { return &main_common_; }
     39   JSGraph* jsgraph() { return &jsgraph_; }
     40   RepresentationChanger* changer() { return &changer_; }
     41 
     42   // TODO(titzer): use ValueChecker / ValueUtil
     43   void CheckInt32Constant(Node* n, int32_t expected) {
     44     Int32Matcher m(n);
     45     CHECK(m.HasValue());
     46     CHECK_EQ(expected, m.Value());
     47   }
     48 
     49   void CheckUint32Constant(Node* n, uint32_t expected) {
     50     Uint32Matcher m(n);
     51     CHECK(m.HasValue());
     52     CHECK_EQ(static_cast<int>(expected), static_cast<int>(m.Value()));
     53   }
     54 
     55   void CheckFloat64Constant(Node* n, double expected) {
     56     Float64Matcher m(n);
     57     CHECK(m.HasValue());
     58     CHECK_DOUBLE_EQ(expected, m.Value());
     59   }
     60 
     61   void CheckFloat32Constant(Node* n, float expected) {
     62     CHECK_EQ(IrOpcode::kFloat32Constant, n->opcode());
     63     float fval = OpParameter<float>(n->op());
     64     CHECK_FLOAT_EQ(expected, fval);
     65   }
     66 
     67   void CheckHeapConstant(Node* n, HeapObject* expected) {
     68     HeapObjectMatcher m(n);
     69     CHECK(m.HasValue());
     70     CHECK_EQ(expected, *m.Value());
     71   }
     72 
     73   void CheckNumberConstant(Node* n, double expected) {
     74     NumberMatcher m(n);
     75     CHECK_EQ(IrOpcode::kNumberConstant, n->opcode());
     76     CHECK(m.HasValue());
     77     CHECK_DOUBLE_EQ(expected, m.Value());
     78   }
     79 
     80   Node* Parameter(int index = 0) {
     81     Node* n = graph()->NewNode(common()->Parameter(index), graph()->start());
     82     NodeProperties::SetType(n, Type::Any());
     83     return n;
     84   }
     85 
     86   Node* Return(Node* input) {
     87     Node* n = graph()->NewNode(common()->Return(), input, graph()->start(),
     88                                graph()->start());
     89     return n;
     90   }
     91 
     92   void CheckTypeError(MachineRepresentation from, Type* from_type,
     93                       MachineRepresentation to) {
     94     changer()->testing_type_errors_ = true;
     95     changer()->type_error_ = false;
     96     Node* n = Parameter(0);
     97     Node* use = Return(n);
     98     Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
     99                                               UseInfo(to, Truncation::None()));
    100     CHECK(changer()->type_error_);
    101     CHECK_EQ(n, c);
    102   }
    103 
    104   void CheckNop(MachineRepresentation from, Type* from_type,
    105                 MachineRepresentation to) {
    106     Node* n = Parameter(0);
    107     Node* use = Return(n);
    108     Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
    109                                               UseInfo(to, Truncation::None()));
    110     CHECK_EQ(n, c);
    111   }
    112 };
    113 
    114 
    115 const MachineType kMachineTypes[] = {
    116     MachineType::Float32(), MachineType::Float64(),  MachineType::Int8(),
    117     MachineType::Uint8(),   MachineType::Int16(),    MachineType::Uint16(),
    118     MachineType::Int32(),   MachineType::Uint32(),   MachineType::Int64(),
    119     MachineType::Uint64(),  MachineType::AnyTagged()};
    120 
    121 
    122 TEST(BoolToBit_constant) {
    123   RepresentationChangerTester r;
    124 
    125   Node* true_node = r.jsgraph()->TrueConstant();
    126   Node* true_use = r.Return(true_node);
    127   Node* true_bit = r.changer()->GetRepresentationFor(
    128       true_node, MachineRepresentation::kTagged, Type::None(), true_use,
    129       UseInfo(MachineRepresentation::kBit, Truncation::None()));
    130   r.CheckInt32Constant(true_bit, 1);
    131 
    132   Node* false_node = r.jsgraph()->FalseConstant();
    133   Node* false_use = r.Return(false_node);
    134   Node* false_bit = r.changer()->GetRepresentationFor(
    135       false_node, MachineRepresentation::kTagged, Type::None(), false_use,
    136       UseInfo(MachineRepresentation::kBit, Truncation::None()));
    137   r.CheckInt32Constant(false_bit, 0);
    138 }
    139 
    140 
    141 TEST(BitToBool_constant) {
    142   RepresentationChangerTester r;
    143 
    144   for (int i = -5; i < 5; i++) {
    145     Node* node = r.jsgraph()->Int32Constant(i);
    146     Node* use = r.Return(node);
    147     Node* val = r.changer()->GetRepresentationFor(
    148         node, MachineRepresentation::kBit, Type::Boolean(), use,
    149         UseInfo(MachineRepresentation::kTagged, Truncation::None()));
    150     r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value()
    151                                     : r.isolate()->heap()->true_value());
    152   }
    153 }
    154 
    155 
    156 TEST(ToTagged_constant) {
    157   RepresentationChangerTester r;
    158 
    159   {
    160     FOR_FLOAT64_INPUTS(i) {
    161       Node* n = r.jsgraph()->Float64Constant(*i);
    162   Node* use = r.Return(n);
    163   Node* c = r.changer()->GetRepresentationFor(
    164       n, MachineRepresentation::kFloat64, Type::None(), use,
    165       UseInfo(MachineRepresentation::kTagged, Truncation::None()));
    166   r.CheckNumberConstant(c, *i);
    167     }
    168   }
    169 
    170   {
    171     FOR_FLOAT64_INPUTS(i) {
    172       Node* n = r.jsgraph()->Constant(*i);
    173   Node* use = r.Return(n);
    174   Node* c = r.changer()->GetRepresentationFor(
    175       n, MachineRepresentation::kFloat64, Type::None(), use,
    176       UseInfo(MachineRepresentation::kTagged, Truncation::None()));
    177   r.CheckNumberConstant(c, *i);
    178     }
    179   }
    180 
    181   {
    182     FOR_FLOAT32_INPUTS(i) {
    183       Node* n = r.jsgraph()->Float32Constant(*i);
    184   Node* use = r.Return(n);
    185   Node* c = r.changer()->GetRepresentationFor(
    186       n, MachineRepresentation::kFloat32, Type::None(), use,
    187       UseInfo(MachineRepresentation::kTagged, Truncation::None()));
    188   r.CheckNumberConstant(c, *i);
    189     }
    190   }
    191 
    192   {
    193     FOR_INT32_INPUTS(i) {
    194       Node* n = r.jsgraph()->Int32Constant(*i);
    195   Node* use = r.Return(n);
    196   Node* c = r.changer()->GetRepresentationFor(
    197       n, MachineRepresentation::kWord32, Type::Signed32(), use,
    198       UseInfo(MachineRepresentation::kTagged, Truncation::None()));
    199   r.CheckNumberConstant(c, *i);
    200     }
    201   }
    202 
    203   {
    204     FOR_UINT32_INPUTS(i) {
    205       Node* n = r.jsgraph()->Int32Constant(*i);
    206       Node* use = r.Return(n);
    207       Node* c = r.changer()->GetRepresentationFor(
    208           n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
    209           UseInfo(MachineRepresentation::kTagged, Truncation::None()));
    210       r.CheckNumberConstant(c, *i);
    211     }
    212   }
    213 }
    214 
    215 
    216 TEST(ToFloat64_constant) {
    217   RepresentationChangerTester r;
    218 
    219   {
    220     FOR_FLOAT64_INPUTS(i) {
    221       Node* n = r.jsgraph()->Float64Constant(*i);
    222   Node* use = r.Return(n);
    223   Node* c = r.changer()->GetRepresentationFor(
    224       n, MachineRepresentation::kFloat64, Type::None(), use,
    225       UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
    226   CHECK_EQ(n, c);
    227     }
    228   }
    229 
    230   {
    231     FOR_FLOAT64_INPUTS(i) {
    232       Node* n = r.jsgraph()->Constant(*i);
    233   Node* use = r.Return(n);
    234   Node* c = r.changer()->GetRepresentationFor(
    235       n, MachineRepresentation::kTagged, Type::None(), use,
    236       UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
    237   r.CheckFloat64Constant(c, *i);
    238     }
    239   }
    240 
    241   {
    242     FOR_FLOAT32_INPUTS(i) {
    243       Node* n = r.jsgraph()->Float32Constant(*i);
    244   Node* use = r.Return(n);
    245   Node* c = r.changer()->GetRepresentationFor(
    246       n, MachineRepresentation::kFloat32, Type::None(), use,
    247       UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
    248   r.CheckFloat64Constant(c, *i);
    249     }
    250   }
    251 
    252   {
    253     FOR_INT32_INPUTS(i) {
    254       Node* n = r.jsgraph()->Int32Constant(*i);
    255   Node* use = r.Return(n);
    256   Node* c = r.changer()->GetRepresentationFor(
    257       n, MachineRepresentation::kWord32, Type::Signed32(), use,
    258       UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
    259   r.CheckFloat64Constant(c, *i);
    260     }
    261   }
    262 
    263   {
    264     FOR_UINT32_INPUTS(i) {
    265       Node* n = r.jsgraph()->Int32Constant(*i);
    266       Node* use = r.Return(n);
    267       Node* c = r.changer()->GetRepresentationFor(
    268           n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
    269           UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
    270       r.CheckFloat64Constant(c, *i);
    271     }
    272   }
    273 }
    274 
    275 
    276 static bool IsFloat32Int32(int32_t val) {
    277   return val >= -(1 << 23) && val <= (1 << 23);
    278 }
    279 
    280 
    281 static bool IsFloat32Uint32(uint32_t val) { return val <= (1 << 23); }
    282 
    283 
    284 TEST(ToFloat32_constant) {
    285   RepresentationChangerTester r;
    286 
    287   {
    288     FOR_FLOAT32_INPUTS(i) {
    289       Node* n = r.jsgraph()->Float32Constant(*i);
    290   Node* use = r.Return(n);
    291   Node* c = r.changer()->GetRepresentationFor(
    292       n, MachineRepresentation::kFloat32, Type::None(), use,
    293       UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
    294   CHECK_EQ(n, c);
    295     }
    296   }
    297 
    298   {
    299     FOR_FLOAT32_INPUTS(i) {
    300       Node* n = r.jsgraph()->Constant(*i);
    301   Node* use = r.Return(n);
    302   Node* c = r.changer()->GetRepresentationFor(
    303       n, MachineRepresentation::kTagged, Type::None(), use,
    304       UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
    305   r.CheckFloat32Constant(c, *i);
    306     }
    307   }
    308 
    309   {
    310     FOR_FLOAT32_INPUTS(i) {
    311       Node* n = r.jsgraph()->Float64Constant(*i);
    312   Node* use = r.Return(n);
    313   Node* c = r.changer()->GetRepresentationFor(
    314       n, MachineRepresentation::kFloat64, Type::None(), use,
    315       UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
    316   r.CheckFloat32Constant(c, *i);
    317     }
    318   }
    319 
    320   {
    321     FOR_INT32_INPUTS(i) {
    322       if (!IsFloat32Int32(*i)) continue;
    323       Node* n = r.jsgraph()->Int32Constant(*i);
    324       Node* use = r.Return(n);
    325       Node* c = r.changer()->GetRepresentationFor(
    326           n, MachineRepresentation::kWord32, Type::Signed32(), use,
    327           UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
    328       r.CheckFloat32Constant(c, static_cast<float>(*i));
    329     }
    330   }
    331 
    332   {
    333     FOR_UINT32_INPUTS(i) {
    334       if (!IsFloat32Uint32(*i)) continue;
    335       Node* n = r.jsgraph()->Int32Constant(*i);
    336       Node* use = r.Return(n);
    337       Node* c = r.changer()->GetRepresentationFor(
    338           n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
    339           UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
    340       r.CheckFloat32Constant(c, static_cast<float>(*i));
    341     }
    342   }
    343 }
    344 
    345 
    346 TEST(ToInt32_constant) {
    347   RepresentationChangerTester r;
    348 
    349   {
    350     FOR_INT32_INPUTS(i) {
    351       Node* n = r.jsgraph()->Int32Constant(*i);
    352   Node* use = r.Return(n);
    353   Node* c = r.changer()->GetRepresentationFor(
    354       n, MachineRepresentation::kWord32, Type::Signed32(), use,
    355       UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    356   r.CheckInt32Constant(c, *i);
    357     }
    358   }
    359 
    360   {
    361     FOR_INT32_INPUTS(i) {
    362       if (!IsFloat32Int32(*i)) continue;
    363       Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
    364       Node* use = r.Return(n);
    365       Node* c = r.changer()->GetRepresentationFor(
    366           n, MachineRepresentation::kFloat32, Type::Signed32(), use,
    367           UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    368       r.CheckInt32Constant(c, *i);
    369     }
    370   }
    371 
    372   {
    373     FOR_INT32_INPUTS(i) {
    374       Node* n = r.jsgraph()->Float64Constant(*i);
    375   Node* use = r.Return(n);
    376   Node* c = r.changer()->GetRepresentationFor(
    377       n, MachineRepresentation::kFloat64, Type::Signed32(), use,
    378       UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    379   r.CheckInt32Constant(c, *i);
    380     }
    381   }
    382 
    383   {
    384     FOR_INT32_INPUTS(i) {
    385       Node* n = r.jsgraph()->Constant(*i);
    386       Node* use = r.Return(n);
    387       Node* c = r.changer()->GetRepresentationFor(
    388           n, MachineRepresentation::kTagged, Type::Signed32(), use,
    389           UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    390       r.CheckInt32Constant(c, *i);
    391     }
    392   }
    393 }
    394 
    395 
    396 TEST(ToUint32_constant) {
    397   RepresentationChangerTester r;
    398 
    399   {
    400     FOR_UINT32_INPUTS(i) {
    401       Node* n = r.jsgraph()->Int32Constant(*i);
    402   Node* use = r.Return(n);
    403   Node* c = r.changer()->GetRepresentationFor(
    404       n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
    405       UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    406   r.CheckUint32Constant(c, *i);
    407     }
    408   }
    409 
    410   {
    411     FOR_UINT32_INPUTS(i) {
    412       if (!IsFloat32Uint32(*i)) continue;
    413       Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
    414       Node* use = r.Return(n);
    415       Node* c = r.changer()->GetRepresentationFor(
    416           n, MachineRepresentation::kFloat32, Type::Unsigned32(), use,
    417           UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    418       r.CheckUint32Constant(c, *i);
    419     }
    420   }
    421 
    422   {
    423     FOR_UINT32_INPUTS(i) {
    424       Node* n = r.jsgraph()->Float64Constant(*i);
    425   Node* use = r.Return(n);
    426   Node* c = r.changer()->GetRepresentationFor(
    427       n, MachineRepresentation::kFloat64, Type::Unsigned32(), use,
    428       UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    429   r.CheckUint32Constant(c, *i);
    430     }
    431   }
    432 
    433   {
    434     FOR_UINT32_INPUTS(i) {
    435       Node* n = r.jsgraph()->Constant(static_cast<double>(*i));
    436       Node* use = r.Return(n);
    437       Node* c = r.changer()->GetRepresentationFor(
    438           n, MachineRepresentation::kTagged, Type::Unsigned32(), use,
    439           UseInfo(MachineRepresentation::kWord32, Truncation::None()));
    440       r.CheckUint32Constant(c, *i);
    441     }
    442   }
    443 }
    444 
    445 
    446 static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
    447                         Type* from_type, MachineRepresentation to) {
    448   RepresentationChangerTester r;
    449 
    450   Node* n = r.Parameter();
    451   Node* use = r.Return(n);
    452   Node* c = r.changer()->GetRepresentationFor(n, from, from_type, use,
    453                                               UseInfo(to, Truncation::None()));
    454 
    455   CHECK_NE(c, n);
    456   CHECK_EQ(expected, c->opcode());
    457   CHECK_EQ(n, c->InputAt(0));
    458 }
    459 
    460 
    461 static void CheckTwoChanges(IrOpcode::Value expected2,
    462                             IrOpcode::Value expected1,
    463                             MachineRepresentation from, Type* from_type,
    464                             MachineRepresentation to) {
    465   RepresentationChangerTester r;
    466 
    467   Node* n = r.Parameter();
    468   Node* use = r.Return(n);
    469   Node* c1 = r.changer()->GetRepresentationFor(n, from, from_type, use,
    470                                                UseInfo(to, Truncation::None()));
    471 
    472   CHECK_NE(c1, n);
    473   CHECK_EQ(expected1, c1->opcode());
    474   Node* c2 = c1->InputAt(0);
    475   CHECK_NE(c2, n);
    476   CHECK_EQ(expected2, c2->opcode());
    477   CHECK_EQ(n, c2->InputAt(0));
    478 }
    479 
    480 
    481 TEST(SingleChanges) {
    482   CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
    483               Type::None(), MachineRepresentation::kBit);
    484   CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
    485               Type::None(), MachineRepresentation::kTagged);
    486 
    487   CheckChange(IrOpcode::kChangeInt31ToTaggedSigned,
    488               MachineRepresentation::kWord32, Type::Signed31(),
    489               MachineRepresentation::kTagged);
    490   CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32,
    491               Type::Signed32(), MachineRepresentation::kTagged);
    492   CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32,
    493               Type::Unsigned32(), MachineRepresentation::kTagged);
    494   CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64,
    495               Type::Number(), MachineRepresentation::kTagged);
    496   CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
    497                   IrOpcode::kChangeInt31ToTaggedSigned,
    498                   MachineRepresentation::kFloat64, Type::Signed31(),
    499                   MachineRepresentation::kTagged);
    500   CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
    501                   IrOpcode::kChangeInt32ToTagged,
    502                   MachineRepresentation::kFloat64, Type::Signed32(),
    503                   MachineRepresentation::kTagged);
    504   CheckTwoChanges(IrOpcode::kChangeFloat64ToUint32,
    505                   IrOpcode::kChangeUint32ToTagged,
    506                   MachineRepresentation::kFloat64, Type::Unsigned32(),
    507                   MachineRepresentation::kTagged);
    508 
    509   CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
    510               Type::Signed32(), MachineRepresentation::kWord32);
    511   CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
    512               Type::Unsigned32(), MachineRepresentation::kWord32);
    513   CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
    514               Type::Number(), MachineRepresentation::kFloat64);
    515   CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
    516               Type::Number(), MachineRepresentation::kFloat64);
    517   CheckChange(IrOpcode::kTruncateTaggedToFloat64,
    518               MachineRepresentation::kTagged, Type::NumberOrUndefined(),
    519               MachineRepresentation::kFloat64);
    520   CheckTwoChanges(IrOpcode::kChangeTaggedSignedToInt32,
    521                   IrOpcode::kChangeInt32ToFloat64,
    522                   MachineRepresentation::kTagged, Type::TaggedSigned(),
    523                   MachineRepresentation::kFloat64);
    524 
    525   // Int32,Uint32 <-> Float64 are actually machine conversions.
    526   CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
    527               Type::Signed32(), MachineRepresentation::kFloat64);
    528   CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineRepresentation::kWord32,
    529               Type::Unsigned32(), MachineRepresentation::kFloat64);
    530   CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
    531               Type::Signed32(), MachineRepresentation::kWord32);
    532   CheckChange(IrOpcode::kChangeFloat64ToUint32, MachineRepresentation::kFloat64,
    533               Type::Unsigned32(), MachineRepresentation::kWord32);
    534 
    535   CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
    536               MachineRepresentation::kFloat64, Type::None(),
    537               MachineRepresentation::kFloat32);
    538 
    539   // Int32,Uint32 <-> Float32 require two changes.
    540   CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
    541                   IrOpcode::kTruncateFloat64ToFloat32,
    542                   MachineRepresentation::kWord32, Type::Signed32(),
    543                   MachineRepresentation::kFloat32);
    544   CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64,
    545                   IrOpcode::kTruncateFloat64ToFloat32,
    546                   MachineRepresentation::kWord32, Type::Unsigned32(),
    547                   MachineRepresentation::kFloat32);
    548   CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
    549                   IrOpcode::kChangeFloat64ToInt32,
    550                   MachineRepresentation::kFloat32, Type::Signed32(),
    551                   MachineRepresentation::kWord32);
    552   CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
    553                   IrOpcode::kChangeFloat64ToUint32,
    554                   MachineRepresentation::kFloat32, Type::Unsigned32(),
    555                   MachineRepresentation::kWord32);
    556 
    557   // Float32 <-> Tagged require two changes.
    558   CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
    559                   IrOpcode::kChangeFloat64ToTagged,
    560                   MachineRepresentation::kFloat32, Type::None(),
    561                   MachineRepresentation::kTagged);
    562   CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
    563                   IrOpcode::kTruncateFloat64ToFloat32,
    564                   MachineRepresentation::kTagged, Type::None(),
    565                   MachineRepresentation::kFloat32);
    566 }
    567 
    568 
    569 TEST(SignednessInWord32) {
    570   RepresentationChangerTester r;
    571 
    572   CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
    573               Type::Signed32(), MachineRepresentation::kWord32);
    574   CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
    575               Type::Unsigned32(), MachineRepresentation::kWord32);
    576   CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
    577               Type::None(), MachineRepresentation::kFloat64);
    578   CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
    579               Type::Signed32(), MachineRepresentation::kWord32);
    580   CheckChange(IrOpcode::kTruncateFloat64ToWord32,
    581               MachineRepresentation::kFloat64, Type::Number(),
    582               MachineRepresentation::kWord32);
    583 
    584   CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
    585                   IrOpcode::kTruncateFloat64ToFloat32,
    586                   MachineRepresentation::kWord32, Type::None(),
    587                   MachineRepresentation::kFloat32);
    588   CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
    589                   IrOpcode::kTruncateFloat64ToWord32,
    590                   MachineRepresentation::kFloat32, Type::Number(),
    591                   MachineRepresentation::kWord32);
    592 }
    593 
    594 
    595 TEST(Nops) {
    596   RepresentationChangerTester r;
    597 
    598   // X -> X is always a nop for any single representation X.
    599   for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
    600     r.CheckNop(kMachineTypes[i].representation(), Type::None(),
    601                kMachineTypes[i].representation());
    602   }
    603 
    604   // 32-bit floats.
    605   r.CheckNop(MachineRepresentation::kFloat32, Type::None(),
    606              MachineRepresentation::kFloat32);
    607   r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
    608              MachineRepresentation::kFloat32);
    609 
    610   // 32-bit words can be used as smaller word sizes and vice versa, because
    611   // loads from memory implicitly sign or zero extend the value to the
    612   // full machine word size, and stores implicitly truncate.
    613   r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
    614              MachineRepresentation::kWord8);
    615   r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
    616              MachineRepresentation::kWord16);
    617   r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
    618              MachineRepresentation::kWord32);
    619   r.CheckNop(MachineRepresentation::kWord8, Type::Signed32(),
    620              MachineRepresentation::kWord32);
    621   r.CheckNop(MachineRepresentation::kWord16, Type::Signed32(),
    622              MachineRepresentation::kWord32);
    623 
    624   // kRepBit (result of comparison) is implicitly a wordish thing.
    625   r.CheckNop(MachineRepresentation::kBit, Type::None(),
    626              MachineRepresentation::kWord8);
    627   r.CheckNop(MachineRepresentation::kBit, Type::None(),
    628              MachineRepresentation::kWord16);
    629   r.CheckNop(MachineRepresentation::kBit, Type::None(),
    630              MachineRepresentation::kWord32);
    631   r.CheckNop(MachineRepresentation::kBit, Type::None(),
    632              MachineRepresentation::kWord64);
    633   r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
    634              MachineRepresentation::kWord8);
    635   r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
    636              MachineRepresentation::kWord16);
    637   r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
    638              MachineRepresentation::kWord32);
    639   r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
    640              MachineRepresentation::kWord64);
    641 }
    642 
    643 
    644 TEST(TypeErrors) {
    645   RepresentationChangerTester r;
    646 
    647   // Wordish cannot be implicitly converted to/from comparison conditions.
    648   r.CheckTypeError(MachineRepresentation::kWord8, Type::None(),
    649                    MachineRepresentation::kBit);
    650   r.CheckTypeError(MachineRepresentation::kWord16, Type::None(),
    651                    MachineRepresentation::kBit);
    652   r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
    653                    MachineRepresentation::kBit);
    654   r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
    655                    MachineRepresentation::kBit);
    656 
    657   // Floats cannot be implicitly converted to/from comparison conditions.
    658   r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(),
    659                    MachineRepresentation::kBit);
    660   r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
    661                    MachineRepresentation::kFloat64);
    662   r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
    663                    MachineRepresentation::kFloat64);
    664 
    665   // Floats cannot be implicitly converted to/from comparison conditions.
    666   r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(),
    667                    MachineRepresentation::kBit);
    668   r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
    669                    MachineRepresentation::kFloat32);
    670   r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
    671                    MachineRepresentation::kFloat32);
    672 
    673   // Word64 is internal and shouldn't be implicitly converted.
    674   r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
    675                    MachineRepresentation::kTagged);
    676   r.CheckTypeError(MachineRepresentation::kTagged, Type::None(),
    677                    MachineRepresentation::kWord64);
    678   r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
    679                    MachineRepresentation::kWord64);
    680 
    681   // Word64 / Word32 shouldn't be implicitly converted.
    682   r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
    683                    MachineRepresentation::kWord32);
    684   r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
    685                    MachineRepresentation::kWord64);
    686   r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(),
    687                    MachineRepresentation::kWord64);
    688   r.CheckTypeError(MachineRepresentation::kWord32, Type::Unsigned32(),
    689                    MachineRepresentation::kWord64);
    690 }
    691 
    692 }  // namespace compiler
    693 }  // namespace internal
    694 }  // namespace v8
    695