[turbofan] ia32 lea multiplication matching
authordcarney@chromium.org <dcarney@chromium.org>
Tue, 30 Sep 2014 11:22:14 +0000 (11:22 +0000)
committerdcarney@chromium.org <dcarney@chromium.org>
Tue, 30 Sep 2014 11:22:14 +0000 (11:22 +0000)
R=bmeurer@chromium.org

BUG=

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24326 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

index a99beed..4bb7500 100644 (file)
@@ -435,6 +435,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         __ movss(operand, i.InputDoubleRegister(index));
       }
       break;
+    case kIA32Lea:
+      __ lea(i.OutputRegister(), i.MemoryOperand());
+      break;
     case kIA32Push:
       if (HasImmediateInput(instr, 0)) {
         __ push(i.InputImmediate(0));
index 268a59d..91844c4 100644 (file)
@@ -50,6 +50,7 @@ namespace compiler {
   V(IA32Movl)                      \
   V(IA32Movss)                     \
   V(IA32Movsd)                     \
+  V(IA32Lea)                       \
   V(IA32Push)                      \
   V(IA32StoreWriteBarrier)
 
index 1aab75c..9e50276 100644 (file)
@@ -388,12 +388,12 @@ TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) {
 TEST_F(AddressingModeUnitTest, AddressingMode_M1) {
   Node* base = null_ptr;
   Node* index = index_reg;
-  Run(base, index, kMode_MR);
+  Run(base, index, kMode_M1);
 }
 
 
 TEST_F(AddressingModeUnitTest, AddressingMode_MN) {
-  AddressingMode expected[] = {kMode_MR, kMode_M2, kMode_M4, kMode_M8};
+  AddressingMode expected[] = {kMode_M1, kMode_M2, kMode_M4, kMode_M8};
   for (size_t i = 0; i < arraysize(scales); ++i) {
     Reset();
     Node* base = null_ptr;
@@ -406,12 +406,12 @@ TEST_F(AddressingModeUnitTest, AddressingMode_MN) {
 TEST_F(AddressingModeUnitTest, AddressingMode_M1I) {
   Node* base = null_ptr;
   Node* index = m->Int32Add(index_reg, non_zero);
-  Run(base, index, kMode_MRI);
+  Run(base, index, kMode_M1I);
 }
 
 
 TEST_F(AddressingModeUnitTest, AddressingMode_MNI) {
-  AddressingMode expected[] = {kMode_MRI, kMode_M2I, kMode_M4I, kMode_M8I};
+  AddressingMode expected[] = {kMode_M1I, kMode_M2I, kMode_M4I, kMode_M8I};
   for (size_t i = 0; i < arraysize(scales); ++i) {
     Reset();
     Node* base = null_ptr;
@@ -434,6 +434,82 @@ TEST_F(AddressingModeUnitTest, AddressingMode_MI) {
   }
 }
 
+
+// -----------------------------------------------------------------------------
+// Multiplication.
+
+namespace {
+
+struct MultParam {
+  int value;
+  bool lea_expected;
+  AddressingMode addressing_mode;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const MultParam& m) {
+  return os << m.value << "." << m.lea_expected << "." << m.addressing_mode;
+}
+
+
+const MultParam kMultParams[] = {{-1, false, kMode_None},
+                                 {0, false, kMode_None},
+                                 {1, true, kMode_M1},
+                                 {2, true, kMode_M2},
+                                 {3, true, kMode_MR2},
+                                 {4, true, kMode_M4},
+                                 {5, true, kMode_MR4},
+                                 {6, false, kMode_None},
+                                 {7, false, kMode_None},
+                                 {8, true, kMode_M8},
+                                 {9, true, kMode_MR8},
+                                 {10, false, kMode_None},
+                                 {11, false, kMode_None}};
+
+}  // namespace
+
+
+typedef InstructionSelectorTestWithParam<MultParam> InstructionSelectorMultTest;
+
+
+static unsigned InputCountForLea(AddressingMode mode) {
+  switch (mode) {
+    case kMode_MR1:
+    case kMode_MR2:
+    case kMode_MR4:
+    case kMode_MR8:
+      return 2U;
+    case kMode_M1:
+    case kMode_M2:
+    case kMode_M4:
+    case kMode_M8:
+      return 1U;
+    default:
+      UNREACHABLE();
+      return 0U;
+  }
+}
+
+
+TEST_P(InstructionSelectorMultTest, Mult32) {
+  const MultParam m_param = GetParam();
+  StreamBuilder m(this, kMachInt32, kMachInt32);
+  Node* param = m.Parameter(0);
+  Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value));
+  m.Return(mult);
+  Stream s = m.Build();
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode());
+  if (m_param.lea_expected) {
+    EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
+    ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount());
+  } else {
+    EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
+    ASSERT_EQ(2U, s[0]->InputCount());
+  }
+  EXPECT_EQ(param->id(), s.ToVreg(s[0]->InputAt(0)));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
index 0f5c7b2..b252e71 100644 (file)
@@ -44,6 +44,15 @@ class IA32OperandGenerator FINAL : public OperandGenerator {
 };
 
 
+// Get the AddressingMode of scale factor N from the AddressingMode of scale
+// factor 1.
+static AddressingMode AdjustAddressingMode(AddressingMode base_mode,
+                                           int power) {
+  DCHECK(0 <= power && power < 4);
+  return static_cast<AddressingMode>(static_cast<int>(base_mode) + power);
+}
+
+
 class AddressingModeMatcher {
  public:
   AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index)
@@ -104,21 +113,11 @@ class AddressingModeMatcher {
         }
       }
       // 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;
-      }
+      mode_ = AdjustAddressingMode(mode_, matcher.power());
     }
     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.
@@ -386,18 +385,39 @@ void InstructionSelector::VisitInt32Sub(Node* node) {
 
 void InstructionSelector::VisitInt32Mul(Node* node) {
   IA32OperandGenerator g(this);
-  Int32BinopMatcher m(node);
-  Node* left = m.left().node();
-  Node* right = m.right().node();
-  if (g.CanBeImmediate(right)) {
-    Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
-         g.UseImmediate(right));
+  LeaMultiplyMatcher lea(node);
+  // Try to match lea.
+  if (lea.Matches()) {
+    ArchOpcode opcode = kIA32Lea;
+    AddressingMode mode;
+    size_t input_count;
+    InstructionOperand* left = g.UseRegister(lea.Left());
+    InstructionOperand* inputs[] = {left, left};
+    if (lea.Displacement() != 0) {
+      input_count = 2;
+      mode = kMode_MR1;
+    } else {
+      input_count = 1;
+      mode = kMode_M1;
+    }
+    mode = AdjustAddressingMode(mode, lea.Power());
+    InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
+    Emit(opcode | AddressingModeField::encode(mode), 1, outputs, input_count,
+         inputs);
   } else {
-    if (g.CanBeBetterLeftOperand(right)) {
-      std::swap(left, right);
+    Int32BinopMatcher m(node);
+    Node* left = m.left().node();
+    Node* right = m.right().node();
+    if (g.CanBeImmediate(right)) {
+      Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
+           g.UseImmediate(right));
+    } else {
+      if (g.CanBeBetterLeftOperand(right)) {
+        std::swap(left, right);
+      }
+      Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
+           g.Use(right));
     }
-    Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
-         g.Use(right));
   }
 }