[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:
parent
ee7f97c8a0
commit
6161d4305d
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user