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