[llvm] [AArch64][GlobalISel] Fold (icmp op, (sub 0, y)) into a register CCMN before immediate / plain CCMP forms. (PR #192878)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 19 15:22:26 PDT 2026
https://github.com/SiliconA-Z created https://github.com/llvm/llvm-project/pull/192878
None
>From 773cf3e74af6a9bf68428b0dc7181f468364c74e Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 19 Apr 2026 18:15:03 -0400
Subject: [PATCH] [AArch64][GlobalISel] Fold (icmp op, (sub 0, y)) into a
register CCMN before immediate / plain CCMP forms.
---
.../GISel/AArch64InstructionSelector.cpp | 27 ++++++++++++----
.../AArch64/GlobalISel/ccmp-cmn-sub.ll | 32 +++++++++++++++++++
2 files changed, 52 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/ccmp-cmn-sub.ll
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 2fa0fca176c88..8d590f23acca3 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -4783,13 +4783,26 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
std::optional<ValueAndVReg> C;
if (CmpInst::isIntPredicate(CC)) {
assert(OpTy.getSizeInBits() == 32 || OpTy.getSizeInBits() == 64);
- C = getIConstantVRegValWithLookThrough(RHS, MRI);
- if (!C || C->Value.sgt(31) || C->Value.slt(-31))
- CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr;
- else if (C->Value.ule(31))
- CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
- else
- CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMNWi : AArch64::CCMNXi;
+ const bool Is32Bit = OpTy.getSizeInBits() == 32;
+ // Fold (icmp op, (sub 0, y)) into a register CCMN before immediate / plain
+ // CCMP forms.
+ if (MachineInstr *RHSDef = getDefIgnoringCopies(RHS, MRI);
+ isCMN(RHSDef, CC, MRI)) {
+ CCmpOpc = Is32Bit ? AArch64::CCMNWr : AArch64::CCMNXr;
+ RHS = RHSDef->getOperand(2).getReg();
+ } else if (MachineInstr *LHSDef = getDefIgnoringCopies(LHS, MRI);
+ CmpInst::isEquality(CC) && isCMN(LHSDef, CC, MRI)) {
+ CCmpOpc = Is32Bit ? AArch64::CCMNWr : AArch64::CCMNXr;
+ LHS = LHSDef->getOperand(2).getReg();
+ } else {
+ C = getIConstantVRegValWithLookThrough(RHS, MRI);
+ if (!C || C->Value.sgt(31) || C->Value.slt(-31))
+ CCmpOpc = Is32Bit ? AArch64::CCMPWr : AArch64::CCMPXr;
+ else if (C->Value.ule(31))
+ CCmpOpc = Is32Bit ? AArch64::CCMPWi : AArch64::CCMPXi;
+ else
+ CCmpOpc = Is32Bit ? AArch64::CCMNWi : AArch64::CCMNXi;
+ }
} else {
assert(OpTy.getSizeInBits() == 16 || OpTy.getSizeInBits() == 32 ||
OpTy.getSizeInBits() == 64);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ccmp-cmn-sub.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ccmp-cmn-sub.ll
new file mode 100644
index 0000000000000..d794717d4202b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/ccmp-cmn-sub.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions may be updated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=aarch64-- -global-isel -verify-machineinstrs %s -o - | FileCheck %s
+
+define i32 @ccmp_cmn_rhs(i32 %a, i32 %b, i32 %c, i32 %x, i32 %y) {
+; CHECK-LABEL: ccmp_cmn_rhs:
+; CHECK-DAG: cmp w0, #5
+; CHECK: ccmn w2, w1, #0, eq
+; CHECK-NEXT: csel
+entry:
+ %neg = sub nsw i32 0, %b
+ %cmp_sub = icmp eq i32 %c, %neg
+ %cmp_simple = icmp eq i32 %a, 5
+ %and = and i1 %cmp_sub, %cmp_simple
+ %s = select i1 %and, i32 %x, i32 %y
+ ret i32 %s
+}
+
+; LHS of icmp is (sub 0, %a) with equality: commute to CCMN.
+
+define i32 @ccmp_cmn_lhs_eq(i32 %a, i32 %b, i32 %c, i32 %x, i32 %y) {
+; CHECK-LABEL: ccmp_cmn_lhs_eq:
+; CHECK-DAG: cmp w2, #7
+; CHECK: ccmn w0, w1, #0, eq
+; CHECK-NEXT: csel
+entry:
+ %neg = sub nsw i32 0, %a
+ %cmp_sub = icmp eq i32 %neg, %b
+ %cmp_simple = icmp eq i32 %c, 7
+ %and = and i1 %cmp_sub, %cmp_simple
+ %s = select i1 %and, i32 %x, i32 %y
+ ret i32 %s
+}
More information about the llvm-commits
mailing list