| Index: src/compiler/ia32/instruction-selector-ia32.cc
|
| diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc
|
| index d72f0dc1e36c4cbeed63b421108e354d4a6c903a..70bee35a2f4d3a7e4d3d34176403b500128fc644 100644
|
| --- a/src/compiler/ia32/instruction-selector-ia32.cc
|
| +++ b/src/compiler/ia32/instruction-selector-ia32.cc
|
| @@ -44,10 +44,108 @@ class IA32OperandGenerator FINAL : public OperandGenerator {
|
| };
|
|
|
|
|
| +class AddressingModeMatcher {
|
| + public:
|
| + AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index)
|
| + : base_operand_(NULL),
|
| + index_operand_(NULL),
|
| + displacement_operand_(NULL),
|
| + mode_(kMode_None) {
|
| + Int32Matcher index_imm(index);
|
| + if (index_imm.HasValue()) {
|
| + int32_t displacement = index_imm.Value();
|
| + // Compute base operand and fold base immediate into displacement.
|
| + Int32Matcher base_imm(base);
|
| + if (!base_imm.HasValue()) {
|
| + base_operand_ = g->UseRegister(base);
|
| + } else {
|
| + displacement += base_imm.Value();
|
| + }
|
| + if (displacement != 0 || base_operand_ == NULL) {
|
| + displacement_operand_ = g->TempImmediate(displacement);
|
| + }
|
| + if (base_operand_ == NULL) {
|
| + mode_ = kMode_MI;
|
| + } else {
|
| + if (displacement == 0) {
|
| + mode_ = kMode_MR;
|
| + } else {
|
| + mode_ = kMode_MRI;
|
| + }
|
| + }
|
| + } else {
|
| + // Compute index and displacement.
|
| + IndexAndDisplacementMatcher matcher(index);
|
| + index_operand_ = g->UseRegister(matcher.index_node());
|
| + int32_t displacement = matcher.displacement();
|
| + // Compute base operand and fold base immediate into displacement.
|
| + Int32Matcher base_imm(base);
|
| + if (!base_imm.HasValue()) {
|
| + base_operand_ = g->UseRegister(base);
|
| + } else {
|
| + displacement += base_imm.Value();
|
| + }
|
| + // Compute displacement operand.
|
| + if (displacement != 0) {
|
| + displacement_operand_ = g->TempImmediate(displacement);
|
| + }
|
| + // Compute mode with scale factor one.
|
| + if (base_operand_ == NULL) {
|
| + if (displacement_operand_ == NULL) {
|
| + mode_ = kMode_M1;
|
| + } else {
|
| + mode_ = kMode_M1I;
|
| + }
|
| + } else {
|
| + if (displacement_operand_ == NULL) {
|
| + mode_ = kMode_MR1;
|
| + } else {
|
| + mode_ = kMode_MR1I;
|
| + }
|
| + }
|
| + // Adjust mode to actual scale factor.
|
| + mode_ = GetMode(mode_, matcher.power());
|
| + // Don't emit instructions with scale factor 1 if there's no base.
|
| + if (mode_ == kMode_M1) {
|
| + mode_ = kMode_MR;
|
| + } else if (mode_ == kMode_M1I) {
|
| + mode_ = kMode_MRI;
|
| + }
|
| + }
|
| + 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.
|
| + if (base_operand_ != NULL) {
|
| + inputs[input_count++] = base_operand_;
|
| + }
|
| + if (index_operand_ != NULL) {
|
| + inputs[input_count++] = index_operand_;
|
| + }
|
| + if (displacement_operand_ != NULL) {
|
| + inputs[input_count++] = displacement_operand_;
|
| + }
|
| + DCHECK_NE(input_count, 0);
|
| + return input_count;
|
| + }
|
| +
|
| + static const int kMaxInputCount = 3;
|
| + InstructionOperand* base_operand_;
|
| + InstructionOperand* index_operand_;
|
| + InstructionOperand* displacement_operand_;
|
| + AddressingMode mode_;
|
| +};
|
| +
|
| +
|
| void InstructionSelector::VisitLoad(Node* node) {
|
| MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
|
| MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
|
| - IA32OperandGenerator g(this);
|
| Node* base = node->InputAt(0);
|
| Node* index = node->InputAt(1);
|
|
|
| @@ -75,23 +173,14 @@ void InstructionSelector::VisitLoad(Node* node) {
|
| UNREACHABLE();
|
| return;
|
| }
|
| - if (g.CanBeImmediate(base)) {
|
| - if (Int32Matcher(index).Is(0)) { // load [#base + #0]
|
| - Emit(opcode | AddressingModeField::encode(kMode_MI),
|
| - g.DefineAsRegister(node), g.UseImmediate(base));
|
| - } else { // load [#base + %index]
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRI),
|
| - g.DefineAsRegister(node), g.UseRegister(index),
|
| - g.UseImmediate(base));
|
| - }
|
| - } else if (g.CanBeImmediate(index)) { // load [%base + #index]
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRI),
|
| - g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
|
| - } else { // load [%base + %index + K]
|
| - Emit(opcode | AddressingModeField::encode(kMode_MR1I),
|
| - g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
|
| - }
|
| - // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
|
| +
|
| + IA32OperandGenerator g(this);
|
| + AddressingModeMatcher matcher(&g, base, index);
|
| + InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
|
| + InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
|
| + InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount];
|
| + size_t input_count = matcher.SetInputs(inputs);
|
| + Emit(code, 1, outputs, input_count, inputs);
|
| }
|
|
|
|
|
| @@ -115,14 +204,7 @@ void InstructionSelector::VisitStore(Node* node) {
|
| return;
|
| }
|
| DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
|
| - InstructionOperand* val;
|
| - if (g.CanBeImmediate(value)) {
|
| - val = g.UseImmediate(value);
|
| - } else if (rep == kRepWord8 || rep == kRepBit) {
|
| - val = g.UseByteRegister(value);
|
| - } else {
|
| - val = g.UseRegister(value);
|
| - }
|
| +
|
| ArchOpcode opcode;
|
| switch (rep) {
|
| case kRepFloat32:
|
| @@ -146,22 +228,22 @@ void InstructionSelector::VisitStore(Node* node) {
|
| UNREACHABLE();
|
| return;
|
| }
|
| - if (g.CanBeImmediate(base)) {
|
| - if (Int32Matcher(index).Is(0)) { // store [#base], %|#value
|
| - Emit(opcode | AddressingModeField::encode(kMode_MI), NULL,
|
| - g.UseImmediate(base), val);
|
| - } else { // store [#base + %index], %|#value
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
|
| - g.UseRegister(index), g.UseImmediate(base), val);
|
| - }
|
| - } else if (g.CanBeImmediate(index)) { // store [%base + #index], %|#value
|
| - Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
|
| - g.UseRegister(base), g.UseImmediate(index), val);
|
| - } else { // store [%base + %index], %|#value
|
| - Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
|
| - g.UseRegister(base), g.UseRegister(index), val);
|
| +
|
| + InstructionOperand* val;
|
| + if (g.CanBeImmediate(value)) {
|
| + val = g.UseImmediate(value);
|
| + } else if (rep == kRepWord8 || rep == kRepBit) {
|
| + val = g.UseByteRegister(value);
|
| + } else {
|
| + val = g.UseRegister(value);
|
| }
|
| - // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
|
| +
|
| + AddressingModeMatcher matcher(&g, base, index);
|
| + InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
|
| + InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1];
|
| + size_t input_count = matcher.SetInputs(inputs);
|
| + inputs[input_count++] = val;
|
| + Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
|
| }
|
|
|
|
|
|
|