[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}
This commit is contained in:
parent
38d303c5ca
commit
8df194c14a
@ -46,8 +46,10 @@ void ControlFlowOptimizer::Enqueue(Node* node) {
|
||||
|
||||
|
||||
void ControlFlowOptimizer::VisitNode(Node* node) {
|
||||
for (Node* use : node->uses()) {
|
||||
if (NodeProperties::IsControl(use)) Enqueue(use);
|
||||
for (Edge edge : node->use_edges()) {
|
||||
if (NodeProperties::IsControlEdge(edge)) {
|
||||
Enqueue(edge.from());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,20 +260,18 @@ bool ControlFlowOptimizer::TryBuildSwitch(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
|
||||
if (branch == node) {
|
||||
DCHECK_EQ(1u, values.size());
|
||||
Enqueue(if_true);
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -21,25 +21,32 @@ namespace compiler {
|
||||
class ControlFlowOptimizerTest : public GraphTest {
|
||||
public:
|
||||
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 {}
|
||||
|
||||
protected:
|
||||
void Optimize() {
|
||||
JSOperatorBuilder javascript(zone());
|
||||
JSGraph jsgraph(isolate(), graph(), common(), &javascript, machine());
|
||||
ControlFlowOptimizer optimizer(&jsgraph, zone());
|
||||
ControlFlowOptimizer optimizer(jsgraph(), zone());
|
||||
optimizer.Optimize();
|
||||
}
|
||||
|
||||
Node* EmptyFrameState() { return jsgraph()->EmptyFrameState(); }
|
||||
|
||||
JSGraph* jsgraph() { return &jsgraph_; }
|
||||
JSOperatorBuilder* javascript() { return &javascript_; }
|
||||
MachineOperatorBuilder* machine() { return &machine_; }
|
||||
|
||||
private:
|
||||
MachineOperatorBuilder machine_;
|
||||
JSOperatorBuilder javascript_;
|
||||
JSGraph jsgraph_;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(ControlFlowOptimizerTest, BuildSwitch) {
|
||||
TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
|
||||
Node* index = Parameter(0);
|
||||
Node* branch0 = graph()->NewNode(
|
||||
common()->Branch(),
|
||||
@ -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) {
|
||||
Node* cond0 = Parameter(0);
|
||||
Node* cond1 = Parameter(1);
|
||||
|
@ -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,
|
||||
const Matcher<Node*>& control_matcher) {
|
||||
return MakeMatcher(new IsSwitchMatcher(value_matcher, control_matcher));
|
||||
|
@ -47,6 +47,7 @@ Matcher<Node*> IsLoop(const Matcher<Node*>& control0_matcher,
|
||||
const Matcher<Node*>& control2_matcher);
|
||||
Matcher<Node*> IsIfTrue(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,
|
||||
const Matcher<Node*>& control_matcher);
|
||||
Matcher<Node*> IsIfValue(const Matcher<int32_t>& value_matcher,
|
||||
|
Loading…
Reference in New Issue
Block a user