Index: test/unittests/compiler/effect-control-linearizer-unittest.cc |
diff --git a/test/unittests/compiler/effect-control-linearizer-unittest.cc b/test/unittests/compiler/effect-control-linearizer-unittest.cc |
index 95927df61dc2e7b0b0b8df0bacdf10f2c2d4f6ac..417444ed27d5268000f5843feafdc3542ec9b889 100644 |
--- a/test/unittests/compiler/effect-control-linearizer-unittest.cc |
+++ b/test/unittests/compiler/effect-control-linearizer-unittest.cc |
@@ -5,6 +5,7 @@ |
#include "src/compiler/effect-control-linearizer.h" |
#include "src/compiler/access-builder.h" |
#include "src/compiler/js-graph.h" |
+#include "src/compiler/linkage.h" |
#include "src/compiler/node-properties.h" |
#include "src/compiler/schedule.h" |
#include "src/compiler/simplified-operator.h" |
@@ -140,6 +141,127 @@ TEST_F(EffectControlLinearizerTest, DiamondLoad) { |
ret, IsReturn(phi, IsEffectPhi(vtrue, graph()->start(), merge), merge)); |
} |
+TEST_F(EffectControlLinearizerTest, FloatingDiamondsControlWiring) { |
+ Schedule schedule(zone()); |
+ |
+ // Create the graph and schedule. Roughly (omitting effects and unimportant |
+ // nodes): |
+ // |
+ // BLOCK 0: |
+ // r1: Start |
+ // c1: Call |
+ // b1: Branch(const0, s1) |
+ // | |
+ // +-------+------+ |
+ // | | |
+ // BLOCK 1: BLOCK 2: |
+ // t1: IfTrue(b1) f1: IfFalse(b1) |
+ // | | |
+ // +-------+------+ |
+ // | |
+ // BLOCK 3: |
+ // m1: Merge(t1, f1) |
+ // c2: IfSuccess(c1) |
+ // b2: Branch(const0 , s1) |
+ // | |
+ // +-------+------+ |
+ // | | |
+ // BLOCK 4: BLOCK 5: |
+ // t2: IfTrue(b2) f2:IfFalse(b2) |
+ // | | |
+ // +-------+------+ |
+ // | |
+ // BLOCK 6: |
+ // m2: Merge(t2, f2) |
+ // r1: Return(c1, c2) |
+ MachineType kMachineSignature[] = {MachineType::AnyTagged(), |
+ MachineType::AnyTagged()}; |
+ LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0), |
+ LinkageLocation::ForRegister(1)}; |
+ const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor( |
+ CallDescriptor::kCallCodeObject, MachineType::AnyTagged(), |
+ LinkageLocation::ForRegister(0), |
+ new (zone()) MachineSignature(1, 1, kMachineSignature), |
+ new (zone()) LocationSignature(1, 1, kLocationSignature), 0, |
+ Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); |
+ Node* p0 = Parameter(0); |
+ Node* p1 = Parameter(1); |
+ Node* const0 = Int32Constant(0); |
+ Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, |
+ graph()->start(), graph()->start()); |
+ Node* if_success = graph()->NewNode(common()->IfSuccess(), call); |
+ |
+ // First Floating diamond. |
+ Node* branch1 = |
+ graph()->NewNode(common()->Branch(), const0, 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); |
+ |
+ // Second floating diamond. |
+ Node* branch2 = |
+ graph()->NewNode(common()->Branch(), const0, graph()->start()); |
+ 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* ret = |
+ graph()->NewNode(common()->Return(), call, graph()->start(), if_success); |
+ |
+ // Build the basic block structure. |
+ BasicBlock* start = schedule.start(); |
+ schedule.rpo_order()->push_back(start); |
+ start->set_rpo_number(0); |
+ |
+ BasicBlock* t1block = AddBlockToSchedule(&schedule); |
+ BasicBlock* f1block = AddBlockToSchedule(&schedule); |
+ BasicBlock* m1block = AddBlockToSchedule(&schedule); |
+ |
+ BasicBlock* t2block = AddBlockToSchedule(&schedule); |
+ BasicBlock* f2block = AddBlockToSchedule(&schedule); |
+ BasicBlock* m2block = AddBlockToSchedule(&schedule); |
+ |
+ // Populate the basic blocks with nodes. |
+ schedule.AddNode(start, graph()->start()); |
+ schedule.AddNode(start, p0); |
+ schedule.AddNode(start, p1); |
+ schedule.AddNode(start, const0); |
+ schedule.AddNode(start, call); |
+ schedule.AddBranch(start, branch1, t1block, f1block); |
+ |
+ schedule.AddNode(t1block, if_true1); |
+ schedule.AddGoto(t1block, m1block); |
+ |
+ schedule.AddNode(f1block, if_false1); |
+ schedule.AddGoto(f1block, m1block); |
+ |
+ schedule.AddNode(m1block, merge1); |
+ // The scheduler does not always put the IfSuccess node to the corresponding |
+ // call's block, simulate that here. |
+ schedule.AddNode(m1block, if_success); |
+ schedule.AddBranch(m1block, branch2, t2block, f2block); |
+ |
+ schedule.AddNode(t2block, if_true2); |
+ schedule.AddGoto(t2block, m2block); |
+ |
+ schedule.AddNode(f2block, if_false2); |
+ schedule.AddGoto(f2block, m2block); |
+ |
+ schedule.AddNode(m2block, merge2); |
+ schedule.AddReturn(m2block, ret); |
+ |
+ // Run the state effect introducer. |
+ EffectControlLinearizer introducer(jsgraph(), &schedule, zone()); |
+ introducer.Run(); |
+ |
+ // The effect input to the return should be an effect phi with the |
+ // newly introduced effectful change operators. |
+ ASSERT_THAT(ret, IsReturn(call, call, merge2)); |
+ ASSERT_THAT(branch2, IsBranch(const0, merge1)); |
+ ASSERT_THAT(branch1, IsBranch(const0, if_success)); |
+ ASSERT_THAT(if_success, IsIfSuccess(call)); |
+} |
+ |
TEST_F(EffectControlLinearizerTest, LoopLoad) { |
Schedule schedule(zone()); |