Revision: 24357
Author: [email protected]
Date: Wed Oct 1 10:47:14 2014 UTC
Log: [turbofan] intel lea add multiply matchers
[email protected]
BUG=
Review URL: https://codereview.chromium.org/614013002
https://code.google.com/p/v8/source/detail?r=24357
Modified:
/branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
/branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
/branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc
/branches/bleeding_edge/test/cctest/compiler/value-helper.h
/branches/bleeding_edge/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
/branches/bleeding_edge/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Wed Oct 1 10:39:11 2014 UTC
+++ /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Wed Oct 1 10:47:14 2014 UTC
@@ -365,9 +365,39 @@
void InstructionSelector::VisitWord32Ror(Node* node) {
VisitShift(this, node, kIA32Ror);
}
+
+
+static bool TryEmitLeaMultAdd(InstructionSelector* selector, Node* node) {
+ Int32BinopMatcher m(node);
+ if (!m.right().HasValue()) return false;
+ int32_t displacement_value = m.right().Value();
+ Node* left = m.left().node();
+ LeaMultiplyMatcher lmm(left);
+ if (!lmm.Matches()) return false;
+ AddressingMode mode;
+ size_t input_count;
+ IA32OperandGenerator g(selector);
+ InstructionOperand* index = g.UseRegister(lmm.Left());
+ InstructionOperand* displacement = g.TempImmediate(displacement_value);
+ InstructionOperand* inputs[] = {index, displacement, displacement};
+ if (lmm.Displacement() != 0) {
+ input_count = 3;
+ inputs[1] = index;
+ mode = kMode_MR1I;
+ } else {
+ input_count = 2;
+ mode = kMode_M1I;
+ }
+ mode = AdjustAddressingMode(mode, lmm.Power());
+ InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
+ selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs,
+ input_count, inputs);
+ return true;
+}
void InstructionSelector::VisitInt32Add(Node* node) {
+ if (TryEmitLeaMultAdd(this, node)) return;
VisitBinop(this, node, kIA32Add);
}
@@ -383,41 +413,45 @@
}
-void InstructionSelector::VisitInt32Mul(Node* node) {
- IA32OperandGenerator g(this);
+static bool TryEmitLeaMult(InstructionSelector* selector, Node* node) {
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);
+ if (!lea.Matches()) return false;
+ AddressingMode mode;
+ size_t input_count;
+ IA32OperandGenerator g(selector);
+ InstructionOperand* left = g.UseRegister(lea.Left());
+ InstructionOperand* inputs[] = {left, left};
+ if (lea.Displacement() != 0) {
+ input_count = 2;
+ mode = kMode_MR1;
} else {
- 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));
+ input_count = 1;
+ mode = kMode_M1;
+ }
+ mode = AdjustAddressingMode(mode, lea.Power());
+ InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
+ selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs,
+ input_count, inputs);
+ return true;
+}
+
+
+void InstructionSelector::VisitInt32Mul(Node* node) {
+ if (TryEmitLeaMult(this, node)) return;
+ 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));
+ } else {
+ if (g.CanBeBetterLeftOperand(right)) {
+ std::swap(left, right);
}
+ Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
+ g.Use(right));
}
}
=======================================
--- /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Wed Oct 1 10:39:11 2014 UTC
+++ /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Wed Oct 1 10:47:14 2014 UTC
@@ -432,14 +432,59 @@
void InstructionSelector::VisitWord64Ror(Node* node) {
VisitWord64Shift(this, node, kX64Ror);
}
+
+
+static bool TryEmitLeaMultAdd(InstructionSelector* selector, Node* node,
+ ArchOpcode opcode) {
+ int32_t displacement_value;
+ Node* left;
+ {
+ Int32BinopMatcher m32(node);
+ left = m32.left().node();
+ if (m32.right().HasValue()) {
+ displacement_value = m32.right().Value();
+ } else {
+ Int64BinopMatcher m64(node);
+ if (!m64.right().HasValue()) {
+ return false;
+ }
+ int64_t value_64 = m64.right().Value();
+ displacement_value = static_cast<int32_t>(value_64);
+ if (displacement_value != value_64) return false;
+ }
+ }
+ LeaMultiplyMatcher lmm(left);
+ if (!lmm.Matches()) return false;
+ AddressingMode mode;
+ size_t input_count;
+ X64OperandGenerator g(selector);
+ InstructionOperand* index = g.UseRegister(lmm.Left());
+ InstructionOperand* displacement = g.TempImmediate(displacement_value);
+ InstructionOperand* inputs[] = {index, displacement, displacement};
+ if (lmm.Displacement() != 0) {
+ input_count = 3;
+ inputs[1] = index;
+ mode = kMode_MR1I;
+ } else {
+ input_count = 2;
+ mode = kMode_M1I;
+ }
+ mode = AdjustAddressingMode(mode, lmm.Power());
+ InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
+ selector->Emit(opcode | AddressingModeField::encode(mode), 1, outputs,
+ input_count, inputs);
+ return true;
+}
void InstructionSelector::VisitInt32Add(Node* node) {
+ if (TryEmitLeaMultAdd(this, node, kX64Lea32)) return;
VisitBinop(this, node, kX64Add32);
}
void InstructionSelector::VisitInt64Add(Node* node) {
+ if (TryEmitLeaMultAdd(this, node, kX64Lea)) return;
VisitBinop(this, node, kX64Add);
}
@@ -464,63 +509,60 @@
VisitBinop(this, node, kX64Sub);
}
}
+
+
+static bool TryEmitLeaMult(InstructionSelector* selector, Node* node,
+ ArchOpcode opcode) {
+ LeaMultiplyMatcher lea(node);
+ // Try to match lea.
+ if (!lea.Matches()) return false;
+ AddressingMode mode;
+ size_t input_count;
+ X64OperandGenerator g(selector);
+ 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)};
+ selector->Emit(opcode | AddressingModeField::encode(mode), 1, outputs,
+ input_count, inputs);
+ return true;
+}
static void VisitMul(InstructionSelector* selector, Node* node,
ArchOpcode opcode) {
X64OperandGenerator g(selector);
- LeaMultiplyMatcher lea(node);
- // Try to match lea.
- if (lea.Matches()) {
- switch (opcode) {
- case kX64Imul32:
- opcode = kX64Lea32;
- break;
- case kX64Imul:
- opcode = kX64Lea;
- break;
- default:
- UNREACHABLE();
- }
- 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)};
- selector->Emit(opcode | AddressingModeField::encode(mode), 1, outputs,
- input_count, inputs);
+ Int32BinopMatcher m(node);
+ Node* left = m.left().node();
+ Node* right = m.right().node();
+ if (g.CanBeImmediate(right)) {
+ selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left),
+ g.UseImmediate(right));
} else {
- Int32BinopMatcher m(node);
- Node* left = m.left().node();
- Node* right = m.right().node();
- if (g.CanBeImmediate(right)) {
- selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left),
- g.UseImmediate(right));
- } else {
- if (g.CanBeBetterLeftOperand(right)) {
- std::swap(left, right);
- }
- selector->Emit(opcode, g.DefineSameAsFirst(node),
g.UseRegister(left),
- g.Use(right));
+ if (g.CanBeBetterLeftOperand(right)) {
+ std::swap(left, right);
}
+ selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
+ g.Use(right));
}
}
void InstructionSelector::VisitInt32Mul(Node* node) {
+ if (TryEmitLeaMult(this, node, kX64Lea32)) return;
VisitMul(this, node, kX64Imul32);
}
void InstructionSelector::VisitInt64Mul(Node* node) {
+ if (TryEmitLeaMult(this, node, kX64Lea)) return;
VisitMul(this, node, kX64Imul);
}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Wed
Oct 1 10:39:11 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Wed
Oct 1 10:47:14 2014 UTC
@@ -1258,6 +1258,22 @@
TEST(RunInt32MulAndInt32AddP) {
+ {
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ int32_t p0 = *i;
+ int32_t p1 = *j;
+ m.Return(m.Int32Add(m.Int32Constant(p0),
+ m.Int32Mul(m.Parameter(0),
m.Int32Constant(p1))));
+ FOR_INT32_INPUTS(k) {
+ int32_t p2 = *k;
+ int expected = p0 + static_cast<int32_t>(p1 * p2);
+ CHECK_EQ(expected, m.Call(p2));
+ }
+ }
+ }
+ }
{
RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32,
kMachInt32);
m.Return(
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/value-helper.h Wed Sep 24
11:08:35 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/value-helper.h Wed Oct 1
10:47:14 2014 UTC
@@ -121,6 +121,8 @@
static const std::vector<uint32_t> uint32_vector() {
static const uint32_t kValues[] = {
0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8,
0xcc0de5bf,
+ // This row is useful for testing lea optimizations on intel.
+ 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008,
0x00000009,
0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc,
0x11223344,
0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc,
0x002b3b4c,
0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761,
0x7fffff00,
=======================================
---
/branches/bleeding_edge/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
Wed Oct 1 08:34:25 2014 UTC
+++
/branches/bleeding_edge/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
Wed Oct 1 10:47:14 2014 UTC
@@ -474,6 +474,16 @@
static unsigned InputCountForLea(AddressingMode mode) {
switch (mode) {
+ case kMode_MR1I:
+ case kMode_MR2I:
+ case kMode_MR4I:
+ case kMode_MR8I:
+ return 3U;
+ case kMode_M1I:
+ case kMode_M2I:
+ case kMode_M4I:
+ case kMode_M8I:
+ return 2U;
case kMode_MR1:
case kMode_MR2:
case kMode_MR4:
@@ -489,6 +499,31 @@
return 0U;
}
}
+
+
+static AddressingMode AddressingModeForAddMult(const MultParam& m) {
+ switch (m.addressing_mode) {
+ case kMode_MR1:
+ return kMode_MR1I;
+ case kMode_MR2:
+ return kMode_MR2I;
+ case kMode_MR4:
+ return kMode_MR4I;
+ case kMode_MR8:
+ return kMode_MR8I;
+ case kMode_M1:
+ return kMode_M1I;
+ case kMode_M2:
+ return kMode_M2I;
+ case kMode_M4:
+ return kMode_M4I;
+ case kMode_M8:
+ return kMode_M8I;
+ default:
+ UNREACHABLE();
+ return kMode_None;
+ }
+}
TEST_P(InstructionSelectorMultTest, Mult32) {
@@ -509,6 +544,33 @@
}
EXPECT_EQ(param->id(), s.ToVreg(s[0]->InputAt(0)));
}
+
+
+TEST_P(InstructionSelectorMultTest, MultAdd32) {
+ TRACED_FOREACH(int32_t, imm, kImmediates) {
+ const MultParam m_param = GetParam();
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ Node* param = m.Parameter(0);
+ Node* mult = m.Int32Add(m.Int32Mul(param,
m.Int32Constant(m_param.value)),
+ m.Int32Constant(imm));
+ m.Return(mult);
+ Stream s = m.Build();
+ if (m_param.lea_expected) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
+ EXPECT_EQ(AddressingModeForAddMult(m_param),
s[0]->addressing_mode());
+ unsigned input_count = InputCountForLea(s[0]->addressing_mode());
+ ASSERT_EQ(input_count, s[0]->InputCount());
+ ASSERT_EQ(InstructionOperand::IMMEDIATE,
+ s[0]->InputAt(input_count - 1)->kind());
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(input_count - 1)));
+ } else {
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kIA32Imul, s[0]->arch_opcode());
+ EXPECT_EQ(kIA32Add, s[1]->arch_opcode());
+ }
+ }
+}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
InstructionSelectorMultTest,
=======================================
---
/branches/bleeding_edge/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
Wed Oct 1 08:34:25 2014 UTC
+++
/branches/bleeding_edge/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
Wed Oct 1 10:47:14 2014 UTC
@@ -10,6 +10,16 @@
namespace internal {
namespace compiler {
+namespace {
+
+// Immediates (random subset).
+static const int32_t kImmediates[] = {
+ kMinInt, -42, -1, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt};
+
+} // namespace
+
+
//
-----------------------------------------------------------------------------
// Conversions.
@@ -337,6 +347,16 @@
static unsigned InputCountForLea(AddressingMode mode) {
switch (mode) {
+ case kMode_MR1I:
+ case kMode_MR2I:
+ case kMode_MR4I:
+ case kMode_MR8I:
+ return 3U;
+ case kMode_M1I:
+ case kMode_M2I:
+ case kMode_M4I:
+ case kMode_M8I:
+ return 2U;
case kMode_MR1:
case kMode_MR2:
case kMode_MR4:
@@ -352,6 +372,31 @@
return 0U;
}
}
+
+
+static AddressingMode AddressingModeForAddMult(const MultParam& m) {
+ switch (m.addressing_mode) {
+ case kMode_MR1:
+ return kMode_MR1I;
+ case kMode_MR2:
+ return kMode_MR2I;
+ case kMode_MR4:
+ return kMode_MR4I;
+ case kMode_MR8:
+ return kMode_MR8I;
+ case kMode_M1:
+ return kMode_M1I;
+ case kMode_M2:
+ return kMode_M2I;
+ case kMode_M4:
+ return kMode_M4I;
+ case kMode_M8:
+ return kMode_M8I;
+ default:
+ UNREACHABLE();
+ return kMode_None;
+ }
+}
TEST_P(InstructionSelectorMultTest, Mult32) {
@@ -394,6 +439,60 @@
EXPECT_EQ(param->id(), s.ToVreg(s[0]->InputAt(1)));
}
}
+
+
+TEST_P(InstructionSelectorMultTest, MultAdd32) {
+ TRACED_FOREACH(int32_t, imm, kImmediates) {
+ const MultParam m_param = GetParam();
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ Node* param = m.Parameter(0);
+ Node* mult = m.Int32Add(m.Int32Mul(param,
m.Int32Constant(m_param.value)),
+ m.Int32Constant(imm));
+ m.Return(mult);
+ Stream s = m.Build();
+ if (m_param.lea_expected) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
+ EXPECT_EQ(AddressingModeForAddMult(m_param),
s[0]->addressing_mode());
+ unsigned input_count = InputCountForLea(s[0]->addressing_mode());
+ ASSERT_EQ(input_count, s[0]->InputCount());
+ ASSERT_EQ(InstructionOperand::IMMEDIATE,
+ s[0]->InputAt(input_count - 1)->kind());
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(input_count - 1)));
+ } else {
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kX64Imul32, s[0]->arch_opcode());
+ EXPECT_EQ(kX64Add32, s[1]->arch_opcode());
+ }
+ }
+}
+
+
+TEST_P(InstructionSelectorMultTest, MultAdd64) {
+ TRACED_FOREACH(int32_t, imm, kImmediates) {
+ const MultParam m_param = GetParam();
+ StreamBuilder m(this, kMachInt64, kMachInt64);
+ Node* param = m.Parameter(0);
+ Node* mult = m.Int64Add(m.Int64Mul(param,
m.Int64Constant(m_param.value)),
+ m.Int64Constant(imm));
+ m.Return(mult);
+ Stream s = m.Build();
+ if (m_param.lea_expected) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Lea, s[0]->arch_opcode());
+ EXPECT_EQ(AddressingModeForAddMult(m_param),
s[0]->addressing_mode());
+ unsigned input_count = InputCountForLea(s[0]->addressing_mode());
+ ASSERT_EQ(input_count, s[0]->InputCount());
+ ASSERT_EQ(InstructionOperand::IMMEDIATE,
+ s[0]->InputAt(input_count - 1)->kind());
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(input_count - 1)));
+ } else {
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kX64Imul, s[0]->arch_opcode());
+ EXPECT_EQ(kX64Add, s[1]->arch_opcode());
+ }
+ }
+}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
InstructionSelectorMultTest,
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.