[turbofan] add new ia32 addressing modes
authordcarney@chromium.org <dcarney@chromium.org>
Mon, 29 Sep 2014 10:15:55 +0000 (10:15 +0000)
committerdcarney@chromium.org <dcarney@chromium.org>
Mon, 29 Sep 2014 10:15:55 +0000 (10:15 +0000)
R=bmeurer@chromium.org

BUG=

Review URL: https://codereview.chromium.org/613643002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24277 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/compiler/ia32/code-generator-ia32.cc
src/compiler/ia32/instruction-codes-ia32.h
src/compiler/ia32/instruction-selector-ia32-unittest.cc
src/compiler/ia32/instruction-selector-ia32.cc
src/compiler/node-matchers.h
src/compiler/x64/instruction-selector-x64.cc

index 97b3706..d9f8833 100644 (file)
@@ -76,25 +76,83 @@ class IA32OperandConverter : public InstructionOperandConverter {
     return Immediate(-1);
   }
 
-  Operand MemoryOperand(int* first_input) {
-    const int offset = *first_input;
-    switch (AddressingModeField::decode(instr_->opcode())) {
+  static int NextOffset(int* offset) {
+    int i = *offset;
+    (*offset)++;
+    return i;
+  }
+
+  static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) {
+    STATIC_ASSERT(0 == static_cast<int>(times_1));
+    STATIC_ASSERT(1 == static_cast<int>(times_2));
+    STATIC_ASSERT(2 == static_cast<int>(times_4));
+    STATIC_ASSERT(3 == static_cast<int>(times_8));
+    int scale = static_cast<int>(mode - one);
+    DCHECK(scale >= 0 && scale < 4);
+    return static_cast<ScaleFactor>(scale);
+  }
+
+  Operand MemoryOperand(int* offset) {
+    AddressingMode mode = AddressingModeField::decode(instr_->opcode());
+    switch (mode) {
+      case kMode_MR: {
+        Register base = InputRegister(NextOffset(offset));
+        int32_t disp = 0;
+        return Operand(base, disp);
+      }
+      case kMode_MRI: {
+        Register base = InputRegister(NextOffset(offset));
+        int32_t disp = InputInt32(NextOffset(offset));
+        return Operand(base, disp);
+      }
+      case kMode_MR1:
+      case kMode_MR2:
+      case kMode_MR4:
+      case kMode_MR8: {
+        Register base = InputRegister(NextOffset(offset));
+        Register index = InputRegister(NextOffset(offset));
+        ScaleFactor scale = ScaleFor(kMode_MR1, mode);
+        int32_t disp = 0;
+        return Operand(base, index, scale, disp);
+      }
       case kMode_MR1I:
-        *first_input += 2;
-        return Operand(InputRegister(offset + 0), InputRegister(offset + 1),
-                       times_1,
-                       0);  // TODO(dcarney): K != 0
-      case kMode_MRI:
-        *first_input += 2;
-        return Operand::ForRegisterPlusImmediate(InputRegister(offset + 0),
-                                                 InputImmediate(offset + 1));
-      case kMode_MI:
-        *first_input += 1;
-        return Operand(InputImmediate(offset + 0));
-      default:
+      case kMode_MR2I:
+      case kMode_MR4I:
+      case kMode_MR8I: {
+        Register base = InputRegister(NextOffset(offset));
+        Register index = InputRegister(NextOffset(offset));
+        ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
+        int32_t disp = InputInt32(NextOffset(offset));
+        return Operand(base, index, scale, disp);
+      }
+      case kMode_M1:
+      case kMode_M2:
+      case kMode_M4:
+      case kMode_M8: {
+        Register index = InputRegister(NextOffset(offset));
+        ScaleFactor scale = ScaleFor(kMode_M1, mode);
+        int32_t disp = 0;
+        return Operand(index, scale, disp);
+      }
+      case kMode_M1I:
+      case kMode_M2I:
+      case kMode_M4I:
+      case kMode_M8I: {
+        Register index = InputRegister(NextOffset(offset));
+        ScaleFactor scale = ScaleFor(kMode_M1I, mode);
+        int32_t disp = InputInt32(NextOffset(offset));
+        return Operand(index, scale, disp);
+      }
+      case kMode_MI: {
+        int32_t disp = InputInt32(NextOffset(offset));
+        return Operand(Immediate(disp));
+      }
+      case kMode_None:
         UNREACHABLE();
-        return Operand(no_reg);
+        return Operand(no_reg, 0);
     }
+    UNREACHABLE();
+    return Operand(no_reg, 0);
   }
 
   Operand MemoryOperand() {
index 3b11000..268a59d 100644 (file)
@@ -61,23 +61,31 @@ namespace compiler {
 //
 // We use the following local notation for addressing modes:
 //
-// R = register
-// O = register or stack slot
-// D = double register
-// I = immediate (handle, external, int32)
-// MR = [register]
-// MI = [immediate]
-// MRN = [register + register * N in {1, 2, 4, 8}]
-// MRI = [register + immediate]
-// MRNI = [register + register * N in {1, 2, 4, 8} + immediate]
+// M = memory operand
+// R = base register
+// N = index register * N for N in {1, 2, 4, 8}
+// I = immediate displacement (int32_t)
+
 #define TARGET_ADDRESSING_MODE_LIST(V) \
-  V(MI)   /* [K] */                    \
-  V(MR)   /* [%r0] */                  \
-  V(MRI)  /* [%r0 + K] */              \
-  V(MR1I) /* [%r0 + %r1 * 1 + K] */    \
-  V(MR2I) /* [%r0 + %r1 * 2 + K] */    \
-  V(MR4I) /* [%r0 + %r1 * 4 + K] */    \
-  V(MR8I) /* [%r0 + %r1 * 8 + K] */
+  V(MR)   /* [%r1            ] */      \
+  V(MRI)  /* [%r1         + K] */      \
+  V(MR1)  /* [%r1 + %r2*1    ] */      \
+  V(MR2)  /* [%r1 + %r2*2    ] */      \
+  V(MR4)  /* [%r1 + %r2*4    ] */      \
+  V(MR8)  /* [%r1 + %r2*8    ] */      \
+  V(MR1I) /* [%r1 + %r2*1 + K] */      \
+  V(MR2I) /* [%r1 + %r2*2 + K] */      \
+  V(MR4I) /* [%r1 + %r2*3 + K] */      \
+  V(MR8I) /* [%r1 + %r2*4 + K] */      \
+  V(M1)   /* [      %r2*1    ] */      \
+  V(M2)   /* [      %r2*2    ] */      \
+  V(M4)   /* [      %r2*4    ] */      \
+  V(M8)   /* [      %r2*8    ] */      \
+  V(M1I)  /* [      %r2*1 + K] */      \
+  V(M2I)  /* [      %r2*2 + K] */      \
+  V(M4I)  /* [      %r2*4 + K] */      \
+  V(M8I)  /* [      %r2*8 + K] */      \
+  V(MI)   /* [              K] */
 
 }  // namespace compiler
 }  // namespace internal
index 50e1358..89d150f 100644 (file)
@@ -189,9 +189,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) {
     Stream s = m.Build();
     ASSERT_EQ(1U, s.size());
     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
+    if (base == 0) {
+      ASSERT_EQ(1U, s[0]->InputCount());
+    } else {
     ASSERT_EQ(2U, s[0]->InputCount());
     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
     EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1)));
+    }
     EXPECT_EQ(1U, s[0]->OutputCount());
   }
 }
@@ -205,9 +209,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
     Stream s = m.Build();
     ASSERT_EQ(1U, s.size());
     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
+    if (index == 0) {
+      ASSERT_EQ(1U, s[0]->InputCount());
+    } else {
     ASSERT_EQ(2U, s[0]->InputCount());
     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
+    }
     EXPECT_EQ(1U, s[0]->OutputCount());
   }
 }
@@ -235,9 +243,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) {
     Stream s = m.Build();
     ASSERT_EQ(1U, s.size());
     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
+    if (base == 0) {
+      ASSERT_EQ(2U, s[0]->InputCount());
+    } else {
     ASSERT_EQ(3U, s[0]->InputCount());
     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
     EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1)));
+    }
     EXPECT_EQ(0U, s[0]->OutputCount());
   }
 }
@@ -253,9 +265,13 @@ TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
     Stream s = m.Build();
     ASSERT_EQ(1U, s.size());
     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
-    ASSERT_EQ(3U, s[0]->InputCount());
-    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
-    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
+    if (index == 0) {
+      ASSERT_EQ(2U, s[0]->InputCount());
+    } else {
+      ASSERT_EQ(3U, s[0]->InputCount());
+      ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+      EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
+    }
     EXPECT_EQ(0U, s[0]->OutputCount());
   }
 }
@@ -265,6 +281,149 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
                         InstructionSelectorMemoryAccessTest,
                         ::testing::ValuesIn(kMemoryAccesses));
 
+
+// -----------------------------------------------------------------------------
+// AddressingMode for loads and stores.
+
+class AddressingModeUnitTest : public InstructionSelectorTest {
+ public:
+  AddressingModeUnitTest() : m(NULL) { Reset(); }
+  ~AddressingModeUnitTest() { delete m; }
+
+  void Run(Node* base, Node* index, AddressingMode mode) {
+    Node* load = m->Load(kMachInt32, base, index);
+    m->Store(kMachInt32, base, index, load);
+    m->Return(m->Int32Constant(0));
+    Stream s = m->Build();
+    ASSERT_EQ(2U, s.size());
+    EXPECT_EQ(mode, s[0]->addressing_mode());
+    EXPECT_EQ(mode, s[1]->addressing_mode());
+  }
+
+  Node* zero;
+  Node* null_ptr;
+  Node* non_zero;
+  Node* base_reg;   // opaque value to generate base as register
+  Node* index_reg;  // opaque value to generate index as register
+  Node* scales[4];
+  StreamBuilder* m;
+
+  void Reset() {
+    delete m;
+    m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32);
+    zero = m->Int32Constant(0);
+    null_ptr = m->Int32Constant(0);
+    non_zero = m->Int32Constant(127);
+    base_reg = m->Parameter(0);
+    index_reg = m->Parameter(0);
+
+    scales[0] = m->Int32Constant(1);
+    scales[1] = m->Int32Constant(2);
+    scales[2] = m->Int32Constant(4);
+    scales[3] = m->Int32Constant(8);
+  }
+};
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MR) {
+  Node* base = base_reg;
+  Node* index = zero;
+  Run(base, index, kMode_MR);
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MRI) {
+  Node* base = base_reg;
+  Node* index = non_zero;
+  Run(base, index, kMode_MRI);
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MR1) {
+  Node* base = base_reg;
+  Node* index = index_reg;
+  Run(base, index, kMode_MR1);
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MRN) {
+  AddressingMode expected[] = {kMode_MR1, kMode_MR2, kMode_MR4, kMode_MR8};
+  for (size_t i = 0; i < arraysize(scales); ++i) {
+    Reset();
+    Node* base = base_reg;
+    Node* index = m->Int32Mul(index_reg, scales[i]);
+    Run(base, index, expected[i]);
+  }
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MR1I) {
+  Node* base = base_reg;
+  Node* index = m->Int32Add(index_reg, non_zero);
+  Run(base, index, kMode_MR1I);
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) {
+  AddressingMode expected[] = {kMode_MR1I, kMode_MR2I, kMode_MR4I, kMode_MR8I};
+  for (size_t i = 0; i < arraysize(scales); ++i) {
+    Reset();
+    Node* base = base_reg;
+    Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
+    Run(base, index, expected[i]);
+  }
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_M1) {
+  Node* base = null_ptr;
+  Node* index = index_reg;
+  Run(base, index, kMode_MR);
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MN) {
+  AddressingMode expected[] = {kMode_MR, kMode_M2, kMode_M4, kMode_M8};
+  for (size_t i = 0; i < arraysize(scales); ++i) {
+    Reset();
+    Node* base = null_ptr;
+    Node* index = m->Int32Mul(index_reg, scales[i]);
+    Run(base, index, expected[i]);
+  }
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_M1I) {
+  Node* base = null_ptr;
+  Node* index = m->Int32Add(index_reg, non_zero);
+  Run(base, index, kMode_MRI);
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MNI) {
+  AddressingMode expected[] = {kMode_MRI, kMode_M2I, kMode_M4I, kMode_M8I};
+  for (size_t i = 0; i < arraysize(scales); ++i) {
+    Reset();
+    Node* base = null_ptr;
+    Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
+    Run(base, index, expected[i]);
+  }
+}
+
+
+TEST_F(AddressingModeUnitTest, AddressingMode_MI) {
+  Node* bases[] = {null_ptr, non_zero};
+  Node* indices[] = {zero, non_zero};
+  for (size_t i = 0; i < arraysize(bases); ++i) {
+    for (size_t j = 0; j < arraysize(indices); ++j) {
+      Reset();
+      Node* base = bases[i];
+      Node* index = indices[j];
+      Run(base, index, kMode_MI);
+    }
+  }
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
index d72f0dc..70bee35 100644 (file)
@@ -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);
 }
 
 
index e62eaee..6019cba 100644 (file)
@@ -139,6 +139,96 @@ typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher;
 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher;
 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
 
+
+// Fairly intel-specify node matcher used for matching scale factors in
+// addressing modes.
+// Matches nodes of form [x * N] for N in {1,2,4,8}
+class ScaleFactorMatcher : public NodeMatcher {
+ public:
+  explicit ScaleFactorMatcher(Node* node)
+      : NodeMatcher(node), left_(NULL), power_(0) {
+    Match();
+  }
+
+  bool Matches() { return left_ != NULL; }
+  int Power() {
+    DCHECK(Matches());
+    return power_;
+  }
+  Node* Left() {
+    DCHECK(Matches());
+    return left_;
+  }
+
+ private:
+  void Match() {
+    if (opcode() != IrOpcode::kInt32Mul) return;
+    Int32BinopMatcher m(node());
+    if (!m.right().HasValue()) return;
+    int32_t value = m.right().Value();
+    switch (value) {
+      case 8:
+        power_++;  // Fall through.
+      case 4:
+        power_++;  // Fall through.
+      case 2:
+        power_++;  // Fall through.
+      case 1:
+        break;
+      default:
+        return;
+    }
+    left_ = m.left().node();
+  }
+
+  Node* left_;
+  int power_;
+};
+
+
+// Fairly intel-specify node matcher used for matching index and displacement
+// operands in addressing modes.
+// Matches nodes of form:
+//  [x * N]
+//  [x * N + K]
+//  [x + K]
+//  [x] -- fallback case
+// for N in {1,2,4,8} and K int32_t
+class IndexAndDisplacementMatcher : public NodeMatcher {
+ public:
+  explicit IndexAndDisplacementMatcher(Node* node)
+      : NodeMatcher(node), index_node_(node), displacement_(0), power_(0) {
+    Match();
+  }
+
+  Node* index_node() { return index_node_; }
+  int displacement() { return displacement_; }
+  int power() { return power_; }
+
+ private:
+  void Match() {
+    if (opcode() == IrOpcode::kInt32Add) {
+      // Assume reduction has put constant on the right.
+      Int32BinopMatcher m(node());
+      if (m.right().HasValue()) {
+        displacement_ = m.right().Value();
+        index_node_ = m.left().node();
+      }
+    }
+    // Test scale factor.
+    ScaleFactorMatcher scale_matcher(index_node_);
+    if (scale_matcher.Matches()) {
+      index_node_ = scale_matcher.Left();
+      power_ = scale_matcher.Power();
+    }
+  }
+
+  Node* index_node_;
+  int displacement_;
+  int power_;
+};
+
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
index bcfd209..82d1e33 100644 (file)
@@ -54,91 +54,6 @@ class X64OperandGenerator FINAL : public OperandGenerator {
 };
 
 
-// Matches nodes of form [x * N] for N in {1,2,4,8}
-class ScaleFactorMatcher : public NodeMatcher {
- public:
-  explicit ScaleFactorMatcher(Node* node)
-      : NodeMatcher(node), left_(NULL), power_(0) {
-    Match();
-  }
-
-  bool Matches() { return left_ != NULL; }
-  int Power() {
-    DCHECK(Matches());
-    return power_;
-  }
-  Node* Left() {
-    DCHECK(Matches());
-    return left_;
-  }
-
- private:
-  void Match() {
-    if (opcode() != IrOpcode::kInt32Mul) return;
-    Int32BinopMatcher m(node());
-    if (!m.right().HasValue()) return;
-    int32_t value = m.right().Value();
-    switch (value) {
-      case 8:
-        power_++;  // Fall through.
-      case 4:
-        power_++;  // Fall through.
-      case 2:
-        power_++;  // Fall through.
-      case 1:
-        break;
-      default:
-        return;
-    }
-    left_ = m.left().node();
-  }
-
-  Node* left_;
-  int power_;
-};
-
-
-// Matches nodes of form:
-//  [x * N]
-//  [x * N + K]
-//  [x + K]
-//  [x] -- fallback case
-// for N in {1,2,4,8} and K int32_t
-class IndexAndDisplacementMatcher : public NodeMatcher {
- public:
-  explicit IndexAndDisplacementMatcher(Node* node)
-      : NodeMatcher(node), index_node_(node), displacement_(0), power_(0) {
-    Match();
-  }
-
-  Node* index_node() { return index_node_; }
-  int displacement() { return displacement_; }
-  int power() { return power_; }
-
- private:
-  void Match() {
-    if (opcode() == IrOpcode::kInt32Add) {
-      // Assume reduction has put constant on the right.
-      Int32BinopMatcher m(node());
-      if (m.right().HasValue()) {
-        displacement_ = m.right().Value();
-        index_node_ = m.left().node();
-      }
-    }
-    // Test scale factor.
-    ScaleFactorMatcher scale_matcher(index_node_);
-    if (scale_matcher.Matches()) {
-      index_node_ = scale_matcher.Left();
-      power_ = scale_matcher.Power();
-    }
-  }
-
-  Node* index_node_;
-  int displacement_;
-  int power_;
-};
-
-
 class AddressingModeMatcher {
  public:
   AddressingModeMatcher(X64OperandGenerator* g, Node* base, Node* index)