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

Unified Diff: test/unittests/compiler/branch-elimination-unittest.cc

Issue 1376293005: [turbofan] Redundant branch elimination. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Comments Created 5 years, 2 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 | « src/compiler/pipeline.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/unittests/compiler/branch-elimination-unittest.cc
diff --git a/test/unittests/compiler/branch-elimination-unittest.cc b/test/unittests/compiler/branch-elimination-unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..efa490d7ec264854932965a209ec546c5500630b
--- /dev/null
+++ b/test/unittests/compiler/branch-elimination-unittest.cc
@@ -0,0 +1,204 @@
+// 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/branch-elimination.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-properties.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class BranchEliminationTest : public TypedGraphTest {
+ public:
+ BranchEliminationTest()
+ : machine_(zone(), kMachPtr, MachineOperatorBuilder::kNoFlags) {}
+
+ MachineOperatorBuilder* machine() { return &machine_; }
+
+ void Reduce() {
+ JSOperatorBuilder javascript(zone());
+ JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
+ machine());
+ GraphReducer graph_reducer(zone(), graph(), jsgraph.Dead());
+ BranchElimination branch_condition_elimination(&graph_reducer, &jsgraph,
+ zone());
+ graph_reducer.AddReducer(&branch_condition_elimination);
+ graph_reducer.ReduceGraph();
+ }
+
+ private:
+ MachineOperatorBuilder machine_;
+};
+
+
+TEST_F(BranchEliminationTest, NestedBranchSameTrue) {
+ // { return (x ? (x ? 1 : 2) : 3; }
+ // should be reduced to
+ // { return (x ? 1 : 3; }
+ Node* condition = Parameter(0);
+ Node* outer_branch =
+ graph()->NewNode(common()->Branch(), condition, graph()->start());
+
+ Node* outer_if_true = graph()->NewNode(common()->IfTrue(), outer_branch);
+ Node* inner_branch =
+ graph()->NewNode(common()->Branch(), condition, outer_if_true);
+ Node* inner_if_true = graph()->NewNode(common()->IfTrue(), inner_branch);
+ Node* inner_if_false = graph()->NewNode(common()->IfFalse(), inner_branch);
+ Node* inner_merge =
+ graph()->NewNode(common()->Merge(2), inner_if_true, inner_if_false);
+ Node* inner_phi =
+ graph()->NewNode(common()->Phi(kMachInt32, 2), Int32Constant(1),
+ Int32Constant(2), inner_merge);
+
+ Node* outer_if_false = graph()->NewNode(common()->IfFalse(), outer_branch);
+ Node* outer_merge =
+ graph()->NewNode(common()->Merge(2), inner_merge, outer_if_false);
+ Node* outer_phi = graph()->NewNode(common()->Phi(kMachInt32, 2), inner_phi,
+ Int32Constant(3), outer_merge);
+
+ Node* ret = graph()->NewNode(common()->Return(), outer_phi, graph()->start(),
+ outer_merge);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduce();
+
+ // Outer branch should not be rewritten, the inner branch should be discarded.
+ EXPECT_THAT(outer_branch, IsBranch(condition, graph()->start()));
+ EXPECT_THAT(inner_phi,
+ IsPhi(kMachInt32, IsInt32Constant(1), IsInt32Constant(2),
+ IsMerge(outer_if_true, IsDead())));
+}
+
+
+TEST_F(BranchEliminationTest, NestedBranchSameFalse) {
+ // { return (x ? 1 : (x ? 2 : 3); }
+ // should be reduced to
+ // { return (x ? 1 : 3; }
+ Node* condition = Parameter(0);
+ Node* outer_branch =
+ graph()->NewNode(common()->Branch(), condition, graph()->start());
+
+ Node* outer_if_true = graph()->NewNode(common()->IfTrue(), outer_branch);
+
+ Node* outer_if_false = graph()->NewNode(common()->IfFalse(), outer_branch);
+ Node* inner_branch =
+ graph()->NewNode(common()->Branch(), condition, outer_if_false);
+ Node* inner_if_true = graph()->NewNode(common()->IfTrue(), inner_branch);
+ Node* inner_if_false = graph()->NewNode(common()->IfFalse(), inner_branch);
+ Node* inner_merge =
+ graph()->NewNode(common()->Merge(2), inner_if_true, inner_if_false);
+ Node* inner_phi =
+ graph()->NewNode(common()->Phi(kMachInt32, 2), Int32Constant(2),
+ Int32Constant(3), inner_merge);
+
+ Node* outer_merge =
+ graph()->NewNode(common()->Merge(2), outer_if_true, inner_merge);
+ Node* outer_phi = graph()->NewNode(common()->Phi(kMachInt32, 2),
+ Int32Constant(1), inner_phi, outer_merge);
+
+ Node* ret = graph()->NewNode(common()->Return(), outer_phi, graph()->start(),
+ outer_merge);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduce();
+
+ // Outer branch should not be rewritten, the inner branch should be discarded.
+ EXPECT_THAT(outer_branch, IsBranch(condition, graph()->start()));
+ EXPECT_THAT(inner_phi,
+ IsPhi(kMachInt32, IsInt32Constant(2), IsInt32Constant(3),
+ IsMerge(IsDead(), outer_if_false)));
+}
+
+
+TEST_F(BranchEliminationTest, BranchAfterDiamond) {
+ // { var y = x ? 1 : 2; return y + x ? 3 : 4; }
+ // should not be reduced.
+ Node* condition = Parameter(0);
+
+ Node* branch1 =
+ graph()->NewNode(common()->Branch(), condition, graph()->start());
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), Int32Constant(1),
+ Int32Constant(2), merge1);
+
+ Node* branch2 = graph()->NewNode(common()->Branch(), condition, merge1);
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+ Node* phi2 = graph()->NewNode(common()->Phi(kMachInt32, 2), Int32Constant(3),
+ Int32Constant(4), merge1);
+
+
+ Node* add = graph()->NewNode(machine()->Int32Add(), phi1, phi2);
+ Node* ret =
+ graph()->NewNode(common()->Return(), add, graph()->start(), merge2);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduce();
+
+ // Outer branch should not be rewritten, the inner branch condition should
+ // be true.
+ EXPECT_THAT(branch1, IsBranch(condition, graph()->start()));
+ EXPECT_THAT(branch2, IsBranch(condition, merge1));
+}
+
+
+TEST_F(BranchEliminationTest, BranchInsideLoopSame) {
+ // if (x) while (x) { return 2; } else { return 1; }
+ // should be rewritten to
+ // if (x) while (true) { return 2; } else { return 1; }
+
+ Node* condition = Parameter(0);
+
+ Node* outer_branch =
+ graph()->NewNode(common()->Branch(), condition, graph()->start());
+ Node* outer_if_true = graph()->NewNode(common()->IfTrue(), outer_branch);
+
+
+ Node* loop = graph()->NewNode(common()->Loop(1), outer_if_true);
+ Node* effect =
+ graph()->NewNode(common()->EffectPhi(1), graph()->start(), loop);
+
+ Node* inner_branch = graph()->NewNode(common()->Branch(), condition, loop);
+
+ Node* inner_if_true = graph()->NewNode(common()->IfTrue(), inner_branch);
+ Node* ret1 = graph()->NewNode(common()->Return(), Int32Constant(2), effect,
+ inner_if_true);
+
+ Node* inner_if_false = graph()->NewNode(common()->IfFalse(), inner_branch);
+ loop->AppendInput(zone(), inner_if_false);
+ NodeProperties::ChangeOp(loop, common()->Loop(2));
+ effect->InsertInput(zone(), 1, effect);
+ NodeProperties::ChangeOp(effect, common()->EffectPhi(2));
+
+ Node* outer_if_false = graph()->NewNode(common()->IfFalse(), outer_branch);
+ Node* outer_merge =
+ graph()->NewNode(common()->Merge(2), loop, outer_if_false);
+ Node* outer_ephi = graph()->NewNode(common()->EffectPhi(2), effect,
+ graph()->start(), outer_merge);
+
+ Node* ret2 = graph()->NewNode(common()->Return(), Int32Constant(1),
+ outer_ephi, outer_merge);
+
+ Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop);
+ graph()->SetEnd(graph()->NewNode(common()->End(3), ret1, ret2, terminate));
+
+ Reduce();
+
+ // Outer branch should not be rewritten, the inner branch should be discarded.
+ EXPECT_THAT(outer_branch, IsBranch(condition, graph()->start()));
+ EXPECT_THAT(ret1, IsReturn(IsInt32Constant(2), effect, loop));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
« no previous file with comments | « src/compiler/pipeline.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698