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/graph.h" | 10 #include "src/compiler/graph.h" |
11 #include "src/compiler/machine-operator.h" | 11 #include "src/compiler/machine-operator.h" |
12 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
13 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 namespace compiler { | 17 namespace compiler { |
18 | 18 |
| 19 namespace { |
| 20 |
| 21 enum class Decision { kUnknown, kTrue, kFalse }; |
| 22 |
| 23 Decision DecideCondition(Node* const cond) { |
| 24 switch (cond->opcode()) { |
| 25 case IrOpcode::kInt32Constant: { |
| 26 Int32Matcher mcond(cond); |
| 27 return mcond.Value() ? Decision::kTrue : Decision::kFalse; |
| 28 } |
| 29 case IrOpcode::kInt64Constant: { |
| 30 Int64Matcher mcond(cond); |
| 31 return mcond.Value() ? Decision::kTrue : Decision::kFalse; |
| 32 } |
| 33 case IrOpcode::kHeapConstant: { |
| 34 HeapObjectMatcher<HeapObject> mcond(cond); |
| 35 return mcond.Value().handle()->BooleanValue() ? Decision::kTrue |
| 36 : Decision::kFalse; |
| 37 } |
| 38 default: |
| 39 return Decision::kUnknown; |
| 40 } |
| 41 } |
| 42 |
| 43 } // namespace |
| 44 |
| 45 |
19 Reduction CommonOperatorReducer::Reduce(Node* node) { | 46 Reduction CommonOperatorReducer::Reduce(Node* node) { |
20 switch (node->opcode()) { | 47 switch (node->opcode()) { |
| 48 case IrOpcode::kBranch: |
| 49 return ReduceBranch(node); |
| 50 case IrOpcode::kMerge: |
| 51 return ReduceMerge(node); |
21 case IrOpcode::kEffectPhi: | 52 case IrOpcode::kEffectPhi: |
22 return ReduceEffectPhi(node); | 53 return ReduceEffectPhi(node); |
23 case IrOpcode::kPhi: | 54 case IrOpcode::kPhi: |
24 return ReducePhi(node); | 55 return ReducePhi(node); |
25 case IrOpcode::kSelect: | 56 case IrOpcode::kSelect: |
26 return ReduceSelect(node); | 57 return ReduceSelect(node); |
27 default: | 58 default: |
28 break; | 59 break; |
29 } | 60 } |
30 return NoChange(); | 61 return NoChange(); |
31 } | 62 } |
32 | 63 |
33 | 64 |
| 65 Reduction CommonOperatorReducer::ReduceBranch(Node* node) { |
| 66 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); |
| 67 Node* const cond = node->InputAt(0); |
| 68 Decision const decision = DecideCondition(cond); |
| 69 if (decision == Decision::kUnknown) return NoChange(); |
| 70 Node* const control = node->InputAt(1); |
| 71 node->set_op(common()->Dead()); |
| 72 node->TrimInputCount(0); |
| 73 for (Node* const use : node->uses()) { |
| 74 switch (use->opcode()) { |
| 75 case IrOpcode::kIfTrue: |
| 76 Replace(use, (decision == Decision::kTrue) ? control : node); |
| 77 break; |
| 78 case IrOpcode::kIfFalse: |
| 79 Replace(use, (decision == Decision::kFalse) ? control : node); |
| 80 break; |
| 81 default: |
| 82 UNREACHABLE(); |
| 83 } |
| 84 } |
| 85 return Changed(node); |
| 86 } |
| 87 |
| 88 |
| 89 Reduction CommonOperatorReducer::ReduceMerge(Node* node) { |
| 90 DCHECK_EQ(IrOpcode::kMerge, node->opcode()); |
| 91 // |
| 92 // Check if this is a merge that belongs to an unused diamond, which means |
| 93 // that: |
| 94 // |
| 95 // a) the {Merge} has no {Phi} or {EffectPhi} uses, and |
| 96 // b) the {Merge} has two inputs, one {IfTrue} and one {IfFalse}, which are |
| 97 // both owned by the Merge, and |
| 98 // c) and the {IfTrue} and {IfFalse} nodes point to the same {Branch}. |
| 99 // |
| 100 if (node->InputCount() == 2) { |
| 101 for (Node* const use : node->uses()) { |
| 102 if (IrOpcode::IsPhiOpcode(use->opcode())) return NoChange(); |
| 103 } |
| 104 Node* if_true = node->InputAt(0); |
| 105 Node* if_false = node->InputAt(1); |
| 106 if (if_true->opcode() != IrOpcode::kIfTrue) std::swap(if_true, if_false); |
| 107 if (if_true->opcode() == IrOpcode::kIfTrue && |
| 108 if_false->opcode() == IrOpcode::kIfFalse && |
| 109 if_true->InputAt(0) == if_false->InputAt(0) && if_true->OwnedBy(node) && |
| 110 if_false->OwnedBy(node)) { |
| 111 Node* const branch = if_true->InputAt(0); |
| 112 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); |
| 113 DCHECK(branch->OwnedBy(if_true, if_false)); |
| 114 Node* const control = branch->InputAt(1); |
| 115 // Mark the {branch} as {Dead}. |
| 116 branch->set_op(common()->Dead()); |
| 117 branch->TrimInputCount(0); |
| 118 return Replace(control); |
| 119 } |
| 120 } |
| 121 return NoChange(); |
| 122 } |
| 123 |
| 124 |
34 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { | 125 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { |
35 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); | 126 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); |
36 int const input_count = node->InputCount() - 1; | 127 int const input_count = node->InputCount() - 1; |
37 DCHECK_LE(1, input_count); | 128 DCHECK_LE(1, input_count); |
38 Node* const merge = node->InputAt(input_count); | 129 Node* const merge = node->InputAt(input_count); |
39 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); | 130 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
40 DCHECK_EQ(input_count, merge->InputCount()); | 131 DCHECK_EQ(input_count, merge->InputCount()); |
41 Node* const effect = node->InputAt(0); | 132 Node* const effect = node->InputAt(0); |
42 DCHECK_NE(node, effect); | 133 DCHECK_NE(node, effect); |
43 for (int i = 1; i < input_count; ++i) { | 134 for (int i = 1; i < input_count; ++i) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 return Replace(value); | 230 return Replace(value); |
140 } | 231 } |
141 | 232 |
142 | 233 |
143 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { | 234 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { |
144 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); | 235 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); |
145 Node* const cond = node->InputAt(0); | 236 Node* const cond = node->InputAt(0); |
146 Node* const vtrue = node->InputAt(1); | 237 Node* const vtrue = node->InputAt(1); |
147 Node* const vfalse = node->InputAt(2); | 238 Node* const vfalse = node->InputAt(2); |
148 if (vtrue == vfalse) return Replace(vtrue); | 239 if (vtrue == vfalse) return Replace(vtrue); |
| 240 switch (DecideCondition(cond)) { |
| 241 case Decision::kTrue: |
| 242 return Replace(vtrue); |
| 243 case Decision::kFalse: |
| 244 return Replace(vfalse); |
| 245 case Decision::kUnknown: |
| 246 break; |
| 247 } |
149 switch (cond->opcode()) { | 248 switch (cond->opcode()) { |
150 case IrOpcode::kHeapConstant: { | |
151 HeapObjectMatcher<HeapObject> mcond(cond); | |
152 return Replace(mcond.Value().handle()->BooleanValue() ? vtrue : vfalse); | |
153 } | |
154 case IrOpcode::kFloat32LessThan: { | 249 case IrOpcode::kFloat32LessThan: { |
155 Float32BinopMatcher mcond(cond); | 250 Float32BinopMatcher mcond(cond); |
156 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 251 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
157 vfalse->opcode() == IrOpcode::kFloat32Sub) { | 252 vfalse->opcode() == IrOpcode::kFloat32Sub) { |
158 Float32BinopMatcher mvfalse(vfalse); | 253 Float32BinopMatcher mvfalse(vfalse); |
159 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { | 254 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { |
160 return Change(node, machine()->Float32Abs(), vtrue); | 255 return Change(node, machine()->Float32Abs(), vtrue); |
161 } | 256 } |
162 } | 257 } |
163 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && | 258 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 node->set_op(op); | 303 node->set_op(op); |
209 node->ReplaceInput(0, a); | 304 node->ReplaceInput(0, a); |
210 node->ReplaceInput(1, b); | 305 node->ReplaceInput(1, b); |
211 node->TrimInputCount(2); | 306 node->TrimInputCount(2); |
212 return Changed(node); | 307 return Changed(node); |
213 } | 308 } |
214 | 309 |
215 } // namespace compiler | 310 } // namespace compiler |
216 } // namespace internal | 311 } // namespace internal |
217 } // namespace v8 | 312 } // namespace v8 |
OLD | NEW |