| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits> | 5 #include <limits> |
| 6 | 6 |
| 7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
| 8 #include "src/compiler/change-lowering.h" |
| 8 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 9 #include "src/compiler/generic-node-inl.h" | 10 #include "src/compiler/generic-node-inl.h" |
| 11 #include "src/compiler/graph-reducer.h" |
| 10 #include "src/compiler/graph-visualizer.h" | 12 #include "src/compiler/graph-visualizer.h" |
| 11 #include "src/compiler/node-properties-inl.h" | 13 #include "src/compiler/node-properties-inl.h" |
| 12 #include "src/compiler/pipeline.h" | 14 #include "src/compiler/pipeline.h" |
| 13 #include "src/compiler/representation-change.h" | 15 #include "src/compiler/representation-change.h" |
| 14 #include "src/compiler/simplified-lowering.h" | 16 #include "src/compiler/simplified-lowering.h" |
| 15 #include "src/compiler/typer.h" | 17 #include "src/compiler/typer.h" |
| 16 #include "src/compiler/verifier.h" | 18 #include "src/compiler/verifier.h" |
| 17 #include "src/execution.h" | 19 #include "src/execution.h" |
| 18 #include "src/parser.h" | 20 #include "src/parser.h" |
| 19 #include "src/rewriter.h" | 21 #include "src/rewriter.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 44 Typer typer; | 46 Typer typer; |
| 45 JSOperatorBuilder javascript; | 47 JSOperatorBuilder javascript; |
| 46 JSGraph jsgraph; | 48 JSGraph jsgraph; |
| 47 SimplifiedLowering lowering; | 49 SimplifiedLowering lowering; |
| 48 | 50 |
| 49 void LowerAllNodes() { | 51 void LowerAllNodes() { |
| 50 this->End(); | 52 this->End(); |
| 51 lowering.LowerAllNodes(); | 53 lowering.LowerAllNodes(); |
| 52 } | 54 } |
| 53 | 55 |
| 56 void LowerAllNodesAndLowerChanges() { |
| 57 this->End(); |
| 58 typer.Run(jsgraph.graph(), MaybeHandle<Context>()); |
| 59 lowering.LowerAllNodes(); |
| 60 |
| 61 Zone* zone = this->zone(); |
| 62 CompilationInfo info(zone->isolate(), zone); |
| 63 Linkage linkage( |
| 64 &info, Linkage::GetSimplifiedCDescriptor(zone, this->machine_sig_)); |
| 65 ChangeLowering lowering(&jsgraph, &linkage); |
| 66 GraphReducer reducer(this->graph()); |
| 67 reducer.AddReducer(&lowering); |
| 68 reducer.ReduceGraph(); |
| 69 Verifier::Run(this->graph()); |
| 70 } |
| 71 |
| 54 Factory* factory() { return this->isolate()->factory(); } | 72 Factory* factory() { return this->isolate()->factory(); } |
| 55 Heap* heap() { return this->isolate()->heap(); } | 73 Heap* heap() { return this->isolate()->heap(); } |
| 56 }; | 74 }; |
| 57 | 75 |
| 58 | 76 |
| 59 // TODO(titzer): factor these tests out to test-run-simplifiedops.cc. | 77 // TODO(titzer): factor these tests out to test-run-simplifiedops.cc. |
| 60 // TODO(titzer): test tagged representation for input to NumberToInt32. | 78 // TODO(titzer): test tagged representation for input to NumberToInt32. |
| 61 TEST(RunNumberToInt32_float64) { | 79 TEST(RunNumberToInt32_float64) { |
| 62 // TODO(titzer): explicit load/stores here are only because of representations | 80 // TODO(titzer): explicit load/stores here are only because of representations |
| 63 double input; | 81 double input; |
| 64 int32_t result; | 82 int32_t result; |
| 65 SimplifiedLoweringTester<Object*> t; | 83 SimplifiedLoweringTester<Object*> t; |
| 66 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 84 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), |
| 67 kMachFloat64}; | 85 kMachFloat64}; |
| 68 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 86 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 87 NodeProperties::SetBounds(loaded, Bounds(Type::Number())); |
| 69 Node* convert = t.NumberToInt32(loaded); | 88 Node* convert = t.NumberToInt32(loaded); |
| 70 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), | 89 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), |
| 71 kMachInt32}; | 90 kMachInt32}; |
| 72 t.StoreField(store, t.PointerConstant(&result), convert); | 91 t.StoreField(store, t.PointerConstant(&result), convert); |
| 73 t.Return(t.jsgraph.TrueConstant()); | 92 t.Return(t.jsgraph.TrueConstant()); |
| 74 t.LowerAllNodes(); | 93 t.LowerAllNodes(); |
| 75 t.GenerateCode(); | 94 t.GenerateCode(); |
| 76 | 95 |
| 77 if (Pipeline::SupportedTarget()) { | 96 if (Pipeline::SupportedTarget()) { |
| 78 FOR_FLOAT64_INPUTS(i) { | 97 FOR_FLOAT64_INPUTS(i) { |
| 79 input = *i; | 98 input = *i; |
| 80 int32_t expected = DoubleToInt32(*i); | 99 int32_t expected = DoubleToInt32(*i); |
| 81 t.Call(); | 100 t.Call(); |
| 82 CHECK_EQ(expected, result); | 101 CHECK_EQ(expected, result); |
| 83 } | 102 } |
| 84 } | 103 } |
| 85 } | 104 } |
| 86 | 105 |
| 87 | 106 |
| 88 // TODO(titzer): test tagged representation for input to NumberToUint32. | 107 // TODO(titzer): test tagged representation for input to NumberToUint32. |
| 89 TEST(RunNumberToUint32_float64) { | 108 TEST(RunNumberToUint32_float64) { |
| 90 // TODO(titzer): explicit load/stores here are only because of representations | 109 // TODO(titzer): explicit load/stores here are only because of representations |
| 91 double input; | 110 double input; |
| 92 uint32_t result; | 111 uint32_t result; |
| 93 SimplifiedLoweringTester<Object*> t; | 112 SimplifiedLoweringTester<Object*> t; |
| 94 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 113 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), |
| 95 kMachFloat64}; | 114 kMachFloat64}; |
| 96 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 115 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 116 NodeProperties::SetBounds(loaded, Bounds(Type::Number())); |
| 97 Node* convert = t.NumberToUint32(loaded); | 117 Node* convert = t.NumberToUint32(loaded); |
| 98 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), | 118 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), |
| 99 kMachUint32}; | 119 kMachUint32}; |
| 100 t.StoreField(store, t.PointerConstant(&result), convert); | 120 t.StoreField(store, t.PointerConstant(&result), convert); |
| 101 t.Return(t.jsgraph.TrueConstant()); | 121 t.Return(t.jsgraph.TrueConstant()); |
| 102 t.LowerAllNodes(); | 122 t.LowerAllNodes(); |
| 103 t.GenerateCode(); | 123 t.GenerateCode(); |
| 104 | 124 |
| 105 if (Pipeline::SupportedTarget()) { | 125 if (Pipeline::SupportedTarget()) { |
| 106 FOR_FLOAT64_INPUTS(i) { | 126 FOR_FLOAT64_INPUTS(i) { |
| (...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 t.Return(use); | 1017 t.Return(use); |
| 998 t.Lower(); | 1018 t.Lower(); |
| 999 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0)); | 1019 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0)); |
| 1000 } | 1020 } |
| 1001 | 1021 |
| 1002 | 1022 |
| 1003 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { | 1023 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { |
| 1004 // NumberToInt32(x: kRepFloat64) used as kMachInt32 | 1024 // NumberToInt32(x: kRepFloat64) used as kMachInt32 |
| 1005 TestingGraph t(Type::Number()); | 1025 TestingGraph t(Type::Number()); |
| 1006 Node* p0 = t.ExampleWithOutput(kMachFloat64); | 1026 Node* p0 = t.ExampleWithOutput(kMachFloat64); |
| 1027 // TODO(titzer): run the typer here, or attach machine type to param. |
| 1028 NodeProperties::SetBounds(p0, Bounds(Type::Number())); |
| 1007 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); | 1029 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); |
| 1008 Node* use = t.Use(trunc, kMachInt32); | 1030 Node* use = t.Use(trunc, kMachInt32); |
| 1009 t.Return(use); | 1031 t.Return(use); |
| 1010 t.Lower(); | 1032 t.Lower(); |
| 1011 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); | 1033 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); |
| 1012 } | 1034 } |
| 1013 | 1035 |
| 1014 | 1036 |
| 1015 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { | 1037 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { |
| 1016 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 | 1038 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 t.Return(use); | 1090 t.Return(use); |
| 1069 t.Lower(); | 1091 t.Lower(); |
| 1070 CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0)); | 1092 CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0)); |
| 1071 } | 1093 } |
| 1072 | 1094 |
| 1073 | 1095 |
| 1074 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) { | 1096 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) { |
| 1075 // NumberToUint32(x: kRepFloat64) used as kMachUint32 | 1097 // NumberToUint32(x: kRepFloat64) used as kMachUint32 |
| 1076 TestingGraph t(Type::Number()); | 1098 TestingGraph t(Type::Number()); |
| 1077 Node* p0 = t.ExampleWithOutput(kMachFloat64); | 1099 Node* p0 = t.ExampleWithOutput(kMachFloat64); |
| 1100 // TODO(titzer): run the typer here, or attach machine type to param. |
| 1101 NodeProperties::SetBounds(p0, Bounds(Type::Number())); |
| 1078 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), p0); | 1102 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), p0); |
| 1079 Node* use = t.Use(trunc, kMachUint32); | 1103 Node* use = t.Use(trunc, kMachUint32); |
| 1080 t.Return(use); | 1104 t.Return(use); |
| 1081 t.Lower(); | 1105 t.Lower(); |
| 1082 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); | 1106 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); |
| 1083 } | 1107 } |
| 1084 | 1108 |
| 1085 | 1109 |
| 1086 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) { | 1110 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) { |
| 1087 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachUint32 | 1111 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachUint32 |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1519 Node* phi = t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), load0, | 1543 Node* phi = t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), load0, |
| 1520 load1, t.start); | 1544 load1, t.start); |
| 1521 t.Return(t.Use(phi, kMachineTypes[i])); | 1545 t.Return(t.Use(phi, kMachineTypes[i])); |
| 1522 t.Lower(); | 1546 t.Lower(); |
| 1523 | 1547 |
| 1524 CHECK_EQ(IrOpcode::kPhi, phi->opcode()); | 1548 CHECK_EQ(IrOpcode::kPhi, phi->opcode()); |
| 1525 CHECK_EQ(RepresentationOf(kMachineTypes[i]), | 1549 CHECK_EQ(RepresentationOf(kMachineTypes[i]), |
| 1526 RepresentationOf(OpParameter<MachineType>(phi))); | 1550 RepresentationOf(OpParameter<MachineType>(phi))); |
| 1527 } | 1551 } |
| 1528 } | 1552 } |
| 1553 |
| 1554 |
| 1555 TEST(RunNumberDivide_minus_1_TruncatingToInt32) { |
| 1556 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1557 Node* num = t.NumberToInt32(t.Parameter(0)); |
| 1558 Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1)); |
| 1559 Node* trunc = t.NumberToInt32(div); |
| 1560 t.Return(trunc); |
| 1561 |
| 1562 if (Pipeline::SupportedTarget()) { |
| 1563 t.LowerAllNodesAndLowerChanges(); |
| 1564 t.GenerateCode(); |
| 1565 |
| 1566 FOR_INT32_INPUTS(i) { |
| 1567 Handle<HeapNumber> num = t.factory()->NewHeapNumber(*i); |
| 1568 int32_t x = 0 - *i; |
| 1569 // TODO(titzer): make calls to NewHeapNumber work in cctests. |
| 1570 if (x <= Smi::kMinValue) continue; |
| 1571 if (x >= Smi::kMaxValue) continue; |
| 1572 Handle<HeapNumber> expected = t.factory()->NewHeapNumber(x); |
| 1573 Object* result = t.Call(*num); |
| 1574 CHECK(expected->SameValue(result)); |
| 1575 } |
| 1576 } |
| 1577 } |
| 1578 |
| 1579 |
| 1580 TEST(RunNumberDivide_2_TruncatingToUint32) { |
| 1581 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1582 Node* num = t.NumberToUint32(t.Parameter(0)); |
| 1583 Node* div = t.NumberDivide(num, t.jsgraph.Constant(2)); |
| 1584 Node* trunc = t.NumberToUint32(div); |
| 1585 t.Return(trunc); |
| 1586 |
| 1587 if (Pipeline::SupportedTarget()) { |
| 1588 t.LowerAllNodesAndLowerChanges(); |
| 1589 { |
| 1590 FILE* dot_file = fopen("/tmp/test.dot", "w+"); |
| 1591 OFStream dot_of(dot_file); |
| 1592 dot_of << AsDOT(*t.jsgraph.graph()); |
| 1593 fclose(dot_file); |
| 1594 } |
| 1595 t.GenerateCode(); |
| 1596 |
| 1597 FOR_UINT32_INPUTS(i) { |
| 1598 Handle<HeapNumber> num = |
| 1599 t.factory()->NewHeapNumber(static_cast<double>(*i)); |
| 1600 uint32_t x = *i / 2; |
| 1601 // TODO(titzer): make calls to NewHeapNumber work in cctests. |
| 1602 if (x >= static_cast<uint32_t>(Smi::kMaxValue)) continue; |
| 1603 Handle<HeapNumber> expected = |
| 1604 t.factory()->NewHeapNumber(static_cast<double>(x)); |
| 1605 Object* result = t.Call(*num); |
| 1606 CHECK(expected->SameValue(result)); |
| 1607 } |
| 1608 } |
| 1609 } |
| OLD | NEW |