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 |