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 |