[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