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 "src/ast/scopes.h"
      8 #include "src/compiler/access-builder.h"
      9 #include "src/compiler/change-lowering.h"
     10 #include "src/compiler/control-builders.h"
     11 #include "src/compiler/graph-reducer.h"
     12 #include "src/compiler/graph-visualizer.h"
     13 #include "src/compiler/node-properties.h"
     14 #include "src/compiler/pipeline.h"
     15 #include "src/compiler/representation-change.h"
     16 #include "src/compiler/simplified-lowering.h"
     17 #include "src/compiler/source-position.h"
     18 #include "src/compiler/typer.h"
     19 #include "src/compiler/verifier.h"
     20 #include "src/execution.h"
     21 #include "src/parsing/parser.h"
     22 #include "src/parsing/rewriter.h"
     23 #include "test/cctest/cctest.h"
     24 #include "test/cctest/compiler/codegen-tester.h"
     25 #include "test/cctest/compiler/function-tester.h"
     26 #include "test/cctest/compiler/graph-builder-tester.h"
     27 #include "test/cctest/compiler/value-helper.h"
     28 
     29 namespace v8 {
     30 namespace internal {
     31 namespace compiler {
     32 
     33 template <typename ReturnType>
     34 class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
     35  public:
     36   SimplifiedLoweringTester(MachineType p0 = MachineType::None(),
     37                            MachineType p1 = MachineType::None())
     38       : GraphBuilderTester<ReturnType>(p0, p1),
     39         typer(this->isolate(), this->graph()),
     40         javascript(this->zone()),
     41         jsgraph(this->isolate(), this->graph(), this->common(), &javascript,
     42                 this->simplified(), this->machine()),
     43         source_positions(jsgraph.graph()),
     44         lowering(&jsgraph, this->zone(), &source_positions) {}
     45 
     46   Typer typer;
     47   JSOperatorBuilder javascript;
     48   JSGraph jsgraph;
     49   SourcePositionTable source_positions;
     50   SimplifiedLowering lowering;
     51 
     52   void LowerAllNodes() {
     53     this->End();
     54     typer.Run();
     55     lowering.LowerAllNodes();
     56   }
     57 
     58   void LowerAllNodesAndLowerChanges() {
     59     this->End();
     60     typer.Run();
     61     lowering.LowerAllNodes();
     62 
     63     ChangeLowering lowering(&jsgraph);
     64     GraphReducer reducer(this->zone(), this->graph());
     65     reducer.AddReducer(&lowering);
     66     reducer.ReduceGraph();
     67     Verifier::Run(this->graph());
     68   }
     69 
     70   void CheckNumberCall(double expected, double input) {
     71     // TODO(titzer): make calls to NewNumber work in cctests.
     72     if (expected <= Smi::kMinValue) return;
     73     if (expected >= Smi::kMaxValue) return;
     74     Handle<Object> num = factory()->NewNumber(input);
     75     Object* result = this->Call(*num);
     76     CHECK(factory()->NewNumber(expected)->SameValue(result));
     77   }
     78 
     79   template <typename T>
     80   T* CallWithPotentialGC() {
     81     // TODO(titzer): we wrap the code in a JSFunction here to reuse the
     82     // JSEntryStub; that could be done with a special prologue or other stub.
     83     Handle<JSFunction> fun = FunctionTester::ForMachineGraph(this->graph(), 0);
     84     Handle<Object>* args = NULL;
     85     MaybeHandle<Object> result = Execution::Call(
     86         this->isolate(), fun, factory()->undefined_value(), 0, args);
     87     return T::cast(*result.ToHandleChecked());
     88   }
     89 
     90   Factory* factory() { return this->isolate()->factory(); }
     91   Heap* heap() { return this->isolate()->heap(); }
     92 };
     93 
     94 
     95 // TODO(titzer): factor these tests out to test-run-simplifiedops.cc.
     96 // TODO(titzer): test tagged representation for input to NumberToInt32.
     97 TEST(RunNumberToInt32_float64) {
     98   // TODO(titzer): explicit load/stores here are only because of representations
     99   double input;
    100   int32_t result;
    101   SimplifiedLoweringTester<Object*> t;
    102   FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
    103                       MachineType::Float64()};
    104   Node* loaded = t.LoadField(load, t.PointerConstant(&input));
    105   NodeProperties::SetType(loaded, Type::Number());
    106   Node* convert = t.NumberToInt32(loaded);
    107   FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(),
    108                        MachineType::Int32()};
    109   t.StoreField(store, t.PointerConstant(&result), convert);
    110   t.Return(t.jsgraph.TrueConstant());
    111   t.LowerAllNodesAndLowerChanges();
    112   t.GenerateCode();
    113 
    114     FOR_FLOAT64_INPUTS(i) {
    115       input = *i;
    116       int32_t expected = DoubleToInt32(*i);
    117       t.Call();
    118       CHECK_EQ(expected, result);
    119     }
    120 }
    121 
    122 
    123 // TODO(titzer): test tagged representation for input to NumberToUint32.
    124 TEST(RunNumberToUint32_float64) {
    125   // TODO(titzer): explicit load/stores here are only because of representations
    126   double input;
    127   uint32_t result;
    128   SimplifiedLoweringTester<Object*> t;
    129   FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
    130                       MachineType::Float64()};
    131   Node* loaded = t.LoadField(load, t.PointerConstant(&input));
    132   NodeProperties::SetType(loaded, Type::Number());
    133   Node* convert = t.NumberToUint32(loaded);
    134   FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(),
    135                        MachineType::Uint32()};
    136   t.StoreField(store, t.PointerConstant(&result), convert);
    137   t.Return(t.jsgraph.TrueConstant());
    138   t.LowerAllNodesAndLowerChanges();
    139   t.GenerateCode();
    140 
    141     FOR_FLOAT64_INPUTS(i) {
    142       input = *i;
    143       uint32_t expected = DoubleToUint32(*i);
    144       t.Call();
    145       CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result));
    146     }
    147   }
    148 
    149 
    150 // Create a simple JSObject with a unique map.
    151 static Handle<JSObject> TestObject() {
    152   static int index = 0;
    153   char buffer[50];
    154   v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++);
    155   return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer)));
    156 }
    157 
    158 
    159 TEST(RunLoadMap) {
    160   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
    161   FieldAccess access = AccessBuilder::ForMap();
    162   Node* load = t.LoadField(access, t.Parameter(0));
    163   t.Return(load);
    164 
    165   t.LowerAllNodesAndLowerChanges();
    166   t.GenerateCode();
    167 
    168   Handle<JSObject> src = TestObject();
    169   Handle<Map> src_map(src->map());
    170   Object* result = t.Call(*src);  // TODO(titzer): raw pointers in call
    171   CHECK_EQ(*src_map, result);
    172 }
    173 
    174 
    175 TEST(RunStoreMap) {
    176   SimplifiedLoweringTester<int32_t> t(MachineType::AnyTagged(),
    177                                       MachineType::AnyTagged());
    178   FieldAccess access = AccessBuilder::ForMap();
    179   t.StoreField(access, t.Parameter(1), t.Parameter(0));
    180   t.Return(t.jsgraph.TrueConstant());
    181 
    182   t.LowerAllNodesAndLowerChanges();
    183   t.GenerateCode();
    184 
    185     Handle<JSObject> src = TestObject();
    186     Handle<Map> src_map(src->map());
    187     Handle<JSObject> dst = TestObject();
    188     CHECK(src->map() != dst->map());
    189     t.Call(*src_map, *dst);  // TODO(titzer): raw pointers in call
    190     CHECK(*src_map == dst->map());
    191   }
    192 
    193 
    194 TEST(RunLoadProperties) {
    195   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
    196   FieldAccess access = AccessBuilder::ForJSObjectProperties();
    197   Node* load = t.LoadField(access, t.Parameter(0));
    198   t.Return(load);
    199 
    200   t.LowerAllNodesAndLowerChanges();
    201   t.GenerateCode();
    202 
    203     Handle<JSObject> src = TestObject();
    204     Handle<FixedArray> src_props(src->properties());
    205     Object* result = t.Call(*src);  // TODO(titzer): raw pointers in call
    206     CHECK_EQ(*src_props, result);
    207 }
    208 
    209 
    210 TEST(RunLoadStoreMap) {
    211   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged(),
    212                                       MachineType::AnyTagged());
    213   FieldAccess access = AccessBuilder::ForMap();
    214   Node* load = t.LoadField(access, t.Parameter(0));
    215   t.StoreField(access, t.Parameter(1), load);
    216   t.Return(load);
    217 
    218   t.LowerAllNodesAndLowerChanges();
    219   t.GenerateCode();
    220 
    221     Handle<JSObject> src = TestObject();
    222     Handle<Map> src_map(src->map());
    223     Handle<JSObject> dst = TestObject();
    224     CHECK(src->map() != dst->map());
    225     Object* result = t.Call(*src, *dst);  // TODO(titzer): raw pointers in call
    226     CHECK(result->IsMap());
    227     CHECK_EQ(*src_map, result);
    228     CHECK(*src_map == dst->map());
    229 }
    230 
    231 
    232 TEST(RunLoadStoreFixedArrayIndex) {
    233   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
    234   ElementAccess access = AccessBuilder::ForFixedArrayElement();
    235   Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0));
    236   t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load);
    237   t.Return(load);
    238 
    239   t.LowerAllNodesAndLowerChanges();
    240   t.GenerateCode();
    241 
    242     Handle<FixedArray> array = t.factory()->NewFixedArray(2);
    243     Handle<JSObject> src = TestObject();
    244     Handle<JSObject> dst = TestObject();
    245     array->set(0, *src);
    246     array->set(1, *dst);
    247     Object* result = t.Call(*array);
    248     CHECK_EQ(*src, result);
    249     CHECK_EQ(*src, array->get(0));
    250     CHECK_EQ(*src, array->get(1));
    251 }
    252 
    253 
    254 TEST(RunLoadStoreArrayBuffer) {
    255   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
    256   const int index = 12;
    257   const int array_length = 2 * index;
    258   ElementAccess buffer_access =
    259       AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true);
    260   Node* backing_store = t.LoadField(
    261       AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0));
    262   Node* load =
    263       t.LoadElement(buffer_access, backing_store, t.Int32Constant(index));
    264   t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1),
    265                  load);
    266   t.Return(t.jsgraph.TrueConstant());
    267 
    268   t.LowerAllNodesAndLowerChanges();
    269   t.GenerateCode();
    270 
    271     Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
    272     JSArrayBuffer::SetupAllocatingData(array, t.isolate(), array_length);
    273     uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
    274     for (int i = 0; i < array_length; i++) {
    275       data[i] = i;
    276     }
    277 
    278     // TODO(titzer): raw pointers in call
    279     Object* result = t.Call(*array);
    280     CHECK_EQ(t.isolate()->heap()->true_value(), result);
    281     for (int i = 0; i < array_length; i++) {
    282       uint8_t expected = i;
    283       if (i == (index + 1)) expected = index;
    284       CHECK_EQ(data[i], expected);
    285     }
    286   }
    287 
    288 
    289 TEST(RunLoadFieldFromUntaggedBase) {
    290   Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)};
    291 
    292   for (size_t i = 0; i < arraysize(smis); i++) {
    293     int offset = static_cast<int>(i * sizeof(Smi*));
    294     FieldAccess access = {kUntaggedBase, offset, Handle<Name>(),
    295                           Type::Integral32(), MachineType::AnyTagged()};
    296 
    297     SimplifiedLoweringTester<Object*> t;
    298     Node* load = t.LoadField(access, t.PointerConstant(smis));
    299     t.Return(load);
    300     t.LowerAllNodesAndLowerChanges();
    301 
    302     for (int j = -5; j <= 5; j++) {
    303       Smi* expected = Smi::FromInt(j);
    304       smis[i] = expected;
    305       CHECK_EQ(expected, t.Call());
    306     }
    307   }
    308 }
    309 
    310 
    311 TEST(RunStoreFieldToUntaggedBase) {
    312   Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)};
    313 
    314   for (size_t i = 0; i < arraysize(smis); i++) {
    315     int offset = static_cast<int>(i * sizeof(Smi*));
    316     FieldAccess access = {kUntaggedBase, offset, Handle<Name>(),
    317                           Type::Integral32(), MachineType::AnyTagged()};
    318 
    319     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
    320     Node* p0 = t.Parameter(0);
    321     t.StoreField(access, t.PointerConstant(smis), p0);
    322     t.Return(p0);
    323     t.LowerAllNodesAndLowerChanges();
    324 
    325     for (int j = -5; j <= 5; j++) {
    326       Smi* expected = Smi::FromInt(j);
    327       smis[i] = Smi::FromInt(-100);
    328       CHECK_EQ(expected, t.Call(expected));
    329       CHECK_EQ(expected, smis[i]);
    330     }
    331   }
    332 }
    333 
    334 
    335 TEST(RunLoadElementFromUntaggedBase) {
    336   Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3),
    337                  Smi::FromInt(4), Smi::FromInt(5)};
    338 
    339   for (size_t i = 0; i < arraysize(smis); i++) {    // for header sizes
    340     for (size_t j = 0; (i + j) < arraysize(smis); j++) {  // for element index
    341       int offset = static_cast<int>(i * sizeof(Smi*));
    342       ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
    343                               MachineType::AnyTagged()};
    344 
    345       SimplifiedLoweringTester<Object*> t;
    346       Node* load = t.LoadElement(access, t.PointerConstant(smis),
    347                                  t.Int32Constant(static_cast<int>(j)));
    348       t.Return(load);
    349       t.LowerAllNodesAndLowerChanges();
    350 
    351       for (int k = -5; k <= 5; k++) {
    352         Smi* expected = Smi::FromInt(k);
    353         smis[i + j] = expected;
    354         CHECK_EQ(expected, t.Call());
    355       }
    356     }
    357   }
    358 }
    359 
    360 
    361 TEST(RunStoreElementFromUntaggedBase) {
    362   Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3),
    363                  Smi::FromInt(4), Smi::FromInt(5)};
    364 
    365   for (size_t i = 0; i < arraysize(smis); i++) {    // for header sizes
    366     for (size_t j = 0; (i + j) < arraysize(smis); j++) {  // for element index
    367       int offset = static_cast<int>(i * sizeof(Smi*));
    368       ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
    369                               MachineType::AnyTagged()};
    370 
    371       SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
    372       Node* p0 = t.Parameter(0);
    373       t.StoreElement(access, t.PointerConstant(smis),
    374                      t.Int32Constant(static_cast<int>(j)), p0);
    375       t.Return(p0);
    376       t.LowerAllNodesAndLowerChanges();
    377 
    378       for (int k = -5; k <= 5; k++) {
    379         Smi* expected = Smi::FromInt(k);
    380         smis[i + j] = Smi::FromInt(-100);
    381         CHECK_EQ(expected, t.Call(expected));
    382         CHECK_EQ(expected, smis[i + j]);
    383       }
    384 
    385       // TODO(titzer): assert the contents of the array.
    386     }
    387   }
    388 }
    389 
    390 
    391 // A helper class for accessing fields and elements of various types, on both
    392 // tagged and untagged base pointers. Contains both tagged and untagged buffers
    393 // for testing direct memory access from generated code.
    394 template <typename E>
    395 class AccessTester : public HandleAndZoneScope {
    396  public:
    397   bool tagged;
    398   MachineType rep;
    399   E* original_elements;
    400   size_t num_elements;
    401   E* untagged_array;
    402   Handle<ByteArray> tagged_array;  // TODO(titzer): use FixedArray for tagged.
    403 
    404   AccessTester(bool t, MachineType r, E* orig, size_t num)
    405       : tagged(t),
    406         rep(r),
    407         original_elements(orig),
    408         num_elements(num),
    409         untagged_array(static_cast<E*>(malloc(ByteSize()))),
    410         tagged_array(main_isolate()->factory()->NewByteArray(
    411             static_cast<int>(ByteSize()))) {
    412     Reinitialize();
    413   }
    414 
    415   ~AccessTester() { free(untagged_array); }
    416 
    417   size_t ByteSize() { return num_elements * sizeof(E); }
    418 
    419   // Nuke both {untagged_array} and {tagged_array} with {original_elements}.
    420   void Reinitialize() {
    421     memcpy(untagged_array, original_elements, ByteSize());
    422     CHECK_EQ(static_cast<int>(ByteSize()), tagged_array->length());
    423     E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
    424     memcpy(raw, original_elements, ByteSize());
    425   }
    426 
    427   // Create and run code that copies the element in either {untagged_array}
    428   // or {tagged_array} at index {from_index} to index {to_index}.
    429   void RunCopyElement(int from_index, int to_index) {
    430     // TODO(titzer): test element and field accesses where the base is not
    431     // a constant in the code.
    432     BoundsCheck(from_index);
    433     BoundsCheck(to_index);
    434     ElementAccess access = GetElementAccess();
    435 
    436     SimplifiedLoweringTester<Object*> t;
    437     Node* ptr = GetBaseNode(&t);
    438     Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index));
    439     t.StoreElement(access, ptr, t.Int32Constant(to_index), load);
    440     t.Return(t.jsgraph.TrueConstant());
    441     t.LowerAllNodesAndLowerChanges();
    442     t.GenerateCode();
    443 
    444       Object* result = t.Call();
    445       CHECK_EQ(t.isolate()->heap()->true_value(), result);
    446   }
    447 
    448   // Create and run code that copies the field in either {untagged_array}
    449   // or {tagged_array} at index {from_index} to index {to_index}.
    450   void RunCopyField(int from_index, int to_index) {
    451     BoundsCheck(from_index);
    452     BoundsCheck(to_index);
    453     FieldAccess from_access = GetFieldAccess(from_index);
    454     FieldAccess to_access = GetFieldAccess(to_index);
    455 
    456     SimplifiedLoweringTester<Object*> t;
    457     Node* ptr = GetBaseNode(&t);
    458     Node* load = t.LoadField(from_access, ptr);
    459     t.StoreField(to_access, ptr, load);
    460     t.Return(t.jsgraph.TrueConstant());
    461     t.LowerAllNodesAndLowerChanges();
    462     t.GenerateCode();
    463 
    464       Object* result = t.Call();
    465       CHECK_EQ(t.isolate()->heap()->true_value(), result);
    466   }
    467 
    468   // Create and run code that copies the elements from {this} to {that}.
    469   void RunCopyElements(AccessTester<E>* that) {
    470 // TODO(titzer): Rewrite this test without StructuredGraphBuilder support.
    471 #if 0
    472     SimplifiedLoweringTester<Object*> t;
    473 
    474     Node* one = t.Int32Constant(1);
    475     Node* index = t.Int32Constant(0);
    476     Node* limit = t.Int32Constant(static_cast<int>(num_elements));
    477     t.environment()->Push(index);
    478     Node* src = this->GetBaseNode(&t);
    479     Node* dst = that->GetBaseNode(&t);
    480     {
    481       LoopBuilder loop(&t);
    482       loop.BeginLoop();
    483       // Loop exit condition
    484       index = t.environment()->Top();
    485       Node* condition = t.Int32LessThan(index, limit);
    486       loop.BreakUnless(condition);
    487       // dst[index] = src[index]
    488       index = t.environment()->Pop();
    489       Node* load = t.LoadElement(this->GetElementAccess(), src, index);
    490       t.StoreElement(that->GetElementAccess(), dst, index, load);
    491       // index++
    492       index = t.Int32Add(index, one);
    493       t.environment()->Push(index);
    494       // continue
    495       loop.EndBody();
    496       loop.EndLoop();
    497     }
    498     index = t.environment()->Pop();
    499     t.Return(t.jsgraph.TrueConstant());
    500     t.LowerAllNodes();
    501     t.GenerateCode();
    502 
    503       Object* result = t.Call();
    504       CHECK_EQ(t.isolate()->heap()->true_value(), result);
    505 #endif
    506   }
    507 
    508   E GetElement(int index) {
    509     BoundsCheck(index);
    510     if (tagged) {
    511       return GetTaggedElement(index);
    512     } else {
    513       return untagged_array[index];
    514     }
    515   }
    516 
    517  private:
    518   ElementAccess GetElementAccess() {
    519     ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase,
    520                             tagged ? FixedArrayBase::kHeaderSize : 0,
    521                             Type::Any(), rep};
    522     return access;
    523   }
    524 
    525   FieldAccess GetFieldAccess(int field) {
    526     int offset = field * sizeof(E);
    527     FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase,
    528                           offset + (tagged ? FixedArrayBase::kHeaderSize : 0),
    529                           Handle<Name>(), Type::Any(), rep};
    530     return access;
    531   }
    532 
    533   template <typename T>
    534   Node* GetBaseNode(SimplifiedLoweringTester<T>* t) {
    535     return tagged ? t->HeapConstant(tagged_array)
    536                   : t->PointerConstant(untagged_array);
    537   }
    538 
    539   void BoundsCheck(int index) {
    540     CHECK_GE(index, 0);
    541     CHECK_LT(index, static_cast<int>(num_elements));
    542     CHECK_EQ(static_cast<int>(ByteSize()), tagged_array->length());
    543   }
    544 
    545   E GetTaggedElement(int index) {
    546     E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
    547     return raw[index];
    548   }
    549 };
    550 
    551 template <>
    552 double AccessTester<double>::GetTaggedElement(int index) {
    553   return ReadDoubleValue(tagged_array->GetDataStartAddress() +
    554                          index * sizeof(double));
    555 }
    556 
    557 
    558 template <typename E>
    559 static void RunAccessTest(MachineType rep, E* original_elements, size_t num) {
    560   int num_elements = static_cast<int>(num);
    561 
    562   for (int taggedness = 0; taggedness < 2; taggedness++) {
    563     AccessTester<E> a(taggedness == 1, rep, original_elements, num);
    564     for (int field = 0; field < 2; field++) {
    565       for (int i = 0; i < num_elements - 1; i++) {
    566         a.Reinitialize();
    567         if (field == 0) {
    568           a.RunCopyField(i, i + 1);  // Test field read/write.
    569         } else {
    570           a.RunCopyElement(i, i + 1);  // Test element read/write.
    571         }
    572           for (int j = 0; j < num_elements; j++) {
    573             E expect =
    574                 j == (i + 1) ? original_elements[i] : original_elements[j];
    575             CHECK_EQ(expect, a.GetElement(j));
    576           }
    577       }
    578     }
    579   }
    580   // Test array copy.
    581   for (int tf = 0; tf < 2; tf++) {
    582     for (int tt = 0; tt < 2; tt++) {
    583       AccessTester<E> a(tf == 1, rep, original_elements, num);
    584       AccessTester<E> b(tt == 1, rep, original_elements, num);
    585       a.RunCopyElements(&b);
    586         for (int i = 0; i < num_elements; i++) {
    587           CHECK_EQ(a.GetElement(i), b.GetElement(i));
    588       }
    589     }
    590   }
    591 }
    592 
    593 
    594 TEST(RunAccessTests_uint8) {
    595   uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99,
    596                     0xab, 0x78, 0x89, 0x19, 0x2b, 0x38};
    597   RunAccessTest<uint8_t>(MachineType::Int8(), data, arraysize(data));
    598 }
    599 
    600 
    601 TEST(RunAccessTests_uint16) {
    602   uint16_t data[] = {0x071a, 0x162b, 0x253c, 0x344d, 0x435e, 0x7777};
    603   RunAccessTest<uint16_t>(MachineType::Int16(), data, arraysize(data));
    604 }
    605 
    606 
    607 TEST(RunAccessTests_int32) {
    608   int32_t data[] = {-211, 211, 628347, 2000000000, -2000000000, -1, -100000034};
    609   RunAccessTest<int32_t>(MachineType::Int32(), data, arraysize(data));
    610 }
    611 
    612 
    613 #define V8_2PART_INT64(a, b) (((static_cast<int64_t>(a) << 32) + 0x##b##u))
    614 
    615 
    616 TEST(RunAccessTests_int64) {
    617   if (kPointerSize != 8) return;
    618   int64_t data[] = {V8_2PART_INT64(0x10111213, 14151617),
    619                     V8_2PART_INT64(0x20212223, 24252627),
    620                     V8_2PART_INT64(0x30313233, 34353637),
    621                     V8_2PART_INT64(0xa0a1a2a3, a4a5a6a7),
    622                     V8_2PART_INT64(0xf0f1f2f3, f4f5f6f7)};
    623   RunAccessTest<int64_t>(MachineType::Int64(), data, arraysize(data));
    624 }
    625 
    626 
    627 TEST(RunAccessTests_float64) {
    628   double data[] = {1.25, -1.25, 2.75, 11.0, 11100.8};
    629   RunAccessTest<double>(MachineType::Float64(), data, arraysize(data));
    630 }
    631 
    632 
    633 TEST(RunAccessTests_Smi) {
    634   Smi* data[] = {Smi::FromInt(-1),    Smi::FromInt(-9),
    635                  Smi::FromInt(0),     Smi::FromInt(666),
    636                  Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)};
    637   RunAccessTest<Smi*>(MachineType::AnyTagged(), data, arraysize(data));
    638 }
    639 
    640 
    641 TEST(RunAllocate) {
    642   PretenureFlag flag[] = {NOT_TENURED, TENURED};
    643 
    644   for (size_t i = 0; i < arraysize(flag); i++) {
    645     SimplifiedLoweringTester<HeapObject*> t;
    646     FieldAccess access = AccessBuilder::ForMap();
    647     Node* size = t.jsgraph.Constant(HeapNumber::kSize);
    648     Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size);
    649     Node* map = t.jsgraph.Constant(t.factory()->heap_number_map());
    650     t.StoreField(access, alloc, map);
    651     t.Return(alloc);
    652 
    653     t.LowerAllNodesAndLowerChanges();
    654     t.GenerateCode();
    655 
    656       HeapObject* result = t.CallWithPotentialGC<HeapObject>();
    657       CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED);
    658       CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED);
    659       CHECK(result->IsHeapNumber());
    660   }
    661 }
    662 
    663 
    664 // Fills in most of the nodes of the graph in order to make tests shorter.
    665 class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
    666  public:
    667   Typer typer;
    668   JSOperatorBuilder javascript;
    669   JSGraph jsgraph;
    670   Node* p0;
    671   Node* p1;
    672   Node* p2;
    673   Node* start;
    674   Node* end;
    675   Node* ret;
    676 
    677   explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(),
    678                         Type* p2_type = Type::None())
    679       : GraphAndBuilders(main_zone()),
    680         typer(main_isolate(), graph()),
    681         javascript(main_zone()),
    682         jsgraph(main_isolate(), graph(), common(), &javascript, simplified(),
    683                 machine()) {
    684     start = graph()->NewNode(common()->Start(4));
    685     graph()->SetStart(start);
    686     ret =
    687         graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start);
    688     end = graph()->NewNode(common()->End(1), ret);
    689     graph()->SetEnd(end);
    690     p0 = graph()->NewNode(common()->Parameter(0), start);
    691     p1 = graph()->NewNode(common()->Parameter(1), start);
    692     p2 = graph()->NewNode(common()->Parameter(2), start);
    693     typer.Run();
    694     NodeProperties::SetType(p0, p0_type);
    695     NodeProperties::SetType(p1, p1_type);
    696     NodeProperties::SetType(p2, p2_type);
    697   }
    698 
    699   void CheckLoweringBinop(IrOpcode::Value expected, const Operator* op) {
    700     Node* node = Return(graph()->NewNode(op, p0, p1));
    701     Lower();
    702     CHECK_EQ(expected, node->opcode());
    703   }
    704 
    705   void CheckLoweringStringBinop(IrOpcode::Value expected, const Operator* op) {
    706     Node* node = Return(
    707         graph()->NewNode(op, p0, p1, graph()->start(), graph()->start()));
    708     Lower();
    709     CHECK_EQ(expected, node->opcode());
    710   }
    711 
    712   void CheckLoweringTruncatedBinop(IrOpcode::Value expected, const Operator* op,
    713                                    const Operator* trunc) {
    714     Node* node = graph()->NewNode(op, p0, p1);
    715     Return(graph()->NewNode(trunc, node));
    716     Lower();
    717     CHECK_EQ(expected, node->opcode());
    718   }
    719 
    720   void Lower() {
    721     SourcePositionTable table(jsgraph.graph());
    722     SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
    723   }
    724 
    725   void LowerAllNodesAndLowerChanges() {
    726     SourcePositionTable table(jsgraph.graph());
    727     SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
    728 
    729     ChangeLowering lowering(&jsgraph);
    730     GraphReducer reducer(this->zone(), this->graph());
    731     reducer.AddReducer(&lowering);
    732     reducer.ReduceGraph();
    733     Verifier::Run(this->graph());
    734   }
    735 
    736   // Inserts the node as the return value of the graph.
    737   Node* Return(Node* node) {
    738     ret->ReplaceInput(0, node);
    739     return node;
    740   }
    741 
    742   // Inserts the node as the effect input to the return of the graph.
    743   void Effect(Node* node) { ret->ReplaceInput(1, node); }
    744 
    745   Node* ExampleWithOutput(MachineType type) {
    746     if (type.semantic() == MachineSemantic::kInt32) {
    747       return graph()->NewNode(machine()->Int32Add(), jsgraph.Int32Constant(1),
    748                               jsgraph.Int32Constant(1));
    749     } else if (type.semantic() == MachineSemantic::kUint32) {
    750       return graph()->NewNode(machine()->Word32Shr(), jsgraph.Int32Constant(1),
    751                               jsgraph.Int32Constant(1));
    752     } else if (type.representation() == MachineRepresentation::kFloat64) {
    753       return graph()->NewNode(machine()->Float64Add(),
    754                               jsgraph.Float64Constant(1),
    755                               jsgraph.Float64Constant(1));
    756     } else if (type.representation() == MachineRepresentation::kBit) {
    757       return graph()->NewNode(machine()->Word32Equal(),
    758                               jsgraph.Int32Constant(1),
    759                               jsgraph.Int32Constant(1));
    760     } else if (type.representation() == MachineRepresentation::kWord64) {
    761       return graph()->NewNode(machine()->Int64Add(), Int64Constant(1),
    762                               Int64Constant(1));
    763     } else {
    764       CHECK(type.representation() == MachineRepresentation::kTagged);
    765       return p0;
    766     }
    767   }
    768 
    769   Node* Use(Node* node, MachineType type) {
    770     if (type.semantic() == MachineSemantic::kInt32) {
    771       return graph()->NewNode(machine()->Int32LessThan(), node,
    772                               jsgraph.Int32Constant(1));
    773     } else if (type.semantic() == MachineSemantic::kUint32) {
    774       return graph()->NewNode(machine()->Uint32LessThan(), node,
    775                               jsgraph.Int32Constant(1));
    776     } else if (type.representation() == MachineRepresentation::kFloat64) {
    777       return graph()->NewNode(machine()->Float64Add(), node,
    778                               jsgraph.Float64Constant(1));
    779     } else if (type.representation() == MachineRepresentation::kWord64) {
    780       return graph()->NewNode(machine()->Int64LessThan(), node,
    781                               Int64Constant(1));
    782     } else if (type.representation() == MachineRepresentation::kWord32) {
    783       return graph()->NewNode(machine()->Word32Equal(), node,
    784                               jsgraph.Int32Constant(1));
    785     } else {
    786       return graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), node,
    787                               jsgraph.TrueConstant());
    788     }
    789   }
    790 
    791   Node* Branch(Node* cond) {
    792     Node* br = graph()->NewNode(common()->Branch(), cond, start);
    793     Node* tb = graph()->NewNode(common()->IfTrue(), br);
    794     Node* fb = graph()->NewNode(common()->IfFalse(), br);
    795     Node* m = graph()->NewNode(common()->Merge(2), tb, fb);
    796     NodeProperties::ReplaceControlInput(ret, m);
    797     return br;
    798   }
    799 
    800   Node* Int64Constant(int64_t v) {
    801     return graph()->NewNode(common()->Int64Constant(v));
    802   }
    803 
    804   SimplifiedOperatorBuilder* simplified() { return &main_simplified_; }
    805   MachineOperatorBuilder* machine() { return &main_machine_; }
    806   CommonOperatorBuilder* common() { return &main_common_; }
    807   Graph* graph() { return main_graph_; }
    808 };
    809 
    810 
    811 TEST(LowerBooleanNot_bit_bit) {
    812   // BooleanNot(x: kRepBit) used as kRepBit
    813   TestingGraph t(Type::Boolean());
    814   Node* b = t.ExampleWithOutput(MachineType::Bool());
    815   Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
    816   Node* use = t.Branch(inv);
    817   t.Lower();
    818   Node* cmp = use->InputAt(0);
    819   CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
    820   CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
    821   Node* f = t.jsgraph.Int32Constant(0);
    822   CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
    823 }
    824 
    825 
    826 TEST(LowerBooleanNot_bit_tagged) {
    827   // BooleanNot(x: kRepBit) used as kRepTagged
    828   TestingGraph t(Type::Boolean());
    829   Node* b = t.ExampleWithOutput(MachineType::Bool());
    830   Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
    831   Node* use = t.Use(inv, MachineType::AnyTagged());
    832   t.Return(use);
    833   t.Lower();
    834   CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
    835   Node* cmp = use->InputAt(0)->InputAt(0);
    836   CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
    837   CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
    838   Node* f = t.jsgraph.Int32Constant(0);
    839   CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
    840 }
    841 
    842 
    843 TEST(LowerBooleanNot_tagged_bit) {
    844   // BooleanNot(x: kRepTagged) used as kRepBit
    845   TestingGraph t(Type::Boolean());
    846   Node* b = t.p0;
    847   Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
    848   Node* use = t.Branch(inv);
    849   t.Lower();
    850   Node* cmp = use->InputAt(0);
    851   CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
    852   CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
    853   Node* f = t.jsgraph.FalseConstant();
    854   CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
    855 }
    856 
    857 
    858 TEST(LowerBooleanNot_tagged_tagged) {
    859   // BooleanNot(x: kRepTagged) used as kRepTagged
    860   TestingGraph t(Type::Boolean());
    861   Node* b = t.p0;
    862   Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
    863   Node* use = t.Use(inv, MachineType::AnyTagged());
    864   t.Return(use);
    865   t.Lower();
    866   CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
    867   Node* cmp = use->InputAt(0)->InputAt(0);
    868   CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
    869   CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
    870   Node* f = t.jsgraph.FalseConstant();
    871   CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
    872 }
    873 
    874 
    875 TEST(LowerBooleanToNumber_bit_int32) {
    876   // BooleanToNumber(x: kRepBit) used as MachineType::Int32()
    877   TestingGraph t(Type::Boolean());
    878   Node* b = t.ExampleWithOutput(MachineType::Bool());
    879   Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
    880   Node* use = t.Use(cnv, MachineType::Int32());
    881   t.Return(use);
    882   t.Lower();
    883   CHECK_EQ(b, use->InputAt(0));
    884 }
    885 
    886 
    887 TEST(LowerBooleanToNumber_tagged_int32) {
    888   // BooleanToNumber(x: kRepTagged) used as MachineType::Int32()
    889   TestingGraph t(Type::Boolean());
    890   Node* b = t.p0;
    891   Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
    892   Node* use = t.Use(cnv, MachineType::Int32());
    893   t.Return(use);
    894   t.Lower();
    895   CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
    896   CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
    897   Node* c = t.jsgraph.TrueConstant();
    898   CHECK(c == cnv->InputAt(0) || c == cnv->InputAt(1));
    899 }
    900 
    901 
    902 TEST(LowerBooleanToNumber_bit_tagged) {
    903   // BooleanToNumber(x: kRepBit) used as MachineType::AnyTagged()
    904   TestingGraph t(Type::Boolean());
    905   Node* b = t.ExampleWithOutput(MachineType::Bool());
    906   Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
    907   Node* use = t.Use(cnv, MachineType::AnyTagged());
    908   t.Return(use);
    909   t.Lower();
    910   CHECK_EQ(b, use->InputAt(0)->InputAt(0));
    911   CHECK_EQ(IrOpcode::kChangeUint32ToTagged, use->InputAt(0)->opcode());
    912 }
    913 
    914 
    915 TEST(LowerBooleanToNumber_tagged_tagged) {
    916   // BooleanToNumber(x: kRepTagged) used as MachineType::AnyTagged()
    917   TestingGraph t(Type::Boolean());
    918   Node* b = t.p0;
    919   Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
    920   Node* use = t.Use(cnv, MachineType::AnyTagged());
    921   t.Return(use);
    922   t.Lower();
    923   CHECK_EQ(cnv, use->InputAt(0)->InputAt(0));
    924   CHECK_EQ(IrOpcode::kChangeUint32ToTagged, use->InputAt(0)->opcode());
    925   CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
    926   CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
    927   Node* c = t.jsgraph.TrueConstant();
    928   CHECK(c == cnv->InputAt(0) || c == cnv->InputAt(1));
    929 }
    930 
    931 
    932 static Type* test_types[] = {Type::Signed32(), Type::Unsigned32(),
    933                              Type::Number(), Type::Any()};
    934 
    935 
    936 TEST(LowerNumberCmp_to_int32) {
    937   TestingGraph t(Type::Signed32(), Type::Signed32());
    938 
    939   t.CheckLoweringBinop(IrOpcode::kWord32Equal, t.simplified()->NumberEqual());
    940   t.CheckLoweringBinop(IrOpcode::kInt32LessThan,
    941                        t.simplified()->NumberLessThan());
    942   t.CheckLoweringBinop(IrOpcode::kInt32LessThanOrEqual,
    943                        t.simplified()->NumberLessThanOrEqual());
    944 }
    945 
    946 
    947 TEST(LowerNumberCmp_to_uint32) {
    948   TestingGraph t(Type::Unsigned32(), Type::Unsigned32());
    949 
    950   t.CheckLoweringBinop(IrOpcode::kWord32Equal, t.simplified()->NumberEqual());
    951   t.CheckLoweringBinop(IrOpcode::kUint32LessThan,
    952                        t.simplified()->NumberLessThan());
    953   t.CheckLoweringBinop(IrOpcode::kUint32LessThanOrEqual,
    954                        t.simplified()->NumberLessThanOrEqual());
    955 }
    956 
    957 
    958 TEST(LowerNumberCmp_to_float64) {
    959   static Type* types[] = {Type::Number(), Type::Any()};
    960 
    961   for (size_t i = 0; i < arraysize(types); i++) {
    962     TestingGraph t(types[i], types[i]);
    963 
    964     t.CheckLoweringBinop(IrOpcode::kFloat64Equal,
    965                          t.simplified()->NumberEqual());
    966     t.CheckLoweringBinop(IrOpcode::kFloat64LessThan,
    967                          t.simplified()->NumberLessThan());
    968     t.CheckLoweringBinop(IrOpcode::kFloat64LessThanOrEqual,
    969                          t.simplified()->NumberLessThanOrEqual());
    970   }
    971 }
    972 
    973 
    974 TEST(LowerNumberAddSub_to_int32) {
    975   HandleAndZoneScope scope;
    976   Type* small_range = Type::Range(1, 10, scope.main_zone());
    977   Type* large_range = Type::Range(-1e+13, 1e+14, scope.main_zone());
    978   static Type* types[] = {Type::Signed32(), Type::Integral32(), small_range,
    979                           large_range};
    980 
    981   for (size_t i = 0; i < arraysize(types); i++) {
    982     for (size_t j = 0; j < arraysize(types); j++) {
    983       TestingGraph t(types[i], types[j]);
    984       t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Add,
    985                                     t.simplified()->NumberAdd(),
    986                                     t.simplified()->NumberToInt32());
    987       t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Sub,
    988                                     t.simplified()->NumberSubtract(),
    989                                     t.simplified()->NumberToInt32());
    990     }
    991   }
    992 }
    993 
    994 
    995 TEST(LowerNumberAddSub_to_uint32) {
    996   HandleAndZoneScope scope;
    997   Type* small_range = Type::Range(1, 10, scope.main_zone());
    998   Type* large_range = Type::Range(-1e+13, 1e+14, scope.main_zone());
    999   static Type* types[] = {Type::Signed32(), Type::Integral32(), small_range,
   1000                           large_range};
   1001 
   1002   for (size_t i = 0; i < arraysize(types); i++) {
   1003     for (size_t j = 0; j < arraysize(types); j++) {
   1004       TestingGraph t(types[i], types[j]);
   1005       t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Add,
   1006                                     t.simplified()->NumberAdd(),
   1007                                     t.simplified()->NumberToUint32());
   1008       t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Sub,
   1009                                     t.simplified()->NumberSubtract(),
   1010                                     t.simplified()->NumberToUint32());
   1011     }
   1012   }
   1013 }
   1014 
   1015 
   1016 TEST(LowerNumberAddSub_to_float64) {
   1017   for (size_t i = 0; i < arraysize(test_types); i++) {
   1018     TestingGraph t(test_types[i], test_types[i]);
   1019 
   1020     t.CheckLoweringBinop(IrOpcode::kFloat64Add, t.simplified()->NumberAdd());
   1021     t.CheckLoweringBinop(IrOpcode::kFloat64Sub,
   1022                          t.simplified()->NumberSubtract());
   1023   }
   1024 }
   1025 
   1026 
   1027 TEST(LowerNumberDivMod_to_float64) {
   1028   for (size_t i = 0; i < arraysize(test_types); i++) {
   1029     TestingGraph t(test_types[i], test_types[i]);
   1030 
   1031     t.CheckLoweringBinop(IrOpcode::kFloat64Div, t.simplified()->NumberDivide());
   1032     if (!test_types[i]->Is(Type::Unsigned32())) {
   1033       t.CheckLoweringBinop(IrOpcode::kFloat64Mod,
   1034                            t.simplified()->NumberModulus());
   1035     }
   1036   }
   1037 }
   1038 
   1039 
   1040 static void CheckChangeOf(IrOpcode::Value change, Node* of, Node* node) {
   1041   CHECK_EQ(change, node->opcode());
   1042   CHECK_EQ(of, node->InputAt(0));
   1043 }
   1044 
   1045 
   1046 TEST(LowerNumberToInt32_to_ChangeTaggedToInt32) {
   1047   // NumberToInt32(x: kRepTagged | kTypeInt32) used as kRepWord32
   1048   TestingGraph t(Type::Signed32());
   1049   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
   1050   Node* use = t.Use(trunc, MachineType::Int32());
   1051   t.Return(use);
   1052   t.Lower();
   1053   CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0));
   1054 }
   1055 
   1056 
   1057 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) {
   1058   // NumberToInt32(x: kRepFloat64) used as MachineType::Int32()
   1059   TestingGraph t(Type::Number());
   1060   Node* p0 = t.ExampleWithOutput(MachineType::Float64());
   1061   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0);
   1062   Node* use = t.Use(trunc, MachineType::Int32());
   1063   t.Return(use);
   1064   t.Lower();
   1065   CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
   1066 }
   1067 
   1068 
   1069 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) {
   1070   // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Int32()
   1071   TestingGraph t(Type::Number());
   1072   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
   1073   Node* use = t.Use(trunc, MachineType::Int32());
   1074   t.Return(use);
   1075   t.Lower();
   1076   Node* node = use->InputAt(0);
   1077   CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode());
   1078   Node* of = node->InputAt(0);
   1079   CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode());
   1080   CHECK_EQ(t.p0, of->InputAt(0));
   1081 }
   1082 
   1083 
   1084 TEST(LowerNumberToUint32_to_ChangeTaggedToUint32) {
   1085   // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepWord32
   1086   TestingGraph t(Type::Unsigned32());
   1087   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
   1088   Node* use = t.Use(trunc, MachineType::Uint32());
   1089   t.Return(use);
   1090   t.Lower();
   1091   CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0));
   1092 }
   1093 
   1094 
   1095 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) {
   1096   // NumberToUint32(x: kRepFloat64) used as MachineType::Uint32()
   1097   TestingGraph t(Type::Number());
   1098   Node* p0 = t.ExampleWithOutput(MachineType::Float64());
   1099   // TODO(titzer): run the typer here, or attach machine type to param.
   1100   NodeProperties::SetType(p0, Type::Number());
   1101   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), p0);
   1102   Node* use = t.Use(trunc, MachineType::Uint32());
   1103   t.Return(use);
   1104   t.Lower();
   1105   CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
   1106 }
   1107 
   1108 
   1109 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) {
   1110   // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Uint32()
   1111   TestingGraph t(Type::Number());
   1112   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
   1113   Node* use = t.Use(trunc, MachineType::Uint32());
   1114   t.Return(use);
   1115   t.Lower();
   1116   Node* node = use->InputAt(0);
   1117   CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode());
   1118   Node* of = node->InputAt(0);
   1119   CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode());
   1120   CHECK_EQ(t.p0, of->InputAt(0));
   1121 }
   1122 
   1123 
   1124 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) {
   1125   // NumberToUint32(x: kRepFloat64) used as kRepWord32
   1126   TestingGraph t(Type::Unsigned32());
   1127   Node* input = t.ExampleWithOutput(MachineType::Float64());
   1128   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input);
   1129   Node* use = t.Use(trunc, MachineType::RepWord32());
   1130   t.Return(use);
   1131   t.Lower();
   1132   CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0));
   1133 }
   1134 
   1135 
   1136 TEST(LowerReferenceEqual_to_wordeq) {
   1137   TestingGraph t(Type::Any(), Type::Any());
   1138   IrOpcode::Value opcode =
   1139       static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode());
   1140   t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any()));
   1141 }
   1142 
   1143 
   1144 TEST(LowerStringOps_to_call_and_compare) {
   1145     // These tests need linkage for the calls.
   1146     TestingGraph t(Type::String(), Type::String());
   1147     IrOpcode::Value compare_eq =
   1148         static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode());
   1149     IrOpcode::Value compare_lt =
   1150         static_cast<IrOpcode::Value>(t.machine()->IntLessThan()->opcode());
   1151     IrOpcode::Value compare_le = static_cast<IrOpcode::Value>(
   1152         t.machine()->IntLessThanOrEqual()->opcode());
   1153     t.CheckLoweringStringBinop(compare_eq, t.simplified()->StringEqual());
   1154     t.CheckLoweringStringBinop(compare_lt, t.simplified()->StringLessThan());
   1155     t.CheckLoweringStringBinop(compare_le,
   1156                                t.simplified()->StringLessThanOrEqual());
   1157   }
   1158 
   1159 
   1160   void CheckChangeInsertion(IrOpcode::Value expected, MachineType from,
   1161                             MachineType to, Type* type = Type::Any()) {
   1162   TestingGraph t(Type::Any());
   1163   Node* in = t.ExampleWithOutput(from);
   1164   NodeProperties::SetType(in, type);
   1165   Node* use = t.Use(in, to);
   1166   t.Return(use);
   1167   t.Lower();
   1168   CHECK_EQ(expected, use->InputAt(0)->opcode());
   1169   CHECK_EQ(in, use->InputAt(0)->InputAt(0));
   1170 }
   1171 
   1172 
   1173 TEST(InsertBasicChanges) {
   1174   CheckChangeInsertion(IrOpcode::kChangeFloat64ToInt32, MachineType::Float64(),
   1175                        MachineType::Int32(), Type::Signed32());
   1176   CheckChangeInsertion(IrOpcode::kChangeFloat64ToUint32, MachineType::Float64(),
   1177                        MachineType::Uint32(), Type::Unsigned32());
   1178   CheckChangeInsertion(IrOpcode::kTruncateFloat64ToInt32,
   1179                        MachineType::Float64(), MachineType::Uint32(),
   1180                        Type::Integral32());
   1181   CheckChangeInsertion(IrOpcode::kChangeTaggedToInt32, MachineType::AnyTagged(),
   1182                        MachineType::Int32(), Type::Signed32());
   1183   CheckChangeInsertion(IrOpcode::kChangeTaggedToUint32,
   1184                        MachineType::AnyTagged(), MachineType::Uint32(),
   1185                        Type::Unsigned32());
   1186 
   1187   CheckChangeInsertion(IrOpcode::kChangeFloat64ToTagged, MachineType::Float64(),
   1188                        MachineType::AnyTagged());
   1189   CheckChangeInsertion(IrOpcode::kChangeTaggedToFloat64,
   1190                        MachineType::AnyTagged(), MachineType::Float64());
   1191 
   1192   CheckChangeInsertion(IrOpcode::kChangeInt32ToFloat64, MachineType::Int32(),
   1193                        MachineType::Float64());
   1194   CheckChangeInsertion(IrOpcode::kChangeInt32ToTagged, MachineType::Int32(),
   1195                        MachineType::AnyTagged());
   1196 
   1197   CheckChangeInsertion(IrOpcode::kChangeUint32ToFloat64, MachineType::Uint32(),
   1198                        MachineType::Float64());
   1199   CheckChangeInsertion(IrOpcode::kChangeUint32ToTagged, MachineType::Uint32(),
   1200                        MachineType::AnyTagged());
   1201 }
   1202 
   1203 
   1204 static void CheckChangesAroundBinop(TestingGraph* t, const Operator* op,
   1205                                     IrOpcode::Value input_change,
   1206                                     IrOpcode::Value output_change) {
   1207   Node* binop =
   1208       op->ControlInputCount() == 0
   1209           ? t->graph()->NewNode(op, t->p0, t->p1)
   1210           : t->graph()->NewNode(op, t->p0, t->p1, t->graph()->start());
   1211   t->Return(binop);
   1212   t->Lower();
   1213   CHECK_EQ(input_change, binop->InputAt(0)->opcode());
   1214   CHECK_EQ(input_change, binop->InputAt(1)->opcode());
   1215   CHECK_EQ(t->p0, binop->InputAt(0)->InputAt(0));
   1216   CHECK_EQ(t->p1, binop->InputAt(1)->InputAt(0));
   1217   CHECK_EQ(output_change, t->ret->InputAt(0)->opcode());
   1218   CHECK_EQ(binop, t->ret->InputAt(0)->InputAt(0));
   1219 }
   1220 
   1221 
   1222 TEST(InsertChangesAroundInt32Binops) {
   1223   TestingGraph t(Type::Signed32(), Type::Signed32());
   1224 
   1225   const Operator* ops[] = {t.machine()->Int32Add(),  t.machine()->Int32Sub(),
   1226                            t.machine()->Int32Mul(),  t.machine()->Int32Div(),
   1227                            t.machine()->Int32Mod(),  t.machine()->Word32And(),
   1228                            t.machine()->Word32Or(),  t.machine()->Word32Xor(),
   1229                            t.machine()->Word32Shl(), t.machine()->Word32Sar()};
   1230 
   1231   for (size_t i = 0; i < arraysize(ops); i++) {
   1232     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToInt32,
   1233                             IrOpcode::kChangeInt32ToTagged);
   1234   }
   1235 }
   1236 
   1237 
   1238 TEST(InsertChangesAroundInt32Cmp) {
   1239   TestingGraph t(Type::Signed32(), Type::Signed32());
   1240 
   1241   const Operator* ops[] = {t.machine()->Int32LessThan(),
   1242                            t.machine()->Int32LessThanOrEqual()};
   1243 
   1244   for (size_t i = 0; i < arraysize(ops); i++) {
   1245     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToInt32,
   1246                             IrOpcode::kChangeBitToBool);
   1247   }
   1248 }
   1249 
   1250 
   1251 TEST(InsertChangesAroundUint32Cmp) {
   1252   TestingGraph t(Type::Unsigned32(), Type::Unsigned32());
   1253 
   1254   const Operator* ops[] = {t.machine()->Uint32LessThan(),
   1255                            t.machine()->Uint32LessThanOrEqual()};
   1256 
   1257   for (size_t i = 0; i < arraysize(ops); i++) {
   1258     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToUint32,
   1259                             IrOpcode::kChangeBitToBool);
   1260   }
   1261 }
   1262 
   1263 
   1264 TEST(InsertChangesAroundFloat64Binops) {
   1265   TestingGraph t(Type::Number(), Type::Number());
   1266 
   1267   const Operator* ops[] = {
   1268       t.machine()->Float64Add(), t.machine()->Float64Sub(),
   1269       t.machine()->Float64Mul(), t.machine()->Float64Div(),
   1270       t.machine()->Float64Mod(),
   1271   };
   1272 
   1273   for (size_t i = 0; i < arraysize(ops); i++) {
   1274     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64,
   1275                             IrOpcode::kChangeFloat64ToTagged);
   1276   }
   1277 }
   1278 
   1279 
   1280 TEST(InsertChangesAroundFloat64Cmp) {
   1281   TestingGraph t(Type::Number(), Type::Number());
   1282 
   1283   const Operator* ops[] = {t.machine()->Float64Equal(),
   1284                            t.machine()->Float64LessThan(),
   1285                            t.machine()->Float64LessThanOrEqual()};
   1286 
   1287   for (size_t i = 0; i < arraysize(ops); i++) {
   1288     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64,
   1289                             IrOpcode::kChangeBitToBool);
   1290   }
   1291 }
   1292 
   1293 
   1294 namespace {
   1295 
   1296 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) {
   1297   IntPtrMatcher mindex(load_or_store->InputAt(1));
   1298   CHECK(mindex.Is(access.offset - access.tag()));
   1299 }
   1300 
   1301 
   1302 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) {
   1303   Node* index = load_or_store->InputAt(1);
   1304   if (kPointerSize == 8) {
   1305     CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode());
   1306     index = index->InputAt(0);
   1307   }
   1308 
   1309   Int32BinopMatcher mindex(index);
   1310   CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode());
   1311   CHECK(mindex.right().Is(access.header_size - access.tag()));
   1312 
   1313   const int element_size_shift =
   1314       ElementSizeLog2Of(access.machine_type.representation());
   1315   if (element_size_shift) {
   1316     Int32BinopMatcher shl(mindex.left().node());
   1317     CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode());
   1318     CHECK(shl.right().Is(element_size_shift));
   1319     return shl.left().node();
   1320   } else {
   1321     return mindex.left().node();
   1322   }
   1323 }
   1324 
   1325 
   1326 const MachineType kMachineReps[] = {
   1327     MachineType::Int8(),     MachineType::Int16(), MachineType::Int32(),
   1328     MachineType::Uint32(),   MachineType::Int64(), MachineType::Float64(),
   1329     MachineType::AnyTagged()};
   1330 
   1331 }  // namespace
   1332 
   1333 
   1334 TEST(LowerLoadField_to_load) {
   1335   TestingGraph t(Type::Any(), Type::Signed32());
   1336 
   1337   for (size_t i = 0; i < arraysize(kMachineReps); i++) {
   1338     FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1339                           Handle<Name>::null(), Type::Any(), kMachineReps[i]};
   1340 
   1341     Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
   1342                                     t.start, t.start);
   1343     Node* use = t.Use(load, kMachineReps[i]);
   1344     t.Return(use);
   1345     t.LowerAllNodesAndLowerChanges();
   1346     CHECK_EQ(IrOpcode::kLoad, load->opcode());
   1347     CHECK_EQ(t.p0, load->InputAt(0));
   1348     CheckFieldAccessArithmetic(access, load);
   1349 
   1350     MachineType rep = LoadRepresentationOf(load->op());
   1351     CHECK_EQ(kMachineReps[i], rep);
   1352   }
   1353 }
   1354 
   1355 
   1356 TEST(LowerStoreField_to_store) {
   1357   {
   1358     TestingGraph t(Type::Any(), Type::Signed32());
   1359 
   1360     for (size_t i = 0; i < arraysize(kMachineReps); i++) {
   1361       FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1362                             Handle<Name>::null(), Type::Any(), kMachineReps[i]};
   1363 
   1364 
   1365       Node* val = t.ExampleWithOutput(kMachineReps[i]);
   1366       Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
   1367                                        val, t.start, t.start);
   1368       t.Effect(store);
   1369       t.LowerAllNodesAndLowerChanges();
   1370       CHECK_EQ(IrOpcode::kStore, store->opcode());
   1371       CHECK_EQ(val, store->InputAt(2));
   1372       CheckFieldAccessArithmetic(access, store);
   1373 
   1374       StoreRepresentation rep = StoreRepresentationOf(store->op());
   1375       if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
   1376         CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
   1377       }
   1378       CHECK_EQ(kMachineReps[i].representation(), rep.representation());
   1379     }
   1380   }
   1381   {
   1382     HandleAndZoneScope scope;
   1383     Zone* z = scope.main_zone();
   1384     TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(),
   1385                                                 Type::TaggedSigned(), z));
   1386     FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1387                           Handle<Name>::null(), Type::Any(),
   1388                           MachineType::AnyTagged()};
   1389     Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
   1390                                      t.p1, t.start, t.start);
   1391     t.Effect(store);
   1392     t.LowerAllNodesAndLowerChanges();
   1393     CHECK_EQ(IrOpcode::kStore, store->opcode());
   1394     CHECK_EQ(t.p1, store->InputAt(2));
   1395     StoreRepresentation rep = StoreRepresentationOf(store->op());
   1396     CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
   1397   }
   1398 }
   1399 
   1400 
   1401 TEST(LowerLoadElement_to_load) {
   1402   TestingGraph t(Type::Any(), Type::Signed32());
   1403 
   1404   for (size_t i = 0; i < arraysize(kMachineReps); i++) {
   1405     ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1406                             Type::Any(), kMachineReps[i]};
   1407 
   1408     Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
   1409                                     t.p1, t.start, t.start);
   1410     Node* use = t.Use(load, kMachineReps[i]);
   1411     t.Return(use);
   1412     t.LowerAllNodesAndLowerChanges();
   1413     CHECK_EQ(IrOpcode::kLoad, load->opcode());
   1414     CHECK_EQ(t.p0, load->InputAt(0));
   1415     CheckElementAccessArithmetic(access, load);
   1416 
   1417     MachineType rep = LoadRepresentationOf(load->op());
   1418     CHECK_EQ(kMachineReps[i], rep);
   1419   }
   1420 }
   1421 
   1422 
   1423 TEST(LowerStoreElement_to_store) {
   1424   {
   1425     TestingGraph t(Type::Any(), Type::Signed32());
   1426 
   1427     for (size_t i = 0; i < arraysize(kMachineReps); i++) {
   1428       ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1429                               Type::Any(), kMachineReps[i]};
   1430 
   1431       Node* val = t.ExampleWithOutput(kMachineReps[i]);
   1432       Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access),
   1433                                        t.p0, t.p1, val, t.start, t.start);
   1434       t.Effect(store);
   1435       t.LowerAllNodesAndLowerChanges();
   1436       CHECK_EQ(IrOpcode::kStore, store->opcode());
   1437       CHECK_EQ(val, store->InputAt(2));
   1438       CheckElementAccessArithmetic(access, store);
   1439 
   1440       StoreRepresentation rep = StoreRepresentationOf(store->op());
   1441       if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
   1442         CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
   1443       }
   1444       CHECK_EQ(kMachineReps[i].representation(), rep.representation());
   1445     }
   1446   }
   1447   {
   1448     HandleAndZoneScope scope;
   1449     Zone* z = scope.main_zone();
   1450     TestingGraph t(
   1451         Type::Any(), Type::Signed32(),
   1452         Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z));
   1453     ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1454                             Type::Any(), MachineType::AnyTagged()};
   1455     Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
   1456                                      t.p1, t.p2, t.start, t.start);
   1457     t.Effect(store);
   1458     t.LowerAllNodesAndLowerChanges();
   1459     CHECK_EQ(IrOpcode::kStore, store->opcode());
   1460     CHECK_EQ(t.p2, store->InputAt(2));
   1461     StoreRepresentation rep = StoreRepresentationOf(store->op());
   1462     CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
   1463   }
   1464 }
   1465 
   1466 
   1467 TEST(InsertChangeForLoadElementIndex) {
   1468   // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) =>
   1469   //   Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k))
   1470   TestingGraph t(Type::Any(), Type::Signed32());
   1471   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
   1472                           MachineType::AnyTagged()};
   1473 
   1474   Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
   1475                                   t.p1, t.start, t.start);
   1476   t.Return(load);
   1477   t.Lower();
   1478   CHECK_EQ(IrOpcode::kLoadElement, load->opcode());
   1479   CHECK_EQ(t.p0, load->InputAt(0));
   1480   CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, load->InputAt(1));
   1481 }
   1482 
   1483 
   1484 TEST(InsertChangeForStoreElementIndex) {
   1485   // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) =>
   1486   //   Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val)
   1487   TestingGraph t(Type::Any(), Type::Signed32());
   1488   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
   1489                           MachineType::AnyTagged()};
   1490 
   1491   Node* store =
   1492       t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1,
   1493                          t.jsgraph.TrueConstant(), t.start, t.start);
   1494   t.Effect(store);
   1495   t.Lower();
   1496   CHECK_EQ(IrOpcode::kStoreElement, store->opcode());
   1497   CHECK_EQ(t.p0, store->InputAt(0));
   1498   CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, store->InputAt(1));
   1499 }
   1500 
   1501 
   1502 TEST(InsertChangeForLoadElement) {
   1503   // TODO(titzer): test all load/store representation change insertions.
   1504   TestingGraph t(Type::Any(), Type::Signed32(), Type::Any());
   1505   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
   1506                           MachineType::Float64()};
   1507 
   1508   Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
   1509                                   t.p1, t.start, t.start);
   1510   t.Return(load);
   1511   t.Lower();
   1512   CHECK_EQ(IrOpcode::kLoadElement, load->opcode());
   1513   CHECK_EQ(t.p0, load->InputAt(0));
   1514   CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
   1515 }
   1516 
   1517 
   1518 TEST(InsertChangeForLoadField) {
   1519   // TODO(titzer): test all load/store representation change insertions.
   1520   TestingGraph t(Type::Any(), Type::Signed32());
   1521   FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1522                         Handle<Name>::null(), Type::Any(),
   1523                         MachineType::Float64()};
   1524 
   1525   Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
   1526                                   t.start, t.start);
   1527   t.Return(load);
   1528   t.Lower();
   1529   CHECK_EQ(IrOpcode::kLoadField, load->opcode());
   1530   CHECK_EQ(t.p0, load->InputAt(0));
   1531   CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
   1532 }
   1533 
   1534 
   1535 TEST(InsertChangeForStoreElement) {
   1536   // TODO(titzer): test all load/store representation change insertions.
   1537   TestingGraph t(Type::Any(), Type::Signed32());
   1538   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
   1539                           MachineType::Float64()};
   1540 
   1541   Node* store =
   1542       t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
   1543                          t.jsgraph.Int32Constant(0), t.p1, t.start, t.start);
   1544   t.Effect(store);
   1545   t.Lower();
   1546 
   1547   CHECK_EQ(IrOpcode::kStoreElement, store->opcode());
   1548   CHECK_EQ(t.p0, store->InputAt(0));
   1549   CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2));
   1550 }
   1551 
   1552 
   1553 TEST(InsertChangeForStoreField) {
   1554   // TODO(titzer): test all load/store representation change insertions.
   1555   TestingGraph t(Type::Any(), Type::Signed32());
   1556   FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1557                         Handle<Name>::null(), Type::Any(),
   1558                         MachineType::Float64()};
   1559 
   1560   Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
   1561                                    t.p1, t.start, t.start);
   1562   t.Effect(store);
   1563   t.Lower();
   1564 
   1565   CHECK_EQ(IrOpcode::kStoreField, store->opcode());
   1566   CHECK_EQ(t.p0, store->InputAt(0));
   1567   CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(1));
   1568 }
   1569 
   1570 
   1571 TEST(UpdatePhi) {
   1572   TestingGraph t(Type::Any(), Type::Signed32());
   1573   static const MachineType kMachineTypes[] = {
   1574       MachineType::Int32(), MachineType::Uint32(), MachineType::Float64()};
   1575   Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()};
   1576 
   1577   for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
   1578     FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
   1579                           Handle<Name>::null(), kTypes[i], kMachineTypes[i]};
   1580 
   1581     Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
   1582                                      t.start, t.start);
   1583     Node* load1 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p1,
   1584                                      t.start, t.start);
   1585     Node* phi =
   1586         t.graph()->NewNode(t.common()->Phi(MachineRepresentation::kTagged, 2),
   1587                            load0, load1, t.start);
   1588     t.Return(t.Use(phi, kMachineTypes[i]));
   1589     t.Lower();
   1590 
   1591     CHECK_EQ(IrOpcode::kPhi, phi->opcode());
   1592     CHECK_EQ(kMachineTypes[i].representation(), PhiRepresentationOf(phi->op()));
   1593   }
   1594 }
   1595 
   1596 
   1597 TEST(RunNumberDivide_minus_1_TruncatingToInt32) {
   1598   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1599   Node* num = t.NumberToInt32(t.Parameter(0));
   1600   Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1));
   1601   Node* trunc = t.NumberToInt32(div);
   1602   t.Return(trunc);
   1603 
   1604   t.LowerAllNodesAndLowerChanges();
   1605   t.GenerateCode();
   1606 
   1607   FOR_INT32_INPUTS(i) {
   1608     int32_t x = 0 - *i;
   1609     t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1610   }
   1611 }
   1612 
   1613 
   1614 TEST(RunNumberMultiply_TruncatingToInt32) {
   1615   int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000, 3000999};
   1616 
   1617   for (size_t i = 0; i < arraysize(constants); i++) {
   1618     double k = static_cast<double>(constants[i]);
   1619     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1620     Node* num = t.NumberToInt32(t.Parameter(0));
   1621     Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k));
   1622     Node* trunc = t.NumberToInt32(mul);
   1623     t.Return(trunc);
   1624 
   1625       t.LowerAllNodesAndLowerChanges();
   1626       t.GenerateCode();
   1627 
   1628       FOR_INT32_INPUTS(i) {
   1629         int32_t x = DoubleToInt32(static_cast<double>(*i) * k);
   1630         t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1631       }
   1632     }
   1633 }
   1634 
   1635 
   1636 TEST(RunNumberMultiply_TruncatingToUint32) {
   1637   uint32_t constants[] = {0, 1, 2, 3, 4, 100, 1000, 1024, 2048, 3000999};
   1638 
   1639   for (size_t i = 0; i < arraysize(constants); i++) {
   1640     double k = static_cast<double>(constants[i]);
   1641     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1642     Node* num = t.NumberToUint32(t.Parameter(0));
   1643     Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k));
   1644     Node* trunc = t.NumberToUint32(mul);
   1645     t.Return(trunc);
   1646 
   1647       t.LowerAllNodesAndLowerChanges();
   1648       t.GenerateCode();
   1649 
   1650       FOR_UINT32_INPUTS(i) {
   1651         uint32_t x = DoubleToUint32(static_cast<double>(*i) * k);
   1652         t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1653     }
   1654   }
   1655 }
   1656 
   1657 
   1658 TEST(RunNumberDivide_2_TruncatingToUint32) {
   1659   SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1660   Node* num = t.NumberToUint32(t.Parameter(0));
   1661   Node* div = t.NumberDivide(num, t.jsgraph.Constant(2));
   1662   Node* trunc = t.NumberToUint32(div);
   1663   t.Return(trunc);
   1664 
   1665     t.LowerAllNodesAndLowerChanges();
   1666     t.GenerateCode();
   1667 
   1668     FOR_UINT32_INPUTS(i) {
   1669       uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0));
   1670       t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1671     }
   1672 }
   1673 
   1674 
   1675 TEST(NumberMultiply_ConstantOutOfRange) {
   1676   TestingGraph t(Type::Signed32());
   1677   Node* k = t.jsgraph.Constant(1000000023);
   1678   Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k);
   1679   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul);
   1680   t.Return(trunc);
   1681   t.Lower();
   1682 
   1683   CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode());
   1684 }
   1685 
   1686 
   1687 TEST(NumberMultiply_NonTruncating) {
   1688   TestingGraph t(Type::Signed32());
   1689   Node* k = t.jsgraph.Constant(111);
   1690   Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k);
   1691   t.Return(mul);
   1692   t.Lower();
   1693 
   1694   CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode());
   1695 }
   1696 
   1697 
   1698 TEST(NumberDivide_TruncatingToInt32) {
   1699   int32_t constants[] = {-100, -10, 1, 4, 100, 1000};
   1700 
   1701   for (size_t i = 0; i < arraysize(constants); i++) {
   1702     TestingGraph t(Type::Signed32());
   1703     Node* k = t.jsgraph.Constant(constants[i]);
   1704     Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
   1705     Node* use = t.Use(div, MachineType::Int32());
   1706     t.Return(use);
   1707     t.Lower();
   1708 
   1709     CHECK_EQ(IrOpcode::kInt32Div, use->InputAt(0)->opcode());
   1710   }
   1711 }
   1712 
   1713 
   1714 TEST(RunNumberDivide_TruncatingToInt32) {
   1715   int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048};
   1716 
   1717   for (size_t i = 0; i < arraysize(constants); i++) {
   1718     int32_t k = constants[i];
   1719     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1720     Node* num = t.NumberToInt32(t.Parameter(0));
   1721     Node* div = t.NumberDivide(num, t.jsgraph.Constant(k));
   1722     Node* trunc = t.NumberToInt32(div);
   1723     t.Return(trunc);
   1724 
   1725       t.LowerAllNodesAndLowerChanges();
   1726       t.GenerateCode();
   1727 
   1728       FOR_INT32_INPUTS(i) {
   1729         if (*i == INT_MAX) continue;  // exclude max int.
   1730         int32_t x = DoubleToInt32(static_cast<double>(*i) / k);
   1731         t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1732     }
   1733   }
   1734 }
   1735 
   1736 
   1737 TEST(NumberDivide_TruncatingToUint32) {
   1738   double constants[] = {1, 3, 100, 1000, 100998348};
   1739 
   1740   for (size_t i = 0; i < arraysize(constants); i++) {
   1741     TestingGraph t(Type::Unsigned32());
   1742     Node* k = t.jsgraph.Constant(constants[i]);
   1743     Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
   1744     Node* use = t.Use(div, MachineType::Uint32());
   1745     t.Return(use);
   1746     t.Lower();
   1747 
   1748     CHECK_EQ(IrOpcode::kUint32Div, use->InputAt(0)->opcode());
   1749   }
   1750 }
   1751 
   1752 
   1753 TEST(RunNumberDivide_TruncatingToUint32) {
   1754   uint32_t constants[] = {100, 10, 1, 1, 2, 4, 1000, 1024, 2048};
   1755 
   1756   for (size_t i = 0; i < arraysize(constants); i++) {
   1757     uint32_t k = constants[i];
   1758     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1759     Node* num = t.NumberToUint32(t.Parameter(0));
   1760     Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k)));
   1761     Node* trunc = t.NumberToUint32(div);
   1762     t.Return(trunc);
   1763 
   1764       t.LowerAllNodesAndLowerChanges();
   1765       t.GenerateCode();
   1766 
   1767       FOR_UINT32_INPUTS(i) {
   1768         uint32_t x = *i / k;
   1769         t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1770     }
   1771   }
   1772 }
   1773 
   1774 
   1775 TEST(NumberDivide_BadConstants) {
   1776   {
   1777     TestingGraph t(Type::Signed32());
   1778     Node* k = t.jsgraph.Constant(-1);
   1779     Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
   1780     Node* use = t.Use(div, MachineType::Int32());
   1781     t.Return(use);
   1782     t.Lower();
   1783 
   1784     CHECK_EQ(IrOpcode::kInt32Sub, use->InputAt(0)->opcode());
   1785   }
   1786 
   1787   {
   1788     TestingGraph t(Type::Signed32());
   1789     Node* k = t.jsgraph.Constant(0);
   1790     Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
   1791     Node* use = t.Use(div, MachineType::Int32());
   1792     t.Return(use);
   1793     t.Lower();
   1794 
   1795     CHECK_EQ(IrOpcode::kInt32Constant, use->InputAt(0)->opcode());
   1796     CHECK_EQ(0, OpParameter<int32_t>(use->InputAt(0)));
   1797   }
   1798 
   1799   {
   1800     TestingGraph t(Type::Unsigned32());
   1801     Node* k = t.jsgraph.Constant(0);
   1802     Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
   1803     Node* use = t.Use(div, MachineType::Uint32());
   1804     t.Return(use);
   1805     t.Lower();
   1806 
   1807     CHECK_EQ(IrOpcode::kInt32Constant, use->InputAt(0)->opcode());
   1808     CHECK_EQ(0, OpParameter<int32_t>(use->InputAt(0)));
   1809   }
   1810 }
   1811 
   1812 
   1813 TEST(NumberModulus_TruncatingToInt32) {
   1814   int32_t constants[] = {-100, -10, 1, 4, 100, 1000};
   1815 
   1816   for (size_t i = 0; i < arraysize(constants); i++) {
   1817     TestingGraph t(Type::Signed32());
   1818     Node* k = t.jsgraph.Constant(constants[i]);
   1819     Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
   1820     Node* use = t.Use(mod, MachineType::Int32());
   1821     t.Return(use);
   1822     t.Lower();
   1823 
   1824     CHECK_EQ(IrOpcode::kInt32Mod, use->InputAt(0)->opcode());
   1825   }
   1826 }
   1827 
   1828 
   1829 TEST(RunNumberModulus_TruncatingToInt32) {
   1830   int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048};
   1831 
   1832   for (size_t i = 0; i < arraysize(constants); i++) {
   1833     int32_t k = constants[i];
   1834     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1835     Node* num = t.NumberToInt32(t.Parameter(0));
   1836     Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k));
   1837     Node* trunc = t.NumberToInt32(mod);
   1838     t.Return(trunc);
   1839 
   1840       t.LowerAllNodesAndLowerChanges();
   1841       t.GenerateCode();
   1842 
   1843       FOR_INT32_INPUTS(i) {
   1844         if (*i == INT_MAX) continue;  // exclude max int.
   1845         int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k));
   1846         t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1847     }
   1848   }
   1849 }
   1850 
   1851 
   1852 TEST(NumberModulus_TruncatingToUint32) {
   1853   double constants[] = {1, 3, 100, 1000, 100998348};
   1854 
   1855   for (size_t i = 0; i < arraysize(constants); i++) {
   1856     TestingGraph t(Type::Unsigned32());
   1857     Node* k = t.jsgraph.Constant(constants[i]);
   1858     Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
   1859     Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod);
   1860     t.Return(trunc);
   1861     t.Lower();
   1862 
   1863     CHECK_EQ(IrOpcode::kUint32Mod, t.ret->InputAt(0)->InputAt(0)->opcode());
   1864   }
   1865 }
   1866 
   1867 
   1868 TEST(RunNumberModulus_TruncatingToUint32) {
   1869   uint32_t constants[] = {1, 2, 100, 1000, 1024, 2048};
   1870 
   1871   for (size_t i = 0; i < arraysize(constants); i++) {
   1872     uint32_t k = constants[i];
   1873     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
   1874     Node* num = t.NumberToUint32(t.Parameter(0));
   1875     Node* mod =
   1876         t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k)));
   1877     Node* trunc = t.NumberToUint32(mod);
   1878     t.Return(trunc);
   1879 
   1880       t.LowerAllNodesAndLowerChanges();
   1881       t.GenerateCode();
   1882 
   1883       FOR_UINT32_INPUTS(i) {
   1884         uint32_t x = *i % k;
   1885         t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
   1886     }
   1887   }
   1888 }
   1889 
   1890 
   1891 TEST(NumberModulus_Int32) {
   1892   int32_t constants[] = {-100, -10, 1, 4, 100, 1000};
   1893 
   1894   for (size_t i = 0; i < arraysize(constants); i++) {
   1895     TestingGraph t(Type::Signed32());
   1896     Node* k = t.jsgraph.Constant(constants[i]);
   1897     Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
   1898     t.Return(mod);
   1899     t.Lower();
   1900 
   1901     CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode());  // Pesky -0 behavior.
   1902   }
   1903 }
   1904 
   1905 
   1906 TEST(NumberModulus_Uint32) {
   1907   const double kConstants[] = {2, 100, 1000, 1024, 2048};
   1908   const MachineType kTypes[] = {MachineType::Int32(), MachineType::Uint32()};
   1909 
   1910   for (auto const type : kTypes) {
   1911     for (auto const c : kConstants) {
   1912       TestingGraph t(Type::Unsigned32());
   1913       Node* k = t.jsgraph.Constant(c);
   1914       Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
   1915       Node* use = t.Use(mod, type);
   1916       t.Return(use);
   1917       t.Lower();
   1918 
   1919       CHECK_EQ(IrOpcode::kUint32Mod, use->InputAt(0)->opcode());
   1920     }
   1921   }
   1922 }
   1923 
   1924 
   1925 TEST(PhiRepresentation) {
   1926   HandleAndZoneScope scope;
   1927   Zone* z = scope.main_zone();
   1928 
   1929   struct TestData {
   1930     Type* arg1;
   1931     Type* arg2;
   1932     MachineType use;
   1933     MachineRepresentation expected;
   1934   };
   1935 
   1936   TestData test_data[] = {
   1937       {Type::Signed32(), Type::Unsigned32(), MachineType::Int32(),
   1938        MachineRepresentation::kWord32},
   1939       {Type::Signed32(), Type::Unsigned32(), MachineType::Uint32(),
   1940        MachineRepresentation::kWord32},
   1941       {Type::Signed32(), Type::Signed32(), MachineType::Int32(),
   1942        MachineRepresentation::kWord32},
   1943       {Type::Unsigned32(), Type::Unsigned32(), MachineType::Int32(),
   1944        MachineRepresentation::kWord32},
   1945       {Type::Number(), Type::Signed32(), MachineType::Int32(),
   1946        MachineRepresentation::kWord32}};
   1947 
   1948   for (auto const d : test_data) {
   1949     TestingGraph t(d.arg1, d.arg2, Type::Boolean());
   1950 
   1951     Node* br = t.graph()->NewNode(t.common()->Branch(), t.p2, t.start);
   1952     Node* tb = t.graph()->NewNode(t.common()->IfTrue(), br);
   1953     Node* fb = t.graph()->NewNode(t.common()->IfFalse(), br);
   1954     Node* m = t.graph()->NewNode(t.common()->Merge(2), tb, fb);
   1955 
   1956     Node* phi = t.graph()->NewNode(
   1957         t.common()->Phi(MachineRepresentation::kTagged, 2), t.p0, t.p1, m);
   1958 
   1959     Type* phi_type = Type::Union(d.arg1, d.arg2, z);
   1960     NodeProperties::SetType(phi, phi_type);
   1961 
   1962     Node* use = t.Use(phi, d.use);
   1963     t.Return(use);
   1964     t.Lower();
   1965 
   1966     CHECK_EQ(d.expected, PhiRepresentationOf(phi->op()));
   1967   }
   1968 }
   1969 
   1970 }  // namespace compiler
   1971 }  // namespace internal
   1972 }  // namespace v8
   1973