[llvm] [SelectionDAG] Lowering usub.sat(a, 1) to a - (a != 0) (PR #170076)

guan jian via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 8 20:59:26 PST 2025


https://github.com/rez5427 updated https://github.com/llvm/llvm-project/pull/170076

>From 701bcdfccb0335d4dfcd107ac4e66d2c03b659a6 Mon Sep 17 00:00:00 2001
From: "Jian1.Guan" <Jian1.Guan at cixtech.com>
Date: Mon, 1 Dec 2025 13:10:49 +0800
Subject: [PATCH 1/7] [SelectionDAG] Lowering usub.sat(a, 1) to a - (a != 0)

---
 .../CodeGen/SelectionDAG/TargetLowering.cpp   | 10 +++++++
 llvm/test/CodeGen/AArch64/and-mask-removal.ll |  6 ++--
 llvm/test/CodeGen/RISCV/usub_sat.ll           | 28 +++++++++++++++++++
 3 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index c65ddc6c28986..1afbad048f9b4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10877,6 +10877,16 @@ SDValue TargetLowering::expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const {
   assert(VT == RHS.getValueType() && "Expected operands to be the same type");
   assert(VT.isInteger() && "Expected operands to be integers");
 
+  // usub.sat(a, 1) -> a - zext(a != 0)
+  if (Opcode == ISD::USUBSAT && !VT.isVector() && isOneConstant(RHS)) {
+    SDValue Zero = DAG.getConstant(0, dl, VT);
+    EVT BoolVT =
+        getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
+    SDValue IsNonZero = DAG.getSetCC(dl, BoolVT, LHS, Zero, ISD::SETNE);
+    SDValue Subtrahend = DAG.getBoolExtOrTrunc(IsNonZero, dl, VT, BoolVT);
+    return DAG.getNode(ISD::SUB, dl, VT, LHS, Subtrahend);
+  }
+
   // usub.sat(a, b) -> umax(a, b) - b
   if (Opcode == ISD::USUBSAT && isOperationLegal(ISD::UMAX, VT)) {
     SDValue Max = DAG.getNode(ISD::UMAX, dl, VT, LHS, RHS);
diff --git a/llvm/test/CodeGen/AArch64/and-mask-removal.ll b/llvm/test/CodeGen/AArch64/and-mask-removal.ll
index 5046c0571ad2b..855fe5caf97b2 100644
--- a/llvm/test/CodeGen/AArch64/and-mask-removal.ll
+++ b/llvm/test/CodeGen/AArch64/and-mask-removal.ll
@@ -483,9 +483,9 @@ define i64 @pr58109(i8 signext %0) {
 ; CHECK-SD-LABEL: pr58109:
 ; CHECK-SD:       ; %bb.0:
 ; CHECK-SD-NEXT:    add w8, w0, #1
-; CHECK-SD-NEXT:    and w8, w8, #0xff
-; CHECK-SD-NEXT:    subs w8, w8, #1
-; CHECK-SD-NEXT:    csel w0, wzr, w8, lo
+; CHECK-SD-NEXT:    ands w8, w8, #0xff
+; CHECK-SD-NEXT:    cset w9, ne
+; CHECK-SD-NEXT:    sub w0, w8, w9
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: pr58109:
diff --git a/llvm/test/CodeGen/RISCV/usub_sat.ll b/llvm/test/CodeGen/RISCV/usub_sat.ll
index 33056682dcc79..7084885a0ee2c 100644
--- a/llvm/test/CodeGen/RISCV/usub_sat.ll
+++ b/llvm/test/CodeGen/RISCV/usub_sat.ll
@@ -185,3 +185,31 @@ define zeroext i4 @func3(i4 zeroext %x, i4 zeroext %y) nounwind {
   %tmp = call i4 @llvm.usub.sat.i4(i4 %x, i4 %y);
   ret i4 %tmp;
 }
+
+define signext i32 @sat_dec_i32(i32 signext %x) nounwind {
+; RV32I-LABEL: sat_dec_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    snez a1, a0
+; RV32I-NEXT:    sub a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: sat_dec_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    snez a1, a0
+; RV64I-NEXT:    subw a0, a0, a1
+; RV64I-NEXT:    ret
+;
+; RV32IZbb-LABEL: sat_dec_i32:
+; RV32IZbb:       # %bb.0:
+; RV32IZbb-NEXT:    snez a1, a0
+; RV32IZbb-NEXT:    sub a0, a0, a1
+; RV32IZbb-NEXT:    ret
+;
+; RV64IZbb-LABEL: sat_dec_i32:
+; RV64IZbb:       # %bb.0:
+; RV64IZbb-NEXT:    snez a1, a0
+; RV64IZbb-NEXT:    subw a0, a0, a1
+; RV64IZbb-NEXT:    ret
+  %tmp = call i32 @llvm.usub.sat.i32(i32 %x, i32 1)
+  ret i32 %tmp
+}

>From 2cc21b2a3dafdfdaad00f5afa2acab71316a8514 Mon Sep 17 00:00:00 2001
From: guan jian <2023020923 at stu.cdut.edu.cn>
Date: Wed, 3 Dec 2025 22:22:51 +0800
Subject: [PATCH 2/7] Update llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Co-authored-by: Simon Pilgrim <git at redking.me.uk>
---
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 1afbad048f9b4..5b9a1c6138e3f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10877,7 +10877,7 @@ SDValue TargetLowering::expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const {
   assert(VT == RHS.getValueType() && "Expected operands to be the same type");
   assert(VT.isInteger() && "Expected operands to be integers");
 
-  // usub.sat(a, 1) -> a - zext(a != 0)
+  // usub.sat(a, 1) -> sub(a, zext(a != 0))
   if (Opcode == ISD::USUBSAT && !VT.isVector() && isOneConstant(RHS)) {
     SDValue Zero = DAG.getConstant(0, dl, VT);
     EVT BoolVT =

>From 87c6428f5608b7c66a98e4e9155f7df5ff1c9911 Mon Sep 17 00:00:00 2001
From: rez5427 <guanjian at stu.cdut.edu.cn>
Date: Thu, 4 Dec 2025 22:03:59 +0800
Subject: [PATCH 3/7] Use getZExtOrTrunc

---
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 5b9a1c6138e3f..1d3846c54bce4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10878,12 +10878,11 @@ SDValue TargetLowering::expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const {
   assert(VT.isInteger() && "Expected operands to be integers");
 
   // usub.sat(a, 1) -> sub(a, zext(a != 0))
-  if (Opcode == ISD::USUBSAT && !VT.isVector() && isOneConstant(RHS)) {
+  if (Opcode == ISD::USUBSAT && isOneConstant(RHS)) {
     SDValue Zero = DAG.getConstant(0, dl, VT);
-    EVT BoolVT =
-        getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
+    EVT BoolVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
     SDValue IsNonZero = DAG.getSetCC(dl, BoolVT, LHS, Zero, ISD::SETNE);
-    SDValue Subtrahend = DAG.getBoolExtOrTrunc(IsNonZero, dl, VT, BoolVT);
+    SDValue Subtrahend = DAG.getZExtOrTrunc(IsNonZero, dl, VT);
     return DAG.getNode(ISD::SUB, dl, VT, LHS, Subtrahend);
   }
 

>From 0c20d337bfe8e1a7d43248dcbcd7b7a5f8595892 Mon Sep 17 00:00:00 2001
From: rez5427 <guanjian at stu.cdut.edu.cn>
Date: Thu, 4 Dec 2025 23:39:06 +0800
Subject: [PATCH 4/7] Add getBoolExtOrTrunc and and

---
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 1d3846c54bce4..966cb8e71d4f2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10882,7 +10882,8 @@ SDValue TargetLowering::expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const {
     SDValue Zero = DAG.getConstant(0, dl, VT);
     EVT BoolVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
     SDValue IsNonZero = DAG.getSetCC(dl, BoolVT, LHS, Zero, ISD::SETNE);
-    SDValue Subtrahend = DAG.getZExtOrTrunc(IsNonZero, dl, VT);
+    SDValue Subtrahend = DAG.getBoolExtOrTrunc(IsNonZero, dl, VT, BoolVT);
+    Subtrahend = DAG.getNode(ISD::AND, dl, VT, Subtrahend, DAG.getConstant(1, dl, VT));
     return DAG.getNode(ISD::SUB, dl, VT, LHS, Subtrahend);
   }
 

>From ae1bccfe8227a6d1a87279a3297bcf83b5674b9a Mon Sep 17 00:00:00 2001
From: rez5427 <guanjian at stu.cdut.edu.cn>
Date: Sat, 6 Dec 2025 20:09:06 +0800
Subject: [PATCH 5/7] Add freeze, ban vector

---
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 6 ++++--
 llvm/test/CodeGen/X86/combine-sub-usat.ll        | 6 +++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 966cb8e71d4f2..1b25d91d9a316 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10878,12 +10878,14 @@ SDValue TargetLowering::expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const {
   assert(VT.isInteger() && "Expected operands to be integers");
 
   // usub.sat(a, 1) -> sub(a, zext(a != 0))
-  if (Opcode == ISD::USUBSAT && isOneConstant(RHS)) {
+  if (Opcode == ISD::USUBSAT && !VT.isVector() && isOneConstant(RHS)) {
+    LHS = DAG.getFreeze(LHS);
     SDValue Zero = DAG.getConstant(0, dl, VT);
     EVT BoolVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
     SDValue IsNonZero = DAG.getSetCC(dl, BoolVT, LHS, Zero, ISD::SETNE);
     SDValue Subtrahend = DAG.getBoolExtOrTrunc(IsNonZero, dl, VT, BoolVT);
-    Subtrahend = DAG.getNode(ISD::AND, dl, VT, Subtrahend, DAG.getConstant(1, dl, VT));
+    Subtrahend =
+        DAG.getNode(ISD::AND, dl, VT, Subtrahend, DAG.getConstant(1, dl, VT));
     return DAG.getNode(ISD::SUB, dl, VT, LHS, Subtrahend);
   }
 
diff --git a/llvm/test/CodeGen/X86/combine-sub-usat.ll b/llvm/test/CodeGen/X86/combine-sub-usat.ll
index e601c5733bd42..7ec4e062930db 100644
--- a/llvm/test/CodeGen/X86/combine-sub-usat.ll
+++ b/llvm/test/CodeGen/X86/combine-sub-usat.ll
@@ -116,9 +116,9 @@ define <8 x i16> @combine_zero_v8i16(<8 x i16> %a0) {
 define i32 @combine_dec_i32(i32 %a0) {
 ; CHECK-LABEL: combine_dec_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    subl $1, %edi
-; CHECK-NEXT:    cmovael %edi, %eax
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    cmpl $1, %edi
+; CHECK-NEXT:    adcl $-1, %eax
 ; CHECK-NEXT:    retq
   %1 = call i32 @llvm.usub.sat.i32(i32 %a0, i32 1)
   ret i32 %1

>From 2a332621554fd91d4537b80d58ccd269fcfa8b03 Mon Sep 17 00:00:00 2001
From: rez5427 <guanjian at stu.cdut.edu.cn>
Date: Tue, 9 Dec 2025 12:13:21 +0800
Subject: [PATCH 6/7] Add more tests

---
 llvm/test/CodeGen/RISCV/usub_sat.ll | 174 +++++++++++++++++++++++++---
 1 file changed, 157 insertions(+), 17 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/usub_sat.ll b/llvm/test/CodeGen/RISCV/usub_sat.ll
index 7084885a0ee2c..11c45c14fa80d 100644
--- a/llvm/test/CodeGen/RISCV/usub_sat.ll
+++ b/llvm/test/CodeGen/RISCV/usub_sat.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=riscv32 -mattr=+m | FileCheck %s --check-prefix=RV32I
-; RUN: llc < %s -mtriple=riscv64 -mattr=+m | FileCheck %s --check-prefix=RV64I
-; RUN: llc < %s -mtriple=riscv32 -mattr=+m,+zbb | FileCheck %s --check-prefix=RV32IZbb
-; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zbb | FileCheck %s --check-prefix=RV64IZbb
+; RUN: llc < %s -mtriple=riscv32 -mattr=+m,+v | FileCheck %s --check-prefix=RV32I
+; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+v | FileCheck %s --check-prefix=RV64I
+; RUN: llc < %s -mtriple=riscv32 -mattr=+m,+zbb,+v | FileCheck %s --check-prefix=RV32IZbb
+; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zbb,+v | FileCheck %s --check-prefix=RV64IZbb
 
 define signext i32 @func(i32 signext %x, i32 signext %y) nounwind {
 ; RV32I-LABEL: func:
@@ -186,30 +186,170 @@ define zeroext i4 @func3(i4 zeroext %x, i4 zeroext %y) nounwind {
   ret i4 %tmp;
 }
 
-define signext i32 @sat_dec_i32(i32 signext %x) nounwind {
-; RV32I-LABEL: sat_dec_i32:
+define signext i32 @fun9(i32 signext %x) nounwind {
+; RV32I-LABEL: fun9:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    snez a1, a0
-; RV32I-NEXT:    sub a0, a0, a1
+; RV32I-NEXT:    addi a1, a0, -1
+; RV32I-NEXT:    sltu a0, a0, a1
+; RV32I-NEXT:    addi a0, a0, -1
+; RV32I-NEXT:    and a0, a0, a1
 ; RV32I-NEXT:    ret
 ;
-; RV64I-LABEL: sat_dec_i32:
+; RV64I-LABEL: fun9:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    snez a1, a0
-; RV64I-NEXT:    subw a0, a0, a1
+; RV64I-NEXT:    addiw a1, a0, -1
+; RV64I-NEXT:    sltu a0, a0, a1
+; RV64I-NEXT:    addi a0, a0, -1
+; RV64I-NEXT:    and a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
-; RV32IZbb-LABEL: sat_dec_i32:
+; RV32IZbb-LABEL: fun9:
 ; RV32IZbb:       # %bb.0:
-; RV32IZbb-NEXT:    snez a1, a0
-; RV32IZbb-NEXT:    sub a0, a0, a1
+; RV32IZbb-NEXT:    li a1, 1
+; RV32IZbb-NEXT:    maxu a0, a0, a1
+; RV32IZbb-NEXT:    addi a0, a0, -1
 ; RV32IZbb-NEXT:    ret
 ;
-; RV64IZbb-LABEL: sat_dec_i32:
+; RV64IZbb-LABEL: fun9:
 ; RV64IZbb:       # %bb.0:
-; RV64IZbb-NEXT:    snez a1, a0
-; RV64IZbb-NEXT:    subw a0, a0, a1
+; RV64IZbb-NEXT:    li a1, 1
+; RV64IZbb-NEXT:    maxu a0, a0, a1
+; RV64IZbb-NEXT:    addiw a0, a0, -1
 ; RV64IZbb-NEXT:    ret
   %tmp = call i32 @llvm.usub.sat.i32(i32 %x, i32 1)
   ret i32 %tmp
 }
+
+define signext i32 @fun10(i32 signext %x) nounwind {
+; RV32I-LABEL: fun10:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: fun10:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    ret
+;
+; RV32IZbb-LABEL: fun10:
+; RV32IZbb:       # %bb.0:
+; RV32IZbb-NEXT:    ret
+;
+; RV64IZbb-LABEL: fun10:
+; RV64IZbb:       # %bb.0:
+; RV64IZbb-NEXT:    ret
+  %tmp = call i32 @llvm.usub.sat.i32(i32 %x, i32 0)
+  ret i32 %tmp
+}
+
+define signext i32 @fun11(i32 signext %x) nounwind {
+; RV32I-LABEL: fun11:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi a1, a0, 1
+; RV32I-NEXT:    sltu a0, a0, a1
+; RV32I-NEXT:    addi a0, a0, -1
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: fun11:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addiw a1, a0, 1
+; RV64I-NEXT:    sltu a0, a0, a1
+; RV64I-NEXT:    addi a0, a0, -1
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    ret
+;
+; RV32IZbb-LABEL: fun11:
+; RV32IZbb:       # %bb.0:
+; RV32IZbb-NEXT:    li a0, 0
+; RV32IZbb-NEXT:    ret
+;
+; RV64IZbb-LABEL: fun11:
+; RV64IZbb:       # %bb.0:
+; RV64IZbb-NEXT:    li a0, 0
+; RV64IZbb-NEXT:    ret
+  %tmp = call i32 @llvm.usub.sat.i32(i32 %x, i32 -1)
+  ret i32 %tmp
+}
+
+define <4 x i32> @fun12(<4 x i32> %a0) nounwind {
+; RV32I-LABEL: fun12:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32I-NEXT:    vssubu.vx v8, v8, a0
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: fun12:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    li a0, 1
+; RV64I-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64I-NEXT:    vssubu.vx v8, v8, a0
+; RV64I-NEXT:    ret
+;
+; RV32IZbb-LABEL: fun12:
+; RV32IZbb:       # %bb.0:
+; RV32IZbb-NEXT:    li a0, 1
+; RV32IZbb-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32IZbb-NEXT:    vssubu.vx v8, v8, a0
+; RV32IZbb-NEXT:    ret
+;
+; RV64IZbb-LABEL: fun12:
+; RV64IZbb:       # %bb.0:
+; RV64IZbb-NEXT:    li a0, 1
+; RV64IZbb-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64IZbb-NEXT:    vssubu.vx v8, v8, a0
+; RV64IZbb-NEXT:    ret
+  %1 = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %a0, <4 x i32> splat (i32 1))
+  ret <4 x i32> %1
+}
+
+define <4 x i32> @fun13(<4 x i32> %a0) nounwind {
+; RV32I-LABEL: fun13:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a0, -1
+; RV32I-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32I-NEXT:    vssubu.vx v8, v8, a0
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: fun13:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    li a0, -1
+; RV64I-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64I-NEXT:    vssubu.vx v8, v8, a0
+; RV64I-NEXT:    ret
+;
+; RV32IZbb-LABEL: fun13:
+; RV32IZbb:       # %bb.0:
+; RV32IZbb-NEXT:    li a0, -1
+; RV32IZbb-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32IZbb-NEXT:    vssubu.vx v8, v8, a0
+; RV32IZbb-NEXT:    ret
+;
+; RV64IZbb-LABEL: fun13:
+; RV64IZbb:       # %bb.0:
+; RV64IZbb-NEXT:    li a0, -1
+; RV64IZbb-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64IZbb-NEXT:    vssubu.vx v8, v8, a0
+; RV64IZbb-NEXT:    ret
+  %1 = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %a0, <4 x i32> splat (i32 -1))
+  ret <4 x i32> %1
+}
+
+define <4 x i32> @fun14(<4 x i32> %a0) nounwind {
+; RV32I-LABEL: fun14:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: fun14:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    ret
+;
+; RV32IZbb-LABEL: fun14:
+; RV32IZbb:       # %bb.0:
+; RV32IZbb-NEXT:    ret
+;
+; RV64IZbb-LABEL: fun14:
+; RV64IZbb:       # %bb.0:
+; RV64IZbb-NEXT:    ret
+  %1 = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %a0, <4 x i32> splat (i32 0))
+  ret <4 x i32> %1
+}

>From 5e8e9212db85910c41e072f6379995bb74d142b0 Mon Sep 17 00:00:00 2001
From: rez5427 <guanjian at stu.cdut.edu.cn>
Date: Tue, 9 Dec 2025 12:59:11 +0800
Subject: [PATCH 7/7] Change tests

---
 llvm/test/CodeGen/RISCV/usub_sat.ll | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/usub_sat.ll b/llvm/test/CodeGen/RISCV/usub_sat.ll
index 11c45c14fa80d..16234855448c3 100644
--- a/llvm/test/CodeGen/RISCV/usub_sat.ll
+++ b/llvm/test/CodeGen/RISCV/usub_sat.ll
@@ -189,32 +189,26 @@ define zeroext i4 @func3(i4 zeroext %x, i4 zeroext %y) nounwind {
 define signext i32 @fun9(i32 signext %x) nounwind {
 ; RV32I-LABEL: fun9:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    addi a1, a0, -1
-; RV32I-NEXT:    sltu a0, a0, a1
-; RV32I-NEXT:    addi a0, a0, -1
-; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    snez a1, a0
+; RV32I-NEXT:    sub a0, a0, a1
 ; RV32I-NEXT:    ret
 ;
 ; RV64I-LABEL: fun9:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    addiw a1, a0, -1
-; RV64I-NEXT:    sltu a0, a0, a1
-; RV64I-NEXT:    addi a0, a0, -1
-; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    snez a1, a0
+; RV64I-NEXT:    subw a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV32IZbb-LABEL: fun9:
 ; RV32IZbb:       # %bb.0:
-; RV32IZbb-NEXT:    li a1, 1
-; RV32IZbb-NEXT:    maxu a0, a0, a1
-; RV32IZbb-NEXT:    addi a0, a0, -1
+; RV32IZbb-NEXT:    snez a1, a0
+; RV32IZbb-NEXT:    sub a0, a0, a1
 ; RV32IZbb-NEXT:    ret
 ;
 ; RV64IZbb-LABEL: fun9:
 ; RV64IZbb:       # %bb.0:
-; RV64IZbb-NEXT:    li a1, 1
-; RV64IZbb-NEXT:    maxu a0, a0, a1
-; RV64IZbb-NEXT:    addiw a0, a0, -1
+; RV64IZbb-NEXT:    snez a1, a0
+; RV64IZbb-NEXT:    subw a0, a0, a1
 ; RV64IZbb-NEXT:    ret
   %tmp = call i32 @llvm.usub.sat.i32(i32 %x, i32 1)
   ret i32 %tmp



More information about the llvm-commits mailing list