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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 template <typename Matcher> | 216 template <typename Matcher> |
217 void VisitBinop(InstructionSelector* selector, Node* node, | 217 void VisitBinop(InstructionSelector* selector, Node* node, |
218 InstructionCode opcode, ImmediateMode operand_mode, | 218 InstructionCode opcode, ImmediateMode operand_mode, |
219 FlagsContinuation* cont) { | 219 FlagsContinuation* cont) { |
220 Arm64OperandGenerator g(selector); | 220 Arm64OperandGenerator g(selector); |
221 Matcher m(node); | 221 Matcher m(node); |
222 InstructionOperand inputs[5]; | 222 InstructionOperand inputs[5]; |
223 size_t input_count = 0; | 223 size_t input_count = 0; |
224 InstructionOperand outputs[2]; | 224 InstructionOperand outputs[2]; |
225 size_t output_count = 0; | 225 size_t output_count = 0; |
226 bool is_cmp = opcode == kArm64Cmp32; | 226 bool is_cmp = (opcode == kArm64Cmp32) || (opcode == kArm64Cmn32); |
227 | 227 |
228 // We can commute cmp by switching the inputs and commuting the flags | 228 // We can commute cmp by switching the inputs and commuting the flags |
229 // continuation. | 229 // continuation. |
230 bool can_commute = m.HasProperty(Operator::kCommutative) || is_cmp; | 230 bool can_commute = m.HasProperty(Operator::kCommutative) || is_cmp; |
231 | 231 |
232 // The cmp instruction is encoded as sub with zero output register, and | 232 // The cmp and cmn instructions are encoded as sub or add with zero output |
233 // therefore supports the same operand modes. | 233 // register, and therefore support the same operand modes. |
234 bool is_add_sub = m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || | 234 bool is_add_sub = m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || |
235 m.IsInt64Sub() || is_cmp; | 235 m.IsInt64Sub() || is_cmp; |
236 | 236 |
237 Node* left_node = m.left().node(); | 237 Node* left_node = m.left().node(); |
238 Node* right_node = m.right().node(); | 238 Node* right_node = m.right().node(); |
239 | 239 |
240 if (g.CanBeImmediate(right_node, operand_mode)) { | 240 if (g.CanBeImmediate(right_node, operand_mode)) { |
241 inputs[input_count++] = g.UseRegister(left_node); | 241 inputs[input_count++] = g.UseRegister(left_node); |
242 inputs[input_count++] = g.UseImmediate(right_node); | 242 inputs[input_count++] = g.UseImmediate(right_node); |
243 } else if (is_cmp && g.CanBeImmediate(left_node, operand_mode)) { | 243 } else if (is_cmp && g.CanBeImmediate(left_node, operand_mode)) { |
(...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 cont); | 1503 cont); |
1504 } else { | 1504 } else { |
1505 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 1505 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
1506 cont); | 1506 cont); |
1507 } | 1507 } |
1508 } | 1508 } |
1509 | 1509 |
1510 | 1510 |
1511 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 1511 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
1512 FlagsContinuation* cont) { | 1512 FlagsContinuation* cont) { |
1513 VisitBinop<Int32BinopMatcher>(selector, node, kArm64Cmp32, kArithmeticImm, | 1513 Int32BinopMatcher m(node); |
1514 cont); | 1514 ArchOpcode opcode = kArm64Cmp32; |
| 1515 |
| 1516 // Select negated compare for comparisons with negated right input. |
| 1517 if (m.right().IsInt32Sub()) { |
| 1518 Node* sub = m.right().node(); |
| 1519 Int32BinopMatcher msub(sub); |
| 1520 if (msub.left().Is(0)) { |
| 1521 bool can_cover = selector->CanCover(node, sub); |
| 1522 node->ReplaceInput(1, msub.right().node()); |
| 1523 // Even if the comparison node covers the subtraction, after the input |
| 1524 // replacement above, the node still won't cover the input to the |
| 1525 // subtraction; the subtraction still uses it. |
| 1526 // In order to get shifted operations to work, we must remove the rhs |
| 1527 // input to the subtraction, as TryMatchAnyShift requires this node to |
| 1528 // cover the input shift. We do this by setting it to the lhs input, |
| 1529 // as we know it's zero, and the result of the subtraction isn't used by |
| 1530 // any other node. |
| 1531 if (can_cover) sub->ReplaceInput(1, msub.left().node()); |
| 1532 opcode = kArm64Cmn32; |
| 1533 } |
| 1534 } |
| 1535 VisitBinop<Int32BinopMatcher>(selector, node, opcode, kArithmeticImm, cont); |
1515 } | 1536 } |
1516 | 1537 |
1517 | 1538 |
1518 void VisitWordTest(InstructionSelector* selector, Node* node, | 1539 void VisitWordTest(InstructionSelector* selector, Node* node, |
1519 InstructionCode opcode, FlagsContinuation* cont) { | 1540 InstructionCode opcode, FlagsContinuation* cont) { |
1520 Arm64OperandGenerator g(selector); | 1541 Arm64OperandGenerator g(selector); |
1521 VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), | 1542 VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), |
1522 cont); | 1543 cont); |
1523 } | 1544 } |
1524 | 1545 |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1979 MachineOperatorBuilder::kFloat64RoundTruncate | | 2000 MachineOperatorBuilder::kFloat64RoundTruncate | |
1980 MachineOperatorBuilder::kFloat64RoundTiesAway | | 2001 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1981 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2002 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1982 MachineOperatorBuilder::kInt32DivIsSafe | | 2003 MachineOperatorBuilder::kInt32DivIsSafe | |
1983 MachineOperatorBuilder::kUint32DivIsSafe; | 2004 MachineOperatorBuilder::kUint32DivIsSafe; |
1984 } | 2005 } |
1985 | 2006 |
1986 } // namespace compiler | 2007 } // namespace compiler |
1987 } // namespace internal | 2008 } // namespace internal |
1988 } // namespace v8 | 2009 } // namespace v8 |
OLD | NEW |