Commit ad815be7 authored by baptiste.afsa@arm.com's avatar baptiste.afsa@arm.com

[turbofan] Use cbz/cbnz when possible on arm64.

R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25288}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25288 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 37b00b91
......@@ -172,12 +172,10 @@ class Arm64OperandConverter FINAL : public InstructionOperandConverter {
} while (0)
#define ASSEMBLE_TEST_AND_BRANCH(asm_instr, width) \
do { \
bool fallthrough = IsNextInAssemblyOrder(i.InputRpo(3)); \
__ asm_instr(i.InputRegister##width(0), i.InputInt6(1), \
GetLabel(i.InputRpo(2))); \
if (!fallthrough) __ B(GetLabel(i.InputRpo(3))); \
#define ASSEMBLE_BRANCH_TO(target) \
do { \
bool fallthrough = IsNextInAssemblyOrder(target); \
if (!fallthrough) __ B(GetLabel(target)); \
} while (0)
......@@ -430,16 +428,28 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
i.InputInt8(2));
break;
case kArm64Tbz:
ASSEMBLE_TEST_AND_BRANCH(Tbz, 64);
__ Tbz(i.InputRegister64(0), i.InputInt6(1), GetLabel(i.InputRpo(2)));
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
break;
case kArm64Tbz32:
ASSEMBLE_TEST_AND_BRANCH(Tbz, 32);
__ Tbz(i.InputRegister32(0), i.InputInt5(1), GetLabel(i.InputRpo(2)));
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
break;
case kArm64Tbnz:
ASSEMBLE_TEST_AND_BRANCH(Tbnz, 64);
__ Tbnz(i.InputRegister64(0), i.InputInt6(1), GetLabel(i.InputRpo(2)));
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
break;
case kArm64Tbnz32:
ASSEMBLE_TEST_AND_BRANCH(Tbnz, 32);
__ Tbnz(i.InputRegister32(0), i.InputInt5(1), GetLabel(i.InputRpo(2)));
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
break;
case kArm64Cbz32:
__ Cbz(i.InputRegister32(0), GetLabel(i.InputRpo(1)));
ASSEMBLE_BRANCH_TO(i.InputRpo(2));
break;
case kArm64Cbnz32:
__ Cbnz(i.InputRegister32(0), GetLabel(i.InputRpo(1)));
ASSEMBLE_BRANCH_TO(i.InputRpo(2));
break;
case kArm64Claim: {
int words = MiscField::decode(instr->opcode());
......
......@@ -72,6 +72,8 @@ namespace compiler {
V(Arm64Tbz32) \
V(Arm64Tbnz) \
V(Arm64Tbnz32) \
V(Arm64Cbz32) \
V(Arm64Cbnz32) \
V(Arm64Claim) \
V(Arm64Poke) \
V(Arm64PokePairZero) \
......
......@@ -1270,8 +1270,11 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
}
}
// Branch could not be combined with a compare, emit compare against 0.
VisitWord32Test(this, value, &cont);
// Branch could not be combined with a compare, compare against 0 and branch.
DCHECK((cont.condition() == kEqual) || (cont.condition() == kNotEqual));
ArchOpcode opcode = (cont.condition() == kEqual) ? kArm64Cbz32 : kArm64Cbnz32;
Emit(opcode, NULL, g.UseRegister(value), g.Label(cont.true_block()),
g.Label(cont.false_block()))->MarkAsControl();
}
......
......@@ -952,6 +952,41 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
}
TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);
MLabel a, b;
Node* p0 = m.Parameter(0);
m.Branch(p0, &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(kArm64Cbnz32, s[0]->arch_opcode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
}
{
StreamBuilder m(this, kMachInt32, kMachInt32);
MLabel a, b;
Node* p0 = m.Parameter(0);
m.Branch(m.Word32BinaryNot(p0), &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(kArm64Cbz32, s[0]->arch_opcode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
}
}
// -----------------------------------------------------------------------------
// Add and subtract instructions with overflow.
......
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