Commit d4e20246 authored by Ryan Everett's avatar Ryan Everett Committed by V8 LUCI CQ

[baseline][arm64] Improve code generation for conditional branches

Generate Tbz/Tbnz instead of (tst;bcc),
and Cbz/Cbnz instead of (cmp;bcc), where possible.

This improves Speedometer2 by 0.22% on a Neoverse-N1 machine.

Change-Id: Ie86bae7189a7a4bd4975f946e7413225c9023316
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3833816
Commit-Queue: Martyn Capewell <martyn.capewell@arm.com>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82657}
parent 086f0be5
......@@ -125,8 +125,14 @@ void BaselineAssembler::JumpIfImmediate(Condition cc, Register left, int right,
void BaselineAssembler::TestAndBranch(Register value, int mask, Condition cc,
Label* target, Label::Distance) {
__ Tst(value, Immediate(mask));
__ B(AsMasmCondition(cc), target);
if (cc == Condition::kZero) {
__ TestAndBranchIfAllClear(value, mask, target);
} else if (cc == Condition::kNotZero) {
__ TestAndBranchIfAnySet(value, mask, target);
} else {
__ Tst(value, Immediate(mask));
__ B(AsMasmCondition(cc), target);
}
}
void BaselineAssembler::JumpIf(Condition cc, Register lhs, const Operand& rhs,
......
......@@ -1366,8 +1366,8 @@ void TurboAssembler::PushArgument(const Register& arg) { Push(padreg, arg); }
void TurboAssembler::CompareAndBranch(const Register& lhs, const Operand& rhs,
Condition cond, Label* label) {
if (rhs.IsImmediate() && (rhs.ImmediateValue() == 0) &&
((cond == eq) || (cond == ne))) {
if (cond == eq) {
((cond == eq) || (cond == ne) || (cond == hi) || (cond == ls))) {
if ((cond == eq) || (cond == ls)) {
Cbz(lhs, label);
} else {
Cbnz(lhs, label);
......
......@@ -82,6 +82,54 @@ TEST_F(TurboAssemblerTest, TestCheck) {
ASSERT_DEATH_IF_SUPPORTED({ f.Call(17); }, ERROR_MESSAGE("abort: no reason"));
}
TEST_F(TurboAssemblerTest, CompareAndBranch) {
const int kTestCases[] = {-42, 0, 42};
static_assert(Condition::eq == 0);
static_assert(Condition::le == 13);
TRACED_FORRANGE(int, cc, 0, 13) { // All conds except al and nv
Condition cond = static_cast<Condition>(cc);
TRACED_FOREACH(int, imm, kTestCases) {
auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(isolate(), AssemblerOptions{},
CodeObjectRequired::kNo, buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true);
{
AssemblerBufferWriteScope rw_scope(*buffer);
__ CodeEntry();
Label start, lab;
__ Bind(&start);
__ CompareAndBranch(x0, Immediate(imm), cond, &lab);
if (imm == 0 && ((cond == eq) || (cond == ne) || (cond == hi) ||
(cond == ls))) { // One instruction generated
ASSERT_EQ(kInstrSize, __ SizeOfCodeGeneratedSince(&start));
} else { // Two instructions generated
ASSERT_EQ(static_cast<uint8_t>(2 * kInstrSize),
__ SizeOfCodeGeneratedSince(&start));
}
__ Cmp(x0, Immediate(imm));
__ Check(NegateCondition(cond),
AbortReason::kNoReason); // cond must not hold
__ Ret();
__ Bind(&lab); // Branch leads here
__ Cmp(x0, Immediate(imm));
__ Check(cond, AbortReason::kNoReason); // cond must hold
__ Ret();
CodeDesc desc;
tasm.GetCode(isolate(), &desc);
}
// We need an isolate here to execute in the simulator.
auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
TRACED_FOREACH(int, n, kTestCases) { f.Call(n); }
}
}
}
struct MoveObjectAndSlotTestCase {
const char* comment;
Register dst_object;
......
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