| 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-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 return false; | 37 return false; |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 | 40 |
| 41 bool CanBeBetterLeftOperand(Node* node) const { | 41 bool CanBeBetterLeftOperand(Node* node) const { |
| 42 return !selector()->IsLive(node); | 42 return !selector()->IsLive(node); |
| 43 } | 43 } |
| 44 }; | 44 }; |
| 45 | 45 |
| 46 | 46 |
| 47 // Get the AddressingMode of scale factor N from the AddressingMode of scale |
| 48 // factor 1. |
| 49 static AddressingMode AdjustAddressingMode(AddressingMode base_mode, |
| 50 int power) { |
| 51 DCHECK(0 <= power && power < 4); |
| 52 return static_cast<AddressingMode>(static_cast<int>(base_mode) + power); |
| 53 } |
| 54 |
| 55 |
| 47 class AddressingModeMatcher { | 56 class AddressingModeMatcher { |
| 48 public: | 57 public: |
| 49 AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index) | 58 AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index) |
| 50 : base_operand_(NULL), | 59 : base_operand_(NULL), |
| 51 index_operand_(NULL), | 60 index_operand_(NULL), |
| 52 displacement_operand_(NULL), | 61 displacement_operand_(NULL), |
| 53 mode_(kMode_None) { | 62 mode_(kMode_None) { |
| 54 Int32Matcher index_imm(index); | 63 Int32Matcher index_imm(index); |
| 55 if (index_imm.HasValue()) { | 64 if (index_imm.HasValue()) { |
| 56 int32_t displacement = index_imm.Value(); | 65 int32_t displacement = index_imm.Value(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 mode_ = kMode_M1I; | 106 mode_ = kMode_M1I; |
| 98 } | 107 } |
| 99 } else { | 108 } else { |
| 100 if (displacement_operand_ == NULL) { | 109 if (displacement_operand_ == NULL) { |
| 101 mode_ = kMode_MR1; | 110 mode_ = kMode_MR1; |
| 102 } else { | 111 } else { |
| 103 mode_ = kMode_MR1I; | 112 mode_ = kMode_MR1I; |
| 104 } | 113 } |
| 105 } | 114 } |
| 106 // Adjust mode to actual scale factor. | 115 // Adjust mode to actual scale factor. |
| 107 mode_ = GetMode(mode_, matcher.power()); | 116 mode_ = AdjustAddressingMode(mode_, matcher.power()); |
| 108 // Don't emit instructions with scale factor 1 if there's no base. | |
| 109 if (mode_ == kMode_M1) { | |
| 110 mode_ = kMode_MR; | |
| 111 } else if (mode_ == kMode_M1I) { | |
| 112 mode_ = kMode_MRI; | |
| 113 } | |
| 114 } | 117 } |
| 115 DCHECK_NE(kMode_None, mode_); | 118 DCHECK_NE(kMode_None, mode_); |
| 116 } | 119 } |
| 117 | 120 |
| 118 AddressingMode GetMode(AddressingMode one, int power) { | |
| 119 return static_cast<AddressingMode>(static_cast<int>(one) + power); | |
| 120 } | |
| 121 | |
| 122 size_t SetInputs(InstructionOperand** inputs) { | 121 size_t SetInputs(InstructionOperand** inputs) { |
| 123 size_t input_count = 0; | 122 size_t input_count = 0; |
| 124 // Compute inputs_ and input_count. | 123 // Compute inputs_ and input_count. |
| 125 if (base_operand_ != NULL) { | 124 if (base_operand_ != NULL) { |
| 126 inputs[input_count++] = base_operand_; | 125 inputs[input_count++] = base_operand_; |
| 127 } | 126 } |
| 128 if (index_operand_ != NULL) { | 127 if (index_operand_ != NULL) { |
| 129 inputs[input_count++] = index_operand_; | 128 inputs[input_count++] = index_operand_; |
| 130 } | 129 } |
| 131 if (displacement_operand_ != NULL) { | 130 if (displacement_operand_ != NULL) { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 if (m.left().Is(0)) { | 378 if (m.left().Is(0)) { |
| 380 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); | 379 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
| 381 } else { | 380 } else { |
| 382 VisitBinop(this, node, kIA32Sub); | 381 VisitBinop(this, node, kIA32Sub); |
| 383 } | 382 } |
| 384 } | 383 } |
| 385 | 384 |
| 386 | 385 |
| 387 void InstructionSelector::VisitInt32Mul(Node* node) { | 386 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 388 IA32OperandGenerator g(this); | 387 IA32OperandGenerator g(this); |
| 389 Int32BinopMatcher m(node); | 388 LeaMultiplyMatcher lea(node); |
| 390 Node* left = m.left().node(); | 389 // Try to match lea. |
| 391 Node* right = m.right().node(); | 390 if (lea.Matches()) { |
| 392 if (g.CanBeImmediate(right)) { | 391 ArchOpcode opcode = kIA32Lea; |
| 393 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), | 392 AddressingMode mode; |
| 394 g.UseImmediate(right)); | 393 size_t input_count; |
| 394 InstructionOperand* left = g.UseRegister(lea.Left()); |
| 395 InstructionOperand* inputs[] = {left, left}; |
| 396 if (lea.Displacement() != 0) { |
| 397 input_count = 2; |
| 398 mode = kMode_MR1; |
| 399 } else { |
| 400 input_count = 1; |
| 401 mode = kMode_M1; |
| 402 } |
| 403 mode = AdjustAddressingMode(mode, lea.Power()); |
| 404 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; |
| 405 Emit(opcode | AddressingModeField::encode(mode), 1, outputs, input_count, |
| 406 inputs); |
| 395 } else { | 407 } else { |
| 396 if (g.CanBeBetterLeftOperand(right)) { | 408 Int32BinopMatcher m(node); |
| 397 std::swap(left, right); | 409 Node* left = m.left().node(); |
| 410 Node* right = m.right().node(); |
| 411 if (g.CanBeImmediate(right)) { |
| 412 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), |
| 413 g.UseImmediate(right)); |
| 414 } else { |
| 415 if (g.CanBeBetterLeftOperand(right)) { |
| 416 std::swap(left, right); |
| 417 } |
| 418 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 419 g.Use(right)); |
| 398 } | 420 } |
| 399 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), | |
| 400 g.Use(right)); | |
| 401 } | 421 } |
| 402 } | 422 } |
| 403 | 423 |
| 404 | 424 |
| 405 static inline void VisitDiv(InstructionSelector* selector, Node* node, | 425 static inline void VisitDiv(InstructionSelector* selector, Node* node, |
| 406 ArchOpcode opcode) { | 426 ArchOpcode opcode) { |
| 407 IA32OperandGenerator g(selector); | 427 IA32OperandGenerator g(selector); |
| 408 InstructionOperand* temps[] = {g.TempRegister(edx)}; | 428 InstructionOperand* temps[] = {g.TempRegister(edx)}; |
| 409 size_t temp_count = arraysize(temps); | 429 size_t temp_count = arraysize(temps); |
| 410 selector->Emit(opcode, g.DefineAsFixed(node, eax), | 430 selector->Emit(opcode, g.DefineAsFixed(node, eax), |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 call_instr->MarkAsCall(); | 678 call_instr->MarkAsCall(); |
| 659 if (deoptimization != NULL) { | 679 if (deoptimization != NULL) { |
| 660 DCHECK(continuation != NULL); | 680 DCHECK(continuation != NULL); |
| 661 call_instr->MarkAsControl(); | 681 call_instr->MarkAsControl(); |
| 662 } | 682 } |
| 663 } | 683 } |
| 664 | 684 |
| 665 } // namespace compiler | 685 } // namespace compiler |
| 666 } // namespace internal | 686 } // namespace internal |
| 667 } // namespace v8 | 687 } // namespace v8 |
| OLD | NEW |