Revision: 23148
Author: [email protected]
Date: Mon Aug 18 11:10:01 2014 UTC
Log: [arm] Recognize comparisons of shifts with zero.
For example, recognize
0 == r1 << r2
and generate a single
MOVS rt, r1, lsl r2
instruction.
TEST=cctest,compiler-unittests
[email protected]
Review URL: https://codereview.chromium.org/478233002
http://code.google.com/p/v8/source/detail?r=23148
Modified:
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc
/branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
/branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc
/branches/bleeding_edge/test/compiler-unittests/arm/instruction-selector-arm-unittest.cc
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Aug 4
11:34:54 2014 UTC
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Aug 18
11:10:01 2014 UTC
@@ -152,8 +152,11 @@
// Register move. May do nothing if the registers are identical.
void Move(Register dst, Handle<Object> value);
void Move(Register dst, Register src, Condition cond = al);
- void Move(Register dst, const Operand& src, Condition cond = al) {
- if (!src.is_reg() || !src.rm().is(dst)) mov(dst, src, LeaveCC, cond);
+ void Move(Register dst, const Operand& src, SBit sbit = LeaveCC,
+ Condition cond = al) {
+ if (!src.is_reg() || !src.rm().is(dst) || sbit != LeaveCC) {
+ mov(dst, src, sbit, cond);
+ }
}
void Move(DwVfpRegister dst, DwVfpRegister src);
=======================================
--- /branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc Fri Aug
15 14:35:00 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc Mon Aug
18 11:10:01 2014 UTC
@@ -198,8 +198,7 @@
break;
}
case kArmMov:
- __ Move(i.OutputRegister(), i.InputOperand2(0));
- DCHECK_EQ(LeaveCC, i.OutputSBit());
+ __ Move(i.OutputRegister(), i.InputOperand2(0), i.OutputSBit());
break;
case kArmMvn:
__ mvn(i.OutputRegister(), i.InputOperand2(0), i.OutputSBit());
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Thu Aug 14 09:19:54 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Mon Aug 18 11:10:01 2014 UTC
@@ -480,15 +480,44 @@
template <typename TryMatchShift>
static inline void VisitShift(InstructionSelector* selector, Node* node,
- TryMatchShift try_match_shift) {
+ TryMatchShift try_match_shift,
+ FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
InstructionCode opcode = kArmMov;
- InstructionOperand* value_operand = NULL;
- InstructionOperand* shift_operand = NULL;
- CHECK(
- try_match_shift(selector, &opcode, node, &value_operand,
&shift_operand));
- selector->Emit(opcode, g.DefineAsRegister(node), value_operand,
- shift_operand);
+ InstructionOperand* inputs[4];
+ size_t input_count = 2;
+ InstructionOperand* outputs[2];
+ size_t output_count = 0;
+
+ CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1]));
+
+ if (cont->IsBranch()) {
+ inputs[input_count++] = g.Label(cont->true_block());
+ inputs[input_count++] = g.Label(cont->false_block());
+ }
+
+ outputs[output_count++] = g.DefineAsRegister(node);
+ if (cont->IsSet()) {
+ outputs[output_count++] = g.DefineAsRegister(cont->result());
+ }
+
+ DCHECK_NE(0, input_count);
+ DCHECK_NE(0, output_count);
+ DCHECK_GE(ARRAY_SIZE(inputs), input_count);
+ DCHECK_GE(ARRAY_SIZE(outputs), output_count);
+ DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
+
+ Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
+ outputs, input_count, inputs);
+ if (cont->IsBranch()) instr->MarkAsControl();
+}
+
+
+template <typename TryMatchShift>
+static inline void VisitShift(InstructionSelector* selector, Node* node,
+ TryMatchShift try_match_shift) {
+ FlagsContinuation cont;
+ VisitShift(selector, node, try_match_shift, &cont);
}
@@ -878,6 +907,14 @@
return VisitBinop(this, node, kArmOrr, kArmOrr, cont);
case IrOpcode::kWord32Xor:
return VisitWordCompare(this, node, kArmTeq, cont, true);
+ case IrOpcode::kWord32Sar:
+ return VisitShift(this, node, TryMatchASR, cont);
+ case IrOpcode::kWord32Shl:
+ return VisitShift(this, node, TryMatchLSL, cont);
+ case IrOpcode::kWord32Shr:
+ return VisitShift(this, node, TryMatchLSR, cont);
+ case IrOpcode::kWord32Ror:
+ return VisitShift(this, node, TryMatchROR, cont);
default:
break;
}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Thu
Aug 14 09:19:54 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Mon
Aug 18 11:10:01 2014 UTC
@@ -2212,6 +2212,58 @@
}
}
}
+
+
+TEST(RunWord32ShlInComparison) {
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Uint32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Word32Shl(bt.param0, bt.param1),
m.Int32Constant(0)));
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_SHIFTS(shift) {
+ uint32_t expected = 0 == (*i << shift);
+ CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Uint32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Int32Constant(0), m.Word32Shl(bt.param0,
bt.param1)));
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_SHIFTS(shift) {
+ uint32_t expected = 0 == (*i << shift);
+ CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ FOR_UINT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ m.Return(
+ m.Word32Equal(m.Int32Constant(0),
+ m.Word32Shl(m.Parameter(0),
m.Int32Constant(shift))));
+ FOR_UINT32_INPUTS(i) {
+ uint32_t expected = 0 == (*i << shift);
+ CHECK_UINT32_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+ {
+ FOR_UINT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ m.Return(
+ m.Word32Equal(m.Word32Shl(m.Parameter(0),
m.Int32Constant(shift)),
+ m.Int32Constant(0)));
+ FOR_UINT32_INPUTS(i) {
+ uint32_t expected = 0 == (*i << shift);
+ CHECK_UINT32_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+}
TEST(RunWord32ShrP) {
@@ -2238,6 +2290,58 @@
CHECK_EQ(0x00010000, bt.call(0x80000000, 15));
}
}
+
+
+TEST(RunWord32ShrInComparison) {
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Uint32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Word32Shr(bt.param0, bt.param1),
m.Int32Constant(0)));
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_SHIFTS(shift) {
+ uint32_t expected = 0 == (*i >> shift);
+ CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Uint32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Int32Constant(0), m.Word32Shr(bt.param0,
bt.param1)));
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_SHIFTS(shift) {
+ uint32_t expected = 0 == (*i >> shift);
+ CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ FOR_UINT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ m.Return(
+ m.Word32Equal(m.Int32Constant(0),
+ m.Word32Shr(m.Parameter(0),
m.Int32Constant(shift))));
+ FOR_UINT32_INPUTS(i) {
+ uint32_t expected = 0 == (*i >> shift);
+ CHECK_UINT32_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+ {
+ FOR_UINT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ m.Return(
+ m.Word32Equal(m.Word32Shr(m.Parameter(0),
m.Int32Constant(shift)),
+ m.Int32Constant(0)));
+ FOR_UINT32_INPUTS(i) {
+ uint32_t expected = 0 == (*i >> shift);
+ CHECK_UINT32_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+}
TEST(RunWord32SarP) {
@@ -2264,6 +2368,58 @@
CHECK_EQ(0xFFFF0000, bt.call(0x80000000, 15));
}
}
+
+
+TEST(RunWord32SarInComparison) {
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Int32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Word32Sar(bt.param0, bt.param1),
m.Int32Constant(0)));
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_SHIFTS(shift) {
+ int32_t expected = 0 == (*i >> shift);
+ CHECK_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Int32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Int32Constant(0), m.Word32Sar(bt.param0,
bt.param1)));
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_SHIFTS(shift) {
+ int32_t expected = 0 == (*i >> shift);
+ CHECK_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ FOR_INT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ m.Return(
+ m.Word32Equal(m.Int32Constant(0),
+ m.Word32Sar(m.Parameter(0),
m.Int32Constant(shift))));
+ FOR_INT32_INPUTS(i) {
+ int32_t expected = 0 == (*i >> shift);
+ CHECK_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+ {
+ FOR_INT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ m.Return(
+ m.Word32Equal(m.Word32Sar(m.Parameter(0),
m.Int32Constant(shift)),
+ m.Int32Constant(0)));
+ FOR_INT32_INPUTS(i) {
+ uint32_t expected = 0 == (*i >> shift);
+ CHECK_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+}
TEST(RunWord32RorP) {
@@ -2289,6 +2445,58 @@
}
}
}
+
+
+TEST(RunWord32RorInComparison) {
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Uint32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Word32Ror(bt.param0, bt.param1),
m.Int32Constant(0)));
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_SHIFTS(shift) {
+ uint32_t expected = 0 == bits::RotateRight32(*i, shift);
+ CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Uint32BinopTester bt(&m);
+ bt.AddReturn(
+ m.Word32Equal(m.Int32Constant(0), m.Word32Ror(bt.param0,
bt.param1)));
+ FOR_UINT32_INPUTS(i) {
+ FOR_UINT32_SHIFTS(shift) {
+ uint32_t expected = 0 == bits::RotateRight32(*i, shift);
+ CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ }
+ }
+ }
+ {
+ FOR_UINT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ m.Return(
+ m.Word32Equal(m.Int32Constant(0),
+ m.Word32Ror(m.Parameter(0),
m.Int32Constant(shift))));
+ FOR_UINT32_INPUTS(i) {
+ uint32_t expected = 0 == bits::RotateRight32(*i, shift);
+ CHECK_UINT32_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+ {
+ FOR_UINT32_SHIFTS(shift) {
+ RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ m.Return(
+ m.Word32Equal(m.Word32Ror(m.Parameter(0),
m.Int32Constant(shift)),
+ m.Int32Constant(0)));
+ FOR_UINT32_INPUTS(i) {
+ uint32_t expected = 0 == bits::RotateRight32(*i, shift);
+ CHECK_UINT32_EQ(expected, m.Call(*i));
+ }
+ }
+ }
+}
TEST(RunWord32NotP) {
=======================================
---
/branches/bleeding_edge/test/compiler-unittests/arm/instruction-selector-arm-unittest.cc
Mon Aug 18 07:56:14 2014 UTC
+++
/branches/bleeding_edge/test/compiler-unittests/arm/instruction-selector-arm-unittest.cc
Mon Aug 18 11:10:01 2014 UTC
@@ -1092,6 +1092,43 @@
EXPECT_EQ(kEqual, s[0]->flags_condition());
}
}
+
+
+TEST_P(ShiftTest, Word32EqualToZeroWithParameters) {
+ const Shift shift = GetParam();
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Word32Equal(m.Int32Constant(0),
+ (m.*shift.constructor)(m.Parameter(0),
m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmMov, s[0]->arch_opcode());
+ EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
+ EXPECT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(2U, s[0]->OutputCount());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(kEqual, s[0]->flags_condition());
+}
+
+
+TEST_P(ShiftTest, Word32EqualToZeroWithImmediate) {
+ const Shift shift = GetParam();
+ TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(m.Word32Equal(
+ m.Int32Constant(0),
+ (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmMov, s[0]->arch_opcode());
+ EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
+ EXPECT_EQ(2U, s[0]->OutputCount());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(kEqual, s[0]->flags_condition());
+ }
+}
TEST_P(ShiftTest, Word32NotWithParameters) {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.