[llvm] 5aa8fcc - [RISCV] Support swapped select operands in combineTruncSelectToSMaxUSat. (#226584)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 15:54:09 PDT 2026


Author: Craig Topper
Date: 2026-09-25T15:54:02-07:00
New Revision: 5aa8fcc29bc47056411b3d23b0e7acc981ec3934

URL: https://github.com/llvm/llvm-project/commit/5aa8fcc29bc47056411b3d23b0e7acc981ec3934
DIFF: https://github.com/llvm/llvm-project/commit/5aa8fcc29bc47056411b3d23b0e7acc981ec3934.diff

LOG: [RISCV] Support swapped select operands in combineTruncSelectToSMaxUSat. (#226584)

Handle (trunc (vselect (setugt X, 2^N-1), (sext (setgt X, 0)), X)) in
addition to the existing (trunc (vselect (setult X, 2^N), X,
(sext (setgt X, 0)))) form.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply at anthropic.com>

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/test/CodeGen/RISCV/rvv/trunc-select-to-max-usat.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index cceeaaea82405..3e442bd08d7f8 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -19251,7 +19251,8 @@ static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG) {
   return DAG.getNode(ISD::XOR, DL, VT, Logic, DAG.getConstant(1, DL, VT));
 }
 
-// Fold (vXi8 (trunc (vselect (setltu, X, 256), X, (sext (setgt X, 0))))) to
+// Fold (vXi8 (trunc (vselect (setltu, X, 256), X, (sext (setgt X, 0))))) or
+// (vXi8 (trunc (vselect (setgtu, X, 255), (sext (setgt X, 0)), X))) to
 // (vXi8 (trunc (smin (smax X, 0), 255))). This represents saturating a signed
 // value to an unsigned value. This will be lowered to vmax and series of
 // vnclipu instructions later. This can be extended to other truncated types
@@ -19276,45 +19277,52 @@ static SDValue combineTruncSelectToSMaxUSat(SDNode *N, SelectionDAG &DAG) {
   if (Cond.getOpcode() != ISD::SETCC)
     return SDValue();
 
-  // FIXME: Support the version of this pattern with the select operands
-  // swapped.
-  ISD::CondCode CCVal = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
-  if (CCVal != ISD::SETULT)
-    return SDValue();
-
-  SDValue CondLHS = Cond.getOperand(0);
+  SDValue X = Cond.getOperand(0);
   SDValue CondRHS = Cond.getOperand(1);
+  unsigned ScalarBits = VT.getScalarSizeInBits();
 
-  if (CondLHS != True)
+  ISD::CondCode CCVal = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
+  SDValue Other;
+  uint64_t ExpectedC;
+  if (CCVal == ISD::SETULT) {
+    if (True != X)
+      return SDValue();
+    Other = False;
+    ExpectedC = 1ULL << ScalarBits;
+  } else if (CCVal == ISD::SETUGT) {
+    if (False != X)
+      return SDValue();
+    Other = True;
+    ExpectedC = (1ULL << ScalarBits) - 1;
+  } else {
     return SDValue();
-
-  unsigned ScalarBits = VT.getScalarSizeInBits();
+  }
 
   // FIXME: Support other constants.
   ConstantSDNode *CondRHSC = isConstOrConstSplat(CondRHS);
-  if (!CondRHSC || CondRHSC->getAPIntValue() != (1ULL << ScalarBits))
+  if (!CondRHSC || CondRHSC->getAPIntValue() != ExpectedC)
     return SDValue();
 
-  if (False.getOpcode() != ISD::SIGN_EXTEND)
+  if (Other.getOpcode() != ISD::SIGN_EXTEND)
     return SDValue();
 
-  False = False.getOperand(0);
+  Other = Other.getOperand(0);
 
-  if (False.getOpcode() != ISD::SETCC || False.getOperand(0) != True)
+  if (Other.getOpcode() != ISD::SETCC || Other.getOperand(0) != X)
     return SDValue();
 
-  ConstantSDNode *FalseRHSC = isConstOrConstSplat(False.getOperand(1));
-  if (!FalseRHSC || !FalseRHSC->isZero())
+  ConstantSDNode *OtherRHSC = isConstOrConstSplat(Other.getOperand(1));
+  if (!OtherRHSC || !OtherRHSC->isZero())
     return SDValue();
 
-  ISD::CondCode CCVal2 = cast<CondCodeSDNode>(False.getOperand(2))->get();
+  ISD::CondCode CCVal2 = cast<CondCodeSDNode>(Other.getOperand(2))->get();
   if (CCVal2 != ISD::SETGT)
     return SDValue();
 
   // Emit the signed to unsigned saturation pattern.
   SDLoc DL(N);
   SDValue Max =
-      DAG.getNode(ISD::SMAX, DL, SrcVT, True, DAG.getConstant(0, DL, SrcVT));
+      DAG.getNode(ISD::SMAX, DL, SrcVT, X, DAG.getConstant(0, DL, SrcVT));
   SDValue Min =
       DAG.getNode(ISD::UMIN, DL, SrcVT, Max,
                   DAG.getConstant((1ULL << ScalarBits) - 1, DL, SrcVT));

diff  --git a/llvm/test/CodeGen/RISCV/rvv/trunc-select-to-max-usat.ll b/llvm/test/CodeGen/RISCV/rvv/trunc-select-to-max-usat.ll
index d2f73826e4e9e..c341053742de0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/trunc-select-to-max-usat.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/trunc-select-to-max-usat.ll
@@ -209,3 +209,87 @@ define <vscale x 4 x i32> @test_nxv4i64_nxv4i32(<vscale x 4 x i64> %x) {
   %e = trunc <vscale x 4 x i64> %d to <vscale x 4 x i32>
   ret <vscale x 4 x i32> %e
 }
+
+define <4 x i8> @test_v4i16_v4i8_swapped(<4 x i16> %x) {
+; CHECK-LABEL: test_v4i16_v4i8_swapped:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e16, mf2, ta, ma
+; CHECK-NEXT:    vmax.vx v8, v8, zero
+; CHECK-NEXT:    vsetvli zero, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vnclipu.wi v8, v8, 0
+; CHECK-NEXT:    ret
+  %a = icmp sgt <4 x i16> %x, zeroinitializer
+  %b = sext <4 x i1> %a to <4 x i16>
+  %c = icmp ugt <4 x i16> %x, splat (i16 255)
+  %d = select <4 x i1> %c, <4 x i16> %b, <4 x i16> %x
+  %e = trunc <4 x i16> %d to <4 x i8>
+  ret <4 x i8> %e
+}
+
+define <4 x i8> @test_v4i32_v4i8_swapped(<4 x i32> %x) {
+; CHECK-LABEL: test_v4i32_v4i8_swapped:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vmax.vx v8, v8, zero
+; CHECK-NEXT:    vsetvli zero, zero, e16, mf2, ta, ma
+; CHECK-NEXT:    vnclipu.wi v8, v8, 0
+; CHECK-NEXT:    vsetvli zero, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vnclipu.wi v8, v8, 0
+; CHECK-NEXT:    ret
+  %a = icmp sgt <4 x i32> %x, zeroinitializer
+  %b = sext <4 x i1> %a to <4 x i32>
+  %c = icmp ugt <4 x i32> %x, splat (i32 255)
+  %d = select <4 x i1> %c, <4 x i32> %b, <4 x i32> %x
+  %e = trunc <4 x i32> %d to <4 x i8>
+  ret <4 x i8> %e
+}
+
+define <4 x i16> @test_v4i32_v4i16_swapped(<4 x i32> %x) {
+; CHECK-LABEL: test_v4i32_v4i16_swapped:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vmax.vx v8, v8, zero
+; CHECK-NEXT:    vsetvli zero, zero, e16, mf2, ta, ma
+; CHECK-NEXT:    vnclipu.wi v8, v8, 0
+; CHECK-NEXT:    ret
+  %a = icmp sgt <4 x i32> %x, zeroinitializer
+  %b = sext <4 x i1> %a to <4 x i32>
+  %c = icmp ugt <4 x i32> %x, splat (i32 65535)
+  %d = select <4 x i1> %c, <4 x i32> %b, <4 x i32> %x
+  %e = trunc <4 x i32> %d to <4 x i16>
+  ret <4 x i16> %e
+}
+
+define <vscale x 4 x i8> @test_nxv4i16_nxv4i8_swapped(<vscale x 4 x i16> %x) {
+; CHECK-LABEL: test_nxv4i16_nxv4i8_swapped:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e16, m1, ta, ma
+; CHECK-NEXT:    vmax.vx v8, v8, zero
+; CHECK-NEXT:    vsetvli zero, zero, e8, mf2, ta, ma
+; CHECK-NEXT:    vnclipu.wi v8, v8, 0
+; CHECK-NEXT:    ret
+  %a = icmp sgt <vscale x 4 x i16> %x, zeroinitializer
+  %b = sext <vscale x 4 x i1> %a to <vscale x 4 x i16>
+  %c = icmp ugt <vscale x 4 x i16> %x, splat (i16 255)
+  %d = select <vscale x 4 x i1> %c, <vscale x 4 x i16> %b, <vscale x 4 x i16> %x
+  %e = trunc <vscale x 4 x i16> %d to <vscale x 4 x i8>
+  ret <vscale x 4 x i8> %e
+}
+
+define <vscale x 4 x i16> @test_nxv4i64_nxv4i16_swapped(<vscale x 4 x i64> %x) {
+; CHECK-LABEL: test_nxv4i64_nxv4i16_swapped:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e64, m4, ta, ma
+; CHECK-NEXT:    vmax.vx v8, v8, zero
+; CHECK-NEXT:    vsetvli zero, zero, e32, m2, ta, ma
+; CHECK-NEXT:    vnclipu.wi v12, v8, 0
+; CHECK-NEXT:    vsetvli zero, zero, e16, m1, ta, ma
+; CHECK-NEXT:    vnclipu.wi v8, v12, 0
+; CHECK-NEXT:    ret
+  %a = icmp sgt <vscale x 4 x i64> %x, zeroinitializer
+  %b = sext <vscale x 4 x i1> %a to <vscale x 4 x i64>
+  %c = icmp ugt <vscale x 4 x i64> %x, splat (i64 65535)
+  %d = select <vscale x 4 x i1> %c, <vscale x 4 x i64> %b, <vscale x 4 x i64> %x
+  %e = trunc <vscale x 4 x i64> %d to <vscale x 4 x i16>
+  ret <vscale x 4 x i16> %e
+}


        


More information about the llvm-commits mailing list