[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