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 "src/compiler/common-operator-reducer.h" | 5 #include "src/compiler/common-operator-reducer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/compiler/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/graph.h" |
| 11 #include "src/compiler/machine-operator.h" |
11 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
12 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
13 | 14 |
14 namespace v8 { | 15 namespace v8 { |
15 namespace internal { | 16 namespace internal { |
16 namespace compiler { | 17 namespace compiler { |
17 | 18 |
18 Reduction CommonOperatorReducer::Reduce(Node* node) { | 19 Reduction CommonOperatorReducer::Reduce(Node* node) { |
19 switch (node->opcode()) { | 20 switch (node->opcode()) { |
20 case IrOpcode::kEffectPhi: | 21 case IrOpcode::kEffectPhi: |
21 return ReduceEffectPhi(node); | 22 return ReduceEffectPhi(node); |
22 case IrOpcode::kPhi: | 23 case IrOpcode::kPhi: |
23 return ReducePhi(node); | 24 return ReducePhi(node); |
24 case IrOpcode::kSelect: | 25 case IrOpcode::kSelect: |
25 return ReduceSelect(node); | 26 return ReduceSelect(node); |
26 default: | 27 default: |
27 break; | 28 break; |
28 } | 29 } |
29 return NoChange(); | 30 return NoChange(); |
30 } | 31 } |
31 | 32 |
32 | 33 |
33 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { | 34 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { |
34 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); | 35 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); |
35 int const input_count = node->InputCount(); | 36 int const input_count = node->InputCount() - 1; |
36 if (input_count > 1) { | 37 DCHECK_LE(1, input_count); |
37 Node* const replacement = node->InputAt(0); | 38 Node* const merge = node->InputAt(input_count); |
38 for (int i = 1; i < input_count - 1; ++i) { | 39 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
39 if (node->InputAt(i) != replacement) return NoChange(); | 40 DCHECK_EQ(input_count, merge->InputCount()); |
| 41 Node* const effect = node->InputAt(0); |
| 42 DCHECK_NE(node, effect); |
| 43 for (int i = 1; i < input_count; ++i) { |
| 44 Node* const input = node->InputAt(i); |
| 45 if (input == node) { |
| 46 // Ignore redundant inputs. |
| 47 DCHECK_EQ(IrOpcode::kLoop, merge->opcode()); |
| 48 continue; |
40 } | 49 } |
41 return Replace(replacement); | 50 if (input != effect) return NoChange(); |
42 } | 51 } |
43 return NoChange(); | 52 // We might now be able to further reduce the {merge} node. |
| 53 Revisit(merge); |
| 54 return Replace(effect); |
44 } | 55 } |
45 | 56 |
46 | 57 |
47 Reduction CommonOperatorReducer::ReducePhi(Node* node) { | 58 Reduction CommonOperatorReducer::ReducePhi(Node* node) { |
48 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); | 59 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); |
49 int const input_count = node->InputCount(); | 60 int const input_count = node->InputCount() - 1; |
50 if (input_count == 3) { | 61 DCHECK_LE(1, input_count); |
51 Node* vtrue = NodeProperties::GetValueInput(node, 0); | 62 Node* const merge = node->InputAt(input_count); |
52 Node* vfalse = NodeProperties::GetValueInput(node, 1); | 63 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
53 Node* merge = NodeProperties::GetControlInput(node); | 64 DCHECK_EQ(input_count, merge->InputCount()); |
54 DiamondMatcher matcher(merge); | 65 if (input_count == 2) { |
55 if (matcher.Matched()) { | 66 Node* vtrue = node->InputAt(0); |
56 if (matcher.IfTrue() == merge->InputAt(1)) std::swap(vtrue, vfalse); | 67 Node* vfalse = node->InputAt(1); |
57 Node* cond = matcher.Branch()->InputAt(0); | 68 Node* if_true = merge->InputAt(0); |
| 69 Node* if_false = merge->InputAt(1); |
| 70 if (if_true->opcode() != IrOpcode::kIfTrue) { |
| 71 std::swap(if_true, if_false); |
| 72 std::swap(vtrue, vfalse); |
| 73 } |
| 74 if (if_true->opcode() == IrOpcode::kIfTrue && |
| 75 if_false->opcode() == IrOpcode::kIfFalse && |
| 76 if_true->InputAt(0) == if_false->InputAt(0)) { |
| 77 Node* const branch = if_true->InputAt(0); |
| 78 Node* const cond = branch->InputAt(0); |
58 if (cond->opcode() == IrOpcode::kFloat32LessThan) { | 79 if (cond->opcode() == IrOpcode::kFloat32LessThan) { |
59 Float32BinopMatcher mcond(cond); | 80 Float32BinopMatcher mcond(cond); |
60 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 81 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
61 vfalse->opcode() == IrOpcode::kFloat32Sub) { | 82 vfalse->opcode() == IrOpcode::kFloat32Sub) { |
62 Float32BinopMatcher mvfalse(vfalse); | 83 Float32BinopMatcher mvfalse(vfalse); |
63 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { | 84 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { |
| 85 // We might now be able to further reduce the {merge} node. |
| 86 Revisit(merge); |
64 return Change(node, machine()->Float32Abs(), vtrue); | 87 return Change(node, machine()->Float32Abs(), vtrue); |
65 } | 88 } |
66 } | 89 } |
67 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && | 90 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && |
68 machine()->HasFloat32Min()) { | 91 machine()->HasFloat32Min()) { |
| 92 // We might now be able to further reduce the {merge} node. |
| 93 Revisit(merge); |
69 return Change(node, machine()->Float32Min(), vtrue, vfalse); | 94 return Change(node, machine()->Float32Min(), vtrue, vfalse); |
70 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && | 95 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && |
71 machine()->HasFloat32Max()) { | 96 machine()->HasFloat32Max()) { |
| 97 // We might now be able to further reduce the {merge} node. |
| 98 Revisit(merge); |
72 return Change(node, machine()->Float32Max(), vtrue, vfalse); | 99 return Change(node, machine()->Float32Max(), vtrue, vfalse); |
73 } | 100 } |
74 } else if (cond->opcode() == IrOpcode::kFloat64LessThan) { | 101 } else if (cond->opcode() == IrOpcode::kFloat64LessThan) { |
75 Float64BinopMatcher mcond(cond); | 102 Float64BinopMatcher mcond(cond); |
76 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 103 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
77 vfalse->opcode() == IrOpcode::kFloat64Sub) { | 104 vfalse->opcode() == IrOpcode::kFloat64Sub) { |
78 Float64BinopMatcher mvfalse(vfalse); | 105 Float64BinopMatcher mvfalse(vfalse); |
79 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { | 106 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { |
| 107 // We might now be able to further reduce the {merge} node. |
| 108 Revisit(merge); |
80 return Change(node, machine()->Float64Abs(), vtrue); | 109 return Change(node, machine()->Float64Abs(), vtrue); |
81 } | 110 } |
82 } | 111 } |
83 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && | 112 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && |
84 machine()->HasFloat64Min()) { | 113 machine()->HasFloat64Min()) { |
| 114 // We might now be able to further reduce the {merge} node. |
| 115 Revisit(merge); |
85 return Change(node, machine()->Float64Min(), vtrue, vfalse); | 116 return Change(node, machine()->Float64Min(), vtrue, vfalse); |
86 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && | 117 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && |
87 machine()->HasFloat64Max()) { | 118 machine()->HasFloat64Max()) { |
| 119 // We might now be able to further reduce the {merge} node. |
| 120 Revisit(merge); |
88 return Change(node, machine()->Float64Max(), vtrue, vfalse); | 121 return Change(node, machine()->Float64Max(), vtrue, vfalse); |
89 } | 122 } |
90 } | 123 } |
91 } | 124 } |
92 } | 125 } |
93 if (input_count > 1) { | 126 Node* const value = node->InputAt(0); |
94 Node* const replacement = node->InputAt(0); | 127 DCHECK_NE(node, value); |
95 for (int i = 1; i < input_count - 1; ++i) { | 128 for (int i = 1; i < input_count; ++i) { |
96 if (node->InputAt(i) != replacement) return NoChange(); | 129 Node* const input = node->InputAt(i); |
| 130 if (input == node) { |
| 131 // Ignore redundant inputs. |
| 132 DCHECK_EQ(IrOpcode::kLoop, merge->opcode()); |
| 133 continue; |
97 } | 134 } |
98 return Replace(replacement); | 135 if (input != value) return NoChange(); |
99 } | 136 } |
100 return NoChange(); | 137 // We might now be able to further reduce the {merge} node. |
| 138 Revisit(merge); |
| 139 return Replace(value); |
101 } | 140 } |
102 | 141 |
103 | 142 |
104 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { | 143 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { |
105 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); | 144 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); |
106 Node* cond = NodeProperties::GetValueInput(node, 0); | 145 Node* const cond = node->InputAt(0); |
107 Node* vtrue = NodeProperties::GetValueInput(node, 1); | 146 Node* const vtrue = node->InputAt(1); |
108 Node* vfalse = NodeProperties::GetValueInput(node, 2); | 147 Node* const vfalse = node->InputAt(2); |
109 if (vtrue == vfalse) return Replace(vtrue); | 148 if (vtrue == vfalse) return Replace(vtrue); |
110 switch (cond->opcode()) { | 149 switch (cond->opcode()) { |
111 case IrOpcode::kHeapConstant: { | 150 case IrOpcode::kHeapConstant: { |
112 HeapObjectMatcher<HeapObject> mcond(cond); | 151 HeapObjectMatcher<HeapObject> mcond(cond); |
113 return Replace(mcond.Value().handle()->BooleanValue() ? vtrue : vfalse); | 152 return Replace(mcond.Value().handle()->BooleanValue() ? vtrue : vfalse); |
114 } | 153 } |
115 case IrOpcode::kFloat32LessThan: { | 154 case IrOpcode::kFloat32LessThan: { |
116 Float32BinopMatcher mcond(cond); | 155 Float32BinopMatcher mcond(cond); |
117 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 156 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
118 vfalse->opcode() == IrOpcode::kFloat32Sub) { | 157 vfalse->opcode() == IrOpcode::kFloat32Sub) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 | 205 |
167 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a, | 206 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a, |
168 Node* b) { | 207 Node* b) { |
169 node->set_op(op); | 208 node->set_op(op); |
170 node->ReplaceInput(0, a); | 209 node->ReplaceInput(0, a); |
171 node->ReplaceInput(1, b); | 210 node->ReplaceInput(1, b); |
172 node->TrimInputCount(2); | 211 node->TrimInputCount(2); |
173 return Changed(node); | 212 return Changed(node); |
174 } | 213 } |
175 | 214 |
176 | |
177 CommonOperatorBuilder* CommonOperatorReducer::common() const { | |
178 return jsgraph()->common(); | |
179 } | |
180 | |
181 | |
182 Graph* CommonOperatorReducer::graph() const { return jsgraph()->graph(); } | |
183 | |
184 | |
185 MachineOperatorBuilder* CommonOperatorReducer::machine() const { | |
186 return jsgraph()->machine(); | |
187 } | |
188 | |
189 } // namespace compiler | 215 } // namespace compiler |
190 } // namespace internal | 216 } // namespace internal |
191 } // namespace v8 | 217 } // namespace v8 |
OLD | NEW |