Index: src/compiler/common-operator-reducer.cc |
diff --git a/src/compiler/common-operator-reducer.cc b/src/compiler/common-operator-reducer.cc |
index 694c36edcc8d0f7876618be43fb213ea2737849a..1ed05f1834bf7b214db79526d8fc5a2f3698c736 100644 |
--- a/src/compiler/common-operator-reducer.cc |
+++ b/src/compiler/common-operator-reducer.cc |
@@ -11,6 +11,7 @@ |
#include "src/compiler/machine-operator.h" |
#include "src/compiler/node.h" |
#include "src/compiler/node-matchers.h" |
+#include "src/compiler/node-properties.h" |
namespace v8 { |
namespace internal { |
@@ -43,6 +44,16 @@ Decision DecideCondition(Node* const cond) { |
} // namespace |
+CommonOperatorReducer::CommonOperatorReducer(Editor* editor, Graph* graph, |
+ CommonOperatorBuilder* common, |
+ MachineOperatorBuilder* machine) |
+ : AdvancedReducer(editor), |
+ graph_(graph), |
+ common_(common), |
+ machine_(machine), |
+ dead_(graph->NewNode(common->Dead())) {} |
+ |
+ |
Reduction CommonOperatorReducer::Reduce(Node* node) { |
switch (node->opcode()) { |
case IrOpcode::kBranch: |
@@ -53,6 +64,8 @@ Reduction CommonOperatorReducer::Reduce(Node* node) { |
return ReduceEffectPhi(node); |
case IrOpcode::kPhi: |
return ReducePhi(node); |
+ case IrOpcode::kReturn: |
+ return ReduceReturn(node); |
case IrOpcode::kSelect: |
return ReduceSelect(node); |
default: |
@@ -91,20 +104,19 @@ Reduction CommonOperatorReducer::ReduceBranch(Node* node) { |
Decision const decision = DecideCondition(cond); |
if (decision == Decision::kUnknown) return NoChange(); |
Node* const control = node->InputAt(1); |
- if (!dead_.is_set()) dead_.set(graph()->NewNode(common()->Dead())); |
for (Node* const use : node->uses()) { |
switch (use->opcode()) { |
case IrOpcode::kIfTrue: |
- Replace(use, (decision == Decision::kTrue) ? control : dead_.get()); |
+ Replace(use, (decision == Decision::kTrue) ? control : dead()); |
break; |
case IrOpcode::kIfFalse: |
- Replace(use, (decision == Decision::kFalse) ? control : dead_.get()); |
+ Replace(use, (decision == Decision::kFalse) ? control : dead()); |
break; |
default: |
UNREACHABLE(); |
} |
} |
- return Replace(dead_.get()); |
+ return Replace(dead()); |
} |
@@ -253,6 +265,41 @@ Reduction CommonOperatorReducer::ReducePhi(Node* node) { |
} |
+Reduction CommonOperatorReducer::ReduceReturn(Node* node) { |
+ DCHECK_EQ(IrOpcode::kReturn, node->opcode()); |
+ Node* const value = node->InputAt(0); |
+ Node* const effect = node->InputAt(1); |
+ Node* const control = node->InputAt(2); |
+ if (value->opcode() == IrOpcode::kPhi && |
+ NodeProperties::GetControlInput(value) == control && |
+ effect->opcode() == IrOpcode::kEffectPhi && |
+ NodeProperties::GetControlInput(effect) == control && |
+ control->opcode() == IrOpcode::kMerge) { |
+ int const control_input_count = control->InputCount(); |
+ DCHECK_NE(0, control_input_count); |
+ DCHECK_EQ(control_input_count, value->InputCount() - 1); |
+ DCHECK_EQ(control_input_count, effect->InputCount() - 1); |
+ Node* const end = graph()->end(); |
+ DCHECK_EQ(IrOpcode::kEnd, end->opcode()); |
+ DCHECK_NE(0, end->InputCount()); |
+ for (int i = 0; i < control_input_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(), value->InputAt(i), |
+ effect->InputAt(i), control->InputAt(i)); |
+ end->set_op(common()->End(end->InputCount() + 1)); |
+ end->AppendInput(graph()->zone(), ret); |
+ } |
+ // Mark the merge {control} and return {node} as {dead}. |
+ Replace(control, dead()); |
+ return Replace(dead()); |
+ } |
+ return NoChange(); |
+} |
+ |
+ |
Reduction CommonOperatorReducer::ReduceSelect(Node* node) { |
DCHECK_EQ(IrOpcode::kSelect, node->opcode()); |
Node* const cond = node->InputAt(0); |