| 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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
| 6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
| 7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 explicit Arm64OperandGenerator(InstructionSelector* selector) | 30 explicit Arm64OperandGenerator(InstructionSelector* selector) |
| 31 : OperandGenerator(selector) {} | 31 : OperandGenerator(selector) {} |
| 32 | 32 |
| 33 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { | 33 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { |
| 34 if (CanBeImmediate(node, mode)) { | 34 if (CanBeImmediate(node, mode)) { |
| 35 return UseImmediate(node); | 35 return UseImmediate(node); |
| 36 } | 36 } |
| 37 return UseRegister(node); | 37 return UseRegister(node); |
| 38 } | 38 } |
| 39 | 39 |
| 40 // Use the zero register if the node has the immediate value zero, otherwise |
| 41 // assign a register. |
| 42 InstructionOperand UseRegisterOrImmediateZero(Node* node) { |
| 43 if (IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) { |
| 44 return UseImmediate(node); |
| 45 } |
| 46 return UseRegister(node); |
| 47 } |
| 48 |
| 40 // Use the provided node if it has the required value, or create a | 49 // Use the provided node if it has the required value, or create a |
| 41 // TempImmediate otherwise. | 50 // TempImmediate otherwise. |
| 42 InstructionOperand UseImmediateOrTemp(Node* node, int32_t value) { | 51 InstructionOperand UseImmediateOrTemp(Node* node, int32_t value) { |
| 43 if (GetIntegerConstantValue(node) == value) { | 52 if (GetIntegerConstantValue(node) == value) { |
| 44 return UseImmediate(node); | 53 return UseImmediate(node); |
| 45 } | 54 } |
| 46 return TempImmediate(value); | 55 return TempImmediate(value); |
| 47 } | 56 } |
| 48 | 57 |
| 49 bool IsIntegerConstant(Node* node) { | 58 bool IsIntegerConstant(Node* node) { |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 &inputs[0], &inputs[1], &opcode)) { | 249 &inputs[0], &inputs[1], &opcode)) { |
| 241 input_count += 2; | 250 input_count += 2; |
| 242 } else if (is_add_sub && can_commute && | 251 } else if (is_add_sub && can_commute && |
| 243 TryMatchAnyExtend(&g, selector, node, right_node, left_node, | 252 TryMatchAnyExtend(&g, selector, node, right_node, left_node, |
| 244 &inputs[0], &inputs[1], &opcode)) { | 253 &inputs[0], &inputs[1], &opcode)) { |
| 245 if (is_cmp) cont->Commute(); | 254 if (is_cmp) cont->Commute(); |
| 246 input_count += 2; | 255 input_count += 2; |
| 247 } else if (TryMatchAnyShift(selector, node, right_node, &opcode, | 256 } else if (TryMatchAnyShift(selector, node, right_node, &opcode, |
| 248 !is_add_sub)) { | 257 !is_add_sub)) { |
| 249 Matcher m_shift(right_node); | 258 Matcher m_shift(right_node); |
| 250 inputs[input_count++] = g.UseRegister(left_node); | 259 inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node); |
| 251 inputs[input_count++] = g.UseRegister(m_shift.left().node()); | 260 inputs[input_count++] = g.UseRegister(m_shift.left().node()); |
| 252 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); | 261 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); |
| 253 } else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode, | 262 } else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode, |
| 254 !is_add_sub)) { | 263 !is_add_sub)) { |
| 255 if (is_cmp) cont->Commute(); | 264 if (is_cmp) cont->Commute(); |
| 256 Matcher m_shift(left_node); | 265 Matcher m_shift(left_node); |
| 257 inputs[input_count++] = g.UseRegister(right_node); | 266 inputs[input_count++] = g.UseRegisterOrImmediateZero(right_node); |
| 258 inputs[input_count++] = g.UseRegister(m_shift.left().node()); | 267 inputs[input_count++] = g.UseRegister(m_shift.left().node()); |
| 259 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); | 268 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); |
| 260 } else { | 269 } else { |
| 261 inputs[input_count++] = g.UseRegister(left_node); | 270 inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node); |
| 262 inputs[input_count++] = g.UseRegister(right_node); | 271 inputs[input_count++] = g.UseRegister(right_node); |
| 263 } | 272 } |
| 264 | 273 |
| 265 if (cont->IsBranch()) { | 274 if (cont->IsBranch()) { |
| 266 inputs[input_count++] = g.Label(cont->true_block()); | 275 inputs[input_count++] = g.Label(cont->true_block()); |
| 267 inputs[input_count++] = g.Label(cont->false_block()); | 276 inputs[input_count++] = g.Label(cont->false_block()); |
| 268 } | 277 } |
| 269 | 278 |
| 270 if (!is_cmp) { | 279 if (!is_cmp) { |
| 271 outputs[output_count++] = g.DefineAsRegister(node); | 280 outputs[output_count++] = g.DefineAsRegister(node); |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 // Check multiply can't be later reduced to addition with shift. | 999 // Check multiply can't be later reduced to addition with shift. |
| 991 if (LeftShiftForReducedMultiply(&mright) == 0) { | 1000 if (LeftShiftForReducedMultiply(&mright) == 0) { |
| 992 Emit(kArm64Msub32, g.DefineAsRegister(node), | 1001 Emit(kArm64Msub32, g.DefineAsRegister(node), |
| 993 g.UseRegister(mright.left().node()), | 1002 g.UseRegister(mright.left().node()), |
| 994 g.UseRegister(mright.right().node()), | 1003 g.UseRegister(mright.right().node()), |
| 995 g.UseRegister(m.left().node())); | 1004 g.UseRegister(m.left().node())); |
| 996 return; | 1005 return; |
| 997 } | 1006 } |
| 998 } | 1007 } |
| 999 | 1008 |
| 1000 if (m.left().Is(0)) { | 1009 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Sub32, kArm64Add32); |
| 1001 Emit(kArm64Neg32, g.DefineAsRegister(node), | |
| 1002 g.UseRegister(m.right().node())); | |
| 1003 } else { | |
| 1004 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Sub32, kArm64Add32); | |
| 1005 } | |
| 1006 } | 1010 } |
| 1007 | 1011 |
| 1008 | 1012 |
| 1009 void InstructionSelector::VisitInt64Sub(Node* node) { | 1013 void InstructionSelector::VisitInt64Sub(Node* node) { |
| 1010 Arm64OperandGenerator g(this); | 1014 Arm64OperandGenerator g(this); |
| 1011 Int64BinopMatcher m(node); | 1015 Int64BinopMatcher m(node); |
| 1012 | 1016 |
| 1013 // Select Msub(x, y, a) for Sub(a, Mul(x, y)). | 1017 // Select Msub(x, y, a) for Sub(a, Mul(x, y)). |
| 1014 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { | 1018 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { |
| 1015 Int64BinopMatcher mright(m.right().node()); | 1019 Int64BinopMatcher mright(m.right().node()); |
| 1016 // Check multiply can't be later reduced to addition with shift. | 1020 // Check multiply can't be later reduced to addition with shift. |
| 1017 if (LeftShiftForReducedMultiply(&mright) == 0) { | 1021 if (LeftShiftForReducedMultiply(&mright) == 0) { |
| 1018 Emit(kArm64Msub, g.DefineAsRegister(node), | 1022 Emit(kArm64Msub, g.DefineAsRegister(node), |
| 1019 g.UseRegister(mright.left().node()), | 1023 g.UseRegister(mright.left().node()), |
| 1020 g.UseRegister(mright.right().node()), | 1024 g.UseRegister(mright.right().node()), |
| 1021 g.UseRegister(m.left().node())); | 1025 g.UseRegister(m.left().node())); |
| 1022 return; | 1026 return; |
| 1023 } | 1027 } |
| 1024 } | 1028 } |
| 1025 | 1029 |
| 1026 if (m.left().Is(0)) { | 1030 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); |
| 1027 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); | |
| 1028 } else { | |
| 1029 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); | |
| 1030 } | |
| 1031 } | 1031 } |
| 1032 | 1032 |
| 1033 | 1033 |
| 1034 void InstructionSelector::VisitInt32Mul(Node* node) { | 1034 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 1035 Arm64OperandGenerator g(this); | 1035 Arm64OperandGenerator g(this); |
| 1036 Int32BinopMatcher m(node); | 1036 Int32BinopMatcher m(node); |
| 1037 | 1037 |
| 1038 // First, try to reduce the multiplication to addition with left shift. | 1038 // First, try to reduce the multiplication to addition with left shift. |
| 1039 // x * (2^k + 1) -> x + (x << k) | 1039 // x * (2^k + 1) -> x + (x << k) |
| 1040 int32_t shift = LeftShiftForReducedMultiply(&m); | 1040 int32_t shift = LeftShiftForReducedMultiply(&m); |
| (...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2111 MachineOperatorBuilder::kFloat64RoundTruncate | | 2111 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 2112 MachineOperatorBuilder::kFloat64RoundTiesAway | | 2112 MachineOperatorBuilder::kFloat64RoundTiesAway | |
| 2113 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2113 MachineOperatorBuilder::kWord32ShiftIsSafe | |
| 2114 MachineOperatorBuilder::kInt32DivIsSafe | | 2114 MachineOperatorBuilder::kInt32DivIsSafe | |
| 2115 MachineOperatorBuilder::kUint32DivIsSafe; | 2115 MachineOperatorBuilder::kUint32DivIsSafe; |
| 2116 } | 2116 } |
| 2117 | 2117 |
| 2118 } // namespace compiler | 2118 } // namespace compiler |
| 2119 } // namespace internal | 2119 } // namespace internal |
| 2120 } // namespace v8 | 2120 } // namespace v8 |
| OLD | NEW |