[arm64] Emit CBZ for deoptimisations.
Emit the compare and branch on zero (CBZ) instruction when possible for deoptimisations, as we do for normal branches. BUG= Review-Url: https://codereview.chromium.org/2448113002 Cr-Commit-Position: refs/heads/master@{#40568}
This commit is contained in:
parent
99e845cc9f
commit
3836fc074b
@ -2152,6 +2152,20 @@ FlagsCondition MapForCbz(FlagsCondition cond) {
|
||||
}
|
||||
}
|
||||
|
||||
void EmitBranchOrDeoptimize(InstructionSelector* selector,
|
||||
InstructionCode opcode, InstructionOperand value,
|
||||
FlagsContinuation* cont) {
|
||||
Arm64OperandGenerator g(selector);
|
||||
if (cont->IsBranch()) {
|
||||
selector->Emit(cont->Encode(opcode), g.NoOutput(), value,
|
||||
g.Label(cont->true_block()), g.Label(cont->false_block()));
|
||||
} else {
|
||||
DCHECK(cont->IsDeoptimize());
|
||||
selector->EmitDeoptimize(cont->Encode(opcode), g.NoOutput(), value,
|
||||
cont->reason(), cont->frame_state());
|
||||
}
|
||||
}
|
||||
|
||||
// Try to emit TBZ, TBNZ, CBZ or CBNZ for certain comparisons of {node}
|
||||
// against zero, depending on the condition.
|
||||
bool TryEmitCbzOrTbz(InstructionSelector* selector, Node* node, Node* user,
|
||||
@ -2160,12 +2174,16 @@ bool TryEmitCbzOrTbz(InstructionSelector* selector, Node* node, Node* user,
|
||||
USE(m_user);
|
||||
DCHECK(m_user.right().Is(0) || m_user.left().Is(0));
|
||||
|
||||
// Only handle branches.
|
||||
if (!cont->IsBranch()) return false;
|
||||
// Only handle branches and deoptimisations.
|
||||
if (!cont->IsBranch() && !cont->IsDeoptimize()) return false;
|
||||
|
||||
switch (cond) {
|
||||
case kSignedLessThan:
|
||||
case kSignedGreaterThanOrEqual: {
|
||||
// We don't generate TBZ/TBNZ for deoptimisations, as they have a
|
||||
// shorter range than conditional branches and generating them for
|
||||
// deoptimisations results in more veneers.
|
||||
if (cont->IsDeoptimize()) return false;
|
||||
Arm64OperandGenerator g(selector);
|
||||
cont->Overwrite(MapForTbz(cond));
|
||||
Int32Matcher m(node);
|
||||
@ -2192,9 +2210,8 @@ bool TryEmitCbzOrTbz(InstructionSelector* selector, Node* node, Node* user,
|
||||
case kUnsignedGreaterThan: {
|
||||
Arm64OperandGenerator g(selector);
|
||||
cont->Overwrite(MapForCbz(cond));
|
||||
selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(),
|
||||
g.UseRegister(node), g.Label(cont->true_block()),
|
||||
g.Label(cont->false_block()));
|
||||
EmitBranchOrDeoptimize(selector, kArm64CompareAndBranch32,
|
||||
g.UseRegister(node), cont);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -2380,10 +2397,10 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
||||
kLogical64Imm);
|
||||
}
|
||||
// Merge the Word64Equal(x, 0) comparison into a cbz instruction.
|
||||
if (cont->IsBranch()) {
|
||||
selector->Emit(cont->Encode(kArm64CompareAndBranch), g.NoOutput(),
|
||||
g.UseRegister(left), g.Label(cont->true_block()),
|
||||
g.Label(cont->false_block()));
|
||||
if (cont->IsBranch() || cont->IsDeoptimize()) {
|
||||
EmitBranchOrDeoptimize(selector,
|
||||
cont->Encode(kArm64CompareAndBranch),
|
||||
g.UseRegister(left), cont);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2017,6 +2017,18 @@ void InstructionSelector::VisitReturn(Node* ret) {
|
||||
}
|
||||
}
|
||||
|
||||
Instruction* InstructionSelector::EmitDeoptimize(InstructionCode opcode,
|
||||
InstructionOperand output,
|
||||
InstructionOperand a,
|
||||
DeoptimizeReason reason,
|
||||
Node* frame_state) {
|
||||
size_t output_count = output.IsInvalid() ? 0 : 1;
|
||||
InstructionOperand inputs[] = {a};
|
||||
size_t input_count = arraysize(inputs);
|
||||
return EmitDeoptimize(opcode, output_count, &output, input_count, inputs,
|
||||
reason, frame_state);
|
||||
}
|
||||
|
||||
Instruction* InstructionSelector::EmitDeoptimize(
|
||||
InstructionCode opcode, InstructionOperand output, InstructionOperand a,
|
||||
InstructionOperand b, DeoptimizeReason reason, Node* frame_state) {
|
||||
|
@ -110,6 +110,9 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
|
||||
// ===== Architecture-independent deoptimization exit emission methods. ======
|
||||
// ===========================================================================
|
||||
|
||||
Instruction* EmitDeoptimize(InstructionCode opcode, InstructionOperand output,
|
||||
InstructionOperand a, DeoptimizeReason reason,
|
||||
Node* frame_state);
|
||||
Instruction* EmitDeoptimize(InstructionCode opcode, InstructionOperand output,
|
||||
InstructionOperand a, InstructionOperand b,
|
||||
DeoptimizeReason reason, Node* frame_state);
|
||||
|
Loading…
Reference in New Issue
Block a user