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

Unified Diff: src/compiler/common-operator-reducer.cc

Issue 2668903002: [turbofan] Also push Return into Merge even if there's no EffectPhi. (Closed)
Patch Set: REBASE Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/common-operator-reducer.cc
diff --git a/src/compiler/common-operator-reducer.cc b/src/compiler/common-operator-reducer.cc
index 85d49b7ae61be8508039a5160edd13b1fe080b33..2b62e9c684e592fc479621a4fb5a2f273047e9a1 100644
--- a/src/compiler/common-operator-reducer.cc
+++ b/src/compiler/common-operator-reducer.cc
@@ -284,55 +284,91 @@ Reduction CommonOperatorReducer::ReducePhi(Node* node) {
return Replace(value);
}
-
Reduction CommonOperatorReducer::ReduceReturn(Node* node) {
DCHECK_EQ(IrOpcode::kReturn, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node);
- Node* const control = NodeProperties::GetControlInput(node);
- bool changed = false;
if (effect->opcode() == IrOpcode::kCheckpoint) {
// Any {Return} node can never be used to insert a deoptimization point,
// hence checkpoints can be cut out of the effect chain flowing into it.
effect = NodeProperties::GetEffectInput(effect);
NodeProperties::ReplaceEffectInput(node, effect);
- changed = true;
+ Reduction const reduction = ReduceReturn(node);
+ return reduction.Changed() ? reduction : Changed(node);
}
// TODO(ahaas): Extend the reduction below to multiple return values.
if (ValueInputCountOfReturn(node->op()) != 1) {
return NoChange();
}
- Node* const value = node->InputAt(1);
+ Node* pop_count = NodeProperties::GetValueInput(node, 0);
+ Node* value = NodeProperties::GetValueInput(node, 1);
+ Node* control = NodeProperties::GetControlInput(node);
if (value->opcode() == IrOpcode::kPhi &&
NodeProperties::GetControlInput(value) == control &&
- effect->opcode() == IrOpcode::kEffectPhi &&
- NodeProperties::GetControlInput(effect) == control &&
control->opcode() == IrOpcode::kMerge) {
+ // This optimization pushes {Return} nodes through merges. It checks that
+ // the return value is actually a {Phi} and the return control dependency
+ // is the {Merge} to which the {Phi} belongs.
+
+ // Value1 ... ValueN Control1 ... ControlN
+ // ^ ^ ^ ^
+ // | | | |
+ // +----+-----+ +------+-----+
+ // | |
+ // Phi --------------> Merge
+ // ^ ^
+ // | |
+ // | +-----------------+
+ // | |
+ // Return -----> Effect
+ // ^
+ // |
+ // End
+
+ // Now the effect input to the {Return} node can be either an {EffectPhi}
+ // hanging off the same {Merge}, or the {Merge} node is only connected to
+ // the {Return} and the {Phi}, in which case we know that the effect input
+ // must somehow dominate all merged branches.
+
Node::Inputs control_inputs = control->inputs();
Node::Inputs value_inputs = value->inputs();
- Node::Inputs effect_inputs = effect->inputs();
DCHECK_NE(0, control_inputs.count());
DCHECK_EQ(control_inputs.count(), value_inputs.count() - 1);
- DCHECK_EQ(control_inputs.count(), effect_inputs.count() - 1);
DCHECK_EQ(IrOpcode::kEnd, graph()->end()->opcode());
DCHECK_NE(0, graph()->end()->InputCount());
- for (int i = 0; i < control_inputs.count(); ++i) {
- // Create a new {Return} and connect it to {end}. We don't need to mark
- // {end} as revisit, because we mark {node} as {Dead} below, which was
- // previously connected to {end}, so we know for sure that at some point
- // the reducer logic will visit {end} again.
- Node* ret = graph()->NewNode(common()->Return(), node->InputAt(0),
- value_inputs[i], effect_inputs[i],
- control_inputs[i]);
- NodeProperties::MergeControlToEnd(graph(), common(), ret);
+ if (control->OwnedBy(node, value)) {
+ for (int i = 0; i < control_inputs.count(); ++i) {
+ // Create a new {Return} and connect it to {end}. We don't need to mark
+ // {end} as revisit, because we mark {node} as {Dead} below, which was
+ // previously connected to {end}, so we know for sure that at some point
+ // the reducer logic will visit {end} again.
+ Node* ret = graph()->NewNode(node->op(), pop_count, value_inputs[i],
+ effect, control_inputs[i]);
+ NodeProperties::MergeControlToEnd(graph(), common(), ret);
+ }
+ // Mark the Merge {control} and Return {node} as {dead}.
+ Replace(control, dead());
+ return Replace(dead());
+ } else if (effect->opcode() == IrOpcode::kEffectPhi &&
+ NodeProperties::GetControlInput(effect) == control) {
+ Node::Inputs effect_inputs = effect->inputs();
+ DCHECK_EQ(control_inputs.count(), effect_inputs.count() - 1);
+ for (int i = 0; i < control_inputs.count(); ++i) {
+ // Create a new {Return} and connect it to {end}. We don't need to mark
+ // {end} as revisit, because we mark {node} as {Dead} below, which was
+ // previously connected to {end}, so we know for sure that at some point
+ // the reducer logic will visit {end} again.
+ Node* ret = graph()->NewNode(node->op(), pop_count, value_inputs[i],
+ effect_inputs[i], control_inputs[i]);
+ NodeProperties::MergeControlToEnd(graph(), common(), ret);
+ }
+ // Mark the Merge {control} and Return {node} as {dead}.
+ Replace(control, dead());
+ return Replace(dead());
}
- // Mark the merge {control} and return {node} as {dead}.
- Replace(control, dead());
- return Replace(dead());
}
- return changed ? Changed(node) : NoChange();
+ return NoChange();
}
-
Reduction CommonOperatorReducer::ReduceSelect(Node* node) {
DCHECK_EQ(IrOpcode::kSelect, node->opcode());
Node* const cond = node->InputAt(0);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698