[llvm] [AArch64][SelectionDAG] Snap -32 and 32 to 31 snd -31 for ccmn (PR #192879)

via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 19 15:41:34 PDT 2026


https://github.com/SiliconA-Z created https://github.com/llvm/llvm-project/pull/192879

This is so we can encode it.

>From ef23e3604d17161bec6d35f5e81fd102e8e4078f Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 19 Apr 2026 18:28:56 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)

---
 llvm/test/CodeGen/AArch64/cmp-chains.ll | 93 +++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll
index 3620444a6aad6..ecf1289568261 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -501,3 +501,96 @@ entry:
   %land.ext = zext i1 %0 to i32
   ret i32 %land.ext
 }
+
+; Boundary immediates (±32) in the second conjunct of select-with-and chains.
+define i32 @compare_with_neg_32(i32 %a, i32 %b, i32 %c) {
+; CHECK-SD-LABEL: compare_with_neg_32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmp w0, w2
+; CHECK-SD-NEXT:    mov w8, #-32 // =0xffffffe0
+; CHECK-SD-NEXT:    ccmp w1, w8, #4, lt
+; CHECK-SD-NEXT:    csel w0, w1, w0, gt
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: compare_with_neg_32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mov w8, #-32 // =0xffffffe0
+; CHECK-GI-NEXT:    cmp w0, w2
+; CHECK-GI-NEXT:    ccmp w1, w8, #4, lt
+; CHECK-GI-NEXT:    csel w0, w1, w0, gt
+; CHECK-GI-NEXT:    ret
+  %cmp = icmp sgt i32 %b, -32
+  %cmp1 = icmp slt i32 %a, %c
+  %or.cond = and i1 %cmp, %cmp1
+  %cond = select i1 %or.cond, i32 %b, i32 %a
+  ret i32 %cond
+}
+
+define i32 @compare_with_32(i32 %a, i32 %b, i32 %c) {
+; CHECK-SD-LABEL: compare_with_32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmp w0, w2
+; CHECK-SD-NEXT:    mov w8, #32 // =0x20
+; CHECK-SD-NEXT:    ccmp w1, w8, #0, lt
+; CHECK-SD-NEXT:    csel w0, w1, w0, lt
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: compare_with_32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mov w8, #32 // =0x20
+; CHECK-GI-NEXT:    cmp w0, w2
+; CHECK-GI-NEXT:    ccmp w1, w8, #0, lt
+; CHECK-GI-NEXT:    csel w0, w1, w0, lt
+; CHECK-GI-NEXT:    ret
+  %cmp = icmp slt i32 %b, 32
+  %cmp1 = icmp slt i32 %a, %c
+  %or.cond = and i1 %cmp, %cmp1
+  %cond = select i1 %or.cond, i32 %b, i32 %a
+  ret i32 %cond
+}
+
+define i32 @compare_with_neg_32_unsigned(i32 %a, i32 %b, i32 %c) {
+; CHECK-SD-LABEL: compare_with_neg_32_unsigned:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmp w0, w2
+; CHECK-SD-NEXT:    mov w8, #-32 // =0xffffffe0
+; CHECK-SD-NEXT:    ccmp w1, w8, #0, lo
+; CHECK-SD-NEXT:    csel w0, w1, w0, hi
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: compare_with_neg_32_unsigned:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mov w8, #-32 // =0xffffffe0
+; CHECK-GI-NEXT:    cmp w0, w2
+; CHECK-GI-NEXT:    ccmp w1, w8, #0, lo
+; CHECK-GI-NEXT:    csel w0, w1, w0, hi
+; CHECK-GI-NEXT:    ret
+  %cmp = icmp ugt i32 %b, -32
+  %cmp1 = icmp ult i32 %a, %c
+  %or.cond = and i1 %cmp, %cmp1
+  %cond = select i1 %or.cond, i32 %b, i32 %a
+  ret i32 %cond
+}
+
+define i32 @compare_with_32_unsigned(i32 %a, i32 %b, i32 %c) {
+; CHECK-SD-LABEL: compare_with_32_unsigned:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmp w0, w2
+; CHECK-SD-NEXT:    mov w8, #32 // =0x20
+; CHECK-SD-NEXT:    ccmp w1, w8, #2, lo
+; CHECK-SD-NEXT:    csel w0, w1, w0, lo
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: compare_with_32_unsigned:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mov w8, #32 // =0x20
+; CHECK-GI-NEXT:    cmp w0, w2
+; CHECK-GI-NEXT:    ccmp w1, w8, #2, lo
+; CHECK-GI-NEXT:    csel w0, w1, w0, lo
+; CHECK-GI-NEXT:    ret
+  %cmp = icmp ult i32 %b, 32
+  %cmp1 = icmp ult i32 %a, %c
+  %or.cond = and i1 %cmp, %cmp1
+  %cond = select i1 %or.cond, i32 %b, i32 %a
+  ret i32 %cond
+}

>From 304317d4cf96b2b540faef4e98aeddbdfd598fa2 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 19 Apr 2026 18:41:05 -0400
Subject: [PATCH 2/2] [AArch64][SelectionDAG] Snap -32 and 32 to 31 snd -31 for
 ccmn

This is so we can encode it.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 43 ++++++++++++++++++-
 llvm/test/CodeGen/AArch64/cmp-chains.ll       | 20 ++++-----
 2 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9b34d9b385b4e..ec193e74c328b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3853,6 +3853,43 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
 /// can only implement 1 of the inner (not) operations, but not both!
 /// @{
 
+/// CCMP/CCMN Wi/Xi immediates are restricted to 0..31. When lowering a
+/// \em conditional compare (not the leading CMP in a chain), snap RHS
+/// constants at ±32 to ±31 where equivalent so the CCMP/CCMN immediate form
+/// applies. Plain CMP;CCMP can use a separate \p mov for \p #32; only the
+/// conditional step needs this rewrite.
+static void snapCCmpImmEncodingBounds(SDValue &RHS, ISD::CondCode &CC,
+                                      SelectionDAG &DAG, const SDLoc &DL,
+                                      EVT VT) {
+  auto *C = dyn_cast<ConstantSDNode>(RHS);
+  if (!C)
+    return;
+  APInt Imm = C->getAPIntValue();
+
+  // x < 32  <=>  x <= 31 ;  x <u 32  <=>  x <=u 31
+  if (Imm == 32) {
+    if (CC == ISD::SETLT) {
+      CC = ISD::SETLE;
+      RHS = DAG.getConstant(31, DL, VT);
+    } else if (CC == ISD::SETULT) {
+      CC = ISD::SETULE;
+      RHS = DAG.getConstant(31, DL, VT);
+    }
+    return;
+  }
+
+  // x > -32  <=>  x >= -31
+  if (Imm.getSExtValue() == -32) {
+    if (CC == ISD::SETGT) {
+      CC = ISD::SETGE;
+      RHS = DAG.getSignedConstant(-31, DL, VT);
+    } else if (CC == ISD::SETUGT) {
+      CC = ISD::SETUGE;
+      RHS = DAG.getSignedConstant(-31, DL, VT);
+    }
+  }
+}
+
 /// Create a conditional comparison; Use CCMP, CCMN or FCCMP as appropriate.
 static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
                                          ISD::CondCode CC, SDValue CCOp,
@@ -4000,6 +4037,10 @@ static SDValue emitConjunctionRec(SelectionDAG &DAG, SDValue Val,
     SDLoc DL(Val);
     // Determine OutCC and handle FP special case.
     if (isInteger) {
+      // Immediate snap only for conditional CCMP/CCMN; leading CMP uses
+      // emitComparison and does not share the 0..31 Wi/Xi restriction.
+      if (CCOp)
+        snapCCmpImmEncodingBounds(RHS, CC, DAG, DL, LHS.getValueType());
       OutCC = changeIntCCToAArch64CC(CC, RHS);
     } else {
       assert(LHS.getValueType().isFloatingPoint());
@@ -4009,7 +4050,7 @@ static SDValue emitConjunctionRec(SelectionDAG &DAG, SDValue Val,
       // code. Construct an additional comparison in this case.
       if (ExtraCC != AArch64CC::AL) {
         SDValue ExtraCmp;
-        if (!CCOp.getNode())
+        if (!CCOp)
           ExtraCmp = emitComparison(LHS, RHS, CC, DL, DAG);
         else
           ExtraCmp = emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate,
diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll
index ecf1289568261..4bf443c9cc910 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -507,9 +507,8 @@ define i32 @compare_with_neg_32(i32 %a, i32 %b, i32 %c) {
 ; CHECK-SD-LABEL: compare_with_neg_32:
 ; CHECK-SD:       // %bb.0:
 ; CHECK-SD-NEXT:    cmp w0, w2
-; CHECK-SD-NEXT:    mov w8, #-32 // =0xffffffe0
-; CHECK-SD-NEXT:    ccmp w1, w8, #4, lt
-; CHECK-SD-NEXT:    csel w0, w1, w0, gt
+; CHECK-SD-NEXT:    ccmn w1, #31, #8, lt
+; CHECK-SD-NEXT:    csel w0, w1, w0, ge
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: compare_with_neg_32:
@@ -530,9 +529,8 @@ define i32 @compare_with_32(i32 %a, i32 %b, i32 %c) {
 ; CHECK-SD-LABEL: compare_with_32:
 ; CHECK-SD:       // %bb.0:
 ; CHECK-SD-NEXT:    cmp w0, w2
-; CHECK-SD-NEXT:    mov w8, #32 // =0x20
-; CHECK-SD-NEXT:    ccmp w1, w8, #0, lt
-; CHECK-SD-NEXT:    csel w0, w1, w0, lt
+; CHECK-SD-NEXT:    ccmp w1, #31, #0, lt
+; CHECK-SD-NEXT:    csel w0, w1, w0, le
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: compare_with_32:
@@ -553,9 +551,8 @@ define i32 @compare_with_neg_32_unsigned(i32 %a, i32 %b, i32 %c) {
 ; CHECK-SD-LABEL: compare_with_neg_32_unsigned:
 ; CHECK-SD:       // %bb.0:
 ; CHECK-SD-NEXT:    cmp w0, w2
-; CHECK-SD-NEXT:    mov w8, #-32 // =0xffffffe0
-; CHECK-SD-NEXT:    ccmp w1, w8, #0, lo
-; CHECK-SD-NEXT:    csel w0, w1, w0, hi
+; CHECK-SD-NEXT:    ccmn w1, #31, #0, lo
+; CHECK-SD-NEXT:    csel w0, w1, w0, hs
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: compare_with_neg_32_unsigned:
@@ -576,9 +573,8 @@ define i32 @compare_with_32_unsigned(i32 %a, i32 %b, i32 %c) {
 ; CHECK-SD-LABEL: compare_with_32_unsigned:
 ; CHECK-SD:       // %bb.0:
 ; CHECK-SD-NEXT:    cmp w0, w2
-; CHECK-SD-NEXT:    mov w8, #32 // =0x20
-; CHECK-SD-NEXT:    ccmp w1, w8, #2, lo
-; CHECK-SD-NEXT:    csel w0, w1, w0, lo
+; CHECK-SD-NEXT:    ccmp w1, #31, #2, lo
+; CHECK-SD-NEXT:    csel w0, w1, w0, ls
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: compare_with_32_unsigned:



More information about the llvm-commits mailing list