| 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 |