OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/redundancy-elimination.h" | 5 #include "src/compiler/redundancy-elimination.h" |
6 | 6 |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 16 matching lines...) Expand all Loading... | |
27 case IrOpcode::kCheckedFloat64ToInt32: | 27 case IrOpcode::kCheckedFloat64ToInt32: |
28 case IrOpcode::kCheckedInt32Add: | 28 case IrOpcode::kCheckedInt32Add: |
29 case IrOpcode::kCheckedInt32Sub: | 29 case IrOpcode::kCheckedInt32Sub: |
30 case IrOpcode::kCheckedInt32Div: | 30 case IrOpcode::kCheckedInt32Div: |
31 case IrOpcode::kCheckedInt32Mod: | 31 case IrOpcode::kCheckedInt32Mod: |
32 case IrOpcode::kCheckedInt32Mul: | 32 case IrOpcode::kCheckedInt32Mul: |
33 case IrOpcode::kCheckedTaggedToFloat64: | 33 case IrOpcode::kCheckedTaggedToFloat64: |
34 case IrOpcode::kCheckedTaggedToInt32: | 34 case IrOpcode::kCheckedTaggedToInt32: |
35 case IrOpcode::kCheckedUint32ToInt32: | 35 case IrOpcode::kCheckedUint32ToInt32: |
36 return ReduceCheckNode(node); | 36 return ReduceCheckNode(node); |
37 case IrOpcode::kSpeculativeNumberAdd: | |
38 case IrOpcode::kSpeculativeNumberSubtract: | |
39 case IrOpcode::kSpeculativeNumberMultiply: | |
40 case IrOpcode::kSpeculativeNumberModulus: | |
41 case IrOpcode::kSpeculativeNumberDivide: | |
42 case IrOpcode::kSpeculativeNumberShiftLeft: | |
43 case IrOpcode::kSpeculativeNumberEqual: | |
44 case IrOpcode::kSpeculativeNumberLessThan: | |
45 case IrOpcode::kSpeculativeNumberLessThanOrEqual: | |
46 return ReduceSpeculativeNode(node); | |
37 case IrOpcode::kEffectPhi: | 47 case IrOpcode::kEffectPhi: |
38 return ReduceEffectPhi(node); | 48 return ReduceEffectPhi(node); |
39 case IrOpcode::kDead: | 49 case IrOpcode::kDead: |
40 break; | 50 break; |
41 case IrOpcode::kStart: | 51 case IrOpcode::kStart: |
42 return ReduceStart(node); | 52 return ReduceStart(node); |
43 default: | 53 default: |
44 return ReduceOtherNode(node); | 54 return ReduceOtherNode(node); |
45 } | 55 } |
46 return NoChange(); | 56 return NoChange(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
112 namespace { | 122 namespace { |
113 | 123 |
114 bool IsCompatibleCheck(Node const* a, Node const* b) { | 124 bool IsCompatibleCheck(Node const* a, Node const* b) { |
115 if (a->op() != b->op()) return false; | 125 if (a->op() != b->op()) return false; |
116 for (int i = a->op()->ValueInputCount(); --i >= 0;) { | 126 for (int i = a->op()->ValueInputCount(); --i >= 0;) { |
117 if (a->InputAt(i) != b->InputAt(i)) return false; | 127 if (a->InputAt(i) != b->InputAt(i)) return false; |
118 } | 128 } |
119 return true; | 129 return true; |
120 } | 130 } |
121 | 131 |
132 bool IsCompatibleSpeculative(Node const* a, Node const* b) { | |
133 if (a->opcode() != b->opcode()) return false; | |
134 DCHECK_EQ(a->InputCount(), b->InputCount()); | |
135 for (int i = a->op()->ValueInputCount(); --i >= 0;) { | |
136 if (a->InputAt(i) != b->InputAt(i)) return false; | |
137 } | |
138 return true; | |
139 } | |
140 | |
122 } // namespace | 141 } // namespace |
123 | 142 |
124 Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const { | 143 template <typename Predicate> |
Jarin
2016/07/26 09:39:21
Do we really need to have templates for this? How
| |
144 Node* RedundancyElimination::EffectPathChecks::LookupCheck( | |
145 Node* node, Predicate predicate) const { | |
125 for (Check const* check = head_; check != nullptr; check = check->next) { | 146 for (Check const* check = head_; check != nullptr; check = check->next) { |
126 if (IsCompatibleCheck(check->node, node)) { | 147 if (predicate(check->node, node)) { |
127 DCHECK(!check->node->IsDead()); | 148 DCHECK(!check->node->IsDead()); |
128 return check->node; | 149 return check->node; |
129 } | 150 } |
130 } | 151 } |
131 return nullptr; | 152 return nullptr; |
132 } | 153 } |
133 | 154 |
134 RedundancyElimination::EffectPathChecks const* | 155 RedundancyElimination::EffectPathChecks const* |
135 RedundancyElimination::PathChecksForEffectNodes::Get(Node* node) const { | 156 RedundancyElimination::PathChecksForEffectNodes::Get(Node* node) const { |
136 size_t const id = node->id(); | 157 size_t const id = node->id(); |
137 if (id < info_for_node_.size()) return info_for_node_[id]; | 158 if (id < info_for_node_.size()) return info_for_node_[id]; |
138 return nullptr; | 159 return nullptr; |
139 } | 160 } |
140 | 161 |
141 void RedundancyElimination::PathChecksForEffectNodes::Set( | 162 void RedundancyElimination::PathChecksForEffectNodes::Set( |
142 Node* node, EffectPathChecks const* checks) { | 163 Node* node, EffectPathChecks const* checks) { |
143 size_t const id = node->id(); | 164 size_t const id = node->id(); |
144 if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr); | 165 if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr); |
145 info_for_node_[id] = checks; | 166 info_for_node_[id] = checks; |
146 } | 167 } |
147 | 168 |
148 Reduction RedundancyElimination::ReduceCheckNode(Node* node) { | 169 Reduction RedundancyElimination::ReduceCheckNode(Node* node) { |
149 Node* const effect = NodeProperties::GetEffectInput(node); | 170 Node* const effect = NodeProperties::GetEffectInput(node); |
150 EffectPathChecks const* checks = node_checks_.Get(effect); | 171 EffectPathChecks const* checks = node_checks_.Get(effect); |
151 // If we do not know anything about the predecessor, do not propagate just yet | 172 // If we do not know anything about the predecessor, do not propagate just yet |
152 // because we will have to recompute anyway once we compute the predecessor. | 173 // because we will have to recompute anyway once we compute the predecessor. |
153 if (checks == nullptr) return NoChange(); | 174 if (checks == nullptr) return NoChange(); |
154 // See if we have another check that dominates us. | 175 // See if we have another check that dominates us. |
155 if (Node* check = checks->LookupCheck(node)) { | 176 if (Node* check = checks->LookupCheck(node, IsCompatibleCheck)) { |
156 ReplaceWithValue(node, check); | 177 ReplaceWithValue(node, check); |
157 return Replace(check); | 178 return Replace(check); |
158 } | 179 } |
159 // Learn from this check. | 180 // Learn from this check. |
160 return UpdateChecks(node, checks->AddCheck(zone(), node)); | 181 return UpdateChecks(node, checks->AddCheck(zone(), node)); |
161 } | 182 } |
162 | 183 |
184 Reduction RedundancyElimination::ReduceSpeculativeNode(Node* node) { | |
185 Node* const effect = NodeProperties::GetEffectInput(node); | |
186 EffectPathChecks const* checks = node_checks_.Get(effect); | |
187 // If we do not know anything about the predecessor, do not propagate just yet | |
188 // because we will have to recompute anyway once we compute the predecessor. | |
189 if (checks == nullptr) return NoChange(); | |
190 // See if we have another speculative {node} that dominates us. | |
191 if (Node* check = checks->LookupCheck(node, IsCompatibleSpeculative)) { | |
192 ReplaceWithValue(node, check); | |
193 return Replace(check); | |
194 } | |
195 // Learn from this speculative {node}. | |
196 return UpdateChecks(node, checks->AddCheck(zone(), node)); | |
197 } | |
198 | |
163 Reduction RedundancyElimination::ReduceEffectPhi(Node* node) { | 199 Reduction RedundancyElimination::ReduceEffectPhi(Node* node) { |
164 Node* const control = NodeProperties::GetControlInput(node); | 200 Node* const control = NodeProperties::GetControlInput(node); |
165 if (control->opcode() == IrOpcode::kLoop) { | 201 if (control->opcode() == IrOpcode::kLoop) { |
166 // Here we rely on having only reducible loops: | 202 // Here we rely on having only reducible loops: |
167 // The loop entry edge always dominates the header, so we can just use | 203 // The loop entry edge always dominates the header, so we can just use |
168 // the information from the loop entry edge. | 204 // the information from the loop entry edge. |
169 return TakeChecksFromFirstEffect(node); | 205 return TakeChecksFromFirstEffect(node); |
170 } | 206 } |
171 DCHECK_EQ(IrOpcode::kMerge, control->opcode()); | 207 DCHECK_EQ(IrOpcode::kMerge, control->opcode()); |
172 | 208 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
228 node_checks_.Set(node, checks); | 264 node_checks_.Set(node, checks); |
229 return Changed(node); | 265 return Changed(node); |
230 } | 266 } |
231 } | 267 } |
232 return NoChange(); | 268 return NoChange(); |
233 } | 269 } |
234 | 270 |
235 } // namespace compiler | 271 } // namespace compiler |
236 } // namespace internal | 272 } // namespace internal |
237 } // namespace v8 | 273 } // namespace v8 |
OLD | NEW |