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) { ...@@ -640,6 +640,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMipsOr: case kMipsOr:
__ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsNor:
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsXor: case kMipsXor:
__ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
......
...@@ -25,6 +25,7 @@ namespace compiler { ...@@ -25,6 +25,7 @@ namespace compiler {
V(MipsModU) \ V(MipsModU) \
V(MipsAnd) \ V(MipsAnd) \
V(MipsOr) \ V(MipsOr) \
V(MipsNor) \
V(MipsXor) \ V(MipsXor) \
V(MipsClz) \ V(MipsClz) \
V(MipsShl) \ V(MipsShl) \
......
...@@ -294,6 +294,18 @@ void InstructionSelector::VisitWord32Or(Node* node) { ...@@ -294,6 +294,18 @@ void InstructionSelector::VisitWord32Or(Node* node) {
void InstructionSelector::VisitWord32Xor(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); VisitBinop(this, node, kMipsXor);
} }
......
...@@ -654,6 +654,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -654,6 +654,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMips64Or: case kMips64Or:
__ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMips64Nor:
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64Xor: case kMips64Xor:
__ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
......
...@@ -31,6 +31,7 @@ namespace compiler { ...@@ -31,6 +31,7 @@ namespace compiler {
V(Mips64DmodU) \ V(Mips64DmodU) \
V(Mips64And) \ V(Mips64And) \
V(Mips64Or) \ V(Mips64Or) \
V(Mips64Nor) \
V(Mips64Xor) \ V(Mips64Xor) \
V(Mips64Clz) \ V(Mips64Clz) \
V(Mips64Shl) \ V(Mips64Shl) \
......
...@@ -347,11 +347,35 @@ void InstructionSelector::VisitWord64Or(Node* node) { ...@@ -347,11 +347,35 @@ void InstructionSelector::VisitWord64Or(Node* node) {
void InstructionSelector::VisitWord32Xor(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); VisitBinop(this, node, kMips64Xor);
} }
void InstructionSelector::VisitWord64Xor(Node* node) { 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); VisitBinop(this, node, kMips64Xor);
} }
......
...@@ -362,6 +362,30 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, ...@@ -362,6 +362,30 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
::testing::ValuesIn(kLogicalInstructions)); ::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) { TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
// The available shift operand range is `0 <= imm < 32`, but we also test // The available shift operand range is `0 <= imm < 32`, but we also test
// that immediates outside this range are handled properly (modulo-32). // that immediates outside this range are handled properly (modulo-32).
......
...@@ -400,6 +400,54 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, ...@@ -400,6 +400,54 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
::testing::ValuesIn(kLogicalInstructions)); ::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) { TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
// The available shift operand range is `0 <= imm < 32`, but we also test // The available shift operand range is `0 <= imm < 32`, but we also test
// that immediates outside this range are handled properly (modulo-32). // 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