[llvm] [PPC] Implement custom lowering for SCMP with 0 on PowerPC (PR #207431)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 4 11:45:35 PDT 2026


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/207431

>From 51b333dd0bdfa55a52d7aef723fc6be9b7ec82a5 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 3 Jul 2026 13:00:12 -0400
Subject: [PATCH 1/2] Precommit scmp 0 tests for PowerPC

---
 llvm/test/CodeGen/PowerPC/scmp.ll | 94 +++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/llvm/test/CodeGen/PowerPC/scmp.ll b/llvm/test/CodeGen/PowerPC/scmp.ll
index 107137c0bea7c..c698030f0d314 100644
--- a/llvm/test/CodeGen/PowerPC/scmp.ll
+++ b/llvm/test/CodeGen/PowerPC/scmp.ll
@@ -125,3 +125,97 @@ define i64 @scmp_64_64(i64 %x, i64 %y) nounwind {
   %1 = call i64 @llvm.scmp(i64 %x, i64 %y)
   ret i64 %1
 }
+
+define i8 @scmp_8_8_0(i8 signext %x) nounwind {
+; CHECK-LABEL: scmp_8_8_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cmpwi 3, 0
+; CHECK-NEXT:    neg 4, 3
+; CHECK-NEXT:    li 3, -1
+; CHECK-NEXT:    rldicl 4, 4, 1, 63
+; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    blr
+  %1 = call i8 @llvm.scmp(i8 %x, i8 0)
+  ret i8 %1
+}
+
+define i8 @scmp_8_16_0(i16 signext %x) nounwind {
+; CHECK-LABEL: scmp_8_16_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cmpwi 3, 0
+; CHECK-NEXT:    neg 4, 3
+; CHECK-NEXT:    li 3, -1
+; CHECK-NEXT:    rldicl 4, 4, 1, 63
+; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    blr
+  %1 = call i8 @llvm.scmp(i16 %x, i16 0)
+  ret i8 %1
+}
+
+define i8 @scmp_8_32_0(i32 %x) nounwind {
+; CHECK-LABEL: scmp_8_32_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    extsw. 3, 3
+; CHECK-NEXT:    li 4, -1
+; CHECK-NEXT:    neg 3, 3
+; CHECK-NEXT:    rldicl 3, 3, 1, 63
+; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    blr
+  %1 = call i8 @llvm.scmp(i32 %x, i32 0)
+  ret i8 %1
+}
+
+define i8 @scmp_8_64_0(i64 %x) nounwind {
+; CHECK-LABEL: scmp_8_64_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi 4, 3, -1
+; CHECK-NEXT:    cmpdi 3, 0
+; CHECK-NEXT:    nor 4, 4, 3
+; CHECK-NEXT:    li 3, -1
+; CHECK-NEXT:    rldicl 4, 4, 1, 63
+; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    blr
+  %1 = call i8 @llvm.scmp(i64 %x, i64 0)
+  ret i8 %1
+}
+
+define i32 @scmp_32_32_0(i32 %x) nounwind {
+; CHECK-LABEL: scmp_32_32_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    extsw. 3, 3
+; CHECK-NEXT:    li 4, -1
+; CHECK-NEXT:    neg 3, 3
+; CHECK-NEXT:    rldicl 3, 3, 1, 63
+; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    blr
+  %1 = call i32 @llvm.scmp(i32 %x, i32 0)
+  ret i32 %1
+}
+
+define i32 @scmp_32_64_0(i64 %x) nounwind {
+; CHECK-LABEL: scmp_32_64_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi 4, 3, -1
+; CHECK-NEXT:    cmpdi 3, 0
+; CHECK-NEXT:    nor 4, 4, 3
+; CHECK-NEXT:    li 3, -1
+; CHECK-NEXT:    rldicl 4, 4, 1, 63
+; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    blr
+  %1 = call i32 @llvm.scmp(i64 %x, i64 0)
+  ret i32 %1
+}
+
+define i64 @scmp_64_64_0(i64 %x) nounwind {
+; CHECK-LABEL: scmp_64_64_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi 4, 3, -1
+; CHECK-NEXT:    cmpdi 3, 0
+; CHECK-NEXT:    nor 4, 4, 3
+; CHECK-NEXT:    li 3, -1
+; CHECK-NEXT:    rldicl 4, 4, 1, 63
+; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    blr
+  %1 = call i64 @llvm.scmp(i64 %x, i64 0)
+  ret i64 %1
+}

>From 29067d61be68e8d653d060232d6e1d9e99371bdb Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 3 Jul 2026 13:07:29 -0400
Subject: [PATCH 2/2] Implement custom lowering for SCMP on PowerPC

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 45 +++++++++++++--
 llvm/lib/Target/PowerPC/PPCISelLowering.h   |  2 +-
 llvm/test/CodeGen/PowerPC/scmp.ll           | 61 ++++++++-------------
 3 files changed, 63 insertions(+), 45 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 9a4943aad6289..fa28336693625 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -603,9 +603,12 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
   // We cannot sextinreg(i1).  Expand to shifts.
   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
 
-  // Custom handling for PowerPC ucmp instruction
+  // Custom handling for PowerPC scmp/ucmp instruction
+  setOperationAction(ISD::SCMP, MVT::i32, Custom);
+  setOperationAction(ISD::SCMP, MVT::i64, isPPC64 ? Custom : Expand);
   setOperationAction(ISD::UCMP, MVT::i32, Custom);
   setOperationAction(ISD::UCMP, MVT::i64, isPPC64 ? Custom : Expand);
+
   setOperationAction(ISD::ABDU, MVT::i32, Custom);
   setOperationAction(ISD::ABDU, MVT::i64, isPPC64 ? Custom : Expand);
 
@@ -12853,14 +12856,43 @@ SDValue PPCTargetLowering::LowerABDU(SDValue Op, SelectionDAG &DAG) const {
   return Res;
 }
 
-// Lower unsigned 3-way compare producing -1/0/1.
-SDValue PPCTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
+// Lower unsigned/signed 3-way compare producing -1/0/1.
+SDValue PPCTargetLowering::LowerCMP(SDValue Op, SelectionDAG &DAG) const {
   SDLoc DL(Op);
-  SDValue A = DAG.getFreeze(Op.getOperand(0));
-  SDValue B = DAG.getFreeze(Op.getOperand(1));
+  SDValue A = Op.getOperand(0);
+  SDValue B = Op.getOperand(1);
   EVT OpVT = A.getValueType();
   EVT ResVT = Op.getValueType();
 
+  if (Op.getOpcode() == ISD::SCMP) {
+    if (!isNullConstant(B))
+      return SDValue(); // Fallback to expansion if RHS is not 0
+
+    if (Subtarget.isPPC64() && OpVT != MVT::i64) {
+      A = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, A);
+      OpVT = MVT::i64;
+    }
+
+    // srawi/sradi r4, r3, 31/63
+    SDValue Sra =
+        DAG.getNode(ISD::SRA, DL, OpVT, A,
+                    DAG.getConstant(OpVT.getSizeInBits() - 1, DL, MVT::i32));
+
+    SDVTList VTs = DAG.getVTList(OpVT, MVT::i32);
+    // addic r5, r3, -1
+    SDValue Addc =
+        DAG.getNode(PPCISD::ADDC, DL, VTs, A, DAG.getAllOnesConstant(DL, OpVT));
+    SDValue CA = Addc.getValue(1);
+
+    // adde r6, r4, r4
+    SDValue Adde = DAG.getNode(PPCISD::ADDE, DL, VTs, Sra, Sra, CA);
+
+    return DAG.getSExtOrTrunc(Adde.getValue(0), DL, ResVT);
+  }
+
+  A = DAG.getFreeze(A);
+  B = DAG.getFreeze(B);
+
   // On PPC64, i32 carries are affected by the upper 32 bits of the registers.
   // We must zero-extend to i64 to ensure the carry reflects the 32-bit unsigned
   // comparison.
@@ -12997,8 +13029,9 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::UADDO_CARRY:
   case ISD::USUBO_CARRY:
     return LowerADDSUBO_CARRY(Op, DAG);
+  case ISD::SCMP:
   case ISD::UCMP:
-    return LowerUCMP(Op, DAG);
+    return LowerCMP(Op, DAG);
   case ISD::ABDU:
     return LowerABDU(Op, DAG);
   case ISD::STRICT_LRINT:
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index a39f7e0d3c35f..590149abe7dfe 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -742,7 +742,7 @@ namespace llvm {
     SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerADDSUBO(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerABDU(SDValue Op, SelectionDAG &DAG) const;
-    SDValue LowerUCMP(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerCMP(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerToLibCall(const char *LibCallName, SDValue Op,
                            SelectionDAG &DAG) const;
     SDValue lowerLibCallBasedOnType(const char *LibCallFloatName,
diff --git a/llvm/test/CodeGen/PowerPC/scmp.ll b/llvm/test/CodeGen/PowerPC/scmp.ll
index c698030f0d314..6c3ec14314c5a 100644
--- a/llvm/test/CodeGen/PowerPC/scmp.ll
+++ b/llvm/test/CodeGen/PowerPC/scmp.ll
@@ -129,11 +129,9 @@ define i64 @scmp_64_64(i64 %x, i64 %y) nounwind {
 define i8 @scmp_8_8_0(i8 signext %x) nounwind {
 ; CHECK-LABEL: scmp_8_8_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpwi 3, 0
-; CHECK-NEXT:    neg 4, 3
-; CHECK-NEXT:    li 3, -1
-; CHECK-NEXT:    rldicl 4, 4, 1, 63
-; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.scmp(i8 %x, i8 0)
   ret i8 %1
@@ -142,11 +140,9 @@ define i8 @scmp_8_8_0(i8 signext %x) nounwind {
 define i8 @scmp_8_16_0(i16 signext %x) nounwind {
 ; CHECK-LABEL: scmp_8_16_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpwi 3, 0
-; CHECK-NEXT:    neg 4, 3
-; CHECK-NEXT:    li 3, -1
-; CHECK-NEXT:    rldicl 4, 4, 1, 63
-; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.scmp(i16 %x, i16 0)
   ret i8 %1
@@ -155,11 +151,10 @@ define i8 @scmp_8_16_0(i16 signext %x) nounwind {
 define i8 @scmp_8_32_0(i32 %x) nounwind {
 ; CHECK-LABEL: scmp_8_32_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    extsw. 3, 3
-; CHECK-NEXT:    li 4, -1
-; CHECK-NEXT:    neg 3, 3
-; CHECK-NEXT:    rldicl 3, 3, 1, 63
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    extsw 3, 3
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.scmp(i32 %x, i32 0)
   ret i8 %1
@@ -168,12 +163,9 @@ define i8 @scmp_8_32_0(i32 %x) nounwind {
 define i8 @scmp_8_64_0(i64 %x) nounwind {
 ; CHECK-LABEL: scmp_8_64_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    addi 4, 3, -1
-; CHECK-NEXT:    cmpdi 3, 0
-; CHECK-NEXT:    nor 4, 4, 3
-; CHECK-NEXT:    li 3, -1
-; CHECK-NEXT:    rldicl 4, 4, 1, 63
-; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.scmp(i64 %x, i64 0)
   ret i8 %1
@@ -182,11 +174,10 @@ define i8 @scmp_8_64_0(i64 %x) nounwind {
 define i32 @scmp_32_32_0(i32 %x) nounwind {
 ; CHECK-LABEL: scmp_32_32_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    extsw. 3, 3
-; CHECK-NEXT:    li 4, -1
-; CHECK-NEXT:    neg 3, 3
-; CHECK-NEXT:    rldicl 3, 3, 1, 63
-; CHECK-NEXT:    isellt 3, 4, 3
+; CHECK-NEXT:    extsw 3, 3
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i32 @llvm.scmp(i32 %x, i32 0)
   ret i32 %1
@@ -195,12 +186,9 @@ define i32 @scmp_32_32_0(i32 %x) nounwind {
 define i32 @scmp_32_64_0(i64 %x) nounwind {
 ; CHECK-LABEL: scmp_32_64_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    addi 4, 3, -1
-; CHECK-NEXT:    cmpdi 3, 0
-; CHECK-NEXT:    nor 4, 4, 3
-; CHECK-NEXT:    li 3, -1
-; CHECK-NEXT:    rldicl 4, 4, 1, 63
-; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i32 @llvm.scmp(i64 %x, i64 0)
   ret i32 %1
@@ -209,12 +197,9 @@ define i32 @scmp_32_64_0(i64 %x) nounwind {
 define i64 @scmp_64_64_0(i64 %x) nounwind {
 ; CHECK-LABEL: scmp_64_64_0:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    addi 4, 3, -1
-; CHECK-NEXT:    cmpdi 3, 0
-; CHECK-NEXT:    nor 4, 4, 3
-; CHECK-NEXT:    li 3, -1
-; CHECK-NEXT:    rldicl 4, 4, 1, 63
-; CHECK-NEXT:    isellt 3, 3, 4
+; CHECK-NEXT:    sradi 4, 3, 63
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i64 @llvm.scmp(i64 %x, i64 0)
   ret i64 %1



More information about the llvm-commits mailing list