[llvm] [PowerPC] Use alternative ucmp lowering that does not require freeze (PR #206773)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 30 10:00:22 PDT 2026


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

call i64 @llvm.ucmp(i8 %x, i8 0) is not going to realistically happen. So I removed it.

>From 7110424d4a0396f88ee67532ff9ea43e4c634965 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Tue, 30 Jun 2026 12:59:37 -0400
Subject: [PATCH] [PowerPC] Use alternative ucmp lowering that does not require
 freeze

call i64 @llvm.ucmp(i8 %x, i8 0) is not going to realistically happen. So I removed it.
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 33 +++++----
 llvm/test/CodeGen/PowerPC/memcmp.ll         | 16 ++--
 llvm/test/CodeGen/PowerPC/ucmp.ll           | 81 ++++++++-------------
 3 files changed, 59 insertions(+), 71 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 76cc06f2b4ed9..cdd753e331004 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -12791,8 +12791,8 @@ SDValue PPCTargetLowering::LowerSADDO(SDValue Op, SelectionDAG &DAG) const {
 // Lower unsigned 3-way compare producing -1/0/1.
 SDValue PPCTargetLowering::LowerUCMP(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();
 
@@ -12805,23 +12805,28 @@ SDValue PPCTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
     OpVT = MVT::i64;
   }
 
-  // First compute diff = A - B.
-  SDValue Diff = DAG.getNode(ISD::SUB, DL, OpVT, A, B);
-
-  // Generate B - A using SUBC to capture carry.
   SDVTList VTs = DAG.getVTList(OpVT, MVT::i32);
-  SDValue SubC = DAG.getNode(PPCISD::SUBC, DL, VTs, B, A);
-  SDValue CA0 = SubC.getValue(1);
 
-  // t2 = A - B + CA0 using SUBE.
-  SDValue SubE1 = DAG.getNode(PPCISD::SUBE, DL, VTs, A, B, CA0);
-  SDValue CA1 = SubE1.getValue(1);
+  // 1. subfc r3, r4, r3 -> r3 = A - B, Carry1
+  SDValue SubC = DAG.getNode(PPCISD::SUBC, DL, VTs, A, B);
+  SDValue Diff = SubC.getValue(0);
+  SDValue CA1 = SubC.getValue(1);
+
+  // 2. subfe r4, r3, r3 -> r4 = -1 + Carry1 (mask)
+  SDValue SubE = DAG.getNode(PPCISD::SUBE, DL, VTs, Diff, Diff, CA1);
+  SDValue Mask = SubE.getValue(0);
+
+  // 3. addic r3, r3, -1 -> Overwrite a with Carry flag 2
+  SDValue AddC =
+      DAG.getNode(PPCISD::ADDC, DL, VTs, Diff, DAG.getConstant(-1, DL, OpVT));
+  SDValue CA2 = AddC.getValue(1);
 
-  // res = diff - t2 + CA1 using SUBE (produces desired -1/0/1).
-  SDValue ResPair = DAG.getNode(PPCISD::SUBE, DL, VTs, Diff, SubE1, CA1);
+  // 4. adde  r3, r4, r4 -> r3 = r4 + r4 + Carry2
+  SDValue AddE = DAG.getNode(PPCISD::ADDE, DL, VTs, Mask, Mask, CA2);
+  SDValue Res = AddE.getValue(0);
 
   // Extract the first result and truncate to result type if needed.
-  return DAG.getSExtOrTrunc(ResPair.getValue(0), DL, ResVT);
+  return DAG.getSExtOrTrunc(Res, DL, ResVT);
 }
 
 /// LowerOperation - Provide custom lowering hooks for some operations.
diff --git a/llvm/test/CodeGen/PowerPC/memcmp.ll b/llvm/test/CodeGen/PowerPC/memcmp.ll
index 0cf896d6bbefe..c50367aeca257 100644
--- a/llvm/test/CodeGen/PowerPC/memcmp.ll
+++ b/llvm/test/CodeGen/PowerPC/memcmp.ll
@@ -6,10 +6,10 @@ define signext i32 @memcmp8(ptr nocapture readonly %buffer1, ptr nocapture reado
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    ldbrx 3, 0, 3
 ; CHECK-NEXT:    ldbrx 4, 0, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    extsw 3, 3
 ; CHECK-NEXT:    blr
   %call = tail call signext i32 @memcmp(ptr %buffer1, ptr %buffer2, i64 8)
@@ -21,10 +21,10 @@ define signext i32 @memcmp4(ptr nocapture readonly %buffer1, ptr nocapture reado
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    lwbrx 3, 0, 3
 ; CHECK-NEXT:    lwbrx 4, 0, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    extsw 3, 3
 ; CHECK-NEXT:    blr
   %call = tail call signext i32 @memcmp(ptr %buffer1, ptr %buffer2, i64 4)
diff --git a/llvm/test/CodeGen/PowerPC/ucmp.ll b/llvm/test/CodeGen/PowerPC/ucmp.ll
index a299fbbba3422..c437ee5b75c44 100644
--- a/llvm/test/CodeGen/PowerPC/ucmp.ll
+++ b/llvm/test/CodeGen/PowerPC/ucmp.ll
@@ -4,12 +4,10 @@
 define i8 @ucmp_8_8(i8 zeroext %x, i8 zeroext %y) nounwind {
 ; CHECK-LABEL: ucmp_8_8:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    clrldi 3, 3, 32
-; CHECK-NEXT:    clrldi 4, 4, 32
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.ucmp(i8 %x, i8 %y)
   ret i8 %1
@@ -18,12 +16,10 @@ define i8 @ucmp_8_8(i8 zeroext %x, i8 zeroext %y) nounwind {
 define i8 @ucmp_8_16(i16 zeroext %x, i16 zeroext %y) nounwind {
 ; CHECK-LABEL: ucmp_8_16:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    clrldi 3, 3, 32
-; CHECK-NEXT:    clrldi 4, 4, 32
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.ucmp(i16 %x, i16 %y)
   ret i8 %1
@@ -34,10 +30,10 @@ define i8 @ucmp_8_32(i32 %x, i32 %y) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    clrldi 3, 3, 32
 ; CHECK-NEXT:    clrldi 4, 4, 32
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
   ret i8 %1
@@ -46,10 +42,10 @@ define i8 @ucmp_8_32(i32 %x, i32 %y) nounwind {
 define i8 @ucmp_8_64(i64 %x, i64 %y) nounwind {
 ; CHECK-LABEL: ucmp_8_64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i8 @llvm.ucmp(i64 %x, i64 %y)
   ret i8 %1
@@ -80,10 +76,10 @@ define i32 @ucmp_32_32(i32 %x, i32 %y) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    clrldi 3, 3, 32
 ; CHECK-NEXT:    clrldi 4, 4, 32
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i32 @llvm.ucmp(i32 %x, i32 %y)
   ret i32 %1
@@ -92,10 +88,10 @@ define i32 @ucmp_32_32(i32 %x, i32 %y) nounwind {
 define i32 @ucmp_32_64(i64 %x, i64 %y) nounwind {
 ; CHECK-LABEL: ucmp_32_64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i32 @llvm.ucmp(i64 %x, i64 %y)
   ret i32 %1
@@ -104,37 +100,24 @@ define i32 @ucmp_32_64(i64 %x, i64 %y) nounwind {
 define i64 @ucmp_64_64(i64 %x, i64 %y) nounwind {
 ; CHECK-LABEL: ucmp_64_64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i64 @llvm.ucmp(i64 %x, i64 %y)
   ret i64 %1
 }
 
-define i64 @ucmp_64_8_zero(i8 %x) nounwind {
-; CHECK-LABEL: ucmp_64_8_zero:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    clrldi 3, 3, 56
-; CHECK-NEXT:    subfic 4, 3, 0
-; CHECK-NEXT:    li 4, 0
-; CHECK-NEXT:    subfe 4, 4, 3
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    blr
-  %1 = call i64 @llvm.ucmp(i8 %x, i8 0)
-  ret i64 %1
-}
-
 define i64 @ucmp_64_8(i8 %x, i8 %y) nounwind {
 ; CHECK-LABEL: ucmp_64_8:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    clrldi 3, 3, 56
 ; CHECK-NEXT:    clrldi 4, 4, 56
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    subc 6, 4, 3
-; CHECK-NEXT:    subfe 3, 4, 3
-; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    subc 3, 3, 4
+; CHECK-NEXT:    subfe 4, 3, 3
+; CHECK-NEXT:    addic 3, 3, -1
+; CHECK-NEXT:    adde 3, 4, 4
 ; CHECK-NEXT:    blr
   %1 = call i64 @llvm.ucmp(i8 %x, i8 %y)
   ret i64 %1



More information about the llvm-commits mailing list