Commit 1f876f24 authored by martyn.capewell's avatar martyn.capewell Committed by Commit bot

[turbofan] Merge sar/shr into MulHigh on ARM64

Merge a following arithmetic or logical right shift into the existing shift
of ARM64's Int32MulHigh or Uint32MulHigh code.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#28945}
parent 14755c0a
......@@ -745,6 +745,22 @@ void InstructionSelector::VisitWord32Shr(Node* node) {
} else if (TryEmitBitfieldExtract32(this, node)) {
return;
}
if (m.left().IsUint32MulHigh() && m.right().HasValue() &&
CanCover(node, node->InputAt(0))) {
// Combine this shift with the multiply and shift that would be generated
// by Uint32MulHigh.
Arm64OperandGenerator g(this);
Node* left = m.left().node();
int shift = m.right().Value() & 0x1f;
InstructionOperand const smull_operand = g.TempRegister();
Emit(kArm64Umull, smull_operand, g.UseRegister(left->InputAt(0)),
g.UseRegister(left->InputAt(1)));
Emit(kArm64Lsr, g.DefineAsRegister(node), smull_operand,
g.TempImmediate(32 + shift));
return;
}
VisitRRO(this, kArm64Lsr32, node, kShift32Imm);
}
......@@ -779,6 +795,23 @@ void InstructionSelector::VisitWord32Sar(Node* node) {
if (TryEmitBitfieldExtract32(this, node)) {
return;
}
Int32BinopMatcher m(node);
if (m.left().IsInt32MulHigh() && m.right().HasValue() &&
CanCover(node, node->InputAt(0))) {
// Combine this shift with the multiply and shift that would be generated
// by Int32MulHigh.
Arm64OperandGenerator g(this);
Node* left = m.left().node();
int shift = m.right().Value() & 0x1f;
InstructionOperand const smull_operand = g.TempRegister();
Emit(kArm64Smull, smull_operand, g.UseRegister(left->InputAt(0)),
g.UseRegister(left->InputAt(1)));
Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand,
g.TempImmediate(32 + shift));
return;
}
VisitRRO(this, kArm64Asr32, node, kShift32Imm);
}
......@@ -981,7 +1014,6 @@ void InstructionSelector::VisitInt64Mul(Node* node) {
void InstructionSelector::VisitInt32MulHigh(Node* node) {
// TODO(arm64): Can we do better here?
Arm64OperandGenerator g(this);
InstructionOperand const smull_operand = g.TempRegister();
Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)),
......@@ -991,7 +1023,6 @@ void InstructionSelector::VisitInt32MulHigh(Node* node) {
void InstructionSelector::VisitUint32MulHigh(Node* node) {
// TODO(arm64): Can we do better here?
Arm64OperandGenerator g(this);
InstructionOperand const smull_operand = g.TempRegister();
Emit(kArm64Umull, smull_operand, g.UseRegister(node->InputAt(0)),
......
......@@ -2365,6 +2365,55 @@ TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
}
TEST_F(InstructionSelectorTest, Int32MulHighWithSar) {
TRACED_FORRANGE(int32_t, shift, -32, 63) {
StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
Node* const p0 = m.Parameter(0);
Node* const p1 = m.Parameter(1);
Node* const n = m.Word32Sar(m.Int32MulHigh(p0, p1), m.Int32Constant(shift));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(2U, s.size());
EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
ASSERT_EQ(2U, s[1]->InputCount());
EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
ASSERT_EQ(1U, s[1]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
}
}
TEST_F(InstructionSelectorTest, Uint32MulHighWithShr) {
TRACED_FORRANGE(int32_t, shift, -32, 63) {
StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
Node* const p0 = m.Parameter(0);
Node* const p1 = m.Parameter(1);
Node* const n =
m.Word32Shr(m.Uint32MulHigh(p0, p1), m.Int32Constant(shift));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(2U, s.size());
EXPECT_EQ(kArm64Umull, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kArm64Lsr, s[1]->arch_opcode());
ASSERT_EQ(2U, s[1]->InputCount());
EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
ASSERT_EQ(1U, s[1]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
}
}
TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
TRACED_FORRANGE(int32_t, shift, 1, 31) {
StreamBuilder m(this, kMachInt32, kMachInt32);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment