Commit 55e526c4 authored by jameslahm's avatar jameslahm Committed by V8 LUCI CQ

[compiler] Optimize kWord64And x64 instruction selector

- For y = x & 0xFF, we could use movzxbq y, x.
- For y = x & 0xFFFF, we could use movzxwq y, x.
- For y = x & 0xFFFFFFFF, we could use movl y, x.
- For y = x & immediate and immediate fits into uint32,
we could use andl x, immediate.


Bug: v8:12337
Change-Id: I31f04fa9058c6acabb210f0fce61ac713ed1a382
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3518913Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79668}
parent 98db200c
......@@ -784,7 +784,21 @@ void InstructionSelector::VisitWord32And(Node* node) {
}
void InstructionSelector::VisitWord64And(Node* node) {
VisitBinop(this, node, kX64And);
X64OperandGenerator g(this);
Uint64BinopMatcher m(node);
if (m.right().Is(0xFF)) {
Emit(kX64Movzxbq, g.DefineAsRegister(node), g.Use(m.left().node()));
} else if (m.right().Is(0xFFFF)) {
Emit(kX64Movzxwq, g.DefineAsRegister(node), g.Use(m.left().node()));
} else if (m.right().Is(0xFFFFFFFF)) {
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(m.left().node()));
} else if (m.right().IsInRange(std::numeric_limits<uint32_t>::min(),
std::numeric_limits<uint32_t>::max())) {
Emit(kX64And32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
g.UseImmediate(static_cast<int32_t>(m.right().ResolvedValue())));
} else {
VisitBinop(this, node, kX64And);
}
}
void InstructionSelector::VisitWord32Or(Node* node) {
......
......@@ -1847,6 +1847,151 @@ TEST_F(InstructionSelectorTest, Word32AndWith0xFF) {
}
}
TEST_F(InstructionSelectorTest, Word64AndWith0xFFFFFFFF) {
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(p0, m.Int32Constant(0xFFFFFFFF));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(m.Int32Constant(0xFFFFFFFF), p0);
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
}
TEST_F(InstructionSelectorTest, Word64AndWith0xFFFF) {
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(p0, m.Int32Constant(0xFFFF));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movzxwq, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(m.Int32Constant(0xFFFF), p0);
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movzxwq, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
}
TEST_F(InstructionSelectorTest, Word64AndWith0xFF) {
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(p0, m.Int32Constant(0xFF));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movzxbq, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(m.Int32Constant(0xFF), p0);
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movzxbq, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
}
TEST_F(InstructionSelectorTest, Word64AndWithInt64FitsUint32) {
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(p0, m.Int64Constant(15));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64And32, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(m.Int64Constant(15), p0);
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64And32, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
}
TEST_F(InstructionSelectorTest, Word64AndWithInt64DontFitsUint32) {
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(p0, m.Int64Constant(0x100000000));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64And, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
{
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Node* const p0 = m.Parameter(0);
Node* const n = m.Word64And(m.Int64Constant(0x100000000), p0);
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64And, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
}
TEST_F(InstructionSelectorTest, Word32AndWith0xFFFF) {
{
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
......
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