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 18 matching lines...) Expand all Loading... |
29 case IrOpcode::kCheckedInt32Add: | 29 case IrOpcode::kCheckedInt32Add: |
30 case IrOpcode::kCheckedInt32Sub: | 30 case IrOpcode::kCheckedInt32Sub: |
31 case IrOpcode::kCheckedInt32Div: | 31 case IrOpcode::kCheckedInt32Div: |
32 case IrOpcode::kCheckedInt32Mod: | 32 case IrOpcode::kCheckedInt32Mod: |
33 case IrOpcode::kCheckedInt32Mul: | 33 case IrOpcode::kCheckedInt32Mul: |
34 case IrOpcode::kCheckedTaggedToFloat64: | 34 case IrOpcode::kCheckedTaggedToFloat64: |
35 case IrOpcode::kCheckedTaggedSignedToInt32: | 35 case IrOpcode::kCheckedTaggedSignedToInt32: |
36 case IrOpcode::kCheckedTaggedToInt32: | 36 case IrOpcode::kCheckedTaggedToInt32: |
37 case IrOpcode::kCheckedUint32ToInt32: | 37 case IrOpcode::kCheckedUint32ToInt32: |
38 return ReduceCheckNode(node); | 38 return ReduceCheckNode(node); |
| 39 case IrOpcode::kSpeculativeNumberAdd: |
| 40 case IrOpcode::kSpeculativeNumberSubtract: |
| 41 // For increments and decrements by a constant, try to learn from the last |
| 42 // bounds check. |
| 43 return TryReuseBoundsCheckForFirstInput(node); |
39 case IrOpcode::kEffectPhi: | 44 case IrOpcode::kEffectPhi: |
40 return ReduceEffectPhi(node); | 45 return ReduceEffectPhi(node); |
41 case IrOpcode::kDead: | 46 case IrOpcode::kDead: |
42 break; | 47 break; |
43 case IrOpcode::kStart: | 48 case IrOpcode::kStart: |
44 return ReduceStart(node); | 49 return ReduceStart(node); |
45 default: | 50 default: |
46 return ReduceOtherNode(node); | 51 return ReduceOtherNode(node); |
47 } | 52 } |
48 return NoChange(); | 53 return NoChange(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const { | 131 Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const { |
127 for (Check const* check = head_; check != nullptr; check = check->next) { | 132 for (Check const* check = head_; check != nullptr; check = check->next) { |
128 if (IsCompatibleCheck(check->node, node)) { | 133 if (IsCompatibleCheck(check->node, node)) { |
129 DCHECK(!check->node->IsDead()); | 134 DCHECK(!check->node->IsDead()); |
130 return check->node; | 135 return check->node; |
131 } | 136 } |
132 } | 137 } |
133 return nullptr; | 138 return nullptr; |
134 } | 139 } |
135 | 140 |
| 141 Node* RedundancyElimination::EffectPathChecks::LookupBoundsCheckFor( |
| 142 Node* node) const { |
| 143 for (Check const* check = head_; check != nullptr; check = check->next) { |
| 144 if (check->node->opcode() == IrOpcode::kCheckBounds && |
| 145 check->node->InputAt(0) == node) { |
| 146 return check->node; |
| 147 } |
| 148 } |
| 149 return nullptr; |
| 150 } |
| 151 |
136 RedundancyElimination::EffectPathChecks const* | 152 RedundancyElimination::EffectPathChecks const* |
137 RedundancyElimination::PathChecksForEffectNodes::Get(Node* node) const { | 153 RedundancyElimination::PathChecksForEffectNodes::Get(Node* node) const { |
138 size_t const id = node->id(); | 154 size_t const id = node->id(); |
139 if (id < info_for_node_.size()) return info_for_node_[id]; | 155 if (id < info_for_node_.size()) return info_for_node_[id]; |
140 return nullptr; | 156 return nullptr; |
141 } | 157 } |
142 | 158 |
143 void RedundancyElimination::PathChecksForEffectNodes::Set( | 159 void RedundancyElimination::PathChecksForEffectNodes::Set( |
144 Node* node, EffectPathChecks const* checks) { | 160 Node* node, EffectPathChecks const* checks) { |
145 size_t const id = node->id(); | 161 size_t const id = node->id(); |
146 if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr); | 162 if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr); |
147 info_for_node_[id] = checks; | 163 info_for_node_[id] = checks; |
148 } | 164 } |
149 | 165 |
150 Reduction RedundancyElimination::ReduceCheckNode(Node* node) { | 166 Reduction RedundancyElimination::ReduceCheckNode(Node* node) { |
151 Node* const effect = NodeProperties::GetEffectInput(node); | 167 Node* const effect = NodeProperties::GetEffectInput(node); |
152 EffectPathChecks const* checks = node_checks_.Get(effect); | 168 EffectPathChecks const* checks = node_checks_.Get(effect); |
153 // If we do not know anything about the predecessor, do not propagate just yet | 169 // If we do not know anything about the predecessor, do not propagate just yet |
154 // because we will have to recompute anyway once we compute the predecessor. | 170 // because we will have to recompute anyway once we compute the predecessor. |
155 if (checks == nullptr) return NoChange(); | 171 if (checks == nullptr) return NoChange(); |
156 // See if we have another check that dominates us. | 172 // See if we have another check that dominates us. |
157 if (Node* check = checks->LookupCheck(node)) { | 173 if (Node* check = checks->LookupCheck(node)) { |
158 ReplaceWithValue(node, check); | 174 ReplaceWithValue(node, check); |
159 return Replace(check); | 175 return Replace(check); |
160 } | 176 } |
| 177 |
161 // Learn from this check. | 178 // Learn from this check. |
162 return UpdateChecks(node, checks->AddCheck(zone(), node)); | 179 return UpdateChecks(node, checks->AddCheck(zone(), node)); |
163 } | 180 } |
164 | 181 |
| 182 Reduction RedundancyElimination::TryReuseBoundsCheckForFirstInput(Node* node) { |
| 183 DCHECK(node->opcode() == IrOpcode::kSpeculativeNumberAdd || |
| 184 node->opcode() == IrOpcode::kSpeculativeNumberSubtract); |
| 185 |
| 186 DCHECK_EQ(1, node->op()->EffectInputCount()); |
| 187 DCHECK_EQ(1, node->op()->EffectOutputCount()); |
| 188 |
| 189 Node* const effect = NodeProperties::GetEffectInput(node); |
| 190 EffectPathChecks const* checks = node_checks_.Get(effect); |
| 191 |
| 192 // If we do not know anything about the predecessor, do not propagate just yet |
| 193 // because we will have to recompute anyway once we compute the predecessor. |
| 194 if (checks == nullptr) return NoChange(); |
| 195 |
| 196 Node* left = node->InputAt(0); |
| 197 Node* right = node->InputAt(1); |
| 198 // Only use bounds checks for increments/decrements by a constant. |
| 199 if (right->opcode() == IrOpcode::kNumberConstant) { |
| 200 if (Node* bounds_check = checks->LookupBoundsCheckFor(left)) { |
| 201 // Only use the bounds checked type if it is better. |
| 202 if (NodeProperties::GetType(bounds_check) |
| 203 ->Is(NodeProperties::GetType(left))) { |
| 204 node->ReplaceInput(0, bounds_check); |
| 205 } |
| 206 } |
| 207 } |
| 208 |
| 209 return UpdateChecks(node, checks); |
| 210 } |
| 211 |
165 Reduction RedundancyElimination::ReduceEffectPhi(Node* node) { | 212 Reduction RedundancyElimination::ReduceEffectPhi(Node* node) { |
166 Node* const control = NodeProperties::GetControlInput(node); | 213 Node* const control = NodeProperties::GetControlInput(node); |
167 if (control->opcode() == IrOpcode::kLoop) { | 214 if (control->opcode() == IrOpcode::kLoop) { |
168 // Here we rely on having only reducible loops: | 215 // Here we rely on having only reducible loops: |
169 // The loop entry edge always dominates the header, so we can just use | 216 // The loop entry edge always dominates the header, so we can just use |
170 // the information from the loop entry edge. | 217 // the information from the loop entry edge. |
171 return TakeChecksFromFirstEffect(node); | 218 return TakeChecksFromFirstEffect(node); |
172 } | 219 } |
173 DCHECK_EQ(IrOpcode::kMerge, control->opcode()); | 220 DCHECK_EQ(IrOpcode::kMerge, control->opcode()); |
174 | 221 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 node_checks_.Set(node, checks); | 277 node_checks_.Set(node, checks); |
231 return Changed(node); | 278 return Changed(node); |
232 } | 279 } |
233 } | 280 } |
234 return NoChange(); | 281 return NoChange(); |
235 } | 282 } |
236 | 283 |
237 } // namespace compiler | 284 } // namespace compiler |
238 } // namespace internal | 285 } // namespace internal |
239 } // namespace v8 | 286 } // namespace v8 |
OLD | NEW |