Commit 6b11cc83 authored by dusan.m.milosavljevic's avatar dusan.m.milosavljevic Committed by Commit bot

MIPS:[turbofan] Use Nor instruction for bit negation instead of xori.

Xori instruction can only have unisgned 16-bit immediates for right input,
as such it is not suitable for bit negation on mips.

TEST=unittests/InstructionSecetorTest.Word(32|64)XorMinusOneWithParameter
BUG=

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

Cr-Commit-Position: refs/heads/master@{#32478}
parent 5058f685
...@@ -665,7 +665,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -665,7 +665,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsNor: case kMipsNor:
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); if (instr->InputAt(1)->IsRegister()) {
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
} else {
DCHECK(i.InputOperand(1).immediate() == 0);
__ Nor(i.OutputRegister(), i.InputRegister(0), zero_reg);
}
break; break;
case kMipsXor: case kMipsXor:
__ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
......
...@@ -306,6 +306,13 @@ void InstructionSelector::VisitWord32Xor(Node* node) { ...@@ -306,6 +306,13 @@ void InstructionSelector::VisitWord32Xor(Node* node) {
return; return;
} }
} }
if (m.right().Is(-1)) {
// Use Nor for bit negation and eliminate constant loading for xori.
MipsOperandGenerator g(this);
Emit(kMipsNor, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.TempImmediate(0));
return;
}
VisitBinop(this, node, kMipsXor); VisitBinop(this, node, kMipsXor);
} }
......
...@@ -678,7 +678,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -678,7 +678,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMips64Nor: case kMips64Nor:
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); if (instr->InputAt(1)->IsRegister()) {
__ Nor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
} else {
DCHECK(i.InputOperand(1).immediate() == 0);
__ Nor(i.OutputRegister(), i.InputRegister(0), zero_reg);
}
break; break;
case kMips64Xor: case kMips64Xor:
__ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
......
...@@ -359,6 +359,13 @@ void InstructionSelector::VisitWord32Xor(Node* node) { ...@@ -359,6 +359,13 @@ void InstructionSelector::VisitWord32Xor(Node* node) {
return; return;
} }
} }
if (m.right().Is(-1)) {
// Use Nor for bit negation and eliminate constant loading for xori.
Mips64OperandGenerator g(this);
Emit(kMips64Nor, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.TempImmediate(0));
return;
}
VisitBinop(this, node, kMips64Xor); VisitBinop(this, node, kMips64Xor);
} }
...@@ -376,6 +383,13 @@ void InstructionSelector::VisitWord64Xor(Node* node) { ...@@ -376,6 +383,13 @@ void InstructionSelector::VisitWord64Xor(Node* node) {
return; return;
} }
} }
if (m.right().Is(-1)) {
// Use Nor for bit negation and eliminate constant loading for xori.
Mips64OperandGenerator g(this);
Emit(kMips64Nor, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.TempImmediate(0));
return;
}
VisitBinop(this, node, kMips64Xor); VisitBinop(this, node, kMips64Xor);
} }
......
...@@ -362,6 +362,28 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, ...@@ -362,6 +362,28 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
::testing::ValuesIn(kLogicalInstructions)); ::testing::ValuesIn(kLogicalInstructions));
TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Xor(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.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, Word32XorMinusOneWithWord32Or) { TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
{ {
StreamBuilder m(this, kMachInt32, kMachInt32); StreamBuilder m(this, kMachInt32, kMachInt32);
......
...@@ -400,6 +400,50 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, ...@@ -400,6 +400,50 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
::testing::ValuesIn(kLogicalInstructions)); ::testing::ValuesIn(kLogicalInstructions));
TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
{
StreamBuilder m(this, kMachInt64, kMachInt64);
m.Return(m.Word64Xor(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.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, Word32XorMinusOneWithParameter) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Xor(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.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, Word64XorMinusOneWithWord64Or) { TEST_F(InstructionSelectorTest, Word64XorMinusOneWithWord64Or) {
{ {
StreamBuilder m(this, kMachInt64, kMachInt64); StreamBuilder m(this, kMachInt64, kMachInt64);
......
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