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 843f0883944b4216e56e157835709d64f07b9ac6..ab159a2bbca6b54d635a37e51859cc0bda7f7286 100644 |
--- a/src/compiler/x64/instruction-selector-x64.cc |
+++ b/src/compiler/x64/instruction-selector-x64.cc |
@@ -55,6 +55,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) |
@@ -99,15 +108,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. |
@@ -464,18 +469,48 @@ 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; |
+ size_t input_count; |
+ InstructionOperand* left = g.UseRegister(lea.Left()); |
+ InstructionOperand* inputs[] = {left, left}; |
+ if (lea.Displacement() != 0) { |
+ input_count = 2; |
+ mode = kMode_MR1; |
+ } else { |
+ input_count = 1; |
+ mode = kMode_M1; |
+ } |
+ mode = AdjustAddressingMode(mode, lea.Power()); |
+ InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; |
+ selector->Emit(opcode | AddressingModeField::encode(mode), 1, outputs, |
+ input_count, inputs); |
} 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)); |
} |
} |