OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "src/compiler/dead-code-elimination.h" | |
6 | |
7 #include "src/compiler/common-operator.h" | |
8 #include "src/compiler/graph.h" | |
9 #include "src/compiler/node-properties.h" | |
10 #include "src/compiler/operator-properties.h" | |
11 | |
12 namespace v8 { | |
13 namespace internal { | |
14 namespace compiler { | |
15 | |
16 DeadCodeElimination::DeadCodeElimination(Editor* editor, Graph* graph, | |
17 CommonOperatorBuilder* common) | |
18 : AdvancedReducer(editor), | |
19 graph_(graph), | |
20 common_(common), | |
21 dead_(graph->NewNode(common->Dead())) {} | |
22 | |
23 | |
24 Reduction DeadCodeElimination::Reduce(Node* node) { | |
25 switch (node->opcode()) { | |
26 case IrOpcode::kEnd: | |
27 return ReduceEnd(node); | |
28 case IrOpcode::kLoop: | |
29 case IrOpcode::kMerge: | |
30 return ReduceLoopOrMerge(node); | |
31 default: | |
32 return ReduceNode(node); | |
33 } | |
34 UNREACHABLE(); | |
35 return NoChange(); | |
36 } | |
37 | |
38 | |
39 Reduction DeadCodeElimination::ReduceEnd(Node* node) { | |
40 DCHECK_EQ(IrOpcode::kEnd, node->opcode()); | |
41 int const input_count = node->InputCount(); | |
42 DCHECK_LE(1, input_count); | |
43 int live_input_count = 0; | |
44 for (int i = 0; i < input_count; ++i) { | |
45 Node* const input = node->InputAt(i); | |
46 // Skip dead inputs. | |
47 if (input->opcode() == IrOpcode::kDead) continue; | |
48 // Compact live inputs. | |
49 if (i != live_input_count) node->ReplaceInput(live_input_count, input); | |
50 ++live_input_count; | |
51 } | |
52 if (live_input_count == 0) { | |
Jarin
2015/06/19 09:50:51
Out of curiosity - when does this happen?
Benedikt Meurer
2015/06/19 09:55:31
I guess this can never happen. But I wanted to kee
Jarin
2015/06/19 12:12:11
Indeed, that was my thinking...
| |
53 return Replace(dead()); | |
54 } else if (live_input_count < input_count) { | |
55 node->set_op(common()->End(live_input_count)); | |
56 node->TrimInputCount(live_input_count); | |
57 return Changed(node); | |
58 } | |
59 DCHECK_EQ(input_count, live_input_count); | |
60 return NoChange(); | |
61 } | |
62 | |
63 | |
64 Reduction DeadCodeElimination::ReduceLoopOrMerge(Node* node) { | |
65 DCHECK(IrOpcode::IsMergeOpcode(node->opcode())); | |
66 int const input_count = node->InputCount(); | |
67 DCHECK_LE(1, input_count); | |
68 // Count the number of live inputs to {node} and compact them on the fly, also | |
69 // compacting the inputs of the associated {Phi} and {EffectPhi} uses at the | |
70 // same time. We consider {Loop}s dead even if only the first control input | |
71 // is dead. | |
72 int live_input_count = 0; | |
73 if (node->opcode() != IrOpcode::kLoop || | |
74 node->InputAt(0)->opcode() != IrOpcode::kDead) { | |
75 for (int i = 0; i < input_count; ++i) { | |
76 Node* const input = node->InputAt(i); | |
77 // Skip dead inputs. | |
78 if (input->opcode() == IrOpcode::kDead) continue; | |
79 // Compact live inputs. | |
80 if (live_input_count != i) { | |
81 node->ReplaceInput(live_input_count, input); | |
82 for (Node* const use : node->uses()) { | |
83 if (NodeProperties::IsPhi(use)) { | |
84 DCHECK_EQ(input_count + 1, use->InputCount()); | |
85 use->ReplaceInput(live_input_count, use->InputAt(i)); | |
86 } | |
87 } | |
88 } | |
89 ++live_input_count; | |
90 } | |
91 } | |
92 if (live_input_count == 0) { | |
93 return Replace(dead()); | |
94 } else if (live_input_count == 1) { | |
95 // Due to compaction above, the live input is at offset 0. | |
96 for (Node* const use : node->uses()) { | |
97 if (NodeProperties::IsPhi(use)) { | |
98 Replace(use, use->InputAt(0)); | |
99 } else if (use->opcode() == IrOpcode::kTerminate) { | |
100 DCHECK_EQ(IrOpcode::kLoop, node->opcode()); | |
101 Replace(use, dead()); | |
102 } | |
103 } | |
104 return Replace(node->InputAt(0)); | |
105 } | |
106 DCHECK_LE(2, live_input_count); | |
107 DCHECK_LE(live_input_count, input_count); | |
108 // Trim input count for the {Merge} or {Loop} node. | |
109 if (live_input_count < input_count) { | |
110 // Trim input counts for all phi uses and revisit them. | |
111 for (Node* const use : node->uses()) { | |
112 if (NodeProperties::IsPhi(use)) { | |
113 use->ReplaceInput(live_input_count, node); | |
114 TrimMergeOrPhi(use, live_input_count); | |
115 Revisit(use); | |
116 } | |
117 } | |
118 TrimMergeOrPhi(node, live_input_count); | |
119 return Changed(node); | |
120 } | |
121 return NoChange(); | |
122 } | |
123 | |
124 | |
125 Reduction DeadCodeElimination::ReduceNode(Node* node) { | |
126 // If {node} has exactly one control input and this is {Dead}, | |
127 // replace {node} with {Dead}. | |
128 int const control_input_count = node->op()->ControlInputCount(); | |
129 if (control_input_count == 0) return NoChange(); | |
130 DCHECK_EQ(1, control_input_count); | |
131 Node* control = NodeProperties::GetControlInput(node); | |
132 if (control->opcode() == IrOpcode::kDead) return Replace(control); | |
133 return NoChange(); | |
134 } | |
135 | |
136 | |
137 void DeadCodeElimination::TrimMergeOrPhi(Node* node, int size) { | |
138 const Operator* const op = common()->ResizeMergeOrPhi(node->op(), size); | |
139 node->TrimInputCount(OperatorProperties::GetTotalInputCount(op)); | |
140 node->set_op(op); | |
141 } | |
142 | |
143 } // namespace compiler | |
144 } // namespace internal | |
145 } // namespace v8 | |
OLD | NEW |