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:
parent
fc4c55108d
commit
5d843f26a9
@ -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;
|
||||
|
@ -18,6 +18,7 @@ namespace compiler {
|
||||
V(Mips64Dsub) \
|
||||
V(Mips64Mul) \
|
||||
V(Mips64MulHigh) \
|
||||
V(Mips64DMulHigh) \
|
||||
V(Mips64MulHighU) \
|
||||
V(Mips64Dmul) \
|
||||
V(Mips64Div) \
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user