[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:
George Wort 2022-08-12 14:12:26 +01:00 committed by V8 LUCI CQ
parent 8cfbe0fc75
commit aa541f1c9c
2 changed files with 26 additions and 2 deletions

View File

@ -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);

View File

@ -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.