[llvm] [AArch64][ISel] Enable profile-aware branch condition merging (PR #201486)

Kunal Pathak via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 3 18:05:20 PDT 2026


https://github.com/kunalspathak created https://github.com/llvm/llvm-project/pull/201486

AArch64 previously inherited the default {-1, -1, -1} for `getJumpConditionMergingParams`, causing `shouldKeepJumpConditionsTogether` in SelectionDAGBuilder to always return false. This meant compound branch conditions (br (and/or cond1, cond2)) were always split into separate basic blocks at the DAG level, and profile data from BranchProbabilityInfo was never consulted for the merge/split decision.

Override `getJumpConditionMergingParams` in AArch64TargetLowering with tunable cl::opt parameters matching the X86 structure. Since `CCMP` is part of the base AArch64 ISA, the `CCMP` bias is applied unconditionally. Default values: `BaseCost=2, CcmpBias=6 (effective threshold 8), LikelyBias=0, UnlikelyBias=-1`.

This enables three improvements:
1. Profile-guided merge/split decisions using BranchProbabilityInfo
2. Smarter compare ordering at the DAG level (e.g., placing large immediates in CMP and small ones in CCMP to respect the 0-31 immediate range)
3. Branch elimination in cases like (a == 5 || b == 32) where the post-ISel CCMP pass previously could not merge due to immediate range constraints

Godbolt:  https://godbolt.org/z/PoPGWehjn

>From ed2a2689689d224a6ee6c6432172eee43c0acb22 Mon Sep 17 00:00:00 2001
From: Kunal Pathak <kupathak at fb.com>
Date: Wed, 3 Jun 2026 17:58:33 -0700
Subject: [PATCH] [AArch64][ISel] Enable profile-aware branch condition merging
 via getJumpConditionMergingParams

AArch64 previously inherited the default {-1, -1, -1} for
`getJumpConditionMergingParams``, causing `shouldKeepJumpConditionsTogether`
in SelectionDAGBuilder to always return false. This meant compound
branch conditions (br (and/or cond1, cond2)) were always split into
separate basic blocks at the DAG level, and profile data from
BranchProbabilityInfo was never consulted for the merge/split decision.

Override `getJumpConditionMergingParams`` in AArch64TargetLowering with
tunable cl::opt parameters matching the X86 structure. Since CCMP is
part of the base AArch64 ISA, the CCMP bias is applied unconditionally.
Default values: BaseCost=2, CcmpBias=6 (effective threshold 8),
LikelyBias=0, UnlikelyBias=-1.

This enables three improvements:
1. Profile-guided merge/split decisions using BranchProbabilityInfo
2. Smarter compare ordering at the DAG level (e.g., placing large
    immediates in CMP and small ones in CCMP to respect the 0-31
    immediate range)
3. Branch elimination in cases like (a == 5 || b == 32) where the
    post-ISel CCMP pass previously could not merge due to immediate
    range constraints

Godbolt:  https://godbolt.org/z/M8veW617q
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  53 ++++
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |   4 +
 llvm/test/CodeGen/AArch64/arm64-ccmp.ll       | 235 ++++++++++++------
 3 files changed, 214 insertions(+), 78 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ec52647135722..e9d0412e45472 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -157,6 +157,47 @@ cl::opt<bool> EnableSVEGISel(
 
 // TODO: This option should be removed once we switch to always using PTRADD in
 // the SelectionDAG.
+static cl::opt<int> BrMergingBaseCostThresh(
+    "aarch64-br-merging-base-cost", cl::init(2),
+    cl::desc(
+        "Sets the cost threshold for when multiple conditionals will be merged "
+        "into one branch versus be split in multiple branches. Merging "
+        "conditionals saves branches at the cost of additional instructions. "
+        "This value sets the instruction cost limit, below which conditionals "
+        "will be merged, and above which conditionals will be split. Set to -1 "
+        "to never merge branches."),
+    cl::Hidden);
+
+static cl::opt<int> BrMergingCcmpBias(
+    "aarch64-br-merging-ccmp-bias", cl::init(6),
+    cl::desc("Increases 'aarch64-br-merging-base-cost' to account for the "
+             "CCMP instruction, which is always available on AArch64 and "
+             "makes merging branch conditions cheaper."),
+    cl::Hidden);
+
+static cl::opt<int> BrMergingLikelyBias(
+    "aarch64-br-merging-likely-bias", cl::init(0),
+    cl::desc("Increases 'aarch64-br-merging-base-cost' in cases that it is "
+             "likely that all conditionals will be executed. For example for "
+             "merging the conditionals (a == b && c > d), if its known that "
+             "a == b is likely, then it is likely that if the conditionals are "
+             "split both sides will be executed, so it may be desirable to "
+             "increase the instruction cost threshold. Set to -1 to never "
+             "merge likely branches."),
+    cl::Hidden);
+
+static cl::opt<int> BrMergingUnlikelyBias(
+    "aarch64-br-merging-unlikely-bias", cl::init(-1),
+    cl::desc(
+        "Decreases 'aarch64-br-merging-base-cost' in cases that it is unlikely "
+        "that all conditionals will be executed. For example for merging "
+        "the conditionals (a == b && c > d), if its known that a == b is "
+        "unlikely, then it is unlikely that if the conditionals are split "
+        "both sides will be executed, so it may be desirable to decrease "
+        "the instruction cost threshold. Set to -1 to never merge unlikely "
+        "branches."),
+    cl::Hidden);
+
 static cl::opt<bool> UseFEATCPACodegen(
     "aarch64-use-featcpa-codegen", cl::Hidden,
     cl::desc("Generate ISD::PTRADD nodes for pointer arithmetic in "
@@ -31529,6 +31570,18 @@ bool AArch64TargetLowering::
   return X.getValueType().isScalarInteger() || NewShiftOpcode == ISD::SHL;
 }
 
+TargetLoweringBase::CondMergingParams
+AArch64TargetLowering::getJumpConditionMergingParams(
+    Instruction::BinaryOps Opc, const Value *Lhs, const Value *Rhs) const {
+  int BaseCost = BrMergingBaseCostThresh.getValue();
+  // CCMP is always available on AArch64.
+  if (BaseCost >= 0)
+    BaseCost += BrMergingCcmpBias;
+
+  return {BaseCost, BrMergingLikelyBias.getValue(),
+          BrMergingUnlikelyBias.getValue()};
+}
+
 TargetLowering::ShiftLegalizationStrategy
 AArch64TargetLowering::preferredShiftLegalizationStrategy(
     SelectionDAG &DAG, SDNode *N, unsigned int ExpansionFactor) const {
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 7e4c4e1ba25ff..20c476d076b47 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -441,6 +441,10 @@ class AArch64TargetLowering : public TargetLowering {
   preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N,
                                      unsigned ExpansionFactor) const override;
 
+  CondMergingParams
+  getJumpConditionMergingParams(Instruction::BinaryOps Opc, const Value *Lhs,
+                                const Value *Rhs) const override;
+
   bool shouldTransformSignedTruncationCheck(EVT XVT,
                                             unsigned KeptBits) const override {
     // For vectors, we don't have a preference..
diff --git a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
index 71d26d25c0515..b3ed2cf27bd97 100644
--- a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
@@ -4,18 +4,31 @@
 target triple = "arm64-apple-ios"
 
 define i32 @single_same(i32 %a, i32 %b) nounwind ssp {
-; CHECK-LABEL: single_same:
-; CHECK:       ; %bb.0: ; %entry
-; CHECK-NEXT:    cmp w0, #5
-; CHECK-NEXT:    ccmp w1, #17, #4, ne
-; CHECK-NEXT:    b.ne LBB0_2
-; CHECK-NEXT:  ; %bb.1: ; %if.then
-; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-NEXT:    bl _foo
-; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-NEXT:  LBB0_2: ; %if.end
-; CHECK-NEXT:    mov w0, #7 ; =0x7
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: single_same:
+; CHECK-SD:       ; %bb.0: ; %entry
+; CHECK-SD-NEXT:    cmp w1, #17
+; CHECK-SD-NEXT:    ccmp w0, #5, #4, ne
+; CHECK-SD-NEXT:    b.ne LBB0_2
+; CHECK-SD-NEXT:  ; %bb.1: ; %if.then
+; CHECK-SD-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    bl _foo
+; CHECK-SD-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-SD-NEXT:  LBB0_2: ; %if.end
+; CHECK-SD-NEXT:    mov w0, #7 ; =0x7
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: single_same:
+; CHECK-GI:       ; %bb.0: ; %entry
+; CHECK-GI-NEXT:    cmp w0, #5
+; CHECK-GI-NEXT:    ccmp w1, #17, #4, ne
+; CHECK-GI-NEXT:    b.ne LBB0_2
+; CHECK-GI-NEXT:  ; %bb.1: ; %if.then
+; CHECK-GI-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-GI-NEXT:    bl _foo
+; CHECK-GI-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-GI-NEXT:  LBB0_2: ; %if.end
+; CHECK-GI-NEXT:    mov w0, #7 ; =0x7
+; CHECK-GI-NEXT:    ret
 entry:
   %cmp = icmp eq i32 %a, 5
   %cmp1 = icmp eq i32 %b, 17
@@ -34,9 +47,9 @@ if.end:
 define i32 @single_different(i32 %a, i32 %b) nounwind ssp {
 ; CHECK-SD-LABEL: single_different:
 ; CHECK-SD:       ; %bb.0: ; %entry
-; CHECK-SD-NEXT:    cmp w0, #6
-; CHECK-SD-NEXT:    ccmp w1, #17, #0, ge
-; CHECK-SD-NEXT:    b.eq LBB1_2
+; CHECK-SD-NEXT:    cmp w1, #17
+; CHECK-SD-NEXT:    ccmp w0, #5, #4, eq
+; CHECK-SD-NEXT:    b.gt LBB1_2
 ; CHECK-SD-NEXT:  ; %bb.1: ; %if.then
 ; CHECK-SD-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
 ; CHECK-SD-NEXT:    bl _foo
@@ -276,17 +289,31 @@ if.end:
 
 ; Chain multiple compares.
 define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp {
-; CHECK-LABEL: multi_different:
-; CHECK:       ; %bb.0: ; %entry
-; CHECK-NEXT:    cmp w0, w1
-; CHECK-NEXT:    sdiv w8, w1, w0
-; CHECK-NEXT:    ccmp w8, #5, #0, gt
-; CHECK-NEXT:    ccmp w8, w2, #4, eq
-; CHECK-NEXT:    b.gt LBB6_2
-; CHECK-NEXT:  ; %bb.1: ; %if.end
-; CHECK-NEXT:    ret
-; CHECK-NEXT:  LBB6_2: ; %if.then
-; CHECK-NEXT:    b _foo
+; CHECK-SD-LABEL: multi_different:
+; CHECK-SD:       ; %bb.0: ; %entry
+; CHECK-SD-NEXT:    cmp w0, w1
+; CHECK-SD-NEXT:    b.le LBB6_3
+; CHECK-SD-NEXT:  ; %bb.1: ; %land.lhs.true
+; CHECK-SD-NEXT:    sdiv w8, w1, w0
+; CHECK-SD-NEXT:    cmp w8, w2
+; CHECK-SD-NEXT:    ccmp w8, #5, #0, gt
+; CHECK-SD-NEXT:    b.ne LBB6_3
+; CHECK-SD-NEXT:  ; %bb.2: ; %if.then
+; CHECK-SD-NEXT:    b _foo
+; CHECK-SD-NEXT:  LBB6_3: ; %if.end
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: multi_different:
+; CHECK-GI:       ; %bb.0: ; %entry
+; CHECK-GI-NEXT:    cmp w0, w1
+; CHECK-GI-NEXT:    sdiv w8, w1, w0
+; CHECK-GI-NEXT:    ccmp w8, #5, #0, gt
+; CHECK-GI-NEXT:    ccmp w8, w2, #4, eq
+; CHECK-GI-NEXT:    b.gt LBB6_2
+; CHECK-GI-NEXT:  ; %bb.1: ; %if.end
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:  LBB6_2: ; %if.then
+; CHECK-GI-NEXT:    b _foo
 entry:
   %cmp = icmp sgt i32 %a, %b
   br i1 %cmp, label %land.lhs.true, label %if.end
@@ -308,18 +335,31 @@ if.end:
 
 ; Convert a cbz in the head block.
 define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp {
-; CHECK-LABEL: cbz_head:
-; CHECK:       ; %bb.0: ; %entry
-; CHECK-NEXT:    cmp w0, #0
-; CHECK-NEXT:    ccmp w1, #17, #0, ne
-; CHECK-NEXT:    b.eq LBB7_2
-; CHECK-NEXT:  ; %bb.1: ; %if.then
-; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-NEXT:    bl _foo
-; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-NEXT:  LBB7_2: ; %if.end
-; CHECK-NEXT:    mov w0, #7 ; =0x7
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: cbz_head:
+; CHECK-SD:       ; %bb.0: ; %entry
+; CHECK-SD-NEXT:    cmp w1, #17
+; CHECK-SD-NEXT:    ccmp w0, #0, #4, eq
+; CHECK-SD-NEXT:    b.ne LBB7_2
+; CHECK-SD-NEXT:  ; %bb.1: ; %if.then
+; CHECK-SD-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    bl _foo
+; CHECK-SD-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-SD-NEXT:  LBB7_2: ; %if.end
+; CHECK-SD-NEXT:    mov w0, #7 ; =0x7
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: cbz_head:
+; CHECK-GI:       ; %bb.0: ; %entry
+; CHECK-GI-NEXT:    cmp w0, #0
+; CHECK-GI-NEXT:    ccmp w1, #17, #0, ne
+; CHECK-GI-NEXT:    b.eq LBB7_2
+; CHECK-GI-NEXT:  ; %bb.1: ; %if.then
+; CHECK-GI-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-GI-NEXT:    bl _foo
+; CHECK-GI-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-GI-NEXT:  LBB7_2: ; %if.end
+; CHECK-GI-NEXT:    mov w0, #7 ; =0x7
+; CHECK-GI-NEXT:    ret
 entry:
   %cmp = icmp eq i32 %a, 0
   %cmp1 = icmp ne i32 %b, 17
@@ -338,22 +378,35 @@ if.end:
 ; smaller range of immediates than subs/adds.
 ; The ccmp immediates must be in the range 0-31.
 define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp {
-; CHECK-LABEL: immediate_range:
-; CHECK:       ; %bb.0: ; %entry
-; CHECK-NEXT:    cmp w0, #5
-; CHECK-NEXT:    b.eq LBB8_3
-; CHECK-NEXT:  ; %bb.1: ; %entry
-; CHECK-NEXT:    cmp w1, #32
-; CHECK-NEXT:    b.eq LBB8_3
-; CHECK-NEXT:  ; %bb.2: ; %if.end
-; CHECK-NEXT:    mov w0, #7 ; =0x7
-; CHECK-NEXT:    ret
-; CHECK-NEXT:  LBB8_3: ; %if.then
-; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-NEXT:    bl _foo
-; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-NEXT:    mov w0, #7 ; =0x7
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: immediate_range:
+; CHECK-SD:       ; %bb.0: ; %entry
+; CHECK-SD-NEXT:    cmp w1, #32
+; CHECK-SD-NEXT:    ccmp w0, #5, #4, ne
+; CHECK-SD-NEXT:    b.ne LBB8_2
+; CHECK-SD-NEXT:  ; %bb.1: ; %if.then
+; CHECK-SD-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    bl _foo
+; CHECK-SD-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-SD-NEXT:  LBB8_2: ; %if.end
+; CHECK-SD-NEXT:    mov w0, #7 ; =0x7
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: immediate_range:
+; CHECK-GI:       ; %bb.0: ; %entry
+; CHECK-GI-NEXT:    cmp w0, #5
+; CHECK-GI-NEXT:    b.eq LBB8_3
+; CHECK-GI-NEXT:  ; %bb.1: ; %entry
+; CHECK-GI-NEXT:    cmp w1, #32
+; CHECK-GI-NEXT:    b.eq LBB8_3
+; CHECK-GI-NEXT:  ; %bb.2: ; %if.end
+; CHECK-GI-NEXT:    mov w0, #7 ; =0x7
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:  LBB8_3: ; %if.then
+; CHECK-GI-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-GI-NEXT:    bl _foo
+; CHECK-GI-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-GI-NEXT:    mov w0, #7 ; =0x7
+; CHECK-GI-NEXT:    ret
 entry:
   %cmp = icmp eq i32 %a, 5
   %cmp1 = icmp eq i32 %b, 32
@@ -370,18 +423,31 @@ if.end:
 
 ; Convert a cbz in the second block.
 define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp {
-; CHECK-LABEL: cbz_second:
-; CHECK:       ; %bb.0: ; %entry
-; CHECK-NEXT:    cmp w0, #0
-; CHECK-NEXT:    ccmp w1, #0, #0, ne
-; CHECK-NEXT:    b.eq LBB9_2
-; CHECK-NEXT:  ; %bb.1: ; %if.then
-; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-NEXT:    bl _foo
-; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-NEXT:  LBB9_2: ; %if.end
-; CHECK-NEXT:    mov w0, #7 ; =0x7
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: cbz_second:
+; CHECK-SD:       ; %bb.0: ; %entry
+; CHECK-SD-NEXT:    cmp w1, #0
+; CHECK-SD-NEXT:    ccmp w0, #0, #4, eq
+; CHECK-SD-NEXT:    b.ne LBB9_2
+; CHECK-SD-NEXT:  ; %bb.1: ; %if.then
+; CHECK-SD-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    bl _foo
+; CHECK-SD-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-SD-NEXT:  LBB9_2: ; %if.end
+; CHECK-SD-NEXT:    mov w0, #7 ; =0x7
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: cbz_second:
+; CHECK-GI:       ; %bb.0: ; %entry
+; CHECK-GI-NEXT:    cmp w0, #0
+; CHECK-GI-NEXT:    ccmp w1, #0, #0, ne
+; CHECK-GI-NEXT:    b.eq LBB9_2
+; CHECK-GI-NEXT:  ; %bb.1: ; %if.then
+; CHECK-GI-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-GI-NEXT:    bl _foo
+; CHECK-GI-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-GI-NEXT:  LBB9_2: ; %if.end
+; CHECK-GI-NEXT:    mov w0, #7 ; =0x7
+; CHECK-GI-NEXT:    ret
 entry:
   %cmp = icmp eq i32 %a, 0
   %cmp1 = icmp ne i32 %b, 0
@@ -398,18 +464,31 @@ if.end:
 
 ; Convert a cbnz in the second block.
 define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp {
-; CHECK-LABEL: cbnz_second:
-; CHECK:       ; %bb.0: ; %entry
-; CHECK-NEXT:    cmp w0, #0
-; CHECK-NEXT:    ccmp w1, #0, #4, ne
-; CHECK-NEXT:    b.ne LBB10_2
-; CHECK-NEXT:  ; %bb.1: ; %if.then
-; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-NEXT:    bl _foo
-; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-NEXT:  LBB10_2: ; %if.end
-; CHECK-NEXT:    mov w0, #7 ; =0x7
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: cbnz_second:
+; CHECK-SD:       ; %bb.0: ; %entry
+; CHECK-SD-NEXT:    cmp w1, #0
+; CHECK-SD-NEXT:    ccmp w0, #0, #4, ne
+; CHECK-SD-NEXT:    b.ne LBB10_2
+; CHECK-SD-NEXT:  ; %bb.1: ; %if.then
+; CHECK-SD-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    bl _foo
+; CHECK-SD-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-SD-NEXT:  LBB10_2: ; %if.end
+; CHECK-SD-NEXT:    mov w0, #7 ; =0x7
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: cbnz_second:
+; CHECK-GI:       ; %bb.0: ; %entry
+; CHECK-GI-NEXT:    cmp w0, #0
+; CHECK-GI-NEXT:    ccmp w1, #0, #4, ne
+; CHECK-GI-NEXT:    b.ne LBB10_2
+; CHECK-GI-NEXT:  ; %bb.1: ; %if.then
+; CHECK-GI-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-GI-NEXT:    bl _foo
+; CHECK-GI-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-GI-NEXT:  LBB10_2: ; %if.end
+; CHECK-GI-NEXT:    mov w0, #7 ; =0x7
+; CHECK-GI-NEXT:    ret
 entry:
   %cmp = icmp eq i32 %a, 0
   %cmp1 = icmp eq i32 %b, 0



More information about the llvm-commits mailing list