v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
bmeurer 4940c0bd42 [turbofan] Unify frame state inputs.
Now all nodes that care about deoptimization always take frame state
inputs no matter whether deoptimization is enabled for a particular
function. In case that deoptimization is off, the AstGraphBuilder just
inserts the empty frame state. This greatly simplifies the logic in
various places and makes testing easier as well, and is probably the
first step towards enabling --turbo-deoptimization by default.

There seems to be no noticable performance impact on asm.js programs.

Also fix the graph replay in order to regenerate the scheduler unittests.

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

Cr-Commit-Position: refs/heads/master@{#28026}
2015-04-23 09:04:19 +00:00

138 lines
5.3 KiB
C++

// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/control-flow-optimizer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"
using testing::AllOf;
using testing::Capture;
using testing::CaptureEq;
namespace v8 {
namespace internal {
namespace compiler {
class ControlFlowOptimizerTest : public GraphTest {
public:
explicit ControlFlowOptimizerTest(int num_parameters = 3)
: GraphTest(num_parameters),
machine_(zone()),
javascript_(zone()),
jsgraph_(isolate(), graph(), common(), javascript(), machine()) {}
~ControlFlowOptimizerTest() override {}
protected:
void Optimize() {
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, BuildSwitch1) {
Node* index = Parameter(0);
Node* branch0 = graph()->NewNode(
common()->Branch(),
graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
start());
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, start()))))));
}
TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
Node* input = Parameter(0);
Node* context = Parameter(1);
Node* index = graph()->NewNode(javascript()->ToNumber(), input, context,
EmptyFrameState(), 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);
Node* cond2 = Parameter(2);
Node* branch0 = graph()->NewNode(common()->Branch(), cond0, start());
Node* control1 = graph()->NewNode(common()->IfTrue(), branch0);
Node* control2 = graph()->NewNode(common()->IfFalse(), branch0);
Node* merge0 = graph()->NewNode(common()->Merge(2), control1, control2);
Node* phi0 =
graph()->NewNode(common()->Phi(kRepBit, 2), cond1, cond2, merge0);
Node* branch = graph()->NewNode(common()->Branch(), phi0, merge0);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
graph()->SetEnd(graph()->NewNode(common()->End(), merge));
Optimize();
Capture<Node*> branch1_capture, branch2_capture;
EXPECT_THAT(
end(),
IsEnd(IsMerge(IsMerge(IsIfTrue(CaptureEq(&branch1_capture)),
IsIfTrue(CaptureEq(&branch2_capture))),
IsMerge(IsIfFalse(AllOf(CaptureEq(&branch1_capture),
IsBranch(cond1, control1))),
IsIfFalse(AllOf(CaptureEq(&branch2_capture),
IsBranch(cond2, control2)))))));
}
} // namespace compiler
} // namespace internal
} // namespace v8