Index: src/compiler/x64/instruction-selector-x64.cc |
diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc |
index 82d1e33fa2398c06a89998a7d3b5b7a73b92f49e..04fdb7ef68599389a322a1c14bdc01c69ed9695a 100644 |
--- a/src/compiler/x64/instruction-selector-x64.cc |
+++ b/src/compiler/x64/instruction-selector-x64.cc |
@@ -54,6 +54,15 @@ class X64OperandGenerator FINAL : public OperandGenerator { |
}; |
+// Get the AddressingMode of scale factor N from the AddressingMode of scale |
+// factor 1. |
+static AddressingMode AdjustAddressingMode(AddressingMode base_mode, |
+ int power) { |
+ DCHECK(0 <= power && power < 4); |
+ return static_cast<AddressingMode>(static_cast<int>(base_mode) + power); |
+} |
+ |
+ |
class AddressingModeMatcher { |
public: |
AddressingModeMatcher(X64OperandGenerator* g, Node* base, Node* index) |
@@ -98,15 +107,11 @@ class AddressingModeMatcher { |
} |
} |
// Adjust mode to actual scale factor. |
- mode_ = GetMode(mode_, matcher.power()); |
+ mode_ = AdjustAddressingMode(mode_, matcher.power()); |
} |
DCHECK_NE(kMode_None, mode_); |
} |
- AddressingMode GetMode(AddressingMode one, int power) { |
- return static_cast<AddressingMode>(static_cast<int>(one) + power); |
- } |
- |
size_t SetInputs(InstructionOperand** inputs) { |
size_t input_count = 0; |
// Compute inputs_ and input_count. |
@@ -463,18 +468,42 @@ void InstructionSelector::VisitInt64Sub(Node* node) { |
static void VisitMul(InstructionSelector* selector, Node* node, |
ArchOpcode opcode) { |
X64OperandGenerator g(selector); |
- Int32BinopMatcher m(node); |
- Node* left = m.left().node(); |
- Node* right = m.right().node(); |
- if (g.CanBeImmediate(right)) { |
- selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left), |
- g.UseImmediate(right)); |
+ LeaMultiplyMatcher lea(node); |
+ // Try to match lea. |
+ if (lea.Matches()) { |
+ switch (opcode) { |
+ case kX64Imul32: |
+ opcode = kX64Lea32; |
+ break; |
+ case kX64Imul: |
+ opcode = kX64Lea; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ AddressingMode mode; |
+ if (lea.Displacement() != 0) { |
+ mode = kMode_MX1; |
+ } else { |
+ mode = kMode_M1; |
+ } |
+ mode = AdjustAddressingMode(mode, lea.Power()); |
+ selector->Emit(opcode | AddressingModeField::encode(mode), |
+ g.DefineAsRegister(node), g.UseRegister(lea.Left())); |
} else { |
- if (g.CanBeBetterLeftOperand(right)) { |
- std::swap(left, right); |
+ Int32BinopMatcher m(node); |
+ Node* left = m.left().node(); |
+ Node* right = m.right().node(); |
+ if (g.CanBeImmediate(right)) { |
+ selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left), |
+ g.UseImmediate(right)); |
+ } else { |
+ if (g.CanBeBetterLeftOperand(right)) { |
+ std::swap(left, right); |
+ } |
+ selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
+ g.Use(right)); |
} |
- selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
- g.Use(right)); |
} |
} |