[llvm] [AArch64] Snap 32 and -32 to 31 and -31 if possible for ccmp and ccmn (PR #144166)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 13 15:27:12 PDT 2025


https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/144166

This lets us encode the immediate in the instruction.

>From 57b49a09344afa3b91e6a458950a29e5e725d4ce Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 27 May 2025 12:16:14 -0400
Subject: [PATCH] [AArch64] Snap 32 and -32 to 31 and -31 if possible for ccmp
 and ccmn

This lets us encode the immediate in the instruction.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 49 +++++++++++++++++++
 llvm/test/CodeGen/AArch64/cmp-chains.ll       | 44 +++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 7519ac5260a64..f4935d0acbac0 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3716,6 +3716,55 @@ static SDValue emitConjunctionRec(SelectionDAG &DAG, SDValue Val,
     // Produce a normal comparison if we are first in the chain
     if (!CCOp)
       return emitComparison(LHS, RHS, CC, DL, DAG);
+
+    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
+      EVT VT = RHS.getValueType();
+      APInt C = RHSC->getAPIntValue();
+      // shouldBeAdjustedToZero is a special case to better fold with
+      // emitComparison().
+      if (C.getZExtValue() == 32 && (CC == ISD::SETLT || CC == ISD::SETGE ||
+                                     CC == ISD::SETULT || CC == ISD::SETUGE)) {
+        switch (CC) {
+        case ISD::SETLT:
+          CC = ISD::SETLE;
+          break;
+        case ISD::SETGE:
+          CC = ISD::SETGT;
+          break;
+        case ISD::SETULT:
+          CC = ISD::SETULE;
+          break;
+        case ISD::SETUGE:
+          CC = ISD::SETUGT;
+          break;
+        default:
+          llvm_unreachable("Should not happen");
+        }
+        RHS = DAG.getConstant(31, DL, VT);
+        OutCC = changeIntCCToAArch64CC(CC);
+      } else if (C.getSExtValue() == -32 &&
+                 (CC == ISD::SETLE || CC == ISD::SETGT || CC == ISD::SETULE ||
+                  CC == ISD::SETUGT)) {
+        switch (CC) {
+        case ISD::SETLE:
+          CC = ISD::SETLT;
+          break;
+        case ISD::SETGT:
+          CC = ISD::SETGE;
+          break;
+        case ISD::SETULE:
+          CC = ISD::SETULT;
+          break;
+        case ISD::SETUGT:
+          CC = ISD::SETUGE;
+          break;
+        default:
+          llvm_unreachable("Should not happen");
+        }
+        RHS = DAG.getConstant((C + 1).getZExtValue(), DL, VT); // -31
+        OutCC = changeIntCCToAArch64CC(CC);
+      }
+    }
     // Otherwise produce a ccmp.
     return emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate, OutCC, DL,
                                      DAG);
diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll
index 4b816df75a730..81c3f51a2b422 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -501,3 +501,47 @@ entry:
   %land.ext = zext i1 %0 to i32
   ret i32 %land.ext
 }
+
+define i32 @compare_with_neg_32(i32 %a, i32 %b, i32 %c) {
+; SDISEL-LABEL: compare_with_neg_32:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmp w0, w2
+; SDISEL-NEXT:    ccmn w1, #31, #8, lt
+; SDISEL-NEXT:    csel w0, w1, w0, ge
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: compare_with_neg_32:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #-32 // =0xffffffe0
+; GISEL-NEXT:    cmp w0, w2
+; GISEL-NEXT:    ccmp w1, w8, #4, lt
+; GISEL-NEXT:    csel w0, w1, w0, gt
+; GISEL-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) {
+; SDISEL-LABEL: compare_with_32:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmp w0, w2
+; SDISEL-NEXT:    ccmp w1, #31, #4, lt
+; SDISEL-NEXT:    csel w0, w1, w0, gt
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: compare_with_32:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #32 // =0x20
+; GISEL-NEXT:    cmp w0, w2
+; GISEL-NEXT:    ccmp w1, w8, #8, lt
+; GISEL-NEXT:    csel w0, w1, w0, ge
+; GISEL-NEXT:    ret
+  %cmp = icmp sge 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
+}



More information about the llvm-commits mailing list