[llvm] [AMDGPU] Lower uniform uaddsat.i16 to SALU instructions (PR #210156)
Anshil Gandhi via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 17 09:11:54 PDT 2026
https://github.com/gandhi56 updated https://github.com/llvm/llvm-project/pull/210156
>From 46236da63e677e9394352780ca2d77bb0e22e1d7 Mon Sep 17 00:00:00 2001
From: Anshil Gandhi <Anshil.Gandhi at amd.com>
Date: Thu, 16 Jul 2026 14:56:33 -0500
Subject: [PATCH] [AMDGPU] Lower uniform uaddsat.i16 to SALU instructions
---
llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 1 +
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 12 +-
llvm/lib/Target/AMDGPU/SOPInstructions.td | 5 +-
.../test/CodeGen/AMDGPU/GlobalISel/uaddsat.ll | 190 +++++++++---------
llvm/test/CodeGen/AMDGPU/uaddsat.ll | 56 ++++++
5 files changed, 169 insertions(+), 95 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 4858009fecff5..c42a838388e6a 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -1059,6 +1059,7 @@ bool AMDGPUTargetLowering::isNarrowingProfitable(SDNode *N, EVT SrcVT,
case ISD::UMIN:
case ISD::UMAX:
case ISD::USUBSAT:
+ case ISD::UADDSAT:
if (isTypeLegal(MVT::i16) &&
(!DestVT.isVector() ||
!isOperationLegal(ISD::ADD, MVT::v2i16))) { // Check if VOP3P
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 87e951e489ba5..fa082983eacf6 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -1076,6 +1076,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
ISD::UMIN,
ISD::UMAX,
ISD::USUBSAT,
+ ISD::UADDSAT,
ISD::AND,
ISD::OR,
ISD::XOR,
@@ -8901,6 +8902,7 @@ static unsigned getExtOpcodeForPromotedOp(SDValue Op) {
case ISD::UMIN:
case ISD::UMAX:
case ISD::USUBSAT:
+ case ISD::UADDSAT:
return ISD::ZERO_EXTEND;
case ISD::ADD:
case ISD::SUB:
@@ -8950,7 +8952,7 @@ SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
- Opc == ISD::USUBSAT);
+ Opc == ISD::USUBSAT || Opc == ISD::UADDSAT);
EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
: Op->getOperand(0).getValueType();
@@ -8992,7 +8994,12 @@ SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
SDValue NewVal;
if (Opc == ISD::SELECT)
NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
- else
+ else if (Opc == ISD::UADDSAT) {
+ SDValue Sum = DAG.getNode(ISD::ADD, DL, ExtTy, LHS, RHS);
+ SDValue MaxVal = DAG.getConstant(
+ APInt::getMaxValue(OpTy.getScalarSizeInBits()).zext(32), DL, ExtTy);
+ NewVal = DAG.getNode(ISD::UMIN, DL, ExtTy, Sum, MaxVal);
+ } else
NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
@@ -18671,6 +18678,7 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
case ISD::UMIN:
case ISD::UMAX:
case ISD::USUBSAT:
+ case ISD::UADDSAT:
if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
return Res;
break;
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index 97d50d6142d35..f8171a4c3389a 100644
--- a/llvm/lib/Target/AMDGPU/SOPInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td
@@ -2073,14 +2073,13 @@ let AddedComplexity = 20 in {
>;
}
-// Uniform saturating unsigned subtraction: usubsat(a, b) = max(a, b) - b
-// If a >= b, result is a - b; otherwise max(a, b) = b, so b - b = 0.
// Higher complexity to prefer scalar over VALU patterns for uniform values.
-let AddedComplexity = 20 in {
+let AddedComplexity = 20 in {
def : GCNPat<
(i32 (UniformBinFrag<uaddsat> i32:$src0, i32:$src1)),
(S_ADD_U32 (S_MIN_U32 $src0, (S_NOT_B32 $src1)), $src1)
>;
+
def : GCNPat<
(i32 (UniformBinFrag<usubsat> i32:$src0, i32:$src1)),
(S_SUB_I32 (S_MAX_U32 $src0, $src1), $src1)
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/uaddsat.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/uaddsat.ll
index 9f9d47c09bdfb..7d9bd9d2c7c69 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/uaddsat.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/uaddsat.ll
@@ -1940,15 +1940,16 @@ define amdgpu_ps i32 @s_uaddsat_v2i16(<2 x i16> inreg %lhs, <2 x i16> inreg %rhs
;
; GFX8-LABEL: s_uaddsat_v2i16:
; GFX8: ; %bb.0:
-; GFX8-NEXT: s_lshr_b32 s2, s1, 16
-; GFX8-NEXT: s_lshr_b32 s3, s0, 16
-; GFX8-NEXT: v_mov_b32_e32 v0, s2
-; GFX8-NEXT: v_mov_b32_e32 v1, s3
-; GFX8-NEXT: v_add_u16_sdwa v0, v1, v0 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v1, s1
-; GFX8-NEXT: v_add_u16_e64 v1, s0, v1 clamp
-; GFX8-NEXT: v_or_b32_e32 v0, v1, v0
-; GFX8-NEXT: v_readfirstlane_b32 s0, v0
+; GFX8-NEXT: s_and_b32 s2, s1, 0xffff
+; GFX8-NEXT: s_and_b32 s3, s0, 0xffff
+; GFX8-NEXT: s_lshr_b32 s1, s1, 16
+; GFX8-NEXT: s_lshr_b32 s0, s0, 16
+; GFX8-NEXT: s_add_i32 s0, s0, s1
+; GFX8-NEXT: s_add_i32 s3, s3, s2
+; GFX8-NEXT: s_min_u32 s0, s0, 0xffff
+; GFX8-NEXT: s_min_u32 s2, s3, 0xffff
+; GFX8-NEXT: s_lshl_b32 s0, s0, 16
+; GFX8-NEXT: s_or_b32 s0, s2, s0
; GFX8-NEXT: ; return to shader part epilog
;
; GFX9-LABEL: s_uaddsat_v2i16:
@@ -2157,24 +2158,26 @@ define amdgpu_ps <2 x i32> @s_uaddsat_v4i16(<4 x i16> inreg %lhs, <4 x i16> inre
;
; GFX8-LABEL: s_uaddsat_v4i16:
; GFX8: ; %bb.0:
-; GFX8-NEXT: s_lshr_b32 s4, s3, 16
-; GFX8-NEXT: s_lshr_b32 s5, s1, 16
-; GFX8-NEXT: v_mov_b32_e32 v0, s4
-; GFX8-NEXT: v_mov_b32_e32 v1, s5
-; GFX8-NEXT: v_add_u16_sdwa v0, v1, v0 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v1, s3
-; GFX8-NEXT: v_add_u16_e64 v1, s1, v1 clamp
-; GFX8-NEXT: s_lshr_b32 s1, s2, 16
-; GFX8-NEXT: s_lshr_b32 s3, s0, 16
-; GFX8-NEXT: v_or_b32_e32 v0, v1, v0
-; GFX8-NEXT: v_mov_b32_e32 v1, s1
-; GFX8-NEXT: v_mov_b32_e32 v2, s3
-; GFX8-NEXT: v_add_u16_sdwa v1, v2, v1 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v2, s2
-; GFX8-NEXT: v_add_u16_e64 v2, s0, v2 clamp
-; GFX8-NEXT: v_or_b32_e32 v1, v2, v1
-; GFX8-NEXT: v_readfirstlane_b32 s0, v1
-; GFX8-NEXT: v_readfirstlane_b32 s1, v0
+; GFX8-NEXT: s_and_b32 s4, s3, 0xffff
+; GFX8-NEXT: s_and_b32 s5, s1, 0xffff
+; GFX8-NEXT: s_lshr_b32 s3, s3, 16
+; GFX8-NEXT: s_lshr_b32 s1, s1, 16
+; GFX8-NEXT: s_add_i32 s1, s1, s3
+; GFX8-NEXT: s_add_i32 s5, s5, s4
+; GFX8-NEXT: s_min_u32 s1, s1, 0xffff
+; GFX8-NEXT: s_min_u32 s4, s5, 0xffff
+; GFX8-NEXT: s_lshl_b32 s1, s1, 16
+; GFX8-NEXT: s_or_b32 s1, s4, s1
+; GFX8-NEXT: s_and_b32 s3, s2, 0xffff
+; GFX8-NEXT: s_and_b32 s4, s0, 0xffff
+; GFX8-NEXT: s_lshr_b32 s2, s2, 16
+; GFX8-NEXT: s_lshr_b32 s0, s0, 16
+; GFX8-NEXT: s_add_i32 s0, s0, s2
+; GFX8-NEXT: s_add_i32 s4, s4, s3
+; GFX8-NEXT: s_min_u32 s0, s0, 0xffff
+; GFX8-NEXT: s_min_u32 s3, s4, 0xffff
+; GFX8-NEXT: s_lshl_b32 s0, s0, 16
+; GFX8-NEXT: s_or_b32 s0, s3, s0
; GFX8-NEXT: ; return to shader part epilog
;
; GFX9-LABEL: s_uaddsat_v4i16:
@@ -2347,33 +2350,36 @@ define amdgpu_ps <3 x i32> @s_uaddsat_v6i16(<6 x i16> inreg %lhs, <6 x i16> inre
;
; GFX8-LABEL: s_uaddsat_v6i16:
; GFX8: ; %bb.0:
-; GFX8-NEXT: s_lshr_b32 s6, s5, 16
-; GFX8-NEXT: s_lshr_b32 s7, s2, 16
-; GFX8-NEXT: v_mov_b32_e32 v0, s6
-; GFX8-NEXT: v_mov_b32_e32 v1, s7
-; GFX8-NEXT: v_add_u16_sdwa v0, v1, v0 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v1, s5
-; GFX8-NEXT: v_add_u16_e64 v1, s2, v1 clamp
-; GFX8-NEXT: s_lshr_b32 s2, s4, 16
-; GFX8-NEXT: s_lshr_b32 s5, s1, 16
-; GFX8-NEXT: v_or_b32_e32 v0, v1, v0
-; GFX8-NEXT: v_mov_b32_e32 v1, s2
-; GFX8-NEXT: v_mov_b32_e32 v2, s5
-; GFX8-NEXT: v_add_u16_sdwa v1, v2, v1 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v2, s4
-; GFX8-NEXT: v_add_u16_e64 v2, s1, v2 clamp
-; GFX8-NEXT: s_lshr_b32 s1, s3, 16
-; GFX8-NEXT: s_lshr_b32 s2, s0, 16
-; GFX8-NEXT: v_or_b32_e32 v1, v2, v1
-; GFX8-NEXT: v_mov_b32_e32 v2, s1
-; GFX8-NEXT: v_mov_b32_e32 v3, s2
-; GFX8-NEXT: v_add_u16_sdwa v2, v3, v2 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v3, s3
-; GFX8-NEXT: v_add_u16_e64 v3, s0, v3 clamp
-; GFX8-NEXT: v_or_b32_e32 v2, v3, v2
-; GFX8-NEXT: v_readfirstlane_b32 s0, v2
-; GFX8-NEXT: v_readfirstlane_b32 s1, v1
-; GFX8-NEXT: v_readfirstlane_b32 s2, v0
+; GFX8-NEXT: s_and_b32 s6, s5, 0xffff
+; GFX8-NEXT: s_and_b32 s7, s2, 0xffff
+; GFX8-NEXT: s_lshr_b32 s5, s5, 16
+; GFX8-NEXT: s_lshr_b32 s2, s2, 16
+; GFX8-NEXT: s_add_i32 s2, s2, s5
+; GFX8-NEXT: s_add_i32 s7, s7, s6
+; GFX8-NEXT: s_min_u32 s2, s2, 0xffff
+; GFX8-NEXT: s_min_u32 s6, s7, 0xffff
+; GFX8-NEXT: s_lshl_b32 s2, s2, 16
+; GFX8-NEXT: s_or_b32 s2, s6, s2
+; GFX8-NEXT: s_and_b32 s5, s4, 0xffff
+; GFX8-NEXT: s_and_b32 s6, s1, 0xffff
+; GFX8-NEXT: s_lshr_b32 s4, s4, 16
+; GFX8-NEXT: s_lshr_b32 s1, s1, 16
+; GFX8-NEXT: s_add_i32 s1, s1, s4
+; GFX8-NEXT: s_add_i32 s6, s6, s5
+; GFX8-NEXT: s_min_u32 s1, s1, 0xffff
+; GFX8-NEXT: s_min_u32 s5, s6, 0xffff
+; GFX8-NEXT: s_lshl_b32 s1, s1, 16
+; GFX8-NEXT: s_or_b32 s1, s5, s1
+; GFX8-NEXT: s_and_b32 s4, s3, 0xffff
+; GFX8-NEXT: s_and_b32 s5, s0, 0xffff
+; GFX8-NEXT: s_lshr_b32 s3, s3, 16
+; GFX8-NEXT: s_lshr_b32 s0, s0, 16
+; GFX8-NEXT: s_add_i32 s0, s0, s3
+; GFX8-NEXT: s_add_i32 s5, s5, s4
+; GFX8-NEXT: s_min_u32 s0, s0, 0xffff
+; GFX8-NEXT: s_min_u32 s4, s5, 0xffff
+; GFX8-NEXT: s_lshl_b32 s0, s0, 16
+; GFX8-NEXT: s_or_b32 s0, s4, s0
; GFX8-NEXT: ; return to shader part epilog
;
; GFX9-LABEL: s_uaddsat_v6i16:
@@ -2575,42 +2581,46 @@ define amdgpu_ps <4 x i32> @s_uaddsat_v8i16(<8 x i16> inreg %lhs, <8 x i16> inre
;
; GFX8-LABEL: s_uaddsat_v8i16:
; GFX8: ; %bb.0:
-; GFX8-NEXT: s_lshr_b32 s8, s7, 16
-; GFX8-NEXT: s_lshr_b32 s9, s3, 16
-; GFX8-NEXT: v_mov_b32_e32 v0, s8
-; GFX8-NEXT: v_mov_b32_e32 v1, s9
-; GFX8-NEXT: v_add_u16_sdwa v0, v1, v0 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v1, s7
-; GFX8-NEXT: v_add_u16_e64 v1, s3, v1 clamp
-; GFX8-NEXT: s_lshr_b32 s3, s6, 16
-; GFX8-NEXT: s_lshr_b32 s7, s2, 16
-; GFX8-NEXT: v_or_b32_e32 v0, v1, v0
-; GFX8-NEXT: v_mov_b32_e32 v1, s3
-; GFX8-NEXT: v_mov_b32_e32 v2, s7
-; GFX8-NEXT: v_add_u16_sdwa v1, v2, v1 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v2, s6
-; GFX8-NEXT: v_add_u16_e64 v2, s2, v2 clamp
-; GFX8-NEXT: s_lshr_b32 s2, s5, 16
-; GFX8-NEXT: s_lshr_b32 s3, s1, 16
-; GFX8-NEXT: v_or_b32_e32 v1, v2, v1
-; GFX8-NEXT: v_mov_b32_e32 v2, s2
-; GFX8-NEXT: v_mov_b32_e32 v3, s3
-; GFX8-NEXT: v_add_u16_sdwa v2, v3, v2 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v3, s5
-; GFX8-NEXT: v_add_u16_e64 v3, s1, v3 clamp
-; GFX8-NEXT: s_lshr_b32 s1, s4, 16
-; GFX8-NEXT: s_lshr_b32 s2, s0, 16
-; GFX8-NEXT: v_or_b32_e32 v2, v3, v2
-; GFX8-NEXT: v_mov_b32_e32 v3, s1
-; GFX8-NEXT: v_mov_b32_e32 v4, s2
-; GFX8-NEXT: v_add_u16_sdwa v3, v4, v3 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
-; GFX8-NEXT: v_mov_b32_e32 v4, s4
-; GFX8-NEXT: v_add_u16_e64 v4, s0, v4 clamp
-; GFX8-NEXT: v_or_b32_e32 v3, v4, v3
-; GFX8-NEXT: v_readfirstlane_b32 s0, v3
-; GFX8-NEXT: v_readfirstlane_b32 s1, v2
-; GFX8-NEXT: v_readfirstlane_b32 s2, v1
-; GFX8-NEXT: v_readfirstlane_b32 s3, v0
+; GFX8-NEXT: s_and_b32 s8, s7, 0xffff
+; GFX8-NEXT: s_and_b32 s9, s3, 0xffff
+; GFX8-NEXT: s_lshr_b32 s7, s7, 16
+; GFX8-NEXT: s_lshr_b32 s3, s3, 16
+; GFX8-NEXT: s_add_i32 s3, s3, s7
+; GFX8-NEXT: s_add_i32 s9, s9, s8
+; GFX8-NEXT: s_min_u32 s3, s3, 0xffff
+; GFX8-NEXT: s_min_u32 s8, s9, 0xffff
+; GFX8-NEXT: s_lshl_b32 s3, s3, 16
+; GFX8-NEXT: s_or_b32 s3, s8, s3
+; GFX8-NEXT: s_and_b32 s7, s6, 0xffff
+; GFX8-NEXT: s_and_b32 s8, s2, 0xffff
+; GFX8-NEXT: s_lshr_b32 s6, s6, 16
+; GFX8-NEXT: s_lshr_b32 s2, s2, 16
+; GFX8-NEXT: s_add_i32 s2, s2, s6
+; GFX8-NEXT: s_add_i32 s8, s8, s7
+; GFX8-NEXT: s_min_u32 s2, s2, 0xffff
+; GFX8-NEXT: s_min_u32 s7, s8, 0xffff
+; GFX8-NEXT: s_lshl_b32 s2, s2, 16
+; GFX8-NEXT: s_or_b32 s2, s7, s2
+; GFX8-NEXT: s_and_b32 s6, s5, 0xffff
+; GFX8-NEXT: s_and_b32 s7, s1, 0xffff
+; GFX8-NEXT: s_lshr_b32 s5, s5, 16
+; GFX8-NEXT: s_lshr_b32 s1, s1, 16
+; GFX8-NEXT: s_add_i32 s1, s1, s5
+; GFX8-NEXT: s_add_i32 s7, s7, s6
+; GFX8-NEXT: s_min_u32 s1, s1, 0xffff
+; GFX8-NEXT: s_min_u32 s6, s7, 0xffff
+; GFX8-NEXT: s_lshl_b32 s1, s1, 16
+; GFX8-NEXT: s_or_b32 s1, s6, s1
+; GFX8-NEXT: s_and_b32 s5, s4, 0xffff
+; GFX8-NEXT: s_and_b32 s6, s0, 0xffff
+; GFX8-NEXT: s_lshr_b32 s4, s4, 16
+; GFX8-NEXT: s_lshr_b32 s0, s0, 16
+; GFX8-NEXT: s_add_i32 s0, s0, s4
+; GFX8-NEXT: s_add_i32 s6, s6, s5
+; GFX8-NEXT: s_min_u32 s0, s0, 0xffff
+; GFX8-NEXT: s_min_u32 s5, s6, 0xffff
+; GFX8-NEXT: s_lshl_b32 s0, s0, 16
+; GFX8-NEXT: s_or_b32 s0, s5, s0
; GFX8-NEXT: ; return to shader part epilog
;
; GFX9-LABEL: s_uaddsat_v8i16:
diff --git a/llvm/test/CodeGen/AMDGPU/uaddsat.ll b/llvm/test/CodeGen/AMDGPU/uaddsat.ll
index 60647fef923bc..00ad100021e1f 100644
--- a/llvm/test/CodeGen/AMDGPU/uaddsat.ll
+++ b/llvm/test/CodeGen/AMDGPU/uaddsat.ll
@@ -62,6 +62,62 @@ define i8 @v_uaddsat_i8(i8 %lhs, i8 %rhs) {
ret i8 %result
}
+define i16 @s_uaddsat_i16(i16 inreg %lhs, i16 inreg %rhs) {
+; GFX6-LABEL: s_uaddsat_i16:
+; GFX6: ; %bb.0:
+; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT: s_and_b32 s4, s17, 0xffff
+; GFX6-NEXT: s_and_b32 s5, s16, 0xffff
+; GFX6-NEXT: s_add_i32 s5, s5, s4
+; GFX6-NEXT: s_min_u32 s4, s5, 0xffff
+; GFX6-NEXT: v_mov_b32_e32 v0, s4
+; GFX6-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: s_uaddsat_i16:
+; GFX8: ; %bb.0:
+; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT: s_and_b32 s4, 0xffff, s17
+; GFX8-NEXT: s_and_b32 s5, 0xffff, s16
+; GFX8-NEXT: s_add_i32 s5, s5, s4
+; GFX8-NEXT: s_min_u32 s4, s5, 0xffff
+; GFX8-NEXT: v_mov_b32_e32 v0, s4
+; GFX8-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: s_uaddsat_i16:
+; GFX9: ; %bb.0:
+; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT: s_and_b32 s4, 0xffff, s17
+; GFX9-NEXT: s_and_b32 s5, 0xffff, s16
+; GFX9-NEXT: s_add_i32 s5, s5, s4
+; GFX9-NEXT: s_min_u32 s4, s5, 0xffff
+; GFX9-NEXT: v_mov_b32_e32 v0, s4
+; GFX9-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: s_uaddsat_i16:
+; GFX10: ; %bb.0:
+; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT: s_and_b32 s4, 0xffff, s17
+; GFX10-NEXT: s_and_b32 s5, 0xffff, s16
+; GFX10-NEXT: s_add_i32 s5, s5, s4
+; GFX10-NEXT: s_min_u32 s4, s5, 0xffff
+; GFX10-NEXT: v_mov_b32_e32 v0, s4
+; GFX10-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: s_uaddsat_i16:
+; GFX11: ; %bb.0:
+; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT: s_and_b32 s1, 0xffff, s1
+; GFX11-NEXT: s_and_b32 s0, 0xffff, s0
+; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT: s_add_i32 s0, s0, s1
+; GFX11-NEXT: s_min_u32 s0, s0, 0xffff
+; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1)
+; GFX11-NEXT: v_mov_b32_e32 v0, s0
+; GFX11-NEXT: s_setpc_b64 s[30:31]
+ %result = call i16 @llvm.uadd.sat.i16(i16 %lhs, i16 %rhs)
+ ret i16 %result
+}
+
define i16 @v_uaddsat_i16(i16 %lhs, i16 %rhs) {
; GFX6-LABEL: v_uaddsat_i16:
; GFX6: ; %bb.0:
More information about the llvm-commits
mailing list