MIPS64: [turbofan] Combine untagging shifts with Mul, Div and Mod.

TEST=unittests/InstructionSelectorTest.CombineShiftsWithMul,
     InstructionSelectorTest.CombineShiftsWithDivMod
BUG=

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

Cr-Commit-Position: refs/heads/master@{#32061}
This commit is contained in:
dusan.m.milosavljevic 2015-11-17 14:52:24 -08:00 committed by Commit bot
parent fc4c55108d
commit 5d843f26a9
4 changed files with 93 additions and 7 deletions

View File

@ -618,6 +618,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMips64MulHighU:
__ Mulhu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64DMulHigh:
__ Dmulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64Div:
__ Div(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;

View File

@ -18,6 +18,7 @@ namespace compiler {
V(Mips64Dsub) \
V(Mips64Mul) \
V(Mips64MulHigh) \
V(Mips64DMulHigh) \
V(Mips64MulHighU) \
V(Mips64Dmul) \
V(Mips64Div) \

View File

@ -419,6 +419,21 @@ void InstructionSelector::VisitInt32Mul(Node* node) {
return;
}
}
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
if (CanCover(node, left) && CanCover(node, right)) {
if (left->opcode() == IrOpcode::kWord64Sar &&
right->opcode() == IrOpcode::kWord64Sar) {
Int64BinopMatcher leftInput(left), rightInput(right);
if (leftInput.right().Is(32) && rightInput.right().Is(32)) {
// Combine untagging shifts with Dmul high.
Emit(kMips64DMulHigh, g.DefineSameAsFirst(node),
g.UseRegister(leftInput.left().node()),
g.UseRegister(rightInput.left().node()));
return;
}
}
}
VisitRRR(this, kMips64Mul, node);
}
@ -429,12 +444,7 @@ void InstructionSelector::VisitInt32MulHigh(Node* node) {
void InstructionSelector::VisitUint32MulHigh(Node* node) {
Mips64OperandGenerator g(this);
InstructionOperand const dmul_operand = g.TempRegister();
Emit(kMips64MulHighU, dmul_operand, g.UseRegister(node->InputAt(0)),
g.UseRegister(node->InputAt(1)));
Emit(kMips64Ext, g.DefineAsRegister(node), dmul_operand, g.TempImmediate(0),
g.TempImmediate(32));
VisitRRR(this, kMips64MulHighU, node);
}
@ -477,6 +487,21 @@ void InstructionSelector::VisitInt64Mul(Node* node) {
void InstructionSelector::VisitInt32Div(Node* node) {
Mips64OperandGenerator g(this);
Int32BinopMatcher m(node);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
if (CanCover(node, left) && CanCover(node, right)) {
if (left->opcode() == IrOpcode::kWord64Sar &&
right->opcode() == IrOpcode::kWord64Sar) {
Int64BinopMatcher rightInput(right), leftInput(left);
if (rightInput.right().Is(32) && leftInput.right().Is(32)) {
// Combine both shifted operands with Ddiv.
Emit(kMips64Ddiv, g.DefineSameAsFirst(node),
g.UseRegister(leftInput.left().node()),
g.UseRegister(rightInput.left().node()));
return;
}
}
}
Emit(kMips64Div, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.UseRegister(m.right().node()));
}
@ -493,6 +518,21 @@ void InstructionSelector::VisitUint32Div(Node* node) {
void InstructionSelector::VisitInt32Mod(Node* node) {
Mips64OperandGenerator g(this);
Int32BinopMatcher m(node);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
if (CanCover(node, left) && CanCover(node, right)) {
if (left->opcode() == IrOpcode::kWord64Sar &&
right->opcode() == IrOpcode::kWord64Sar) {
Int64BinopMatcher rightInput(right), leftInput(left);
if (rightInput.right().Is(32) && leftInput.right().Is(32)) {
// Combine both shifted operands with Dmod.
Emit(kMips64Dmod, g.DefineSameAsFirst(node),
g.UseRegister(leftInput.left().node()),
g.UseRegister(rightInput.left().node()));
return;
}
}
}
Emit(kMips64Mod, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.UseRegister(m.right().node()));
}
@ -587,7 +627,8 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
if (m.right().IsInRange(32, 63)) {
// After smi untagging no need for truncate. Combine sequence.
Emit(kMips64Dsar, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()), g.TempImmediate(kSmiShift));
g.UseRegister(m.left().node()),
g.UseImmediate(m.right().node()));
return;
}
break;

View File

@ -469,6 +469,47 @@ TEST_F(InstructionSelectorTest, ChangesFromToSmi) {
}
TEST_F(InstructionSelectorTest, CombineShiftsWithMul) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Int32Mul(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64DMulHigh, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest, CombineShiftsWithDivMod) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Int32Div(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64Ddiv, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Int32Mod(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64Dmod, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
// ----------------------------------------------------------------------------
// Loads and stores.
// ----------------------------------------------------------------------------