| 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 cc0262bdb3278b780f4afdb286087a7a3c549ad1..0432bbd874d9266bd61cd958fc86bc44ecc17b1a 100644
|
| --- a/src/compiler/x64/instruction-selector-x64.cc
|
| +++ b/src/compiler/x64/instruction-selector-x64.cc
|
| @@ -595,15 +595,25 @@ void InstructionSelector::VisitWord32Shl(Node* node) {
|
|
|
| void InstructionSelector::VisitWord64Shl(Node* node) {
|
| X64OperandGenerator g(this);
|
| - Int64BinopMatcher m(node);
|
| - if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) &&
|
| - m.right().IsInRange(32, 63)) {
|
| - // There's no need to sign/zero-extend to 64-bit if we shift out the upper
|
| - // 32 bits anyway.
|
| - Emit(kX64Shl, g.DefineSameAsFirst(node),
|
| - g.UseRegister(m.left().node()->InputAt(0)),
|
| - g.UseImmediate(m.right().node()));
|
| + Int64ScaleMatcher m(node, true);
|
| + if (m.matches()) {
|
| + Node* index = node->InputAt(0);
|
| + Node* base = m.power_of_two_plus_one() ? index : nullptr;
|
| + EmitLea(this, kX64Lea, node, index, m.scale(), base, nullptr,
|
| + kPositiveDisplacement);
|
| return;
|
| + } else {
|
| + Int64BinopMatcher m(node);
|
| + if ((m.left().IsChangeInt32ToInt64() ||
|
| + m.left().IsChangeUint32ToUint64()) &&
|
| + m.right().IsInRange(32, 63)) {
|
| + // There's no need to sign/zero-extend to 64-bit if we shift out the upper
|
| + // 32 bits anyway.
|
| + Emit(kX64Shl, g.DefineSameAsFirst(node),
|
| + g.UseRegister(m.left().node()->InputAt(0)),
|
| + g.UseImmediate(m.right().node()));
|
| + return;
|
| + }
|
| }
|
| VisitWord64Shift(this, node, kX64Shl);
|
| }
|
| @@ -780,6 +790,18 @@ void InstructionSelector::VisitInt32Add(Node* node) {
|
|
|
|
|
| void InstructionSelector::VisitInt64Add(Node* node) {
|
| + X64OperandGenerator g(this);
|
| +
|
| + // Try to match the Add to a leaq pattern
|
| + BaseWithIndexAndDisplacement64Matcher m(node);
|
| + if (m.matches() &&
|
| + (m.displacement() == nullptr || g.CanBeImmediate(m.displacement()))) {
|
| + EmitLea(this, kX64Lea, node, m.index(), m.scale(), m.base(),
|
| + m.displacement(), m.displacement_mode());
|
| + return;
|
| + }
|
| +
|
| + // No leal pattern match, use addq
|
| VisitBinop(this, node, kX64Add);
|
| }
|
|
|
| @@ -819,6 +841,14 @@ void InstructionSelector::VisitInt64Sub(Node* node) {
|
| if (m.left().Is(0)) {
|
| Emit(kX64Neg, g.DefineSameAsFirst(node), g.UseRegister(m.right().node()));
|
| } else {
|
| + if (m.right().HasValue() && g.CanBeImmediate(m.right().node())) {
|
| + // Turn subtractions of constant values into immediate "leaq" instructions
|
| + // by negating the value.
|
| + Emit(kX64Lea | AddressingModeField::encode(kMode_MRI),
|
| + g.DefineAsRegister(node), g.UseRegister(m.left().node()),
|
| + g.TempImmediate(-static_cast<int32_t>(m.right().Value())));
|
| + return;
|
| + }
|
| VisitBinop(this, node, kX64Sub);
|
| }
|
| }
|
|
|