return false;
}
// Grab the IfTrue/IfFalse projections of the Branch.
- Node* control_projections[2];
- NodeProperties::CollectControlProjections(branch, control_projections,
- arraysize(control_projections));
- Node* if_true = control_projections[0];
- Node* if_false = control_projections[1];
- DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode());
- DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
+ BranchMatcher matcher(branch);
// Check/collect other Phi/EffectPhi nodes hanging off the Merge.
NodeVector phis(zone());
for (Node* const use : merge->uses()) {
if (NodeProperties::IsPhi(edge.from())) {
control = NodeProperties::GetControlInput(control, edge.index());
}
- if (control != if_true && control != if_false) return false;
+ if (control != matcher.IfTrue() && control != matcher.IfFalse())
+ return false;
}
phis.push_back(use);
}
if (NodeProperties::IsPhi(edge.from())) {
control = NodeProperties::GetControlInput(control, edge.index());
}
- DCHECK(control == if_true || control == if_false);
- edge.UpdateTo((control == if_true) ? phi_true : phi_false);
+ DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
+ edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
}
phi->Kill();
}
// Fix up IfTrue and IfFalse and kill all dead nodes.
- if_false->ReplaceUses(merge_false);
- if_true->ReplaceUses(merge_true);
- if_false->Kill();
- if_true->Kill();
+ matcher.IfFalse()->ReplaceUses(merge_false);
+ matcher.IfTrue()->ReplaceUses(merge_true);
+ matcher.IfFalse()->Kill();
+ matcher.IfTrue()->Kill();
branch->Kill();
cond->Kill();
merge->Kill();
Node* if_false;
Node* if_true;
while (true) {
- Node* control_projections[2];
- NodeProperties::CollectControlProjections(branch, control_projections, 2);
- if_true = control_projections[0];
- if_false = control_projections[1];
- DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode());
- DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
+ BranchMatcher matcher(branch);
+ DCHECK(matcher.Matched());
+
+ if_true = matcher.IfTrue();
+ if_false = matcher.IfFalse();
auto it = if_false->uses().begin();
if (it == if_false->uses().end()) break;
DCHECK_EQ(IrOpcode::kBranch, node->opcode());
DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
- DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode());
- DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
if (branch == node) {
DCHECK_EQ(1u, values.size());
return false;
}
+TEST_F(NodeMatcherTest, BranchMatcher_match) {
+ Node* zero = graph()->NewNode(common()->Int32Constant(0));
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ BranchMatcher matcher(branch);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ BranchMatcher matcher(branch);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* other = graph()->NewNode(common()->IfValue(33), branch);
+ BranchMatcher matcher(branch);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ USE(other);
+ }
+}
+
+
+TEST_F(NodeMatcherTest, BranchMatcher_fail) {
+ Node* zero = graph()->NewNode(common()->Int32Constant(0));
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ BranchMatcher matcher(branch);
+ EXPECT_FALSE(matcher.Matched());
+ USE(if_true);
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ BranchMatcher matcher(branch);
+ EXPECT_FALSE(matcher.Matched());
+ USE(if_false);
+ }
+
+ {
+ BranchMatcher matcher(zero);
+ EXPECT_FALSE(matcher.Matched());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ EXPECT_TRUE(BranchMatcher(branch).Matched());
+ EXPECT_FALSE(BranchMatcher(if_true).Matched());
+ EXPECT_FALSE(BranchMatcher(if_false).Matched());
+ }
+
+ {
+ Node* sw = graph()->NewNode(common()->Switch(5), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), sw);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), sw);
+ EXPECT_FALSE(BranchMatcher(sw).Matched());
+ EXPECT_FALSE(BranchMatcher(if_true).Matched());
+ EXPECT_FALSE(BranchMatcher(if_false).Matched());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_value = graph()->NewNode(common()->IfValue(2), branch);
+ BranchMatcher matcher(branch);
+ EXPECT_FALSE(matcher.Matched());
+ EXPECT_FALSE(BranchMatcher(if_true).Matched());
+ EXPECT_FALSE(BranchMatcher(if_value).Matched());
+ }
+}
+
+
+TEST_F(NodeMatcherTest, DiamondMatcher_match) {
+ Node* zero = graph()->NewNode(common()->Int32Constant(0));
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ 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);
+ DiamondMatcher matcher(merge);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ EXPECT_EQ(merge, matcher.Merge());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ DiamondMatcher matcher(merge);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ EXPECT_EQ(merge, matcher.Merge());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_false, if_true);
+ DiamondMatcher matcher(merge);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ EXPECT_EQ(merge, matcher.Merge());
+ }
+}
+
+
+TEST_F(NodeMatcherTest, DiamondMatcher_fail) {
+ Node* zero = graph()->NewNode(common()->Int32Constant(0));
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_value = graph()->NewNode(common()->IfValue(1), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_value);
+ DiamondMatcher matcher(merge);
+ EXPECT_FALSE(matcher.Matched());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* if_value = graph()->NewNode(common()->IfValue(1), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_false, if_value);
+ DiamondMatcher matcher(merge);
+ EXPECT_FALSE(matcher.Matched());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ 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);
+ DiamondMatcher matcher(merge);
+ EXPECT_TRUE(matcher.Matched());
+ EXPECT_EQ(branch, matcher.Branch());
+ EXPECT_EQ(if_true, matcher.IfTrue());
+ EXPECT_EQ(if_false, matcher.IfFalse());
+ EXPECT_EQ(merge, matcher.Merge());
+
+ EXPECT_FALSE(DiamondMatcher(branch).Matched()); // Must be the merge.
+ EXPECT_FALSE(DiamondMatcher(if_true).Matched());
+ EXPECT_FALSE(DiamondMatcher(if_false).Matched());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(3), if_true, if_false,
+ graph()->start());
+ DiamondMatcher matcher(merge);
+ EXPECT_FALSE(matcher.Matched()); // Too many inputs to merge.
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* if_false = graph()->start();
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ DiamondMatcher matcher(merge);
+ EXPECT_FALSE(matcher.Matched());
+ }
+
+ {
+ Node* branch = graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->start();
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ DiamondMatcher matcher(merge);
+ EXPECT_FALSE(matcher.Matched());
+ }
+
+ {
+ Node* branch1 =
+ graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* branch2 =
+ graph()->NewNode(common()->Branch(), zero, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ DiamondMatcher matcher(merge);
+ EXPECT_FALSE(matcher.Matched());
+ }
+}
+
+
} // namespace compiler
} // namespace internal
} // namespace v8