Commit 8df194c1 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Fix ControlFlowOptimizer to also handle non-control nodes in the control chain.

Review URL: https://codereview.chromium.org/971223002

Cr-Commit-Position: refs/heads/master@{#26949}
parent 38d303c5
...@@ -46,8 +46,10 @@ void ControlFlowOptimizer::Enqueue(Node* node) { ...@@ -46,8 +46,10 @@ void ControlFlowOptimizer::Enqueue(Node* node) {
void ControlFlowOptimizer::VisitNode(Node* node) { void ControlFlowOptimizer::VisitNode(Node* node) {
for (Node* use : node->uses()) { for (Edge edge : node->use_edges()) {
if (NodeProperties::IsControl(use)) Enqueue(use); if (NodeProperties::IsControlEdge(edge)) {
Enqueue(edge.from());
}
} }
} }
...@@ -258,20 +260,18 @@ bool ControlFlowOptimizer::TryBuildSwitch(Node* node) { ...@@ -258,20 +260,18 @@ bool ControlFlowOptimizer::TryBuildSwitch(Node* node) {
DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode()); DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
if (branch == node) { if (branch == node) {
DCHECK_EQ(1u, values.size()); DCHECK_EQ(1u, values.size());
Enqueue(if_true); return false;
Enqueue(if_false);
} else {
DCHECK_LT(1u, values.size());
node->set_op(common()->Switch(values.size() + 1));
node->ReplaceInput(0, index);
if_true->set_op(common()->IfValue(value));
if_true->ReplaceInput(0, node);
Enqueue(if_true);
if_false->set_op(common()->IfDefault());
if_false->ReplaceInput(0, node);
Enqueue(if_false);
branch->RemoveAllInputs();
} }
DCHECK_LT(1u, values.size());
node->set_op(common()->Switch(values.size() + 1));
node->ReplaceInput(0, index);
if_true->set_op(common()->IfValue(value));
if_true->ReplaceInput(0, node);
Enqueue(if_true);
if_false->set_op(common()->IfDefault());
if_false->ReplaceInput(0, node);
Enqueue(if_false);
branch->RemoveAllInputs();
return true; return true;
} }
......
...@@ -21,25 +21,32 @@ namespace compiler { ...@@ -21,25 +21,32 @@ namespace compiler {
class ControlFlowOptimizerTest : public GraphTest { class ControlFlowOptimizerTest : public GraphTest {
public: public:
explicit ControlFlowOptimizerTest(int num_parameters = 3) explicit ControlFlowOptimizerTest(int num_parameters = 3)
: GraphTest(num_parameters), machine_(zone()) {} : GraphTest(num_parameters),
machine_(zone()),
javascript_(zone()),
jsgraph_(isolate(), graph(), common(), javascript(), machine()) {}
~ControlFlowOptimizerTest() OVERRIDE {} ~ControlFlowOptimizerTest() OVERRIDE {}
protected: protected:
void Optimize() { void Optimize() {
JSOperatorBuilder javascript(zone()); ControlFlowOptimizer optimizer(jsgraph(), zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, machine());
ControlFlowOptimizer optimizer(&jsgraph, zone());
optimizer.Optimize(); optimizer.Optimize();
} }
Node* EmptyFrameState() { return jsgraph()->EmptyFrameState(); }
JSGraph* jsgraph() { return &jsgraph_; }
JSOperatorBuilder* javascript() { return &javascript_; }
MachineOperatorBuilder* machine() { return &machine_; } MachineOperatorBuilder* machine() { return &machine_; }
private: private:
MachineOperatorBuilder machine_; MachineOperatorBuilder machine_;
JSOperatorBuilder javascript_;
JSGraph jsgraph_;
}; };
TEST_F(ControlFlowOptimizerTest, BuildSwitch) { TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
Node* index = Parameter(0); Node* index = Parameter(0);
Node* branch0 = graph()->NewNode( Node* branch0 = graph()->NewNode(
common()->Branch(), common()->Branch(),
...@@ -66,6 +73,41 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch) { ...@@ -66,6 +73,41 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch) {
} }
TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
Node* input = Parameter(0);
Node* context = Parameter(1);
Node* index = FLAG_turbo_deoptimization
? graph()->NewNode(javascript()->ToNumber(), input, context,
EmptyFrameState(), start(), start())
: graph()->NewNode(javascript()->ToNumber(), input, context,
start(), start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), index);
Node* branch0 = graph()->NewNode(
common()->Branch(),
graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
if_success);
Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
Node* branch1 = graph()->NewNode(
common()->Branch(),
graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
if_false0);
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* merge =
graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
graph()->SetEnd(graph()->NewNode(common()->End(), merge));
Optimize();
Capture<Node*> switch_capture;
EXPECT_THAT(
end(),
IsEnd(IsMerge(IsIfValue(0, CaptureEq(&switch_capture)),
IsIfValue(1, CaptureEq(&switch_capture)),
IsIfDefault(AllOf(CaptureEq(&switch_capture),
IsSwitch(index, IsIfSuccess(index)))))));
}
TEST_F(ControlFlowOptimizerTest, CloneBranch) { TEST_F(ControlFlowOptimizerTest, CloneBranch) {
Node* cond0 = Parameter(0); Node* cond0 = Parameter(0);
Node* cond1 = Parameter(1); Node* cond1 = Parameter(1);
......
...@@ -1303,6 +1303,12 @@ Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) { ...@@ -1303,6 +1303,12 @@ Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) {
} }
Matcher<Node*> IsIfSuccess(const Matcher<Node*>& control_matcher) {
return MakeMatcher(
new IsControl1Matcher(IrOpcode::kIfSuccess, control_matcher));
}
Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher, Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) { const Matcher<Node*>& control_matcher) {
return MakeMatcher(new IsSwitchMatcher(value_matcher, control_matcher)); return MakeMatcher(new IsSwitchMatcher(value_matcher, control_matcher));
......
...@@ -47,6 +47,7 @@ Matcher<Node*> IsLoop(const Matcher<Node*>& control0_matcher, ...@@ -47,6 +47,7 @@ Matcher<Node*> IsLoop(const Matcher<Node*>& control0_matcher,
const Matcher<Node*>& control2_matcher); const Matcher<Node*>& control2_matcher);
Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher); Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher);
Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher); Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher);
Matcher<Node*> IsIfSuccess(const Matcher<Node*>& control_matcher);
Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher, Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher); const Matcher<Node*>& control_matcher);
Matcher<Node*> IsIfValue(const Matcher<int32_t>& value_matcher, Matcher<Node*> IsIfValue(const Matcher<int32_t>& value_matcher,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment