Commit 40a501a2 authored by dusan.m.milosavljevic's avatar dusan.m.milosavljevic Committed by Commit bot

MIPS: [turbofan] Add matching rule to use Nor instruction.

TEST=unittests/InstructionSelectorTest.Word32XorMinusOneWithWord32Or,
     Word64XorMinusOneWithWord64Or
BUG=

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

Cr-Commit-Position: refs/heads/master@{#32149}
parent 71be4434
......@@ -640,6 +640,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMipsOr:
__ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsNor:
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsXor:
__ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
......
......@@ -25,6 +25,7 @@ namespace compiler {
V(MipsModU) \
V(MipsAnd) \
V(MipsOr) \
V(MipsNor) \
V(MipsXor) \
V(MipsClz) \
V(MipsShl) \
......
......@@ -294,6 +294,18 @@ void InstructionSelector::VisitWord32Or(Node* node) {
void InstructionSelector::VisitWord32Xor(Node* node) {
Int32BinopMatcher m(node);
if (m.left().IsWord32Or() && CanCover(node, m.left().node()) &&
m.right().Is(-1)) {
Int32BinopMatcher mleft(m.left().node());
if (!mleft.right().HasValue()) {
MipsOperandGenerator g(this);
Emit(kMipsNor, g.DefineAsRegister(node),
g.UseRegister(mleft.left().node()),
g.UseRegister(mleft.right().node()));
return;
}
}
VisitBinop(this, node, kMipsXor);
}
......
......@@ -654,6 +654,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMips64Or:
__ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64Nor:
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64Xor:
__ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
......
......@@ -31,6 +31,7 @@ namespace compiler {
V(Mips64DmodU) \
V(Mips64And) \
V(Mips64Or) \
V(Mips64Nor) \
V(Mips64Xor) \
V(Mips64Clz) \
V(Mips64Shl) \
......
......@@ -347,11 +347,35 @@ void InstructionSelector::VisitWord64Or(Node* node) {
void InstructionSelector::VisitWord32Xor(Node* node) {
Int32BinopMatcher m(node);
if (m.left().IsWord32Or() && CanCover(node, m.left().node()) &&
m.right().Is(-1)) {
Int32BinopMatcher mleft(m.left().node());
if (!mleft.right().HasValue()) {
Mips64OperandGenerator g(this);
Emit(kMips64Nor, g.DefineAsRegister(node),
g.UseRegister(mleft.left().node()),
g.UseRegister(mleft.right().node()));
return;
}
}
VisitBinop(this, node, kMips64Xor);
}
void InstructionSelector::VisitWord64Xor(Node* node) {
Int64BinopMatcher m(node);
if (m.left().IsWord64Or() && CanCover(node, m.left().node()) &&
m.right().Is(-1)) {
Int64BinopMatcher mleft(m.left().node());
if (!mleft.right().HasValue()) {
Mips64OperandGenerator g(this);
Emit(kMips64Nor, g.DefineAsRegister(node),
g.UseRegister(mleft.left().node()),
g.UseRegister(mleft.right().node()));
return;
}
}
VisitBinop(this, node, kMips64Xor);
}
......
......@@ -362,6 +362,30 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
::testing::ValuesIn(kLogicalInstructions));
TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
m.Int32Constant(-1)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Xor(m.Int32Constant(-1),
m.Word32Or(m.Parameter(0), m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
// The available shift operand range is `0 <= imm < 32`, but we also test
// that immediates outside this range are handled properly (modulo-32).
......
......@@ -400,6 +400,54 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
::testing::ValuesIn(kLogicalInstructions));
TEST_F(InstructionSelectorTest, Word64XorMinusOneWithWord64Or) {
{
StreamBuilder m(this, kMachInt64, kMachInt64);
m.Return(m.Word64Xor(m.Word64Or(m.Parameter(0), m.Parameter(0)),
m.Int64Constant(-1)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
{
StreamBuilder m(this, kMachInt64, kMachInt64);
m.Return(m.Word64Xor(m.Int64Constant(-1),
m.Word64Or(m.Parameter(0), m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
m.Int32Constant(-1)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Xor(m.Int32Constant(-1),
m.Word32Or(m.Parameter(0), m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
// The available shift operand range is `0 <= imm < 32`, but we also test
// that immediates outside this range are handled properly (modulo-32).
......
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