[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