[turbofan] Fold "boolean not"-like Selects into branches.

Fold a Select that negates a boolean value, i.e. returning true in the
false case and vice versa, into Branch users, similar to what we already
do for Branch nodes with BooleanNot inputs.

BUG=v8:5267

Review-Url: https://codereview.chromium.org/2308303003
Cr-Commit-Position: refs/heads/master@{#39149}
This commit is contained in:
bmeurer 2016-09-05 00:02:00 -07:00 committed by Commit bot
parent cf3a4a7087
commit 99e91aaeac
2 changed files with 26 additions and 2 deletions

View File

@ -77,8 +77,12 @@ Reduction CommonOperatorReducer::ReduceBranch(Node* node) {
// Swap IfTrue/IfFalse on {branch} if {cond} is a BooleanNot and use the input
// to BooleanNot as new condition for {branch}. Note we assume that {cond} was
// already properly optimized before we get here (as guaranteed by the graph
// reduction logic).
if (cond->opcode() == IrOpcode::kBooleanNot) {
// reduction logic). The same applies if {cond} is a Select acting as boolean
// not (i.e. true being returned in the false case and vice versa).
if (cond->opcode() == IrOpcode::kBooleanNot ||
(cond->opcode() == IrOpcode::kSelect &&
DecideCondition(cond->InputAt(1)) == Decision::kFalse &&
DecideCondition(cond->InputAt(2)) == Decision::kTrue)) {
for (Node* const use : node->uses()) {
switch (use->opcode()) {
case IrOpcode::kIfTrue:

View File

@ -158,6 +158,26 @@ TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) {
}
}
TEST_F(CommonOperatorReducerTest, BranchWithSelect) {
Node* const value = Parameter(0);
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
Node* const control = graph()->start();
Node* const branch = graph()->NewNode(
common()->Branch(hint),
graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
value, FalseConstant(), TrueConstant()),
control);
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
Reduction const r = Reduce(branch);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(branch, r.replacement());
EXPECT_THAT(branch, IsBranch(value, control));
EXPECT_THAT(if_false, IsIfTrue(branch));
EXPECT_THAT(if_true, IsIfFalse(branch));
EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op()));
}
}
// -----------------------------------------------------------------------------
// Merge