summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc')
-rw-r--r--deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc375
1 files changed, 375 insertions, 0 deletions
diff --git a/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc b/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc
new file mode 100644
index 0000000000..8284fd8775
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc
@@ -0,0 +1,375 @@
+// 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/common-operator.h"
+#include "src/compiler/dead-code-elimination.h"
+#include "test/unittests/compiler/graph-reducer-unittest.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::StrictMock;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class DeadCodeEliminationTest : public GraphTest {
+ public:
+ explicit DeadCodeEliminationTest(int num_parameters = 4)
+ : GraphTest(num_parameters) {}
+ ~DeadCodeEliminationTest() override {}
+
+ protected:
+ Reduction Reduce(AdvancedReducer::Editor* editor, Node* node) {
+ DeadCodeElimination reducer(editor, graph(), common());
+ return reducer.Reduce(node);
+ }
+
+ Reduction Reduce(Node* node) {
+ StrictMock<MockAdvancedReducerEditor> editor;
+ return Reduce(&editor, node);
+ }
+};
+
+
+namespace {
+
+const MachineType kMachineTypes[] = {
+ kMachFloat32, kMachFloat64, kMachInt8, kMachUint8, kMachInt16,
+ kMachUint16, kMachInt32, kMachUint32, kMachInt64, kMachUint64,
+ kMachPtr, kMachAnyTagged, kRepBit, kRepWord8, kRepWord16,
+ kRepWord32, kRepWord64, kRepFloat32, kRepFloat64, kRepTagged};
+
+
+const int kMaxInputs = 16;
+
+
+const Operator kOp0(0, Operator::kNoProperties, "Op0", 1, 1, 1, 1, 1, 1);
+
+} // namespace
+
+
+// -----------------------------------------------------------------------------
+// General dead propagation
+
+
+TEST_F(DeadCodeEliminationTest, GeneralDeadPropagation) {
+ Node* const value = Parameter(0);
+ Node* const effect = graph()->start();
+ Node* const dead = graph()->NewNode(common()->Dead());
+ Node* const node = graph()->NewNode(&kOp0, value, effect, dead);
+ Reduction const r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// Branch
+
+
+TEST_F(DeadCodeEliminationTest, BranchWithDeadControlInput) {
+ BranchHint const kHints[] = {BranchHint::kNone, BranchHint::kTrue,
+ BranchHint::kFalse};
+ TRACED_FOREACH(BranchHint, hint, kHints) {
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->Branch(hint), Parameter(0),
+ graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// IfTrue
+
+
+TEST_F(DeadCodeEliminationTest, IfTrueWithDeadInput) {
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->IfTrue(), graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// IfFalse
+
+
+TEST_F(DeadCodeEliminationTest, IfFalseWithDeadInput) {
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->IfFalse(), graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// IfSuccess
+
+
+TEST_F(DeadCodeEliminationTest, IfSuccessWithDeadInput) {
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->IfSuccess(), graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// IfException
+
+
+TEST_F(DeadCodeEliminationTest, IfExceptionWithDeadControlInput) {
+ IfExceptionHint const kHints[] = {IfExceptionHint::kLocallyCaught,
+ IfExceptionHint::kLocallyUncaught};
+ TRACED_FOREACH(IfExceptionHint, hint, kHints) {
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->IfException(hint), graph()->start(),
+ graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// End
+
+
+TEST_F(DeadCodeEliminationTest, EndWithDeadAndStart) {
+ Node* const dead = graph()->NewNode(common()->Dead());
+ Node* const start = graph()->start();
+ Reduction const r = Reduce(graph()->NewNode(common()->End(2), dead, start));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsEnd(start));
+}
+
+
+TEST_F(DeadCodeEliminationTest, EndWithOnlyDeadInputs) {
+ Node* inputs[kMaxInputs];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->NewNode(common()->Dead());
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->End(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Merge
+
+
+TEST_F(DeadCodeEliminationTest, MergeWithOnlyDeadInputs) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->NewNode(common()->Dead());
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->Merge(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(DeadCodeEliminationTest, MergeWithOneLiveAndOneDeadInput) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const e0 = graph()->NewNode(&kOp0, v0, graph()->start(), c0);
+ Node* const e1 = graph()->NewNode(&kOp0, v1, graph()->start(), c1);
+ Node* const merge = graph()->NewNode(common()->Merge(2), c0, c1);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), v0, v1, merge);
+ Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e1, merge);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(phi, v0));
+ EXPECT_CALL(editor, Replace(ephi, e0));
+ Reduction const r = Reduce(&editor, merge);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(c0, r.replacement());
+}
+
+
+TEST_F(DeadCodeEliminationTest, MergeWithTwoLiveAndTwoDeadInputs) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const v2 = Parameter(2);
+ Node* const v3 = Parameter(3);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const c2 = graph()->NewNode(common()->Dead());
+ Node* const c3 = graph()->NewNode(&kOp0, v3, graph()->start(), c0);
+ Node* const e0 = graph()->start();
+ Node* const e1 = graph()->NewNode(&kOp0, v1, e0, c0);
+ Node* const e2 = graph()->NewNode(&kOp0, v2, e1, c0);
+ Node* const e3 = graph()->NewNode(&kOp0, v3, graph()->start(), c3);
+ Node* const merge = graph()->NewNode(common()->Merge(4), c0, c1, c2, c3);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 4), v0, v1, v2, v3, merge);
+ Node* const ephi =
+ graph()->NewNode(common()->EffectPhi(4), e0, e1, e2, e3, merge);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(phi));
+ EXPECT_CALL(editor, Revisit(ephi));
+ Reduction const r = Reduce(&editor, merge);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsMerge(c0, c3));
+ EXPECT_THAT(phi, IsPhi(kMachAnyTagged, v0, v3, r.replacement()));
+ EXPECT_THAT(ephi, IsEffectPhi(e0, e3, r.replacement()));
+}
+
+
+// -----------------------------------------------------------------------------
+// Loop
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithDeadFirstInput) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ inputs[0] = graph()->NewNode(common()->Dead());
+ for (int i = 1; i < input_count; ++i) {
+ inputs[i] = graph()->start();
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->Loop(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithOnlyDeadInputs) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->NewNode(common()->Dead());
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->Loop(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithOneLiveAndOneDeadInput) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const e0 = graph()->NewNode(&kOp0, v0, graph()->start(), c0);
+ Node* const e1 = graph()->NewNode(&kOp0, v1, graph()->start(), c1);
+ Node* const loop = graph()->NewNode(common()->Loop(2), c0, c1);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), v0, v1, loop);
+ Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e1, loop);
+ Node* const terminate = graph()->NewNode(common()->Terminate(), ephi, loop);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(phi, v0));
+ EXPECT_CALL(editor, Replace(ephi, e0));
+ EXPECT_CALL(editor, Replace(terminate, IsDead()));
+ Reduction const r = Reduce(&editor, loop);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(c0, r.replacement());
+}
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithTwoLiveAndTwoDeadInputs) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const v2 = Parameter(2);
+ Node* const v3 = Parameter(3);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const c2 = graph()->NewNode(common()->Dead());
+ Node* const c3 = graph()->NewNode(&kOp0, v3, graph()->start(), c0);
+ Node* const e0 = graph()->start();
+ Node* const e1 = graph()->NewNode(&kOp0, v1, e0, c0);
+ Node* const e2 = graph()->NewNode(&kOp0, v2, e1, c0);
+ Node* const e3 = graph()->NewNode(&kOp0, v3, graph()->start(), c3);
+ Node* const loop = graph()->NewNode(common()->Loop(4), c0, c1, c2, c3);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 4), v0, v1, v2, v3, loop);
+ Node* const ephi =
+ graph()->NewNode(common()->EffectPhi(4), e0, e1, e2, e3, loop);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(phi));
+ EXPECT_CALL(editor, Revisit(ephi));
+ Reduction const r = Reduce(&editor, loop);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsLoop(c0, c3));
+ EXPECT_THAT(phi, IsPhi(kMachAnyTagged, v0, v3, r.replacement()));
+ EXPECT_THAT(ephi, IsEffectPhi(e0, e3, r.replacement()));
+}
+
+
+// -----------------------------------------------------------------------------
+// Phi
+
+
+TEST_F(DeadCodeEliminationTest, PhiWithDeadControlInput) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FOREACH(MachineType, type, kMachineTypes) {
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = Parameter(i);
+ }
+ inputs[input_count] = graph()->NewNode(common()->Dead());
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->Phi(type, input_count), input_count + 1, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// EffectPhi
+
+
+TEST_F(DeadCodeEliminationTest, EffectPhiWithDeadControlInput) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->start();
+ }
+ inputs[input_count] = graph()->NewNode(common()->Dead());
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->EffectPhi(input_count), input_count + 1, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Terminate
+
+
+TEST_F(DeadCodeEliminationTest, TerminateWithDeadControlInput) {
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->Terminate(), graph()->start(),
+ graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8