[arm] Unify instruction selector for Word32Neg.

Previously code generation for Word32Neg (implemented as Word32Xor
with -1) was somewhat adhoc and not complete. Now it's uniform
and supports the full range of operand2's.

TEST=cctest/test-instruction-selector-arm,cctest/test-run-machops
R=titzer@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22789 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
bmeurer@chromium.org 2014-08-01 11:14:47 +00:00
parent ee7f97c8a0
commit 6161d4305d
2 changed files with 113 additions and 24 deletions

View File

@ -217,6 +217,18 @@ static inline bool TryMatchLSR(InstructionSelector* selector,
}
static inline bool TryMatchShift(InstructionSelector* selector,
InstructionCode* opcode_return, Node* node,
InstructionOperand** value_return,
InstructionOperand** shift_return) {
return (
TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
TryMatchLSR(selector, opcode_return, node, value_return, shift_return) ||
TryMatchROR(selector, opcode_return, node, value_return, shift_return));
}
static inline bool TryMatchImmediateOrShift(InstructionSelector* selector,
InstructionCode* opcode_return,
Node* node,
@ -229,10 +241,7 @@ static inline bool TryMatchImmediateOrShift(InstructionSelector* selector,
*input_count_return = 1;
return true;
}
if (TryMatchASR(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
TryMatchLSL(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
TryMatchLSR(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
TryMatchROR(selector, opcode_return, node, &inputs[0], &inputs[1])) {
if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
*input_count_return = 2;
return true;
}
@ -425,23 +434,16 @@ static inline void EmitBic(InstructionSelector* selector, Node* node,
Node* left, Node* right) {
ArmOperandGenerator g(selector);
InstructionCode opcode = kArmBic;
InstructionOperand* inputs[3];
size_t input_count = 0;
InstructionOperand* outputs[1] = {g.DefineAsRegister(node)};
const size_t output_count = ARRAY_SIZE(outputs);
inputs[input_count++] = g.UseRegister(left);
if (!TryMatchImmediateOrShift(selector, &opcode, right, &input_count,
&inputs[input_count])) {
opcode |= AddressingModeField::encode(kMode_Operand2_R);
inputs[input_count++] = g.UseRegister(right);
InstructionOperand* value_operand;
InstructionOperand* shift_operand;
if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
value_operand, shift_operand);
return;
}
ASSERT_NE(0, input_count);
ASSERT_GE(ARRAY_SIZE(inputs), input_count);
ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
selector->Emit(opcode, output_count, outputs, input_count, inputs);
selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
g.DefineAsRegister(node), g.UseRegister(left),
g.UseRegister(right));
}
@ -512,11 +514,19 @@ void InstructionSelector::VisitWord32Xor(Node* node) {
ArmOperandGenerator g(this);
Int32BinopMatcher m(node);
if (m.right().Is(-1)) {
Emit(kArmMvn | AddressingModeField::encode(kMode_Operand2_R),
g.DefineSameAsFirst(node), g.UseRegister(m.left().node()));
} else {
VisitBinop(this, node, kArmEor, kArmEor);
InstructionCode opcode = kArmMvn;
InstructionOperand* value_operand;
InstructionOperand* shift_operand;
if (TryMatchShift(this, &opcode, m.left().node(), &value_operand,
&shift_operand)) {
Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
return;
}
Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
g.DefineAsRegister(node), g.UseRegister(m.left().node()));
return;
}
VisitBinop(this, node, kArmEor, kArmEor);
}

View File

@ -622,6 +622,58 @@ TEST(InstructionSelectorWord32AndAndWord32XorWithMinus1P) {
}
TEST(InstructionSelectorWord32AndAndWord32XorWithMinus1AndShiftP) {
Shifts shifts;
for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
Shift shift = *i;
{
InstructionSelectorTester m;
m.Return(m.Word32And(
m.Parameter(0),
m.Word32Xor(m.Int32Constant(-1),
m.NewNode(shift.op, m.Parameter(1), m.Parameter(2)))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
}
{
InstructionSelectorTester m;
m.Return(m.Word32And(
m.Parameter(0),
m.Word32Xor(m.NewNode(shift.op, m.Parameter(1), m.Parameter(2)),
m.Int32Constant(-1))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
}
{
InstructionSelectorTester m;
m.Return(m.Word32And(
m.Word32Xor(m.Int32Constant(-1),
m.NewNode(shift.op, m.Parameter(0), m.Parameter(1))),
m.Parameter(2)));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
}
{
InstructionSelectorTester m;
m.Return(m.Word32And(
m.Word32Xor(m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
m.Int32Constant(-1)),
m.Parameter(2)));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
}
}
}
TEST(InstructionSelectorWord32XorWithMinus1P) {
{
InstructionSelectorTester m;
@ -642,6 +694,33 @@ TEST(InstructionSelectorWord32XorWithMinus1P) {
}
TEST(InstructionSelectorWord32XorWithMinus1AndShiftP) {
Shifts shifts;
for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
Shift shift = *i;
{
InstructionSelectorTester m;
m.Return(
m.Word32Xor(m.Int32Constant(-1),
m.NewNode(shift.op, m.Parameter(0), m.Parameter(1))));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
CHECK_EQ(kArmMvn, m.code[0]->arch_opcode());
CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
}
{
InstructionSelectorTester m;
m.Return(m.Word32Xor(m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
m.Int32Constant(-1)));
m.SelectInstructions();
CHECK_EQ(1, m.code.size());
CHECK_EQ(kArmMvn, m.code[0]->arch_opcode());
CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
}
}
}
TEST(InstructionSelectorShiftP) {
Shifts shifts;
for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {