[turbofan][arm64] Emit Lsl for Int32MulWithOverflow when possible
Int32MulWithOverflow on arm64 uses a cmp to set flags rather than the multiply instruction itself, thus we can use a left shift when the multiplication is by a power of two. This provides 0.15% for Speedometer2 on a Neoverse-N1 machine, with React being improved by 0.45%. Change-Id: Ic8db42ecc7cb14cf1ac7bbbeab0e9d8359104351 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3829472 Commit-Queue: George Wort <george.wort@arm.com> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/main@{#82499}
This commit is contained in:
parent
8cfbe0fc75
commit
aa541f1c9c
@ -1669,8 +1669,15 @@ void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node,
|
|||||||
Int32BinopMatcher m(node);
|
Int32BinopMatcher m(node);
|
||||||
InstructionOperand result = g.DefineAsRegister(node);
|
InstructionOperand result = g.DefineAsRegister(node);
|
||||||
InstructionOperand left = g.UseRegister(m.left().node());
|
InstructionOperand left = g.UseRegister(m.left().node());
|
||||||
InstructionOperand right = g.UseRegister(m.right().node());
|
|
||||||
selector->Emit(kArm64Smull, result, left, right);
|
if (m.right().HasResolvedValue() &&
|
||||||
|
base::bits::IsPowerOfTwo(m.right().ResolvedValue())) {
|
||||||
|
int32_t shift = base::bits::WhichPowerOfTwo(m.right().ResolvedValue());
|
||||||
|
selector->Emit(kArm64Lsl, result, left, g.TempImmediate(shift));
|
||||||
|
} else {
|
||||||
|
InstructionOperand right = g.UseRegister(m.right().node());
|
||||||
|
selector->Emit(kArm64Smull, result, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
InstructionCode opcode =
|
InstructionCode opcode =
|
||||||
kArm64Cmp | AddressingModeField::encode(kMode_Operand2_R_SXTW);
|
kArm64Cmp | AddressingModeField::encode(kMode_Operand2_R_SXTW);
|
||||||
|
@ -1930,6 +1930,23 @@ TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(InstructionSelectorTest, OvfValMulImmediateOnRight) {
|
||||||
|
TRACED_FORRANGE(int32_t, shift, 0, 30) {
|
||||||
|
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
|
||||||
|
m.Return(m.Projection(0, m.Int32MulWithOverflow(m.Int32Constant(1 << shift),
|
||||||
|
m.Parameter(0))));
|
||||||
|
Stream s = m.Build();
|
||||||
|
|
||||||
|
ASSERT_EQ(2U, s.size());
|
||||||
|
EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kArm64Cmp, s[1]->arch_opcode());
|
||||||
|
ASSERT_EQ(2U, s[0]->InputCount());
|
||||||
|
EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(1)));
|
||||||
|
EXPECT_LE(1U, s[0]->OutputCount());
|
||||||
|
EXPECT_EQ(kFlags_none, s[0]->flags_mode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Shift instructions.
|
// Shift instructions.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user