Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: src/compiler/redundancy-elimination.cc

Issue 2527083002: [turbofan] Use bounds checks to eliminate subsequent inc/dec overflow checks. (Closed)
Patch Set: Remove dead code Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/redundancy-elimination.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/redundancy-elimination.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698