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 c70944bc86d085509da1b3cdb44305f4043212df..d230cfbad35016a355dcf27c0c69aca350762055 100644 |
--- a/src/compiler/x64/instruction-selector-x64.cc |
+++ b/src/compiler/x64/instruction-selector-x64.cc |
@@ -364,8 +364,99 @@ void InstructionSelector::VisitWord64Ror(Node* node) { |
VisitWord64Shift(this, node, kX64Ror); |
} |
+namespace { |
+ |
+static AddressingMode ScaleFactorToAddressingMode( |
titzer
2014/11/06 11:47:06
If you use the scale power of 2, then you can just
danno
2014/11/06 23:34:07
Done.
|
+ int scale_factor, const AddressingMode modes[]) { |
+ switch (scale_factor) { |
+ case 1: |
+ return modes[0]; |
+ break; |
+ case 2: |
+ return modes[1]; |
+ break; |
+ case 4: |
+ return modes[2]; |
+ break; |
+ case 8: |
+ return modes[3]; |
+ break; |
+ default: |
+ break; |
+ } |
+ UNREACHABLE(); |
+ return modes[0]; |
+} |
+ |
+AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled, |
+ int scale_factor, Node* offset, |
+ Node* constant, |
+ InstructionOperand* inputs[], |
+ size_t* input_count) { |
+ AddressingMode mode = kMode_MRI; |
+ if (offset != NULL) { |
+ inputs[(*input_count)++] = g->UseRegister(offset); |
+ if (scaled != NULL) { |
+ inputs[(*input_count)++] = g->UseRegister(scaled); |
+ if (constant != NULL) { |
+ inputs[(*input_count)++] = g->UseImmediate(constant); |
+ static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I, |
+ kMode_MR4I, kMode_MR8I}; |
+ mode = ScaleFactorToAddressingMode(scale_factor, kMRnI_modes); |
+ } else { |
+ static const AddressingMode kMRn_modes[] = {kMode_MR1, kMode_MR2, |
+ kMode_MR4, kMode_MR8}; |
+ mode = ScaleFactorToAddressingMode(scale_factor, kMRn_modes); |
+ } |
+ } else { |
+ DCHECK(constant != NULL); |
+ inputs[(*input_count)++] = g->UseImmediate(constant); |
+ mode = kMode_MRI; |
+ } |
+ } else { |
+ DCHECK(scaled != NULL); |
+ inputs[(*input_count)++] = g->UseRegister(scaled); |
+ if (constant != NULL) { |
+ inputs[(*input_count)++] = g->UseImmediate(constant); |
+ static const AddressingMode kMnI_modes[] = {kMode_M1I, kMode_M2I, |
+ kMode_M4I, kMode_M8I}; |
+ mode = ScaleFactorToAddressingMode(scale_factor, kMnI_modes); |
+ } else { |
+ static const AddressingMode kMn_modes[] = {kMode_M1, kMode_M2, kMode_M4, |
+ kMode_M8}; |
+ mode = ScaleFactorToAddressingMode(scale_factor, kMn_modes); |
+ } |
+ } |
+ return mode; |
+} |
+ |
+} // namespace |
+ |
void InstructionSelector::VisitInt32Add(Node* node) { |
+ // Try to match the Add to a leal pattern |
+ ScaledWithOffsetMatcher m(node); |
+ X64OperandGenerator g(this); |
+ if (m.Matches() && (m.Constant() == NULL || g.CanBeImmediate(m.Constant()))) { |
+ InstructionOperand* inputs[4]; |
+ size_t input_count = 0; |
+ |
+ AddressingMode mode = |
+ GenerateMemoryOperandInputs(&g, m.Scaled(), m.ScaleFactor(), m.Offset(), |
+ m.Constant(), inputs, &input_count); |
+ |
+ DCHECK_NE(0, static_cast<int>(input_count)); |
+ DCHECK_GE(arraysize(inputs), input_count); |
+ |
+ InstructionOperand* outputs[1]; |
+ outputs[0] = g.DefineAsRegister(node); |
+ |
+ InstructionCode opcode = AddressingModeField::encode(mode) | kX64Lea32; |
+ |
+ Emit(opcode, 1, outputs, input_count, inputs); |
+ return; |
+ } |
+ |
VisitBinop(this, node, kX64Add32); |
} |