Revision: 23808
Author: [email protected]
Date: Tue Sep 9 14:13:51 2014 UTC
Log: [turbofan] ARM64 branch selector additions
Add support for selecting Cmp and Cmn instructions, and tests for branching
on
the result of arithmetic or logical operations.
BUG=
[email protected]
Review URL: https://codereview.chromium.org/556823002
https://code.google.com/p/v8/source/detail?r=23808
Modified:
/branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc
/branches/bleeding_edge/src/compiler/arm64/instruction-codes-arm64.h
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64-unittest.cc
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
=======================================
--- /branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc Wed
Sep 3 10:13:21 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc Tue
Sep 9 14:13:51 2014 UTC
@@ -339,6 +339,12 @@
case kArm64Cmp32:
__ Cmp(i.InputRegister32(0), i.InputOperand32(1));
break;
+ case kArm64Cmn:
+ __ Cmn(i.InputRegister(0), i.InputOperand(1));
+ break;
+ case kArm64Cmn32:
+ __ Cmn(i.InputRegister32(0), i.InputOperand32(1));
+ break;
case kArm64Tst:
__ Tst(i.InputRegister(0), i.InputOperand(1));
break;
=======================================
--- /branches/bleeding_edge/src/compiler/arm64/instruction-codes-arm64.h
Wed Aug 27 06:25:02 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm64/instruction-codes-arm64.h
Tue Sep 9 14:13:51 2014 UTC
@@ -18,6 +18,8 @@
V(Arm64And32) \
V(Arm64Cmp) \
V(Arm64Cmp32) \
+ V(Arm64Cmn) \
+ V(Arm64Cmn32) \
V(Arm64Tst) \
V(Arm64Tst32) \
V(Arm64Or) \
=======================================
---
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64-unittest.cc
Mon Sep 8 14:08:16 2014 UTC
+++
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64-unittest.cc
Tue Sep 9 14:13:51 2014 UTC
@@ -12,6 +12,8 @@
namespace {
+typedef RawMachineAssembler::Label MLabel;
+
template <typename T>
struct MachInst {
T constructor;
@@ -88,6 +90,13 @@
15597568, 15892480, 16773120};
+// ARM64 flag setting data processing instructions.
+static const MachInst2 kDPFlagSetInstructions[] = {
+ {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32,
kMachInt32},
+ {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
+ {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32}};
+
+
// ARM64 arithmetic with overflow instructions.
static const MachInst2 kOvfAddSubInstructions[] = {
{&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
@@ -341,6 +350,129 @@
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
+
+
+//
-----------------------------------------------------------------------------
+// Data processing controlled branches.
+
+
+typedef InstructionSelectorTestWithParam<MachInst2>
+ InstructionSelectorDPFlagSetTest;
+
+
+TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
+ const MachInst2 dpi = GetParam();
+ const MachineType type = dpi.machine_type;
+ StreamBuilder m(this, type, type, type);
+ MLabel a, b;
+ m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+}
+
+
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
+ InstructionSelectorDPFlagSetTest,
+ ::testing::ValuesIn(kDPFlagSetInstructions));
+
+
+TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnRight) {
+ TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ MLabel a, b;
+ m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ MLabel a, b;
+ m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ MLabel a, b;
+ m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnLeft) {
+ TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ MLabel a, b;
+ m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
+ ASSERT_LE(1U, s[0]->InputCount());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ MLabel a, b;
+ m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
+ ASSERT_LE(1U, s[0]->InputCount());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+ }
+}
//
-----------------------------------------------------------------------------
@@ -452,6 +584,50 @@
EXPECT_EQ(kOverflow, s[0]->flags_condition());
}
}
+
+
+TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
+ const MachInst2 dpi = GetParam();
+ const MachineType type = dpi.machine_type;
+ StreamBuilder m(this, type, type, type);
+ MLabel a, b;
+ Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
+ m.Branch(m.Projection(1, n), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(0));
+ m.Bind(&b);
+ m.Return(m.Projection(0, n));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(4U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kOverflow, s[0]->flags_condition());
+}
+
+
+TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
+ const MachInst2 dpi = GetParam();
+ const MachineType type = dpi.machine_type;
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+ StreamBuilder m(this, type, type);
+ MLabel a, b;
+ Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
+ m.Branch(m.Projection(1, n), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(0));
+ m.Bind(&b);
+ m.Return(m.Projection(0, n));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ ASSERT_EQ(4U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kOverflow, s[0]->flags_condition());
+ }
+}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
@@ -510,6 +686,29 @@
EXPECT_EQ(kOverflow, s[0]->flags_condition());
}
}
+
+
+TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
+ TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ MLabel a, b;
+ Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
+ m.Branch(m.Projection(1, n), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(0));
+ m.Bind(&b);
+ m.Return(m.Projection(0, n));
+ Stream s = m.Build();
+
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ ASSERT_EQ(4U, s[0]->InputCount());
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kOverflow, s[0]->flags_condition());
+ }
+}
//
-----------------------------------------------------------------------------
=======================================
---
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
Mon Sep 8 14:08:16 2014 UTC
+++
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
Tue Sep 9 14:13:51 2014 UTC
@@ -525,6 +525,10 @@
void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation*
cont) {
switch (node->opcode()) {
+ case IrOpcode::kInt32Add:
+ return VisitWordCompare(this, node, kArm64Cmn32, cont, true);
+ case IrOpcode::kInt32Sub:
+ return VisitWordCompare(this, node, kArm64Cmp32, cont, false);
case IrOpcode::kWord32And:
return VisitWordCompare(this, node, kArm64Tst32, cont, true);
default:
--
--
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.