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

Side by Side Diff: src/compiler/effect-control-linearizer.cc

Issue 1921483002: [turbofan] Wire in floating control during effect linearization phase. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix lines in the drawing (gcc, really?) Created 4 years, 8 months 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 | « no previous file | src/compiler/node-properties.h » ('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 2015 the V8 project authors. All rights reserved. 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 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/effect-control-linearizer.h" 5 #include "src/compiler/effect-control-linearizer.h"
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/compiler/access-builder.h" 8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/linkage.h" 10 #include "src/compiler/linkage.h"
(...skipping 16 matching lines...) Expand all
27 } 27 }
28 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { 28 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
29 return js_graph_->simplified(); 29 return js_graph_->simplified();
30 } 30 }
31 MachineOperatorBuilder* EffectControlLinearizer::machine() const { 31 MachineOperatorBuilder* EffectControlLinearizer::machine() const {
32 return js_graph_->machine(); 32 return js_graph_->machine();
33 } 33 }
34 34
35 namespace { 35 namespace {
36 36
37 struct BlockEffectData { 37 struct BlockEffectControlData {
38 Node* current_effect = nullptr; // New effect. 38 Node* current_effect = nullptr; // New effect.
39 Node* current_control = nullptr; // New control.
39 }; 40 };
40 41
41 // Effect phis that need to be updated after the first pass. 42 // Effect phis that need to be updated after the first pass.
42 struct PendingEffectPhi { 43 struct PendingEffectPhi {
43 Node* effect_phi; 44 Node* effect_phi;
44 BasicBlock* block; 45 BasicBlock* block;
45 46
46 PendingEffectPhi(Node* effect_phi, BasicBlock* block) 47 PendingEffectPhi(Node* effect_phi, BasicBlock* block)
47 : effect_phi(effect_phi), block(block) {} 48 : effect_phi(effect_phi), block(block) {}
48 }; 49 };
49 50
50 void UpdateEffectPhi(Node* node, BasicBlock* block, 51 void UpdateEffectPhi(Node* node, BasicBlock* block,
51 ZoneVector<BlockEffectData>* block_effects) { 52 ZoneVector<BlockEffectControlData>* block_effects) {
52 // Update all inputs to an effect phi with the effects from the given 53 // Update all inputs to an effect phi with the effects from the given
53 // block->effect map. 54 // block->effect map.
54 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); 55 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
55 DCHECK_EQ(node->op()->EffectInputCount(), block->PredecessorCount()); 56 DCHECK_EQ(node->op()->EffectInputCount(), block->PredecessorCount());
56 for (int i = 0; i < node->op()->EffectInputCount(); i++) { 57 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
57 Node* input = node->InputAt(i); 58 Node* input = node->InputAt(i);
58 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); 59 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
59 Node* input_effect = 60 Node* input_effect =
60 (*block_effects)[predecessor->rpo_number()].current_effect; 61 (*block_effects)[predecessor->rpo_number()].current_effect;
61 if (input != input_effect) { 62 if (input != input_effect) {
62 node->ReplaceInput(i, input_effect); 63 node->ReplaceInput(i, input_effect);
63 } 64 }
64 } 65 }
65 } 66 }
66 67
68 void UpdateBlockControl(BasicBlock* block,
69 ZoneVector<BlockEffectControlData>* block_effects) {
70 Node* control = block->NodeAt(0);
71 DCHECK(NodeProperties::IsControl(control));
72
73 // Do not rewire the end node.
74 if (control->opcode() == IrOpcode::kEnd) return;
75
76 // Update all inputs to the given control node with the correct control.
77 DCHECK_EQ(control->op()->ControlInputCount(), block->PredecessorCount());
78 for (int i = 0; i < control->op()->ControlInputCount(); i++) {
79 Node* input = NodeProperties::GetControlInput(control, i);
80 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
81 Node* input_control =
82 (*block_effects)[predecessor->rpo_number()].current_control;
83 if (input != input_control) {
84 NodeProperties::ReplaceControlInput(control, input_control, i);
85 }
86 }
87 }
88
67 bool HasIncomingBackEdges(BasicBlock* block) { 89 bool HasIncomingBackEdges(BasicBlock* block) {
68 for (BasicBlock* pred : block->predecessors()) { 90 for (BasicBlock* pred : block->predecessors()) {
69 if (pred->rpo_number() >= block->rpo_number()) { 91 if (pred->rpo_number() >= block->rpo_number()) {
70 return true; 92 return true;
71 } 93 }
72 } 94 }
73 return false; 95 return false;
74 } 96 }
75 97
76 void RemoveRegionNode(Node* node) { 98 void RemoveRegionNode(Node* node) {
(...skipping 10 matching lines...) Expand all
87 DCHECK(!NodeProperties::IsFrameStateEdge(edge)); 109 DCHECK(!NodeProperties::IsFrameStateEdge(edge));
88 edge.UpdateTo(node->InputAt(0)); 110 edge.UpdateTo(node->InputAt(0));
89 } 111 }
90 } 112 }
91 node->Kill(); 113 node->Kill();
92 } 114 }
93 115
94 } // namespace 116 } // namespace
95 117
96 void EffectControlLinearizer::Run() { 118 void EffectControlLinearizer::Run() {
97 ZoneVector<BlockEffectData> block_effects(temp_zone()); 119 ZoneVector<BlockEffectControlData> block_effects(temp_zone());
98 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); 120 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
121 ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
99 block_effects.resize(schedule()->RpoBlockCount()); 122 block_effects.resize(schedule()->RpoBlockCount());
100 NodeVector inputs_buffer(temp_zone()); 123 NodeVector inputs_buffer(temp_zone());
101 124
102 for (BasicBlock* block : *(schedule()->rpo_order())) { 125 for (BasicBlock* block : *(schedule()->rpo_order())) {
103 size_t instr = 0; 126 size_t instr = 0;
104 127
105 // The control node should be the first. 128 // The control node should be the first.
106 Node* control = block->NodeAt(instr); 129 Node* control = block->NodeAt(instr);
107 DCHECK(NodeProperties::IsControl(control)); 130 DCHECK(NodeProperties::IsControl(control));
131 // Update the control inputs.
132 if (HasIncomingBackEdges(block)) {
133 // If there are back edges, we need to update later because we have not
134 // computed the control yet. This should only happen for loops.
135 DCHECK_EQ(IrOpcode::kLoop, control->opcode());
136 pending_block_controls.push_back(block);
137 } else {
138 // If there are no back edges, we can update now.
139 UpdateBlockControl(block, &block_effects);
140 }
108 instr++; 141 instr++;
109 142
110 // Iterate over the phis and update the effect phis. 143 // Iterate over the phis and update the effect phis.
111 Node* effect = nullptr; 144 Node* effect = nullptr;
112 Node* terminate = nullptr; 145 Node* terminate = nullptr;
113 for (; instr < block->NodeCount(); instr++) { 146 for (; instr < block->NodeCount(); instr++) {
114 Node* node = block->NodeAt(instr); 147 Node* node = block->NodeAt(instr);
115 // Only go through the phis and effect phis. 148 // Only go through the phis and effect phis.
116 if (node->opcode() == IrOpcode::kEffectPhi) { 149 if (node->opcode() == IrOpcode::kEffectPhi) {
117 // There should be at most one effect phi in a block. 150 // There should be at most one effect phi in a block.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 inputs_buffer.clear(); 203 inputs_buffer.clear();
171 inputs_buffer.resize(block->PredecessorCount(), graph()->start()); 204 inputs_buffer.resize(block->PredecessorCount(), graph()->start());
172 inputs_buffer.push_back(control); 205 inputs_buffer.push_back(control);
173 effect = graph()->NewNode( 206 effect = graph()->NewNode(
174 common()->EffectPhi(static_cast<int>(block->PredecessorCount())), 207 common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
175 static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front())); 208 static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
176 // Let us update the effect phi node later. 209 // Let us update the effect phi node later.
177 pending_effect_phis.push_back(PendingEffectPhi(effect, block)); 210 pending_effect_phis.push_back(PendingEffectPhi(effect, block));
178 } else if (control->opcode() == IrOpcode::kIfException) { 211 } else if (control->opcode() == IrOpcode::kIfException) {
179 // The IfException is connected into the effect chain, so we need 212 // The IfException is connected into the effect chain, so we need
180 // to process it here. 213 // to update the effect here.
181 ProcessNode(control, &effect, &control); 214 NodeProperties::ReplaceEffectInput(control, effect);
215 effect = control;
182 } 216 }
183 } 217 }
184 } 218 }
185 219
186 // Fixup the Terminate node. 220 // Fixup the Terminate node.
187 if (terminate != nullptr) { 221 if (terminate != nullptr) {
188 NodeProperties::ReplaceEffectInput(terminate, effect); 222 NodeProperties::ReplaceEffectInput(terminate, effect);
189 } 223 }
190 224
191 // Process the ordinary instructions. 225 // Process the ordinary instructions.
(...skipping 13 matching lines...) Expand all
205 case BasicBlock::kSwitch: 239 case BasicBlock::kSwitch:
206 case BasicBlock::kReturn: 240 case BasicBlock::kReturn:
207 case BasicBlock::kDeoptimize: 241 case BasicBlock::kDeoptimize:
208 case BasicBlock::kThrow: 242 case BasicBlock::kThrow:
209 ProcessNode(block->control_input(), &effect, &control); 243 ProcessNode(block->control_input(), &effect, &control);
210 break; 244 break;
211 } 245 }
212 246
213 // Store the effect for later use. 247 // Store the effect for later use.
214 block_effects[block->rpo_number()].current_effect = effect; 248 block_effects[block->rpo_number()].current_effect = effect;
249 block_effects[block->rpo_number()].current_control = control;
215 } 250 }
216 251
217 // Update the incoming edges of the effect phis that could not be processed 252 // Update the incoming edges of the effect phis that could not be processed
218 // during the first pass (because they could have incoming back edges). 253 // during the first pass (because they could have incoming back edges).
219 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) { 254 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
220 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, 255 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
221 &block_effects); 256 &block_effects);
222 } 257 }
258 for (BasicBlock* pending_block_control : pending_block_controls) {
259 UpdateBlockControl(pending_block_control, &block_effects);
260 }
223 } 261 }
224 262
263 namespace {
264
265 void TryScheduleCallIfSuccess(Node* node, Node** control) {
266 // Schedule the call's IfSuccess node if there is no exception use.
267 if (!NodeProperties::IsExceptionalCall(node)) {
268 for (Edge edge : node->use_edges()) {
269 if (NodeProperties::IsControlEdge(edge) &&
270 edge.from()->opcode() == IrOpcode::kIfSuccess) {
271 *control = edge.from();
272 }
273 }
274 }
275 }
276
277 } // namespace
278
225 void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, 279 void EffectControlLinearizer::ProcessNode(Node* node, Node** effect,
226 Node** control) { 280 Node** control) {
227 // If the node needs to be wired into the effect/control chain, do this 281 // If the node needs to be wired into the effect/control chain, do this
228 // here. 282 // here.
229 if (TryWireInStateEffect(node, effect, control)) { 283 if (TryWireInStateEffect(node, effect, control)) {
230 return; 284 return;
231 } 285 }
232 286
233 // Remove the end markers of 'atomic' allocation region because the 287 // Remove the end markers of 'atomic' allocation region because the
234 // region should be wired-in now. 288 // region should be wired-in now.
235 if (node->opcode() == IrOpcode::kFinishRegion || 289 if (node->opcode() == IrOpcode::kFinishRegion ||
236 node->opcode() == IrOpcode::kBeginRegion) { 290 node->opcode() == IrOpcode::kBeginRegion) {
237 // Update the value uses to the value input of the finish node and 291 // Update the value uses to the value input of the finish node and
238 // the effect uses to the effect input. 292 // the effect uses to the effect input.
239 293
240 // TODO(jarin) Enable this once we make sure everything with side effects 294 // TODO(jarin) Enable this once we make sure everything with side effects
241 // is marked as effectful. 295 // is marked as effectful.
242 if (false) { 296 if (false) {
243 return RemoveRegionNode(node); 297 return RemoveRegionNode(node);
244 } 298 }
245 } 299 }
246 300
301 if (node->opcode() == IrOpcode::kIfSuccess) {
302 // We always schedule IfSuccess with its call, so skip it here.
303 DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
304 // The IfSuccess node should not belong to an exceptional call node
305 // because such IfSuccess nodes should only start a basic block (and
306 // basic block start nodes are not handled in the ProcessNode method).
307 DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
308 return;
309 }
310
247 // If the node takes an effect, replace with the current one. 311 // If the node takes an effect, replace with the current one.
248 if (node->op()->EffectInputCount() > 0) { 312 if (node->op()->EffectInputCount() > 0) {
249 DCHECK_EQ(1, node->op()->EffectInputCount()); 313 DCHECK_EQ(1, node->op()->EffectInputCount());
250 Node* input_effect = NodeProperties::GetEffectInput(node); 314 Node* input_effect = NodeProperties::GetEffectInput(node);
251 315
252 if (input_effect != *effect) { 316 if (input_effect != *effect) {
253 NodeProperties::ReplaceEffectInput(node, *effect); 317 NodeProperties::ReplaceEffectInput(node, *effect);
254 } 318 }
255 319
256 // If the node produces an effect, update our current effect. (However, 320 // If the node produces an effect, update our current effect. (However,
257 // ignore new effect chains started with ValueEffect.) 321 // ignore new effect chains started with ValueEffect.)
258 if (node->op()->EffectOutputCount() > 0) { 322 if (node->op()->EffectOutputCount() > 0) {
259 DCHECK_EQ(1, node->op()->EffectOutputCount()); 323 DCHECK_EQ(1, node->op()->EffectOutputCount());
260 *effect = node; 324 *effect = node;
261 } 325 }
262 } else { 326 } else {
263 // New effect chain is only started with a Start or ValueEffect node. 327 // New effect chain is only started with a Start or ValueEffect node.
264 DCHECK(node->op()->EffectOutputCount() == 0 || 328 DCHECK(node->op()->EffectOutputCount() == 0 ||
265 node->opcode() == IrOpcode::kStart); 329 node->opcode() == IrOpcode::kStart);
266 } 330 }
331 // Rewire control inputs of control nodes, and update the current control
332 // input.
333 if (node->op()->ControlOutputCount() > 0) {
334 DCHECK_EQ(1, node->op()->ControlInputCount());
335 NodeProperties::ReplaceControlInput(node, *control);
336 *control = node;
337
338 if (node->opcode() == IrOpcode::kCall) {
339 // Schedule the call's IfSuccess node (if there is no exception use).
340 TryScheduleCallIfSuccess(node, control);
341 }
342 }
267 } 343 }
268 344
269 bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect, 345 bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
270 Node** control) { 346 Node** control) {
271 ValueEffectControl state(nullptr, nullptr, nullptr); 347 ValueEffectControl state(nullptr, nullptr, nullptr);
272 switch (node->opcode()) { 348 switch (node->opcode()) {
273 case IrOpcode::kChangeInt32ToTagged: 349 case IrOpcode::kChangeInt32ToTagged:
274 state = LowerChangeInt32ToTagged(node, *effect, *control); 350 state = LowerChangeInt32ToTagged(node, *effect, *control);
275 break; 351 break;
276 case IrOpcode::kChangeUint32ToTagged: 352 case IrOpcode::kChangeUint32ToTagged:
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 return jsgraph()->Int32Constant(Smi::kMaxValue); 533 return jsgraph()->Int32Constant(Smi::kMaxValue);
458 } 534 }
459 535
460 Node* EffectControlLinearizer::SmiShiftBitsConstant() { 536 Node* EffectControlLinearizer::SmiShiftBitsConstant() {
461 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize); 537 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
462 } 538 }
463 539
464 } // namespace compiler 540 } // namespace compiler
465 } // namespace internal 541 } // namespace internal
466 } // namespace v8 542 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/node-properties.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698