Index: src/compiler/effect-control-linearizer.cc |
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc |
index ec21247bfc8c30d5b8a6efb5c794c5cd41e2c51f..4165efd586a9d5f5e94863940d2e02c1eb10a5a5 100644 |
--- a/src/compiler/effect-control-linearizer.cc |
+++ b/src/compiler/effect-control-linearizer.cc |
@@ -34,8 +34,9 @@ MachineOperatorBuilder* EffectControlLinearizer::machine() const { |
namespace { |
-struct BlockEffectData { |
+struct BlockEffectControlData { |
Node* current_effect = nullptr; // New effect. |
+ Node* current_control = nullptr; // New control. |
}; |
// Effect phis that need to be updated after the first pass. |
@@ -48,7 +49,7 @@ struct PendingEffectPhi { |
}; |
void UpdateEffectPhi(Node* node, BasicBlock* block, |
- ZoneVector<BlockEffectData>* block_effects) { |
+ ZoneVector<BlockEffectControlData>* block_effects) { |
// Update all inputs to an effect phi with the effects from the given |
// block->effect map. |
DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); |
@@ -64,6 +65,27 @@ void UpdateEffectPhi(Node* node, BasicBlock* block, |
} |
} |
+void UpdateBlockControl(BasicBlock* block, |
+ ZoneVector<BlockEffectControlData>* block_effects) { |
+ Node* control = block->NodeAt(0); |
+ DCHECK(NodeProperties::IsControl(control)); |
+ |
+ // Do not rewire the end node. |
+ if (control->opcode() == IrOpcode::kEnd) return; |
+ |
+ // Update all inputs to the given control node with the correct control. |
+ DCHECK_EQ(control->op()->ControlInputCount(), block->PredecessorCount()); |
+ for (int i = 0; i < control->op()->ControlInputCount(); i++) { |
+ Node* input = NodeProperties::GetControlInput(control, i); |
+ BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); |
+ Node* input_control = |
+ (*block_effects)[predecessor->rpo_number()].current_control; |
+ if (input != input_control) { |
+ NodeProperties::ReplaceControlInput(control, input_control, i); |
+ } |
+ } |
+} |
+ |
bool HasIncomingBackEdges(BasicBlock* block) { |
for (BasicBlock* pred : block->predecessors()) { |
if (pred->rpo_number() >= block->rpo_number()) { |
@@ -94,8 +116,9 @@ void RemoveRegionNode(Node* node) { |
} // namespace |
void EffectControlLinearizer::Run() { |
- ZoneVector<BlockEffectData> block_effects(temp_zone()); |
+ ZoneVector<BlockEffectControlData> block_effects(temp_zone()); |
ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); |
+ ZoneVector<BasicBlock*> pending_block_controls(temp_zone()); |
block_effects.resize(schedule()->RpoBlockCount()); |
NodeVector inputs_buffer(temp_zone()); |
@@ -105,6 +128,16 @@ void EffectControlLinearizer::Run() { |
// The control node should be the first. |
Node* control = block->NodeAt(instr); |
DCHECK(NodeProperties::IsControl(control)); |
+ // Update the control inputs. |
+ if (HasIncomingBackEdges(block)) { |
+ // If there are back edges, we need to update later because we have not |
+ // computed the control yet. This should only happen for loops. |
+ DCHECK_EQ(IrOpcode::kLoop, control->opcode()); |
+ pending_block_controls.push_back(block); |
+ } else { |
+ // If there are no back edges, we can update now. |
+ UpdateBlockControl(block, &block_effects); |
+ } |
instr++; |
// Iterate over the phis and update the effect phis. |
@@ -177,8 +210,9 @@ void EffectControlLinearizer::Run() { |
pending_effect_phis.push_back(PendingEffectPhi(effect, block)); |
} else if (control->opcode() == IrOpcode::kIfException) { |
// The IfException is connected into the effect chain, so we need |
- // to process it here. |
- ProcessNode(control, &effect, &control); |
+ // to update the effect here. |
+ NodeProperties::ReplaceEffectInput(control, effect); |
+ effect = control; |
} |
} |
} |
@@ -212,6 +246,7 @@ void EffectControlLinearizer::Run() { |
// Store the effect for later use. |
block_effects[block->rpo_number()].current_effect = effect; |
+ block_effects[block->rpo_number()].current_control = control; |
} |
// Update the incoming edges of the effect phis that could not be processed |
@@ -220,6 +255,9 @@ void EffectControlLinearizer::Run() { |
UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, |
&block_effects); |
} |
+ for (BasicBlock* pending_block_control : pending_block_controls) { |
+ UpdateBlockControl(pending_block_control, &block_effects); |
+ } |
} |
void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, |
@@ -244,6 +282,25 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, |
} |
} |
+ if (node->opcode() == IrOpcode::kIfSuccess) { |
+ Node* success_input = NodeProperties::GetControlInput(node, 0); |
+ if (*control == success_input) { |
+ // The IfSuccess node refers to the last control node in the schedule, |
+ // so we just update the current control. |
+ *control = node; |
+ } else { |
+ // Some other intervening control has been scheduled after call, |
+ // we need to insert the IfSuccess node just after the call. |
+ for (Edge edge : success_input->use_edges()) { |
Benedikt Meurer
2016/04/24 18:12:49
Not sure I really get this one: This tries to upda
Jarin
2016/04/24 19:21:23
I have changed this to keep the wiring of IfSucces
|
+ if (NodeProperties::IsControlEdge(edge) && edge.from() != node && |
+ edge.from()->op()->ControlOutputCount() > 0) { |
+ edge.UpdateTo(node); |
+ } |
+ } |
+ } |
+ return; |
+ } |
+ |
// If the node takes an effect, replace with the current one. |
if (node->op()->EffectInputCount() > 0) { |
DCHECK_EQ(1, node->op()->EffectInputCount()); |
@@ -264,6 +321,13 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, |
DCHECK(node->op()->EffectOutputCount() == 0 || |
node->opcode() == IrOpcode::kStart); |
} |
+ // Rewire control inputs of control nodes, and update the current control |
+ // input. |
+ if (node->op()->ControlOutputCount() > 0) { |
+ DCHECK_EQ(1, node->op()->ControlInputCount()); |
+ NodeProperties::ReplaceControlInput(node, *control); |
+ *control = node; |
+ } |
} |
bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect, |