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 a87b3fc3494ed8e24362d309643d2d0125522309..07b28d3fc8f890520b8429771c0731aca1c93dc1 100644 |
--- a/src/compiler/x64/instruction-selector-x64.cc |
+++ b/src/compiler/x64/instruction-selector-x64.cc |
@@ -70,6 +70,7 @@ class X64OperandGenerator final : public OperandGenerator { |
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent, |
Node* base, Node* displacement, |
+ DisplacementMode displacement_mode, |
InstructionOperand inputs[], |
size_t* input_count) { |
AddressingMode mode = kMode_MRI; |
@@ -79,7 +80,9 @@ class X64OperandGenerator final : public OperandGenerator { |
DCHECK(scale_exponent >= 0 && scale_exponent <= 3); |
inputs[(*input_count)++] = UseRegister(index); |
if (displacement != nullptr) { |
- inputs[(*input_count)++] = UseImmediate(displacement); |
+ inputs[(*input_count)++] = displacement_mode |
+ ? UseNegatedImmediate(displacement) |
+ : UseImmediate(displacement); |
static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I, |
kMode_MR4I, kMode_MR8I}; |
mode = kMRnI_modes[scale_exponent]; |
@@ -92,7 +95,9 @@ class X64OperandGenerator final : public OperandGenerator { |
if (displacement == nullptr) { |
mode = kMode_MR; |
} else { |
- inputs[(*input_count)++] = UseImmediate(displacement); |
+ inputs[(*input_count)++] = displacement_mode == kNegativeDisplacement |
+ ? UseNegatedImmediate(displacement) |
+ : UseImmediate(displacement); |
mode = kMode_MRI; |
} |
} |
@@ -101,7 +106,9 @@ class X64OperandGenerator final : public OperandGenerator { |
DCHECK(scale_exponent >= 0 && scale_exponent <= 3); |
inputs[(*input_count)++] = UseRegister(index); |
if (displacement != nullptr) { |
- inputs[(*input_count)++] = UseImmediate(displacement); |
+ inputs[(*input_count)++] = displacement_mode == kNegativeDisplacement |
+ ? UseNegatedImmediate(displacement) |
+ : UseImmediate(displacement); |
static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I, |
kMode_M4I, kMode_M8I}; |
mode = kMnI_modes[scale_exponent]; |
@@ -124,8 +131,9 @@ class X64OperandGenerator final : public OperandGenerator { |
BaseWithIndexAndDisplacement64Matcher m(operand, true); |
DCHECK(m.matches()); |
if ((m.displacement() == nullptr || CanBeImmediate(m.displacement()))) { |
- return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), |
- m.displacement(), inputs, input_count); |
+ return GenerateMemoryOperandInputs( |
+ m.index(), m.scale(), m.base(), m.displacement(), |
+ m.displacement_mode(), inputs, input_count); |
} else { |
inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
@@ -542,16 +550,16 @@ void VisitWord64Shift(InstructionSelector* selector, Node* node, |
} |
} |
- |
void EmitLea(InstructionSelector* selector, InstructionCode opcode, |
Node* result, Node* index, int scale, Node* base, |
- Node* displacement) { |
+ Node* displacement, DisplacementMode displacement_mode) { |
X64OperandGenerator g(selector); |
InstructionOperand inputs[4]; |
size_t input_count = 0; |
- AddressingMode mode = g.GenerateMemoryOperandInputs( |
- index, scale, base, displacement, inputs, &input_count); |
+ AddressingMode mode = |
+ g.GenerateMemoryOperandInputs(index, scale, base, displacement, |
+ displacement_mode, inputs, &input_count); |
DCHECK_NE(0u, input_count); |
DCHECK_GE(arraysize(inputs), input_count); |
@@ -572,7 +580,8 @@ void InstructionSelector::VisitWord32Shl(Node* node) { |
if (m.matches()) { |
Node* index = node->InputAt(0); |
Node* base = m.power_of_two_plus_one() ? index : nullptr; |
- EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr); |
+ EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr, |
+ kPositiveDisplacement); |
return; |
} |
VisitWord32Shift(this, node, kX64Shl32); |
@@ -756,7 +765,7 @@ void InstructionSelector::VisitInt32Add(Node* node) { |
if (m.matches() && |
(m.displacement() == nullptr || g.CanBeImmediate(m.displacement()))) { |
EmitLea(this, kX64Lea32, node, m.index(), m.scale(), m.base(), |
- m.displacement()); |
+ m.displacement(), m.displacement_mode()); |
return; |
} |
@@ -881,7 +890,8 @@ void InstructionSelector::VisitInt32Mul(Node* node) { |
if (m.matches()) { |
Node* index = node->InputAt(0); |
Node* base = m.power_of_two_plus_one() ? index : nullptr; |
- EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr); |
+ EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr, |
+ kPositiveDisplacement); |
return; |
} |
VisitMul(this, node, kX64Imul32); |