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 22 matching lines...) Expand all Loading... |
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 | 40 // Use the zero register if the node has the immediate value zero, otherwise |
41 // assign a register. | 41 // assign a register. |
42 InstructionOperand UseRegisterOrImmediateZero(Node* node) { | 42 InstructionOperand UseRegisterOrImmediateZero(Node* node) { |
43 if (IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) { | 43 if ((IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) || |
| 44 (IsFloatConstant(node) && |
| 45 (bit_cast<int64_t>(GetFloatConstantValue(node)) == V8_INT64_C(0)))) { |
44 return UseImmediate(node); | 46 return UseImmediate(node); |
45 } | 47 } |
46 return UseRegister(node); | 48 return UseRegister(node); |
47 } | 49 } |
48 | 50 |
49 // Use the provided node if it has the required value, or create a | 51 // Use the provided node if it has the required value, or create a |
50 // TempImmediate otherwise. | 52 // TempImmediate otherwise. |
51 InstructionOperand UseImmediateOrTemp(Node* node, int32_t value) { | 53 InstructionOperand UseImmediateOrTemp(Node* node, int32_t value) { |
52 if (GetIntegerConstantValue(node) == value) { | 54 if (GetIntegerConstantValue(node) == value) { |
53 return UseImmediate(node); | 55 return UseImmediate(node); |
54 } | 56 } |
55 return TempImmediate(value); | 57 return TempImmediate(value); |
56 } | 58 } |
57 | 59 |
58 bool IsIntegerConstant(Node* node) { | 60 bool IsIntegerConstant(Node* node) { |
59 return (node->opcode() == IrOpcode::kInt32Constant) || | 61 return (node->opcode() == IrOpcode::kInt32Constant) || |
60 (node->opcode() == IrOpcode::kInt64Constant); | 62 (node->opcode() == IrOpcode::kInt64Constant); |
61 } | 63 } |
62 | 64 |
63 int64_t GetIntegerConstantValue(Node* node) { | 65 int64_t GetIntegerConstantValue(Node* node) { |
64 if (node->opcode() == IrOpcode::kInt32Constant) { | 66 if (node->opcode() == IrOpcode::kInt32Constant) { |
65 return OpParameter<int32_t>(node); | 67 return OpParameter<int32_t>(node); |
66 } | 68 } |
67 DCHECK(node->opcode() == IrOpcode::kInt64Constant); | 69 DCHECK(node->opcode() == IrOpcode::kInt64Constant); |
68 return OpParameter<int64_t>(node); | 70 return OpParameter<int64_t>(node); |
69 } | 71 } |
70 | 72 |
| 73 bool IsFloatConstant(Node* node) { |
| 74 return (node->opcode() == IrOpcode::kFloat32Constant) || |
| 75 (node->opcode() == IrOpcode::kFloat64Constant); |
| 76 } |
| 77 |
| 78 double GetFloatConstantValue(Node* node) { |
| 79 if (node->opcode() == IrOpcode::kFloat32Constant) { |
| 80 return OpParameter<float>(node); |
| 81 } |
| 82 DCHECK_EQ(IrOpcode::kFloat64Constant, node->opcode()); |
| 83 return OpParameter<double>(node); |
| 84 } |
| 85 |
71 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 86 bool CanBeImmediate(Node* node, ImmediateMode mode) { |
72 return IsIntegerConstant(node) && | 87 return IsIntegerConstant(node) && |
73 CanBeImmediate(GetIntegerConstantValue(node), mode); | 88 CanBeImmediate(GetIntegerConstantValue(node), mode); |
74 } | 89 } |
75 | 90 |
76 bool CanBeImmediate(int64_t value, ImmediateMode mode) { | 91 bool CanBeImmediate(int64_t value, ImmediateMode mode) { |
77 unsigned ignored; | 92 unsigned ignored; |
78 switch (mode) { | 93 switch (mode) { |
79 case kLogical32Imm: | 94 case kLogical32Imm: |
80 // TODO(dcarney): some unencodable values can be handled by | 95 // TODO(dcarney): some unencodable values can be handled by |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 opcode = kArm64Str; | 485 opcode = kArm64Str; |
471 immediate_mode = kLoadStoreImm64; | 486 immediate_mode = kLoadStoreImm64; |
472 break; | 487 break; |
473 case MachineRepresentation::kSimd128: // Fall through. | 488 case MachineRepresentation::kSimd128: // Fall through. |
474 case MachineRepresentation::kNone: | 489 case MachineRepresentation::kNone: |
475 UNREACHABLE(); | 490 UNREACHABLE(); |
476 return; | 491 return; |
477 } | 492 } |
478 if (g.CanBeImmediate(index, immediate_mode)) { | 493 if (g.CanBeImmediate(index, immediate_mode)) { |
479 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 494 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
480 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 495 g.UseRegister(base), g.UseImmediate(index), |
| 496 g.UseRegisterOrImmediateZero(value)); |
481 } else { | 497 } else { |
482 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), | 498 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), |
483 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); | 499 g.UseRegister(base), g.UseRegister(index), |
| 500 g.UseRegisterOrImmediateZero(value)); |
484 } | 501 } |
485 } | 502 } |
486 } | 503 } |
487 | 504 |
488 | 505 |
489 void InstructionSelector::VisitCheckedLoad(Node* node) { | 506 void InstructionSelector::VisitCheckedLoad(Node* node) { |
490 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); | 507 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); |
491 Arm64OperandGenerator g(this); | 508 Arm64OperandGenerator g(this); |
492 Node* const buffer = node->InputAt(0); | 509 Node* const buffer = node->InputAt(0); |
493 Node* const offset = node->InputAt(1); | 510 Node* const offset = node->InputAt(1); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 opcode = kCheckedStoreFloat64; | 569 opcode = kCheckedStoreFloat64; |
553 break; | 570 break; |
554 case MachineRepresentation::kBit: // Fall through. | 571 case MachineRepresentation::kBit: // Fall through. |
555 case MachineRepresentation::kTagged: // Fall through. | 572 case MachineRepresentation::kTagged: // Fall through. |
556 case MachineRepresentation::kSimd128: // Fall through. | 573 case MachineRepresentation::kSimd128: // Fall through. |
557 case MachineRepresentation::kNone: | 574 case MachineRepresentation::kNone: |
558 UNREACHABLE(); | 575 UNREACHABLE(); |
559 return; | 576 return; |
560 } | 577 } |
561 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset), | 578 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset), |
562 g.UseOperand(length, kArithmeticImm), g.UseRegister(value)); | 579 g.UseOperand(length, kArithmeticImm), |
| 580 g.UseRegisterOrImmediateZero(value)); |
563 } | 581 } |
564 | 582 |
565 | 583 |
566 template <typename Matcher> | 584 template <typename Matcher> |
567 static void VisitLogical(InstructionSelector* selector, Node* node, Matcher* m, | 585 static void VisitLogical(InstructionSelector* selector, Node* node, Matcher* m, |
568 ArchOpcode opcode, bool left_can_cover, | 586 ArchOpcode opcode, bool left_can_cover, |
569 bool right_can_cover, ImmediateMode imm_mode) { | 587 bool right_can_cover, ImmediateMode imm_mode) { |
570 Arm64OperandGenerator g(selector); | 588 Arm64OperandGenerator g(selector); |
571 | 589 |
572 // Map instruction to equivalent operation with inverted right input. | 590 // Map instruction to equivalent operation with inverted right input. |
(...skipping 1713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2286 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2304 MachineOperatorBuilder::kWord32ShiftIsSafe | |
2287 MachineOperatorBuilder::kInt32DivIsSafe | | 2305 MachineOperatorBuilder::kInt32DivIsSafe | |
2288 MachineOperatorBuilder::kUint32DivIsSafe | | 2306 MachineOperatorBuilder::kUint32DivIsSafe | |
2289 MachineOperatorBuilder::kWord32ReverseBits | | 2307 MachineOperatorBuilder::kWord32ReverseBits | |
2290 MachineOperatorBuilder::kWord64ReverseBits; | 2308 MachineOperatorBuilder::kWord64ReverseBits; |
2291 } | 2309 } |
2292 | 2310 |
2293 } // namespace compiler | 2311 } // namespace compiler |
2294 } // namespace internal | 2312 } // namespace internal |
2295 } // namespace v8 | 2313 } // namespace v8 |
OLD | NEW |