[llvm-branch-commits] [llvm] [AArch64] Form CCMP for CBB and CBH (PR #221113)
David Tellenbach via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Sep 6 14:08:09 PDT 2026
https://github.com/dtellenbach updated https://github.com/llvm/llvm-project/pull/221113
>From 47b6025ae445e3047b291a3f14438dbc62df9fb5 Mon Sep 17 00:00:00 2001
From: David Tellenbach <dtellenbach at apple.com>
Date: Wed, 2 Sep 2026 19:55:39 -0700
Subject: [PATCH] [AArch64] Form CCMP for CBB and CBH
AArch64ConditionalCompares forms CMP/CCMP chains to transform patterns
such as
Head Head
/ | CmpBB
/ | / |
| CmpBB => / |
| / | Tail |
| / | | |
Tail | | |
| | | |
... ... ... ...
where Head is terminated by a conditional branch and CmpBB contains
a cmp + conditional branch.
We usually try to split any fused conditional branches to be able to
form CCMP. However, in the case of CBB and CBH, splitting the fused
conditional branch in CmpBB could require the insertion of explicit
zero- or sign-extensions for both operands. In the Head block we can
cheaply fuse at least one of the extensions into cmp.
We therefore convert CBB and CBH unconditionally when we find them in
the Head block. In the CmpBB block, we only do the transformation if
neither operands needs an extension.
---
.../AArch64/AArch64ConditionalCompares.cpp | 40 +-
llvm/test/CodeGen/AArch64/cmpbr-ccmp.ll | 232 ++++++++++
llvm/test/CodeGen/AArch64/cmpbr-ccmp.mir | 406 ++++++++++++++++++
3 files changed, 676 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp b/llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp
index 95a08f701b7cc..8f50c4fcdb774 100644
--- a/llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp
@@ -18,6 +18,7 @@
#include "AArch64.h"
#include "AArch64InstrInfo.h"
+#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
@@ -306,7 +307,7 @@ static bool parseCond(ArrayRef<MachineOperand> Cond, AArch64CC::CondCode &CC) {
CC = AArch64CC::NE;
return true;
- // For CB, cond is { -1, Opcode, CC, Op0, Op1, ... }
+ // For CB, cond is { -1, Opcode, CC, Op0, Op1 }
case AArch64::CBWPri:
case AArch64::CBXPri:
case AArch64::CBWPrr:
@@ -315,6 +316,14 @@ static bool parseCond(ArrayRef<MachineOperand> Cond, AArch64CC::CondCode &CC) {
// Pseudos using standard 4bit Arm condition codes.
CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
return true;
+
+ // For CBB and CBH, cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
+ case AArch64::CBBAssertExt:
+ case AArch64::CBHAssertExt:
+ assert(Cond.size() == 7 && "Unknown Cond array format");
+ // Pseudos using standard 4bit Arm condition codes.
+ CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
+ return true;
}
}
@@ -337,7 +346,7 @@ MachineInstr *SSACCmpConv::findConvertibleCompare(MachineBasicBlock *MBB) {
// CB encodes a uimm6, ccmp wants a uimm5 so we have to check if the
// immediate fits.
case AArch64::CBWPri:
- case AArch64::CBXPri:
+ case AArch64::CBXPri: {
assert(I->getOperand(2).isImm() && "Expected immediate operand");
if (!isUInt<5>(I->getOperand(2).getImm())) {
LLVM_DEBUG(dbgs() << "Immediate out of range for ccmp: " << *I);
@@ -346,6 +355,20 @@ MachineInstr *SSACCmpConv::findConvertibleCompare(MachineBasicBlock *MBB) {
}
return &*I;
}
+ // Check if any of the operands would need zero- or sign-extension. If so,
+ // bail out
+ case AArch64::CBBAssertExt:
+ case AArch64::CBHAssertExt: {
+ assert(I->getOperand(4).isImm() && "Expected immediate operand");
+ assert(I->getOperand(5).isImm() && "Expected immediate operand");
+ if (I->getOperand(4).getImm() != AArch64_AM::InvalidShiftExtend ||
+ I->getOperand(5).getImm() != AArch64_AM::InvalidShiftExtend) {
+ LLVM_DEBUG(dbgs() << "Folded extend can't be folded into ccmp: " << *I);
+ return nullptr;
+ }
+ return &*I;
+ }
+ }
++NumCmpTermRejs;
LLVM_DEBUG(dbgs() << "Flags not used by terminator: " << *I);
return nullptr;
@@ -698,6 +721,8 @@ void SSACCmpConv::convert(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks) {
FirstOp = 1;
break;
case AArch64::CBWPrr:
+ case AArch64::CBBAssertExt:
+ case AArch64::CBHAssertExt:
Opc = AArch64::CCMPWr;
FirstOp = 1;
break;
@@ -744,6 +769,8 @@ void SSACCmpConv::convert(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks) {
break;
case AArch64::CBWPri:
case AArch64::CBXPri:
+ case AArch64::CBBAssertExt:
+ case AArch64::CBHAssertExt:
case AArch64::CBWPrr:
case AArch64::CBXPrr:
CC = static_cast<AArch64CC::CondCode>(CmpMI->getOperand(0).getImm());
@@ -780,6 +807,13 @@ int SSACCmpConv::expectedCodeSizeDelta() const {
// Therefore delta += 1
delta = 1;
break;
+ // The cbb / cbh case might need a zero- or sign-extension, costing another
+ // instruction
+ case AArch64::CBBAssertExt:
+ case AArch64::CBHAssertExt:
+ assert(HeadCond[5].isImm() && "Expected immediate operand");
+ delta = (HeadCond[5].getImm() != AArch64_AM::InvalidShiftExtend ? 2 : 1);
+ break;
default:
llvm_unreachable("Cannot convert Head branch");
}
@@ -798,6 +832,8 @@ int SSACCmpConv::expectedCodeSizeDelta() const {
case AArch64::CBNZX:
case AArch64::CBWPri:
case AArch64::CBXPri:
+ case AArch64::CBBAssertExt:
+ case AArch64::CBHAssertExt:
case AArch64::CBWPrr:
case AArch64::CBXPrr:
break;
diff --git a/llvm/test/CodeGen/AArch64/cmpbr-ccmp.ll b/llvm/test/CodeGen/AArch64/cmpbr-ccmp.ll
index 150a38716afb2..cfb9e1038b7c1 100644
--- a/llvm/test/CodeGen/AArch64/cmpbr-ccmp.ll
+++ b/llvm/test/CodeGen/AArch64/cmpbr-ccmp.ll
@@ -3,6 +3,7 @@
; RUN: llc -mtriple=arm64-apple-ios -mattr -cmpbr -aarch64-stress-ccmp -verify-machineinstrs -o - %s | FileCheck %s --check-prefix=CHECK-NO-CMPBR
declare i32 @foo()
+declare i32 @bar(i32)
define i32 @cb_chain_imm(i32 %a, i32 %b) nounwind {
; CHECK-CMPBR-LABEL: cb_chain_imm:
@@ -517,3 +518,234 @@ if.then:
if.end:
ret i32 7
}
+
+define i32 @cbb_chain_reg(i8 signext %a, i8 signext %b, i8 signext %c, i8 signext %d, i32 %x, i32 %y) nounwind {
+; CHECK-CMPBR-LABEL: cbb_chain_reg:
+; CHECK-CMPBR: ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT: cmp w0, w1
+; CHECK-CMPBR-NEXT: ccmp w2, w3, #0, gt
+; CHECK-CMPBR-NEXT: b.lt LBB11_2
+; CHECK-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+; CHECK-CMPBR-NEXT: LBB11_2: ; %if.then
+; CHECK-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-CMPBR-NEXT: sdiv w0, w4, w5
+; CHECK-CMPBR-NEXT: bl _bar
+; CHECK-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+;
+; CHECK-NO-CMPBR-LABEL: cbb_chain_reg:
+; CHECK-NO-CMPBR: ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT: cmp w0, w1
+; CHECK-NO-CMPBR-NEXT: ccmp w2, w3, #0, gt
+; CHECK-NO-CMPBR-NEXT: b.lt LBB11_2
+; CHECK-NO-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+; CHECK-NO-CMPBR-NEXT: LBB11_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-NO-CMPBR-NEXT: sdiv w0, w4, w5
+; CHECK-NO-CMPBR-NEXT: bl _bar
+; CHECK-NO-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+entry:
+ %cmp = icmp sgt i8 %a, %b
+ br i1 %cmp, label %land.lhs.true, label %if.end
+land.lhs.true:
+ %div = sdiv i32 %x, %y
+ %cmp1 = icmp slt i8 %c, %d
+ br i1 %cmp1, label %if.then, label %if.end
+if.then:
+ %call = tail call i32 @bar(i32 %div) nounwind
+ br label %if.end
+if.end:
+ ret i32 7
+}
+
+define i32 @cbh_chain_reg(i16 signext %a, i16 signext %b, i16 signext %c, i16 signext %d, i32 %x, i32 %y) nounwind {
+; CHECK-CMPBR-LABEL: cbh_chain_reg:
+; CHECK-CMPBR: ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT: cmp w0, w1
+; CHECK-CMPBR-NEXT: ccmp w2, w3, #2, hi
+; CHECK-CMPBR-NEXT: b.lo LBB12_2
+; CHECK-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+; CHECK-CMPBR-NEXT: LBB12_2: ; %if.then
+; CHECK-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-CMPBR-NEXT: sdiv w0, w4, w5
+; CHECK-CMPBR-NEXT: bl _bar
+; CHECK-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+;
+; CHECK-NO-CMPBR-LABEL: cbh_chain_reg:
+; CHECK-NO-CMPBR: ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT: cmp w0, w1
+; CHECK-NO-CMPBR-NEXT: ccmp w2, w3, #2, hi
+; CHECK-NO-CMPBR-NEXT: b.lo LBB12_2
+; CHECK-NO-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+; CHECK-NO-CMPBR-NEXT: LBB12_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-NO-CMPBR-NEXT: sdiv w0, w4, w5
+; CHECK-NO-CMPBR-NEXT: bl _bar
+; CHECK-NO-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+entry:
+ %cmp = icmp ugt i16 %a, %b
+ br i1 %cmp, label %land.lhs.true, label %if.end
+land.lhs.true:
+ %div = sdiv i32 %x, %y
+ %cmp1 = icmp ult i16 %c, %d
+ br i1 %cmp1, label %if.then, label %if.end
+if.then:
+ %call = tail call i32 @bar(i32 %div) nounwind
+ br label %if.end
+if.end:
+ ret i32 7
+}
+
+define i32 @cbb_head_cb_cmpbb(i8 signext %a, i8 signext %b, i32 %x, i32 %y) nounwind {
+; CHECK-CMPBR-LABEL: cbb_head_cb_cmpbb:
+; CHECK-CMPBR: ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT: sdiv w8, w2, w3
+; CHECK-CMPBR-NEXT: cmp w0, w1
+; CHECK-CMPBR-NEXT: ccmp w8, #16, #0, gt
+; CHECK-CMPBR-NEXT: b.le LBB13_2
+; CHECK-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+; CHECK-CMPBR-NEXT: LBB13_2: ; %if.then
+; CHECK-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-CMPBR-NEXT: bl _foo
+; CHECK-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+;
+; CHECK-NO-CMPBR-LABEL: cbb_head_cb_cmpbb:
+; CHECK-NO-CMPBR: ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT: sdiv w8, w2, w3
+; CHECK-NO-CMPBR-NEXT: cmp w0, w1
+; CHECK-NO-CMPBR-NEXT: ccmp w8, #16, #0, gt
+; CHECK-NO-CMPBR-NEXT: b.le LBB13_2
+; CHECK-NO-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+; CHECK-NO-CMPBR-NEXT: LBB13_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-NO-CMPBR-NEXT: bl _foo
+; CHECK-NO-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+entry:
+ %cmp = icmp sgt i8 %a, %b
+ br i1 %cmp, label %land.lhs.true, label %if.end
+land.lhs.true:
+ %div = sdiv i32 %x, %y
+ %cmp1 = icmp slt i32 %div, 17
+ br i1 %cmp1, label %if.then, label %if.end
+if.then:
+ %call = tail call i32 @foo() nounwind
+ br label %if.end
+if.end:
+ ret i32 7
+}
+
+define i32 @cbb_head_sext(i8 signext %a, i32 %n, i32 %x, i32 %y) nounwind {
+; CHECK-CMPBR-LABEL: cbb_head_sext:
+; CHECK-CMPBR: ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT: sdiv w8, w2, w3
+; CHECK-CMPBR-NEXT: sxtb w9, w1
+; CHECK-CMPBR-NEXT: cmp w9, w0
+; CHECK-CMPBR-NEXT: ccmp w8, #16, #0, gt
+; CHECK-CMPBR-NEXT: b.le LBB14_2
+; CHECK-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+; CHECK-CMPBR-NEXT: LBB14_2: ; %if.then
+; CHECK-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-CMPBR-NEXT: bl _foo
+; CHECK-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+;
+; CHECK-NO-CMPBR-LABEL: cbb_head_sext:
+; CHECK-NO-CMPBR: ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT: sdiv w8, w2, w3
+; CHECK-NO-CMPBR-NEXT: cmp w0, w1, sxtb
+; CHECK-NO-CMPBR-NEXT: ccmp w8, #16, #0, lt
+; CHECK-NO-CMPBR-NEXT: b.le LBB14_2
+; CHECK-NO-CMPBR-NEXT: ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+; CHECK-NO-CMPBR-NEXT: LBB14_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-NO-CMPBR-NEXT: bl _foo
+; CHECK-NO-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+entry:
+ %t = trunc i32 %n to i8
+ %cmp = icmp sgt i8 %t, %a
+ br i1 %cmp, label %land.lhs.true, label %if.end
+land.lhs.true:
+ %div = sdiv i32 %x, %y
+ %cmp1 = icmp slt i32 %div, 17
+ br i1 %cmp1, label %if.then, label %if.end
+if.then:
+ %call = tail call i32 @foo() nounwind
+ br label %if.end
+if.end:
+ ret i32 7
+}
+
+define i32 @cbh_cmpbb_sext_reject(i16 signext %a, i32 %x, i32 %y) nounwind {
+; CHECK-CMPBR-LABEL: cbh_cmpbb_sext_reject:
+; CHECK-CMPBR: ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT: cblt w1, #1, LBB15_3
+; CHECK-CMPBR-NEXT: ; %bb.1: ; %land.lhs.true
+; CHECK-CMPBR-NEXT: sdiv w8, w2, w1
+; CHECK-CMPBR-NEXT: cbhge w8, w0, LBB15_3
+; CHECK-CMPBR-NEXT: ; %bb.2: ; %if.then
+; CHECK-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-CMPBR-NEXT: bl _foo
+; CHECK-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-CMPBR-NEXT: LBB15_3: ; %if.end
+; CHECK-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-CMPBR-NEXT: ret
+;
+; CHECK-NO-CMPBR-LABEL: cbh_cmpbb_sext_reject:
+; CHECK-NO-CMPBR: ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT: cmp w1, #1
+; CHECK-NO-CMPBR-NEXT: b.lt LBB15_3
+; CHECK-NO-CMPBR-NEXT: ; %bb.1: ; %land.lhs.true
+; CHECK-NO-CMPBR-NEXT: sdiv w8, w2, w1
+; CHECK-NO-CMPBR-NEXT: cmp w0, w8, sxth
+; CHECK-NO-CMPBR-NEXT: b.le LBB15_3
+; CHECK-NO-CMPBR-NEXT: ; %bb.2: ; %if.then
+; CHECK-NO-CMPBR-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-NO-CMPBR-NEXT: bl _foo
+; CHECK-NO-CMPBR-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-NO-CMPBR-NEXT: LBB15_3: ; %if.end
+; CHECK-NO-CMPBR-NEXT: mov w0, #7 ; =0x7
+; CHECK-NO-CMPBR-NEXT: ret
+entry:
+ %cmp = icmp sgt i32 %x, 0
+ br i1 %cmp, label %land.lhs.true, label %if.end
+land.lhs.true:
+ %div = sdiv i32 %y, %x
+ %t = trunc i32 %div to i16
+ %cmp1 = icmp slt i16 %t, %a
+ br i1 %cmp1, label %if.then, label %if.end
+if.then:
+ %call = tail call i32 @foo() nounwind
+ br label %if.end
+if.end:
+ ret i32 7
+}
diff --git a/llvm/test/CodeGen/AArch64/cmpbr-ccmp.mir b/llvm/test/CodeGen/AArch64/cmpbr-ccmp.mir
index ae536033fb312..3d69de99475c1 100644
--- a/llvm/test/CodeGen/AArch64/cmpbr-ccmp.mir
+++ b/llvm/test/CodeGen/AArch64/cmpbr-ccmp.mir
@@ -792,3 +792,409 @@ body: |
$w0 = COPY %4
RET_ReallyLR implicit $w0
...
+
+---
+name: cbb_chain
+alignment: 4
+tracksRegLiveness: true
+isSSA: true
+registers:
+ - { id: 0, class: gpr32 }
+ - { id: 1, class: gpr32 }
+ - { id: 2, class: gpr32 }
+ - { id: 3, class: gpr32 }
+ - { id: 4, class: gpr32 }
+liveins:
+ - { reg: '$w0', virtual-reg: '%0' }
+ - { reg: '$w1', virtual-reg: '%1' }
+ - { reg: '$w2', virtual-reg: '%2' }
+ - { reg: '$w3', virtual-reg: '%3' }
+body: |
+ ; CHECK-LABEL: name: cbb_chain
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x60000000), %bb.2(0x20000000)
+ ; CHECK-NEXT: liveins: $w0, $w1, $w2, $w3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY $w3
+ ; CHECK-NEXT: $wzr = SUBSWrr [[COPY]], [[COPY1]], implicit-def $nzcv
+ ; CHECK-NEXT: CCMPWr [[COPY2]], [[COPY3]], 4, 1, implicit-def $nzcv, implicit $nzcv
+ ; CHECK-NEXT: Bcc 0, %bb.3, implicit $nzcv
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7
+ ; CHECK-NEXT: $w0 = COPY [[MOVi32imm]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0:
+ successors: %bb.1, %bb.3
+ liveins: $w0, $w1, $w2, $w3
+
+ %0:gpr32 = COPY $w0
+ %1:gpr32 = COPY $w1
+ %2:gpr32 = COPY $w2
+ %3:gpr32 = COPY $w3
+ CBBAssertExt 0, %0, %1, %bb.3, -1, -1
+ B %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ CBBAssertExt 0, %2, %3, %bb.3, -1, -1
+ B %bb.2
+
+ bb.2:
+ successors: %bb.3
+
+ B %bb.3
+
+ bb.3:
+ %4:gpr32 = MOVi32imm 7
+ $w0 = COPY %4
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: cbh_chain
+alignment: 4
+tracksRegLiveness: true
+isSSA: true
+registers:
+ - { id: 0, class: gpr32 }
+ - { id: 1, class: gpr32 }
+ - { id: 2, class: gpr32 }
+ - { id: 3, class: gpr32 }
+ - { id: 4, class: gpr32 }
+liveins:
+ - { reg: '$w0', virtual-reg: '%0' }
+ - { reg: '$w1', virtual-reg: '%1' }
+ - { reg: '$w2', virtual-reg: '%2' }
+ - { reg: '$w3', virtual-reg: '%3' }
+body: |
+ ; CHECK-LABEL: name: cbh_chain
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x60000000), %bb.2(0x20000000)
+ ; CHECK-NEXT: liveins: $w0, $w1, $w2, $w3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY $w3
+ ; CHECK-NEXT: $wzr = SUBSWrr [[COPY]], [[COPY1]], implicit-def $nzcv
+ ; CHECK-NEXT: CCMPWr [[COPY2]], [[COPY3]], 0, 0, implicit-def $nzcv, implicit $nzcv
+ ; CHECK-NEXT: Bcc 1, %bb.3, implicit $nzcv
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7
+ ; CHECK-NEXT: $w0 = COPY [[MOVi32imm]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0:
+ successors: %bb.1, %bb.3
+ liveins: $w0, $w1, $w2, $w3
+
+ %0:gpr32 = COPY $w0
+ %1:gpr32 = COPY $w1
+ %2:gpr32 = COPY $w2
+ %3:gpr32 = COPY $w3
+ CBHAssertExt 1, %0, %1, %bb.3, -1, -1
+ B %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ CBHAssertExt 1, %2, %3, %bb.3, -1, -1
+ B %bb.2
+
+ bb.2:
+ successors: %bb.3
+
+ B %bb.3
+
+ bb.3:
+ %4:gpr32 = MOVi32imm 7
+ $w0 = COPY %4
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: cbb_head_zext
+alignment: 4
+tracksRegLiveness: true
+isSSA: true
+registers:
+ - { id: 0, class: gpr32 }
+ - { id: 1, class: gpr32 }
+ - { id: 2, class: gpr32 }
+ - { id: 3, class: gpr32 }
+ - { id: 4, class: gpr32 }
+liveins:
+ - { reg: '$w0', virtual-reg: '%0' }
+ - { reg: '$w1', virtual-reg: '%1' }
+ - { reg: '$w2', virtual-reg: '%2' }
+ - { reg: '$w3', virtual-reg: '%3' }
+body: |
+ ; CHECK-LABEL: name: cbb_head_zext
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x60000000), %bb.2(0x20000000)
+ ; CHECK-NEXT: liveins: $w0, $w1, $w2, $w3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY $w3
+ ; CHECK-NEXT: [[ANDWri:%[0-9]+]]:gpr32common = ANDWri [[COPY]], 7
+ ; CHECK-NEXT: $wzr = SUBSWrx [[ANDWri]], [[COPY1]], 0, implicit-def $nzcv
+ ; CHECK-NEXT: CCMPWr [[COPY2]], [[COPY3]], 0, 3, implicit-def $nzcv, implicit $nzcv
+ ; CHECK-NEXT: Bcc 12, %bb.3, implicit $nzcv
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7
+ ; CHECK-NEXT: $w0 = COPY [[MOVi32imm]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0:
+ successors: %bb.1, %bb.3
+ liveins: $w0, $w1, $w2, $w3
+
+ %0:gpr32 = COPY $w0
+ %1:gpr32 = COPY $w1
+ %2:gpr32 = COPY $w2
+ %3:gpr32 = COPY $w3
+ CBBAssertExt 2, %0, %1, %bb.3, 0, 0
+ B %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ CBWPrr 12, %2, %3, %bb.3
+ B %bb.2
+
+ bb.2:
+ successors: %bb.3
+
+ B %bb.3
+
+ bb.3:
+ %4:gpr32 = MOVi32imm 7
+ $w0 = COPY %4
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: cbh_head_sext
+alignment: 4
+tracksRegLiveness: true
+isSSA: true
+registers:
+ - { id: 0, class: gpr32 }
+ - { id: 1, class: gpr32 }
+ - { id: 2, class: gpr32 }
+ - { id: 3, class: gpr32 }
+ - { id: 4, class: gpr32 }
+liveins:
+ - { reg: '$w0', virtual-reg: '%0' }
+ - { reg: '$w1', virtual-reg: '%1' }
+ - { reg: '$w2', virtual-reg: '%2' }
+ - { reg: '$w3', virtual-reg: '%3' }
+body: |
+ ; CHECK-LABEL: name: cbh_head_sext
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x60000000), %bb.2(0x20000000)
+ ; CHECK-NEXT: liveins: $w0, $w1, $w2, $w3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY $w3
+ ; CHECK-NEXT: [[SBFMWri:%[0-9]+]]:gpr32common = SBFMWri [[COPY]], 0, 15
+ ; CHECK-NEXT: $wzr = SUBSWrx [[SBFMWri]], [[COPY1]], 40, implicit-def $nzcv
+ ; CHECK-NEXT: CCMPWr [[COPY2]], [[COPY3]], 0, 13, implicit-def $nzcv, implicit $nzcv
+ ; CHECK-NEXT: Bcc 10, %bb.3, implicit $nzcv
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7
+ ; CHECK-NEXT: $w0 = COPY [[MOVi32imm]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0:
+ successors: %bb.1, %bb.3
+ liveins: $w0, $w1, $w2, $w3
+
+ %0:gpr32 = COPY $w0
+ %1:gpr32 = COPY $w1
+ %2:gpr32 = COPY $w2
+ %3:gpr32 = COPY $w3
+ CBHAssertExt 12, %0, %1, %bb.3, 5, 5
+ B %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ CBWPrr 10, %2, %3, %bb.3
+ B %bb.2
+
+ bb.2:
+ successors: %bb.3
+
+ B %bb.3
+
+ bb.3:
+ %4:gpr32 = MOVi32imm 7
+ $w0 = COPY %4
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: cbb_cmpbb_sext_reject
+alignment: 4
+tracksRegLiveness: true
+isSSA: true
+registers:
+ - { id: 0, class: gpr32 }
+ - { id: 1, class: gpr32 }
+ - { id: 2, class: gpr32 }
+ - { id: 3, class: gpr32 }
+ - { id: 4, class: gpr32 }
+liveins:
+ - { reg: '$w0', virtual-reg: '%0' }
+ - { reg: '$w1', virtual-reg: '%1' }
+ - { reg: '$w2', virtual-reg: '%2' }
+ - { reg: '$w3', virtual-reg: '%3' }
+body: |
+ ; CHECK-LABEL: name: cbb_cmpbb_sext_reject
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1, %bb.3
+ ; CHECK-NEXT: liveins: $w0, $w1, $w2, $w3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY $w3
+ ; CHECK-NEXT: CBWPrr 0, [[COPY]], [[COPY1]], %bb.3
+ ; CHECK-NEXT: B %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2, %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: CBBAssertExt 1, [[COPY2]], [[COPY3]], %bb.3, 4, 4
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7
+ ; CHECK-NEXT: $w0 = COPY [[MOVi32imm]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0:
+ successors: %bb.1, %bb.3
+ liveins: $w0, $w1, $w2, $w3
+
+ %0:gpr32 = COPY $w0
+ %1:gpr32 = COPY $w1
+ %2:gpr32 = COPY $w2
+ %3:gpr32 = COPY $w3
+ CBWPrr 0, %0, %1, %bb.3
+ B %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ CBBAssertExt 1, %2, %3, %bb.3, 4, 4
+ B %bb.2
+
+ bb.2:
+ successors: %bb.3
+
+ B %bb.3
+
+ bb.3:
+ %4:gpr32 = MOVi32imm 7
+ $w0 = COPY %4
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: cbh_cmpbb_zext_reject
+alignment: 4
+tracksRegLiveness: true
+isSSA: true
+registers:
+ - { id: 0, class: gpr32 }
+ - { id: 1, class: gpr32 }
+ - { id: 2, class: gpr32 }
+ - { id: 3, class: gpr32 }
+ - { id: 4, class: gpr32 }
+liveins:
+ - { reg: '$w0', virtual-reg: '%0' }
+ - { reg: '$w1', virtual-reg: '%1' }
+ - { reg: '$w2', virtual-reg: '%2' }
+ - { reg: '$w3', virtual-reg: '%3' }
+body: |
+ ; CHECK-LABEL: name: cbh_cmpbb_zext_reject
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1, %bb.3
+ ; CHECK-NEXT: liveins: $w0, $w1, $w2, $w3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY $w3
+ ; CHECK-NEXT: CBWPrr 0, [[COPY]], [[COPY1]], %bb.3
+ ; CHECK-NEXT: B %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2, %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: CBHAssertExt 8, [[COPY2]], [[COPY3]], %bb.3, 1, 1
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7
+ ; CHECK-NEXT: $w0 = COPY [[MOVi32imm]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0:
+ successors: %bb.1, %bb.3
+ liveins: $w0, $w1, $w2, $w3
+
+ %0:gpr32 = COPY $w0
+ %1:gpr32 = COPY $w1
+ %2:gpr32 = COPY $w2
+ %3:gpr32 = COPY $w3
+ CBWPrr 0, %0, %1, %bb.3
+ B %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ CBHAssertExt 8, %2, %3, %bb.3, 1, 1
+ B %bb.2
+
+ bb.2:
+ successors: %bb.3
+
+ B %bb.3
+
+ bb.3:
+ %4:gpr32 = MOVi32imm 7
+ $w0 = COPY %4
+ RET_ReallyLR implicit $w0
+...
More information about the llvm-branch-commits
mailing list