Index: src/compiler/arm64/instruction-selector-arm64.cc |
diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc |
index da27be8626acbc43b653c36b541388a76e5bc5f7..be56d5cc81c37bffafeb04150b75e3636e41cae5 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -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; |
} |
} |