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