Index: test/cctest/compiler/test-control-reducer.cc |
diff --git a/test/cctest/compiler/test-control-reducer.cc b/test/cctest/compiler/test-control-reducer.cc |
deleted file mode 100644 |
index d2bf776a63da60bc566d899ae26280317744489f..0000000000000000000000000000000000000000 |
--- a/test/cctest/compiler/test-control-reducer.cc |
+++ /dev/null |
@@ -1,1119 +0,0 @@ |
-// Copyright 2014 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/v8.h" |
-#include "test/cctest/cctest.h" |
- |
-#include "src/base/bits.h" |
-#include "src/compiler/all-nodes.h" |
-#include "src/compiler/common-operator.h" |
-#include "src/compiler/control-reducer.h" |
-#include "src/compiler/graph.h" |
-#include "src/compiler/js-graph.h" |
-#include "src/compiler/node-properties.h" |
- |
-using namespace v8::internal; |
-using namespace v8::internal::compiler; |
- |
-static const size_t kNumLeafs = 4; |
- |
-enum Decision { kFalse, kUnknown, kTrue }; |
- |
-// TODO(titzer): convert this whole file into unit tests. |
- |
-static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL, |
- Node* i2 = NULL) { |
- int count = 3; |
- if (i2 == NULL) count = 2; |
- if (i1 == NULL) count = 1; |
- if (i0 == NULL) count = 0; |
- CHECK_EQ(count, node->InputCount()); |
- if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); |
- if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1)); |
- if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2)); |
- return count; |
-} |
- |
- |
-static int CheckMerge(Node* node, Node* i0 = NULL, Node* i1 = NULL, |
- Node* i2 = NULL) { |
- CHECK_EQ(IrOpcode::kMerge, node->opcode()); |
- int count = CheckInputs(node, i0, i1, i2); |
- CHECK_EQ(count, node->op()->ControlInputCount()); |
- return count; |
-} |
- |
- |
-static int CheckLoop(Node* node, Node* i0 = NULL, Node* i1 = NULL, |
- Node* i2 = NULL) { |
- CHECK_EQ(IrOpcode::kLoop, node->opcode()); |
- int count = CheckInputs(node, i0, i1, i2); |
- CHECK_EQ(count, node->op()->ControlInputCount()); |
- return count; |
-} |
- |
- |
-bool IsUsedBy(Node* a, Node* b) { |
- auto const uses = a->uses(); |
- return std::find(uses.begin(), uses.end(), b) != uses.end(); |
-} |
- |
- |
-// A helper for all tests dealing with ControlTester. |
-class ControlReducerTester : HandleAndZoneScope { |
- public: |
- ControlReducerTester() |
- : isolate(main_isolate()), |
- common(main_zone()), |
- graph(main_zone()), |
- jsgraph(main_isolate(), &graph, &common, NULL, NULL), |
- start(graph.NewNode(common.Start(1))), |
- end(graph.NewNode(common.End(1), start)), |
- p0(graph.NewNode(common.Parameter(0), start)), |
- zero(jsgraph.Int32Constant(0)), |
- one(jsgraph.OneConstant()), |
- half(jsgraph.Constant(0.5)), |
- self(graph.NewNode(common.Int32Constant(0xaabbccdd))), |
- dead(graph.NewNode(common.DeadControl())) { |
- graph.SetEnd(end); |
- graph.SetStart(start); |
- leaf[0] = zero; |
- leaf[1] = one; |
- leaf[2] = half; |
- leaf[3] = p0; |
- } |
- |
- Isolate* isolate; |
- CommonOperatorBuilder common; |
- Graph graph; |
- JSGraph jsgraph; |
- Node* start; |
- Node* end; |
- Node* p0; |
- Node* zero; |
- Node* one; |
- Node* half; |
- Node* self; |
- Node* dead; |
- Node* leaf[kNumLeafs]; |
- |
- Node* Phi(Node* a) { |
- return SetSelfReferences(graph.NewNode(op(1, false), a, start)); |
- } |
- |
- Node* Phi(Node* a, Node* b) { |
- return SetSelfReferences(graph.NewNode(op(2, false), a, b, start)); |
- } |
- |
- Node* Phi(Node* a, Node* b, Node* c) { |
- return SetSelfReferences(graph.NewNode(op(3, false), a, b, c, start)); |
- } |
- |
- Node* Phi(Node* a, Node* b, Node* c, Node* d) { |
- return SetSelfReferences(graph.NewNode(op(4, false), a, b, c, d, start)); |
- } |
- |
- Node* EffectPhi(Node* a) { |
- return SetSelfReferences(graph.NewNode(op(1, true), a, start)); |
- } |
- |
- Node* EffectPhi(Node* a, Node* b) { |
- return SetSelfReferences(graph.NewNode(op(2, true), a, b, start)); |
- } |
- |
- Node* EffectPhi(Node* a, Node* b, Node* c) { |
- return SetSelfReferences(graph.NewNode(op(3, true), a, b, c, start)); |
- } |
- |
- Node* EffectPhi(Node* a, Node* b, Node* c, Node* d) { |
- return SetSelfReferences(graph.NewNode(op(4, true), a, b, c, d, start)); |
- } |
- |
- Node* SetSelfReferences(Node* node) { |
- for (Edge edge : node->input_edges()) { |
- if (edge.to() == self) node->ReplaceInput(edge.index(), node); |
- } |
- return node; |
- } |
- |
- const Operator* op(int count, bool effect) { |
- return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); |
- } |
- |
- void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } |
- |
- void ReduceMerge(Node* expect, Node* merge) { |
- Node* result = ControlReducer::ReduceMerge(&jsgraph, merge); |
- CHECK_EQ(expect, result); |
- } |
- |
- void ReduceMergeIterative(Node* expect, Node* merge) { |
- p0->ReplaceInput(0, start); // hack: parameters may be trimmed. |
- Node* end = graph.NewNode(common.End(1), merge); |
- graph.SetEnd(end); |
- ReduceGraph(); |
- CheckInputs(end, expect); |
- } |
- |
- void ReduceBranch(Decision expected, Node* branch) { |
- Node* control = branch->InputAt(1); |
- for (Node* use : branch->uses()) { |
- if (use->opcode() == IrOpcode::kIfTrue) { |
- Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); |
- if (expected == kTrue) CHECK_EQ(control, result); |
- if (expected == kFalse) { |
- CHECK_EQ(IrOpcode::kDeadControl, result->opcode()); |
- } |
- if (expected == kUnknown) CHECK_EQ(use, result); |
- } else if (use->opcode() == IrOpcode::kIfFalse) { |
- Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); |
- if (expected == kFalse) CHECK_EQ(control, result); |
- if (expected == kTrue) { |
- CHECK_EQ(IrOpcode::kDeadControl, result->opcode()); |
- } |
- if (expected == kUnknown) CHECK_EQ(use, result); |
- } else { |
- UNREACHABLE(); |
- } |
- } |
- } |
- |
- Node* Return(Node* val, Node* effect, Node* control) { |
- Node* ret = graph.NewNode(common.Return(), val, effect, control); |
- end->ReplaceInput(0, ret); |
- return ret; |
- } |
-}; |
- |
- |
-struct Branch { |
- Node* branch; |
- Node* if_true; |
- Node* if_false; |
- |
- Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) { |
- if (control == NULL) control = R.start; |
- branch = R.graph.NewNode(R.common.Branch(), cond, control); |
- if_true = R.graph.NewNode(R.common.IfTrue(), branch); |
- if_false = R.graph.NewNode(R.common.IfFalse(), branch); |
- } |
-}; |
- |
- |
-// TODO(titzer): use the diamonds from src/compiler/diamond.h here. |
-struct Diamond { |
- Node* branch; |
- Node* if_true; |
- Node* if_false; |
- Node* merge; |
- Node* phi; |
- |
- Diamond(ControlReducerTester& R, Node* cond) { |
- branch = R.graph.NewNode(R.common.Branch(), cond, R.start); |
- if_true = R.graph.NewNode(R.common.IfTrue(), branch); |
- if_false = R.graph.NewNode(R.common.IfFalse(), branch); |
- merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); |
- phi = NULL; |
- } |
- |
- Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) { |
- branch = R.graph.NewNode(R.common.Branch(), cond, R.start); |
- if_true = R.graph.NewNode(R.common.IfTrue(), branch); |
- if_false = R.graph.NewNode(R.common.IfFalse(), branch); |
- merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); |
- phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge); |
- } |
- |
- void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); } |
- |
- // Nest {this} into either the if_true or if_false branch of {that}. |
- void nest(Diamond& that, bool if_true) { |
- if (if_true) { |
- branch->ReplaceInput(1, that.if_true); |
- that.merge->ReplaceInput(0, merge); |
- } else { |
- branch->ReplaceInput(1, that.if_false); |
- that.merge->ReplaceInput(1, merge); |
- } |
- } |
-}; |
- |
- |
-struct While { |
- Node* branch; |
- Node* if_true; |
- Node* exit; |
- Node* loop; |
- |
- While(ControlReducerTester& R, Node* cond) { |
- loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start); |
- branch = R.graph.NewNode(R.common.Branch(), cond, loop); |
- if_true = R.graph.NewNode(R.common.IfTrue(), branch); |
- exit = R.graph.NewNode(R.common.IfFalse(), branch); |
- loop->ReplaceInput(1, if_true); |
- } |
- |
- void chain(Node* control) { loop->ReplaceInput(0, control); } |
-}; |
- |
- |
-// Helper for checking that nodes are *not* reachable from end. |
-struct DeadChecker { |
- Zone zone; |
- AllNodes nodes; |
- explicit DeadChecker(Graph* graph) : zone(), nodes(&zone, graph) {} |
- |
- void Check(Node* node) { CHECK(!nodes.IsLive(node)); } |
- |
- void Check(Diamond& d) { |
- Check(d.branch); |
- Check(d.if_true); |
- Check(d.if_false); |
- Check(d.merge); |
- if (d.phi != NULL) Check(d.phi); |
- } |
- |
- void CheckLive(Diamond& d, bool live_phi = true) { |
- CheckInputs(d.merge, d.if_true, d.if_false); |
- CheckInputs(d.if_true, d.branch); |
- CheckInputs(d.if_false, d.branch); |
- if (d.phi != NULL) { |
- if (live_phi) { |
- CHECK_EQ(3, d.phi->InputCount()); |
- CHECK_EQ(d.merge, d.phi->InputAt(2)); |
- } else { |
- Check(d.phi); |
- } |
- } |
- } |
-}; |
- |
- |
-TEST(CMergeReduce_simple1) { |
- ControlReducerTester R; |
- |
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); |
- R.ReduceMerge(R.start, merge); |
-} |
- |
- |
-TEST(CMergeReduce_simple2) { |
- ControlReducerTester R; |
- |
- Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start); |
- Node* merge2 = R.graph.NewNode(R.common.Merge(1), merge1); |
- R.ReduceMerge(merge1, merge2); |
- R.ReduceMergeIterative(R.start, merge2); |
-} |
- |
- |
-TEST(CMergeReduce_none1) { |
- ControlReducerTester R; |
- |
- Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.start); |
- R.ReduceMerge(merge, merge); |
-} |
- |
- |
-TEST(CMergeReduce_none2) { |
- ControlReducerTester R; |
- |
- Node* t1 = R.graph.NewNode(R.common.IfTrue(), R.start); |
- Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start); |
- Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2); |
- R.ReduceMerge(merge, merge); |
-} |
- |
- |
-TEST(CMergeReduce_self3) { |
- ControlReducerTester R; |
- |
- Node* merge = |
- R.SetSelfReferences(R.graph.NewNode(R.common.Merge(2), R.start, R.self)); |
- R.ReduceMerge(merge, merge); |
-} |
- |
- |
-TEST(CMergeReduce_dead1) { |
- ControlReducerTester R; |
- |
- Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.dead); |
- R.ReduceMerge(R.start, merge); |
-} |
- |
- |
-TEST(CMergeReduce_dead2) { |
- ControlReducerTester R; |
- |
- Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start); |
- Node* merge2 = R.graph.NewNode(R.common.Merge(2), merge1, R.dead); |
- R.ReduceMerge(merge1, merge2); |
- R.ReduceMergeIterative(R.start, merge2); |
-} |
- |
- |
-TEST(CMergeReduce_dead_rm1a) { |
- ControlReducerTester R; |
- |
- for (int i = 0; i < 3; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |
- merge->ReplaceInput(i, R.dead); |
- R.ReduceMerge(merge, merge); |
- CheckMerge(merge, R.start, R.start); |
- } |
-} |
- |
- |
-TEST(CMergeReduce_dead_rm1b) { |
- ControlReducerTester R; |
- |
- Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); |
- Node* f = R.graph.NewNode(R.common.IfTrue(), R.start); |
- for (int i = 0; i < 2; i++) { |
- for (int j = i + 1; j < 3; j++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); |
- merge->ReplaceInput(i, t); |
- merge->ReplaceInput(j, f); |
- R.ReduceMerge(merge, merge); |
- CheckMerge(merge, t, f); |
- } |
- } |
-} |
- |
- |
-TEST(CMergeReduce_dead_rm2) { |
- ControlReducerTester R; |
- |
- for (int i = 0; i < 3; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); |
- merge->ReplaceInput(i, R.start); |
- R.ReduceMerge(R.start, merge); |
- } |
-} |
- |
- |
-TEST(CLoopReduce_dead_rm1) { |
- ControlReducerTester R; |
- |
- for (int i = 0; i < 3; i++) { |
- Node* loop = R.graph.NewNode(R.common.Loop(3), R.dead, R.start, R.start); |
- R.ReduceMerge(loop, loop); |
- CheckLoop(loop, R.start, R.start); |
- } |
-} |
- |
- |
-TEST(CMergeReduce_edit_phi1) { |
- ControlReducerTester R; |
- |
- for (int i = 0; i < 3; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |
- merge->ReplaceInput(i, R.dead); |
- Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0], |
- R.leaf[1], R.leaf[2], merge); |
- R.ReduceMerge(merge, merge); |
- CHECK_EQ(IrOpcode::kPhi, phi->opcode()); |
- CHECK_EQ(2, phi->op()->ValueInputCount()); |
- CHECK_EQ(3, phi->InputCount()); |
- CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); |
- CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); |
- CHECK_EQ(merge, phi->InputAt(2)); |
- } |
-} |
- |
- |
-TEST(CMergeReduce_edit_effect_phi1) { |
- ControlReducerTester R; |
- |
- for (int i = 0; i < 3; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |
- merge->ReplaceInput(i, R.dead); |
- Node* phi = R.graph.NewNode(R.common.EffectPhi(3), R.leaf[0], R.leaf[1], |
- R.leaf[2], merge); |
- R.ReduceMerge(merge, merge); |
- CHECK_EQ(IrOpcode::kEffectPhi, phi->opcode()); |
- CHECK_EQ(0, phi->op()->ValueInputCount()); |
- CHECK_EQ(2, phi->op()->EffectInputCount()); |
- CHECK_EQ(3, phi->InputCount()); |
- CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); |
- CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); |
- CHECK_EQ(merge, phi->InputAt(2)); |
- } |
-} |
- |
- |
-static const int kSelectorSize = 4; |
- |
-// Helper to select K of N nodes according to a mask, useful for the test below. |
-struct Selector { |
- int mask; |
- int count; |
- explicit Selector(int m) { |
- mask = m; |
- count = v8::base::bits::CountPopulation32(m); |
- } |
- bool is_selected(int i) { return (mask & (1 << i)) != 0; } |
- void CheckNode(Node* node, IrOpcode::Value opcode, Node** inputs, |
- Node* control) { |
- CHECK_EQ(opcode, node->opcode()); |
- CHECK_EQ(count + (control != NULL ? 1 : 0), node->InputCount()); |
- int index = 0; |
- for (int i = 0; i < kSelectorSize; i++) { |
- if (mask & (1 << i)) { |
- CHECK_EQ(inputs[i], node->InputAt(index++)); |
- } |
- } |
- CHECK_EQ(count, index); |
- if (control != NULL) CHECK_EQ(control, node->InputAt(index++)); |
- } |
- int single_index() { |
- CHECK_EQ(1, count); |
- return WhichPowerOf2(mask); |
- } |
-}; |
- |
- |
-TEST(CMergeReduce_exhaustive_4) { |
- ControlReducerTester R; |
- Node* controls[] = { |
- R.graph.NewNode(R.common.Start(1)), R.graph.NewNode(R.common.Start(2)), |
- R.graph.NewNode(R.common.Start(3)), R.graph.NewNode(R.common.Start(4))}; |
- Node* values[] = {R.jsgraph.Int32Constant(11), R.jsgraph.Int32Constant(22), |
- R.jsgraph.Int32Constant(33), R.jsgraph.Int32Constant(44)}; |
- Node* effects[] = { |
- R.jsgraph.Float64Constant(123.4), R.jsgraph.Float64Constant(223.4), |
- R.jsgraph.Float64Constant(323.4), R.jsgraph.Float64Constant(423.4)}; |
- |
- for (int mask = 0; mask < (1 << (kSelectorSize - 1)); mask++) { |
- // Reduce a single merge with a given mask. |
- Node* merge = R.graph.NewNode(R.common.Merge(4), controls[0], controls[1], |
- controls[2], controls[3]); |
- Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 4), values[0], |
- values[1], values[2], values[3], merge); |
- Node* ephi = R.graph.NewNode(R.common.EffectPhi(4), effects[0], effects[1], |
- effects[2], effects[3], merge); |
- |
- Node* phi_use = |
- R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start); |
- Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start); |
- |
- Selector selector(mask); |
- |
- for (int i = 0; i < kSelectorSize; i++) { // set up dead merge inputs. |
- if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead); |
- } |
- |
- Node* result = ControlReducer::ReduceMerge(&R.jsgraph, merge); |
- |
- int count = selector.count; |
- if (count == 0) { |
- // result should be dead. |
- CHECK_EQ(IrOpcode::kDeadControl, result->opcode()); |
- } else if (count == 1) { |
- // merge should be replaced with one of the controls. |
- CHECK_EQ(controls[selector.single_index()], result); |
- // Phis should have been directly replaced. |
- CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0)); |
- CHECK_EQ(effects[selector.single_index()], ephi_use->InputAt(0)); |
- } else { |
- // Otherwise, nodes should be edited in place. |
- CHECK_EQ(merge, result); |
- selector.CheckNode(merge, IrOpcode::kMerge, controls, NULL); |
- selector.CheckNode(phi, IrOpcode::kPhi, values, merge); |
- selector.CheckNode(ephi, IrOpcode::kEffectPhi, effects, merge); |
- CHECK_EQ(phi, phi_use->InputAt(0)); |
- CHECK_EQ(ephi, ephi_use->InputAt(0)); |
- CHECK_EQ(count, phi->op()->ValueInputCount()); |
- CHECK_EQ(count + 1, phi->InputCount()); |
- CHECK_EQ(count, ephi->op()->EffectInputCount()); |
- CHECK_EQ(count + 1, ephi->InputCount()); |
- } |
- } |
-} |
- |
- |
-TEST(CMergeReduce_edit_many_phis1) { |
- ControlReducerTester R; |
- |
- const int kPhiCount = 10; |
- Node* phis[kPhiCount]; |
- |
- for (int i = 0; i < 3; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |
- merge->ReplaceInput(i, R.dead); |
- for (int j = 0; j < kPhiCount; j++) { |
- phis[j] = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0], |
- R.leaf[1], R.leaf[2], merge); |
- } |
- R.ReduceMerge(merge, merge); |
- for (int j = 0; j < kPhiCount; j++) { |
- Node* phi = phis[j]; |
- CHECK_EQ(IrOpcode::kPhi, phi->opcode()); |
- CHECK_EQ(2, phi->op()->ValueInputCount()); |
- CHECK_EQ(3, phi->InputCount()); |
- CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); |
- CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); |
- CHECK_EQ(merge, phi->InputAt(2)); |
- } |
- } |
-} |
- |
- |
-TEST(CMergeReduce_simple_chain1) { |
- ControlReducerTester R; |
- for (int i = 0; i < 5; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); |
- for (int j = 0; j < i; j++) { |
- merge = R.graph.NewNode(R.common.Merge(1), merge); |
- } |
- R.ReduceMergeIterative(R.start, merge); |
- } |
-} |
- |
- |
-TEST(CMergeReduce_dead_chain1) { |
- ControlReducerTester R; |
- for (int i = 0; i < 5; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.dead); |
- for (int j = 0; j < i; j++) { |
- merge = R.graph.NewNode(R.common.Merge(1), merge); |
- } |
- Node* end = R.graph.NewNode(R.common.End(1), merge); |
- R.graph.SetEnd(end); |
- R.ReduceGraph(); |
- CHECK(merge->IsDead()); |
- CHECK(!end->InputAt(0)); // end dies. |
- } |
-} |
- |
- |
-TEST(CMergeReduce_dead_chain2) { |
- ControlReducerTester R; |
- for (int i = 0; i < 5; i++) { |
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); |
- for (int j = 0; j < i; j++) { |
- merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead); |
- } |
- R.ReduceMergeIterative(R.start, merge); |
- } |
-} |
- |
- |
-TEST(CBranchReduce_none1) { |
- ControlReducerTester R; |
- Diamond d(R, R.p0); |
- R.ReduceBranch(kUnknown, d.branch); |
-} |
- |
- |
-TEST(CBranchReduce_none2) { |
- ControlReducerTester R; |
- Diamond d1(R, R.p0); |
- Diamond d2(R, R.p0); |
- d2.chain(d1); |
- R.ReduceBranch(kUnknown, d2.branch); |
-} |
- |
- |
-TEST(CBranchReduce_true) { |
- ControlReducerTester R; |
- Node* true_values[] = {R.jsgraph.Int32Constant(2), |
- R.jsgraph.Int64Constant(0x7fffffff), |
- R.jsgraph.TrueConstant()}; |
- for (size_t i = 0; i < arraysize(true_values); i++) { |
- Diamond d(R, true_values[i]); |
- R.ReduceBranch(kTrue, d.branch); |
- } |
-} |
- |
- |
-TEST(CBranchReduce_false) { |
- ControlReducerTester R; |
- Node* false_values[] = {R.jsgraph.Int32Constant(0), |
- R.jsgraph.Int64Constant(0), |
- R.jsgraph.FalseConstant()}; |
- for (size_t i = 0; i < arraysize(false_values); i++) { |
- Diamond d(R, false_values[i]); |
- R.ReduceBranch(kFalse, d.branch); |
- } |
-} |
- |
- |
-TEST(CDiamondReduce_true) { |
- ControlReducerTester R; |
- Diamond d1(R, R.jsgraph.TrueConstant()); |
- R.ReduceMergeIterative(R.start, d1.merge); |
-} |
- |
- |
-TEST(CDiamondReduce_false) { |
- ControlReducerTester R; |
- Diamond d2(R, R.jsgraph.FalseConstant()); |
- R.ReduceMergeIterative(R.start, d2.merge); |
-} |
- |
- |
-TEST(CChainedDiamondsReduce_true_false) { |
- ControlReducerTester R; |
- Diamond d1(R, R.jsgraph.TrueConstant()); |
- Diamond d2(R, R.jsgraph.FalseConstant()); |
- d2.chain(d1); |
- |
- R.ReduceMergeIterative(R.start, d2.merge); |
-} |
- |
- |
-TEST(CChainedDiamondsReduce_x_false) { |
- ControlReducerTester R; |
- Diamond d1(R, R.p0); |
- Diamond d2(R, R.jsgraph.FalseConstant()); |
- d2.chain(d1); |
- |
- R.ReduceMergeIterative(R.start, d2.merge); |
-} |
- |
- |
-TEST(CChainedDiamondsReduce_false_x) { |
- ControlReducerTester R; |
- Diamond d1(R, R.zero); |
- Diamond d2(R, R.p0); |
- d2.chain(d1); |
- |
- R.ReduceMergeIterative(R.start, d2.merge); |
-} |
- |
- |
-TEST(CChainedDiamondsReduce_phi1) { |
- ControlReducerTester R; |
- Diamond d1(R, R.zero, R.one, R.zero); // foldable branch, phi. |
- Diamond d2(R, d1.phi); |
- d2.chain(d1); |
- |
- R.ReduceMergeIterative(R.start, d2.merge); |
-} |
- |
- |
-TEST(CNestedDiamondsReduce_true_true_false) { |
- ControlReducerTester R; |
- Diamond d1(R, R.jsgraph.TrueConstant()); |
- Diamond d2(R, R.jsgraph.FalseConstant()); |
- d2.nest(d1, true); |
- |
- R.ReduceMergeIterative(R.start, d1.merge); |
-} |
- |
- |
-TEST(CNestedDiamondsReduce_false_true_false) { |
- ControlReducerTester R; |
- Diamond d1(R, R.jsgraph.TrueConstant()); |
- Diamond d2(R, R.jsgraph.FalseConstant()); |
- d2.nest(d1, false); |
- |
- R.ReduceMergeIterative(R.start, d1.merge); |
-} |
- |
- |
-TEST(CNestedDiamonds_xyz) { |
- ControlReducerTester R; |
- |
- for (int a = 0; a < 2; a++) { |
- for (int b = 0; b < 2; b++) { |
- for (int c = 0; c < 2; c++) { |
- Diamond d1(R, R.jsgraph.Int32Constant(a)); |
- Diamond d2(R, R.jsgraph.Int32Constant(b)); |
- d2.nest(d1, c); |
- |
- R.ReduceMergeIterative(R.start, d1.merge); |
- } |
- } |
- } |
-} |
- |
- |
-TEST(CUnusedDiamond1) { |
- ControlReducerTester R; |
- // if (p0) { } else { } |
- Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); |
- Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); |
- Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); |
- Node* merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); |
- R.ReduceMergeIterative(R.start, merge); |
-} |
- |
- |
-TEST(CUnusedDiamond2) { |
- ControlReducerTester R; |
- // if (p0) { } else { } |
- Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); |
- Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); |
- Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); |
- Node* merge = R.graph.NewNode(R.common.Merge(2), if_false, if_true); |
- R.ReduceMergeIterative(R.start, merge); |
-} |
- |
- |
-TEST(CDeadLoop1) { |
- ControlReducerTester R; |
- |
- While w(R, R.p0); |
- Diamond d(R, R.zero); |
- // if (0) { while (p0) ; } else { } |
- w.branch->ReplaceInput(1, d.if_true); |
- d.merge->ReplaceInput(0, w.exit); |
- |
- R.ReduceMergeIterative(R.start, d.merge); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d); |
- dead.Check(w.loop); |
-} |
- |
- |
-TEST(Return1) { |
- ControlReducerTester R; |
- Node* ret = R.Return(R.one, R.start, R.start); |
- R.ReduceGraph(); |
- CheckInputs(R.graph.end(), ret); |
- CheckInputs(ret, R.one, R.start, R.start); |
-} |
- |
- |
-TEST(Return2) { |
- ControlReducerTester R; |
- Diamond d(R, R.jsgraph.TrueConstant()); |
- Node* ret = R.Return(R.half, R.start, d.merge); |
- R.ReduceGraph(); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d.branch); |
- dead.Check(d.if_true); |
- dead.Check(d.if_false); |
- dead.Check(d.merge); |
- |
- CheckInputs(R.graph.end(), ret); |
- CheckInputs(ret, R.half, R.start, R.start); |
-} |
- |
- |
-TEST(Return_true1) { |
- ControlReducerTester R; |
- Diamond d(R, R.jsgraph.TrueConstant(), R.half, R.zero); |
- Node* ret = R.Return(d.phi, R.start, d.merge); |
- R.ReduceGraph(); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d.branch); |
- dead.Check(d.if_true); |
- dead.Check(d.if_false); |
- dead.Check(d.merge); |
- dead.Check(d.phi); |
- |
- CheckInputs(R.graph.end(), ret); |
- CheckInputs(ret, R.half, R.start, R.start); |
-} |
- |
- |
-TEST(Return_false1) { |
- ControlReducerTester R; |
- Diamond d(R, R.jsgraph.FalseConstant(), R.one, R.half); |
- Node* ret = R.Return(d.phi, R.start, d.merge); |
- R.ReduceGraph(); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d.branch); |
- dead.Check(d.if_true); |
- dead.Check(d.if_false); |
- dead.Check(d.merge); |
- dead.Check(d.phi); |
- |
- CheckInputs(R.graph.end(), ret); |
- CheckInputs(ret, R.half, R.start, R.start); |
-} |
- |
- |
-TEST(Return_effect1) { |
- ControlReducerTester R; |
- Diamond d(R, R.jsgraph.TrueConstant()); |
- Node* e1 = R.jsgraph.Float64Constant(-100.1); |
- Node* e2 = R.jsgraph.Float64Constant(+100.1); |
- Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge); |
- Node* ret = R.Return(R.p0, effect, d.merge); |
- R.ReduceGraph(); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d); |
- dead.Check(effect); |
- |
- CheckInputs(R.graph.end(), ret); |
- CheckInputs(ret, R.p0, e1, R.start); |
-} |
- |
- |
-TEST(Return_nested_diamonds1) { |
- ControlReducerTester R; |
- Diamond d2(R, R.p0, R.one, R.zero); |
- Diamond d3(R, R.p0, R.one, R.zero); |
- Diamond d1(R, R.p0, d2.phi, d3.phi); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // nothing should happen. |
- |
- CheckInputs(ret, d1.phi, R.start, d1.merge); |
- CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); |
- CheckInputs(d1.merge, d2.merge, d3.merge); |
- |
- DeadChecker dead(&R.graph); |
- dead.CheckLive(d2); |
- dead.CheckLive(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds1_dead1) { |
- ControlReducerTester R; |
- Diamond d2(R, R.p0); // dead diamond |
- Diamond d3(R, R.p0, R.one, R.zero); |
- Diamond d1(R, R.p0, R.one, d3.phi); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); |
- |
- CheckInputs(ret, d1.phi, R.start, d1.merge); |
- CheckInputs(d1.phi, R.one, d3.phi, d1.merge); |
- CheckInputs(d1.merge, d1.if_true, d3.merge); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d2); // d2 was a dead diamond. |
- dead.CheckLive(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds1_dead2) { |
- ControlReducerTester R; |
- Diamond d2(R, R.p0); // dead diamond |
- Diamond d3(R, R.p0); // dead diamond |
- Diamond d1(R, R.p0, R.one, R.zero); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); |
- |
- CheckInputs(ret, d1.phi, R.start, d1.merge); |
- CheckInputs(d1.phi, R.one, R.zero, d1.merge); |
- CheckInputs(d1.merge, d1.if_true, d1.if_false); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d2); |
- dead.Check(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_true1) { |
- ControlReducerTester R; |
- Diamond d2(R, R.p0, R.one, R.zero); |
- Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, R.zero); |
- Diamond d3(R, R.p0); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 gets folded true. |
- |
- CheckInputs(ret, d2.phi, R.start, d2.merge); |
- CheckInputs(d2.branch, R.p0, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.CheckLive(d2); |
- dead.Check(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_false1) { |
- ControlReducerTester R; |
- Diamond d3(R, R.p0, R.one, R.zero); |
- Diamond d1(R, R.zero, R.one, d3.phi); |
- Diamond d2(R, R.p0); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 gets folded false. |
- |
- CheckInputs(ret, d3.phi, R.start, d3.merge); |
- CheckInputs(d3.branch, R.p0, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.Check(d2); |
- dead.CheckLive(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_true_true1) { |
- ControlReducerTester R; |
- Diamond d1(R, R.jsgraph.TrueConstant(), R.one, R.zero); |
- Diamond d2(R, R.jsgraph.TrueConstant()); |
- Diamond d3(R, R.p0); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 and d2 both get folded true. |
- |
- CheckInputs(ret, R.one, R.start, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.Check(d2); |
- dead.Check(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_true_false1) { |
- ControlReducerTester R; |
- Diamond d1(R, R.jsgraph.TrueConstant(), R.one, R.zero); |
- Diamond d2(R, R.jsgraph.FalseConstant()); |
- Diamond d3(R, R.p0); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 gets folded true and d2 gets folded false. |
- |
- CheckInputs(ret, R.one, R.start, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.Check(d2); |
- dead.Check(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds2) { |
- ControlReducerTester R; |
- Node* x2 = R.jsgraph.Float64Constant(11.1); |
- Node* y2 = R.jsgraph.Float64Constant(22.2); |
- Node* x3 = R.jsgraph.Float64Constant(33.3); |
- Node* y3 = R.jsgraph.Float64Constant(44.4); |
- |
- Diamond d2(R, R.p0, x2, y2); |
- Diamond d3(R, R.p0, x3, y3); |
- Diamond d1(R, R.p0, d2.phi, d3.phi); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // nothing should happen. |
- |
- CheckInputs(ret, d1.phi, R.start, d1.merge); |
- CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); |
- CheckInputs(d1.merge, d2.merge, d3.merge); |
- |
- DeadChecker dead(&R.graph); |
- dead.CheckLive(d2); |
- dead.CheckLive(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_true2) { |
- ControlReducerTester R; |
- Node* x2 = R.jsgraph.Float64Constant(11.1); |
- Node* y2 = R.jsgraph.Float64Constant(22.2); |
- Node* x3 = R.jsgraph.Float64Constant(33.3); |
- Node* y3 = R.jsgraph.Float64Constant(44.4); |
- |
- Diamond d2(R, R.p0, x2, y2); |
- Diamond d3(R, R.p0, x3, y3); |
- Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, d3.phi); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 gets folded true. |
- |
- CheckInputs(ret, d2.phi, R.start, d2.merge); |
- CheckInputs(d2.branch, R.p0, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.CheckLive(d2); |
- dead.Check(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_true_true2) { |
- ControlReducerTester R; |
- Node* x2 = R.jsgraph.Float64Constant(11.1); |
- Node* y2 = R.jsgraph.Float64Constant(22.2); |
- Node* x3 = R.jsgraph.Float64Constant(33.3); |
- Node* y3 = R.jsgraph.Float64Constant(44.4); |
- |
- Diamond d2(R, R.jsgraph.TrueConstant(), x2, y2); |
- Diamond d3(R, R.p0, x3, y3); |
- Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, d3.phi); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 gets folded true. |
- |
- CheckInputs(ret, x2, R.start, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.Check(d2); |
- dead.Check(d3); |
-} |
- |
- |
-TEST(Return_nested_diamonds_true_false2) { |
- ControlReducerTester R; |
- Node* x2 = R.jsgraph.Float64Constant(11.1); |
- Node* y2 = R.jsgraph.Float64Constant(22.2); |
- Node* x3 = R.jsgraph.Float64Constant(33.3); |
- Node* y3 = R.jsgraph.Float64Constant(44.4); |
- |
- Diamond d2(R, R.jsgraph.FalseConstant(), x2, y2); |
- Diamond d3(R, R.p0, x3, y3); |
- Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, d3.phi); |
- |
- d2.nest(d1, true); |
- d3.nest(d1, false); |
- |
- Node* ret = R.Return(d1.phi, R.start, d1.merge); |
- |
- R.ReduceGraph(); // d1 gets folded true. |
- |
- CheckInputs(ret, y2, R.start, R.start); |
- |
- DeadChecker dead(&R.graph); |
- dead.Check(d1); |
- dead.Check(d2); |
- dead.Check(d3); |
-} |