1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler/common-operator-reducer.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <algorithm>
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler/common-operator.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/graph.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/machine-operator.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-matchers.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-properties.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace compiler {
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace {
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochDecision DecideCondition(Node* const cond) {
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (cond->opcode()) {
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kInt32Constant: {
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Int32Matcher mcond(cond);
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return mcond.Value() ? Decision::kTrue : Decision::kFalse;
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kHeapConstant: {
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      HeapObjectMatcher mcond(cond);
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return mcond.Value()->BooleanValue() ? Decision::kTrue : Decision::kFalse;
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Decision::kUnknown;
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCommonOperatorReducer::CommonOperatorReducer(Editor* editor, Graph* graph,
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             CommonOperatorBuilder* common,
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             MachineOperatorBuilder* machine)
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    : AdvancedReducer(editor),
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      graph_(graph),
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      common_(common),
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      machine_(machine),
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      dead_(graph->NewNode(common->Dead())) {
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  NodeProperties::SetType(dead_, Type::None());
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierReduction CommonOperatorReducer::Reduce(Node* node) {
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  switch (node->opcode()) {
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kBranch:
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceBranch(node);
543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case IrOpcode::kDeoptimizeIf:
553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case IrOpcode::kDeoptimizeUnless:
563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return ReduceDeoptimizeConditional(node);
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kMerge:
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceMerge(node);
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case IrOpcode::kEffectPhi:
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceEffectPhi(node);
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kPhi:
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReducePhi(node);
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kReturn:
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceReturn(node);
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kSelect:
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return ReduceSelect(node);
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::ReduceBranch(Node* node) {
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kBranch, node->opcode());
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* const cond = node->InputAt(0);
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Swap IfTrue/IfFalse on {branch} if {cond} is a BooleanNot and use the input
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to BooleanNot as new condition for {branch}. Note we assume that {cond} was
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // already properly optimized before we get here (as guaranteed by the graph
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // reduction logic). The same applies if {cond} is a Select acting as boolean
81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // not (i.e. true being returned in the false case and vice versa).
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (cond->opcode() == IrOpcode::kBooleanNot ||
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      (cond->opcode() == IrOpcode::kSelect &&
84f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch       DecideCondition(cond->InputAt(1)) == Decision::kFalse &&
85f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch       DecideCondition(cond->InputAt(2)) == Decision::kTrue)) {
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (Node* const use : node->uses()) {
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      switch (use->opcode()) {
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case IrOpcode::kIfTrue:
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          NodeProperties::ChangeOp(use, common()->IfFalse());
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case IrOpcode::kIfFalse:
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          NodeProperties::ChangeOp(use, common()->IfTrue());
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        default:
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          UNREACHABLE();
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Update the condition of {branch}. No need to mark the uses for revisit,
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // since we tell the graph reducer that the {branch} was changed and the
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // graph reduction logic will ensure that the uses are revisited properly.
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(0, cond->InputAt(0));
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Negate the hint for {branch}.
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node, common()->Branch(NegateBranchHint(BranchHintOf(node->op()))));
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Decision const decision = DecideCondition(cond);
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (decision == Decision::kUnknown) return NoChange();
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* const control = node->InputAt(1);
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (Node* const use : node->uses()) {
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (use->opcode()) {
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kIfTrue:
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Replace(use, (decision == Decision::kTrue) ? control : dead());
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kIfFalse:
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Replace(use, (decision == Decision::kFalse) ? control : dead());
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Replace(dead());
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochReduction CommonOperatorReducer::ReduceDeoptimizeConditional(Node* node) {
1263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(node->opcode() == IrOpcode::kDeoptimizeIf ||
1273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         node->opcode() == IrOpcode::kDeoptimizeUnless);
1283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool condition_is_true = node->opcode() == IrOpcode::kDeoptimizeUnless;
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
1303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* condition = NodeProperties::GetValueInput(node, 0);
1313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* frame_state = NodeProperties::GetValueInput(node, 1);
1323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
1333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
1343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Swap DeoptimizeIf/DeoptimizeUnless on {node} if {cond} is a BooleaNot
1353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // and use the input to BooleanNot as new condition for {node}.  Note we
1363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // assume that {cond} was already properly optimized before we get here
1373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // (as guaranteed by the graph reduction logic).
1383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (condition->opcode() == IrOpcode::kBooleanNot) {
1393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    NodeProperties::ReplaceValueInput(node, condition->InputAt(0), 0);
14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    NodeProperties::ChangeOp(
14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node, condition_is_true
14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  ? common()->DeoptimizeIf(p.kind(), p.reason())
14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  : common()->DeoptimizeUnless(p.kind(), p.reason()));
1443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return Changed(node);
1453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Decision const decision = DecideCondition(condition);
1473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (decision == Decision::kUnknown) return NoChange();
1483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (condition_is_true == (decision == Decision::kTrue)) {
14913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ReplaceWithValue(node, dead(), effect, control);
15013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    control = graph()->NewNode(common()->Deoptimize(p.kind(), p.reason()),
15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               frame_state, effect, control);
15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // TODO(bmeurer): This should be on the AdvancedReducer somehow.
15413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    NodeProperties::MergeControlToEnd(graph(), common(), control);
15513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Revisit(graph()->end());
1563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return Replace(dead());
1583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::ReduceMerge(Node* node) {
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kMerge, node->opcode());
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if this is a merge that belongs to an unused diamond, which means
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // that:
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  a) the {Merge} has no {Phi} or {EffectPhi} uses, and
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  b) the {Merge} has two inputs, one {IfTrue} and one {IfFalse}, which are
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //     both owned by the Merge, and
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  c) and the {IfTrue} and {IfFalse} nodes point to the same {Branch}.
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (node->InputCount() == 2) {
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (Node* const use : node->uses()) {
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (IrOpcode::IsPhiOpcode(use->opcode())) return NoChange();
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* if_true = node->InputAt(0);
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* if_false = node->InputAt(1);
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (if_true->opcode() != IrOpcode::kIfTrue) std::swap(if_true, if_false);
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (if_true->opcode() == IrOpcode::kIfTrue &&
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if_false->opcode() == IrOpcode::kIfFalse &&
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if_true->InputAt(0) == if_false->InputAt(0) && if_true->OwnedBy(node) &&
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if_false->OwnedBy(node)) {
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* const branch = if_true->InputAt(0);
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(branch->OwnedBy(if_true, if_false));
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* const control = branch->InputAt(1);
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Mark the {branch} as {Dead}.
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      branch->TrimInputCount(0);
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ChangeOp(branch, common()->Dead());
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Replace(control);
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::ReduceEffectPhi(Node* node) {
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node::Inputs inputs = node->inputs();
19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int const effect_input_count = inputs.count() - 1;
20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_LE(1, effect_input_count);
20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const merge = inputs[effect_input_count];
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(effect_input_count, merge->InputCount());
20462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const effect = inputs[0];
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(node, effect);
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (int i = 1; i < effect_input_count; ++i) {
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* const input = inputs[i];
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (input == node) {
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Ignore redundant inputs.
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(IrOpcode::kLoop, merge->opcode());
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      continue;
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (input != effect) return NoChange();
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We might now be able to further reduce the {merge} node.
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Revisit(merge);
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Replace(effect);
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::ReducePhi(Node* node) {
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kPhi, node->opcode());
22362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node::Inputs inputs = node->inputs();
22462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int const value_input_count = inputs.count() - 1;
22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_LE(1, value_input_count);
22662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const merge = inputs[value_input_count];
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
22862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(value_input_count, merge->InputCount());
22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (value_input_count == 2) {
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* vtrue = inputs[0];
23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* vfalse = inputs[1];
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node::Inputs merge_inputs = merge->inputs();
23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* if_true = merge_inputs[0];
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* if_false = merge_inputs[1];
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (if_true->opcode() != IrOpcode::kIfTrue) {
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      std::swap(if_true, if_false);
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      std::swap(vtrue, vfalse);
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (if_true->opcode() == IrOpcode::kIfTrue &&
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if_false->opcode() == IrOpcode::kIfFalse &&
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if_true->InputAt(0) == if_false->InputAt(0)) {
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* const branch = if_true->InputAt(0);
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Check that the branch is not dead already.
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (branch->opcode() != IrOpcode::kBranch) return NoChange();
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* const cond = branch->InputAt(0);
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (cond->opcode() == IrOpcode::kFloat32LessThan) {
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Float32BinopMatcher mcond(cond);
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) &&
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            vfalse->opcode() == IrOpcode::kFloat32Sub) {
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Float32BinopMatcher mvfalse(vfalse);
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) {
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // We might now be able to further reduce the {merge} node.
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Revisit(merge);
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            return Change(node, machine()->Float32Abs(), vtrue);
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (cond->opcode() == IrOpcode::kFloat64LessThan) {
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Float64BinopMatcher mcond(cond);
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) &&
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            vfalse->opcode() == IrOpcode::kFloat64Sub) {
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Float64BinopMatcher mvfalse(vfalse);
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) {
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // We might now be able to further reduce the {merge} node.
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Revisit(merge);
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            return Change(node, machine()->Float64Abs(), vtrue);
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const value = inputs[0];
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(node, value);
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (int i = 1; i < value_input_count; ++i) {
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* const input = inputs[i];
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (input == node) {
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Ignore redundant inputs.
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(IrOpcode::kLoop, merge->opcode());
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      continue;
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (input != value) return NoChange();
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We might now be able to further reduce the {merge} node.
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Revisit(merge);
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Replace(value);
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::ReduceReturn(Node* node) {
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kReturn, node->opcode());
289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (effect->opcode() == IrOpcode::kCheckpoint) {
291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Any {Return} node can never be used to insert a deoptimization point,
292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // hence checkpoints can be cut out of the effect chain flowing into it.
293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    effect = NodeProperties::GetEffectInput(effect);
294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    NodeProperties::ReplaceEffectInput(node, effect);
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Reduction const reduction = ReduceReturn(node);
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return reduction.Changed() ? reduction : Changed(node);
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(ahaas): Extend the reduction below to multiple return values.
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (ValueInputCountOfReturn(node->op()) != 1) {
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return NoChange();
301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* pop_count = NodeProperties::GetValueInput(node, 0);
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = NodeProperties::GetValueInput(node, 1);
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* control = NodeProperties::GetControlInput(node);
305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (value->opcode() == IrOpcode::kPhi &&
306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::GetControlInput(value) == control &&
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      control->opcode() == IrOpcode::kMerge) {
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // This optimization pushes {Return} nodes through merges. It checks that
30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // the return value is actually a {Phi} and the return control dependency
31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // is the {Merge} to which the {Phi} belongs.
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Value1 ... ValueN Control1 ... ControlN
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //   ^          ^       ^            ^
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //   |          |       |            |
31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //   +----+-----+       +------+-----+
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //        |                    |
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //       Phi --------------> Merge
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //        ^                    ^
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //        |                    |
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //        |  +-----------------+
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //        |  |
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //       Return -----> Effect
32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //         ^
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //         |
32562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //        End
32662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Now the effect input to the {Return} node can be either an {EffectPhi}
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // hanging off the same {Merge}, or the {Merge} node is only connected to
32962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // the {Return} and the {Phi}, in which case we know that the effect input
33062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // must somehow dominate all merged branches.
33162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node::Inputs control_inputs = control->inputs();
33362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node::Inputs value_inputs = value->inputs();
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_NE(0, control_inputs.count());
33562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(control_inputs.count(), value_inputs.count() - 1);
336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(IrOpcode::kEnd, graph()->end()->opcode());
337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NE(0, graph()->end()->InputCount());
33862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (control->OwnedBy(node, value)) {
33962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      for (int i = 0; i < control_inputs.count(); ++i) {
34062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Create a new {Return} and connect it to {end}. We don't need to mark
34162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // {end} as revisit, because we mark {node} as {Dead} below, which was
34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // previously connected to {end}, so we know for sure that at some point
34362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // the reducer logic will visit {end} again.
34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* ret = graph()->NewNode(node->op(), pop_count, value_inputs[i],
34562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                     effect, control_inputs[i]);
34662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        NodeProperties::MergeControlToEnd(graph(), common(), ret);
34762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
34862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Mark the Merge {control} and Return {node} as {dead}.
34962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Replace(control, dead());
35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return Replace(dead());
35162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } else if (effect->opcode() == IrOpcode::kEffectPhi &&
35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               NodeProperties::GetControlInput(effect) == control) {
35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node::Inputs effect_inputs = effect->inputs();
35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_EQ(control_inputs.count(), effect_inputs.count() - 1);
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      for (int i = 0; i < control_inputs.count(); ++i) {
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Create a new {Return} and connect it to {end}. We don't need to mark
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // {end} as revisit, because we mark {node} as {Dead} below, which was
35862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // previously connected to {end}, so we know for sure that at some point
35962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // the reducer logic will visit {end} again.
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* ret = graph()->NewNode(node->op(), pop_count, value_inputs[i],
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                     effect_inputs[i], control_inputs[i]);
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        NodeProperties::MergeControlToEnd(graph(), common(), ret);
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Mark the Merge {control} and Return {node} as {dead}.
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Replace(control, dead());
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return Replace(dead());
367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return NoChange();
370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::ReduceSelect(Node* node) {
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(IrOpcode::kSelect, node->opcode());
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* const cond = node->InputAt(0);
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* const vtrue = node->InputAt(1);
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* const vfalse = node->InputAt(2);
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (vtrue == vfalse) return Replace(vtrue);
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (DecideCondition(cond)) {
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Decision::kTrue:
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Replace(vtrue);
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Decision::kFalse:
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Replace(vfalse);
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Decision::kUnknown:
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (cond->opcode()) {
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kFloat32LessThan: {
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Float32BinopMatcher mcond(cond);
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) &&
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          vfalse->opcode() == IrOpcode::kFloat32Sub) {
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Float32BinopMatcher mvfalse(vfalse);
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) {
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return Change(node, machine()->Float32Abs(), vtrue);
394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case IrOpcode::kFloat64LessThan: {
399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Float64BinopMatcher mcond(cond);
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) &&
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          vfalse->opcode() == IrOpcode::kFloat64Sub) {
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Float64BinopMatcher mvfalse(vfalse);
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) {
404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return Change(node, machine()->Float64Abs(), vtrue);
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    default:
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NoChange();
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::Change(Node* node, Operator const* op,
417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        Node* a) {
418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(0, a);
419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->TrimInputCount(1);
420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(node, op);
421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Changed(node);
422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a,
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        Node* b) {
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(0, a);
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->ReplaceInput(1, b);
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  node->TrimInputCount(2);
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(node, op);
431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Changed(node);
432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace compiler
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace internal
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
437