| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/common-operator-reducer.h" | 5 #include "src/compiler/common-operator-reducer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "src/compiler/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
| 10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/graph.h" |
| 11 #include "src/compiler/machine-operator.h" |
| 11 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
| 12 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
| 13 | 14 |
| 14 namespace v8 { | 15 namespace v8 { |
| 15 namespace internal { | 16 namespace internal { |
| 16 namespace compiler { | 17 namespace compiler { |
| 17 | 18 |
| 18 Reduction CommonOperatorReducer::Reduce(Node* node) { | 19 Reduction CommonOperatorReducer::Reduce(Node* node) { |
| 19 switch (node->opcode()) { | 20 switch (node->opcode()) { |
| 20 case IrOpcode::kEffectPhi: | 21 case IrOpcode::kEffectPhi: |
| 21 return ReduceEffectPhi(node); | 22 return ReduceEffectPhi(node); |
| 22 case IrOpcode::kPhi: | 23 case IrOpcode::kPhi: |
| 23 return ReducePhi(node); | 24 return ReducePhi(node); |
| 24 case IrOpcode::kSelect: | 25 case IrOpcode::kSelect: |
| 25 return ReduceSelect(node); | 26 return ReduceSelect(node); |
| 26 default: | 27 default: |
| 27 break; | 28 break; |
| 28 } | 29 } |
| 29 return NoChange(); | 30 return NoChange(); |
| 30 } | 31 } |
| 31 | 32 |
| 32 | 33 |
| 33 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { | 34 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { |
| 34 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); | 35 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); |
| 35 int const input_count = node->InputCount(); | 36 int const input_count = node->InputCount() - 1; |
| 36 if (input_count > 1) { | 37 DCHECK_LE(1, input_count); |
| 37 Node* const replacement = node->InputAt(0); | 38 Node* const merge = node->InputAt(input_count); |
| 38 for (int i = 1; i < input_count - 1; ++i) { | 39 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
| 39 if (node->InputAt(i) != replacement) return NoChange(); | 40 DCHECK_EQ(input_count, merge->InputCount()); |
| 41 Node* const effect = node->InputAt(0); |
| 42 DCHECK_NE(node, effect); |
| 43 for (int i = 1; i < input_count; ++i) { |
| 44 Node* const input = node->InputAt(i); |
| 45 if (input == node) { |
| 46 // Ignore redundant inputs. |
| 47 DCHECK_EQ(IrOpcode::kLoop, merge->opcode()); |
| 48 continue; |
| 40 } | 49 } |
| 41 return Replace(replacement); | 50 if (input != effect) return NoChange(); |
| 42 } | 51 } |
| 43 return NoChange(); | 52 // We might now be able to further reduce the {merge} node. |
| 53 Revisit(merge); |
| 54 return Replace(effect); |
| 44 } | 55 } |
| 45 | 56 |
| 46 | 57 |
| 47 Reduction CommonOperatorReducer::ReducePhi(Node* node) { | 58 Reduction CommonOperatorReducer::ReducePhi(Node* node) { |
| 48 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); | 59 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); |
| 49 int const input_count = node->InputCount(); | 60 int const input_count = node->InputCount() - 1; |
| 50 if (input_count == 3) { | 61 DCHECK_LE(1, input_count); |
| 51 Node* vtrue = NodeProperties::GetValueInput(node, 0); | 62 Node* const merge = node->InputAt(input_count); |
| 52 Node* vfalse = NodeProperties::GetValueInput(node, 1); | 63 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
| 53 Node* merge = NodeProperties::GetControlInput(node); | 64 DCHECK_EQ(input_count, merge->InputCount()); |
| 54 DiamondMatcher matcher(merge); | 65 if (input_count == 2) { |
| 55 if (matcher.Matched()) { | 66 Node* vtrue = node->InputAt(0); |
| 56 if (matcher.IfTrue() == merge->InputAt(1)) std::swap(vtrue, vfalse); | 67 Node* vfalse = node->InputAt(1); |
| 57 Node* cond = matcher.Branch()->InputAt(0); | 68 Node* if_true = merge->InputAt(0); |
| 69 Node* if_false = merge->InputAt(1); |
| 70 if (if_true->opcode() != IrOpcode::kIfTrue) { |
| 71 std::swap(if_true, if_false); |
| 72 std::swap(vtrue, vfalse); |
| 73 } |
| 74 if (if_true->opcode() == IrOpcode::kIfTrue && |
| 75 if_false->opcode() == IrOpcode::kIfFalse && |
| 76 if_true->InputAt(0) == if_false->InputAt(0)) { |
| 77 Node* const branch = if_true->InputAt(0); |
| 78 Node* const cond = branch->InputAt(0); |
| 58 if (cond->opcode() == IrOpcode::kFloat32LessThan) { | 79 if (cond->opcode() == IrOpcode::kFloat32LessThan) { |
| 59 Float32BinopMatcher mcond(cond); | 80 Float32BinopMatcher mcond(cond); |
| 60 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 81 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
| 61 vfalse->opcode() == IrOpcode::kFloat32Sub) { | 82 vfalse->opcode() == IrOpcode::kFloat32Sub) { |
| 62 Float32BinopMatcher mvfalse(vfalse); | 83 Float32BinopMatcher mvfalse(vfalse); |
| 63 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { | 84 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { |
| 85 // We might now be able to further reduce the {merge} node. |
| 86 Revisit(merge); |
| 64 return Change(node, machine()->Float32Abs(), vtrue); | 87 return Change(node, machine()->Float32Abs(), vtrue); |
| 65 } | 88 } |
| 66 } | 89 } |
| 67 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && | 90 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && |
| 68 machine()->HasFloat32Min()) { | 91 machine()->HasFloat32Min()) { |
| 92 // We might now be able to further reduce the {merge} node. |
| 93 Revisit(merge); |
| 69 return Change(node, machine()->Float32Min(), vtrue, vfalse); | 94 return Change(node, machine()->Float32Min(), vtrue, vfalse); |
| 70 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && | 95 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && |
| 71 machine()->HasFloat32Max()) { | 96 machine()->HasFloat32Max()) { |
| 97 // We might now be able to further reduce the {merge} node. |
| 98 Revisit(merge); |
| 72 return Change(node, machine()->Float32Max(), vtrue, vfalse); | 99 return Change(node, machine()->Float32Max(), vtrue, vfalse); |
| 73 } | 100 } |
| 74 } else if (cond->opcode() == IrOpcode::kFloat64LessThan) { | 101 } else if (cond->opcode() == IrOpcode::kFloat64LessThan) { |
| 75 Float64BinopMatcher mcond(cond); | 102 Float64BinopMatcher mcond(cond); |
| 76 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 103 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
| 77 vfalse->opcode() == IrOpcode::kFloat64Sub) { | 104 vfalse->opcode() == IrOpcode::kFloat64Sub) { |
| 78 Float64BinopMatcher mvfalse(vfalse); | 105 Float64BinopMatcher mvfalse(vfalse); |
| 79 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { | 106 if (mvfalse.left().IsZero() && mvfalse.right().Equals(vtrue)) { |
| 107 // We might now be able to further reduce the {merge} node. |
| 108 Revisit(merge); |
| 80 return Change(node, machine()->Float64Abs(), vtrue); | 109 return Change(node, machine()->Float64Abs(), vtrue); |
| 81 } | 110 } |
| 82 } | 111 } |
| 83 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && | 112 if (mcond.left().Equals(vtrue) && mcond.right().Equals(vfalse) && |
| 84 machine()->HasFloat64Min()) { | 113 machine()->HasFloat64Min()) { |
| 114 // We might now be able to further reduce the {merge} node. |
| 115 Revisit(merge); |
| 85 return Change(node, machine()->Float64Min(), vtrue, vfalse); | 116 return Change(node, machine()->Float64Min(), vtrue, vfalse); |
| 86 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && | 117 } else if (mcond.left().Equals(vfalse) && mcond.right().Equals(vtrue) && |
| 87 machine()->HasFloat64Max()) { | 118 machine()->HasFloat64Max()) { |
| 119 // We might now be able to further reduce the {merge} node. |
| 120 Revisit(merge); |
| 88 return Change(node, machine()->Float64Max(), vtrue, vfalse); | 121 return Change(node, machine()->Float64Max(), vtrue, vfalse); |
| 89 } | 122 } |
| 90 } | 123 } |
| 91 } | 124 } |
| 92 } | 125 } |
| 93 if (input_count > 1) { | 126 Node* const value = node->InputAt(0); |
| 94 Node* const replacement = node->InputAt(0); | 127 DCHECK_NE(node, value); |
| 95 for (int i = 1; i < input_count - 1; ++i) { | 128 for (int i = 1; i < input_count; ++i) { |
| 96 if (node->InputAt(i) != replacement) return NoChange(); | 129 Node* const input = node->InputAt(i); |
| 130 if (input == node) { |
| 131 // Ignore redundant inputs. |
| 132 DCHECK_EQ(IrOpcode::kLoop, merge->opcode()); |
| 133 continue; |
| 97 } | 134 } |
| 98 return Replace(replacement); | 135 if (input != value) return NoChange(); |
| 99 } | 136 } |
| 100 return NoChange(); | 137 // We might now be able to further reduce the {merge} node. |
| 138 Revisit(merge); |
| 139 return Replace(value); |
| 101 } | 140 } |
| 102 | 141 |
| 103 | 142 |
| 104 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { | 143 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { |
| 105 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); | 144 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); |
| 106 Node* cond = NodeProperties::GetValueInput(node, 0); | 145 Node* const cond = node->InputAt(0); |
| 107 Node* vtrue = NodeProperties::GetValueInput(node, 1); | 146 Node* const vtrue = node->InputAt(1); |
| 108 Node* vfalse = NodeProperties::GetValueInput(node, 2); | 147 Node* const vfalse = node->InputAt(2); |
| 109 if (vtrue == vfalse) return Replace(vtrue); | 148 if (vtrue == vfalse) return Replace(vtrue); |
| 110 switch (cond->opcode()) { | 149 switch (cond->opcode()) { |
| 111 case IrOpcode::kHeapConstant: { | 150 case IrOpcode::kHeapConstant: { |
| 112 HeapObjectMatcher<HeapObject> mcond(cond); | 151 HeapObjectMatcher<HeapObject> mcond(cond); |
| 113 return Replace(mcond.Value().handle()->BooleanValue() ? vtrue : vfalse); | 152 return Replace(mcond.Value().handle()->BooleanValue() ? vtrue : vfalse); |
| 114 } | 153 } |
| 115 case IrOpcode::kFloat32LessThan: { | 154 case IrOpcode::kFloat32LessThan: { |
| 116 Float32BinopMatcher mcond(cond); | 155 Float32BinopMatcher mcond(cond); |
| 117 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && | 156 if (mcond.left().Is(0.0) && mcond.right().Equals(vtrue) && |
| 118 vfalse->opcode() == IrOpcode::kFloat32Sub) { | 157 vfalse->opcode() == IrOpcode::kFloat32Sub) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 205 |
| 167 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a, | 206 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a, |
| 168 Node* b) { | 207 Node* b) { |
| 169 node->set_op(op); | 208 node->set_op(op); |
| 170 node->ReplaceInput(0, a); | 209 node->ReplaceInput(0, a); |
| 171 node->ReplaceInput(1, b); | 210 node->ReplaceInput(1, b); |
| 172 node->TrimInputCount(2); | 211 node->TrimInputCount(2); |
| 173 return Changed(node); | 212 return Changed(node); |
| 174 } | 213 } |
| 175 | 214 |
| 176 | |
| 177 CommonOperatorBuilder* CommonOperatorReducer::common() const { | |
| 178 return jsgraph()->common(); | |
| 179 } | |
| 180 | |
| 181 | |
| 182 Graph* CommonOperatorReducer::graph() const { return jsgraph()->graph(); } | |
| 183 | |
| 184 | |
| 185 MachineOperatorBuilder* CommonOperatorReducer::machine() const { | |
| 186 return jsgraph()->machine(); | |
| 187 } | |
| 188 | |
| 189 } // namespace compiler | 215 } // namespace compiler |
| 190 } // namespace internal | 216 } // namespace internal |
| 191 } // namespace v8 | 217 } // namespace v8 |
| OLD | NEW |