[llvm] [AMDGPU] Promote uniform i16 ABS to i32 (PR #204526)

Lukas Sommer via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 22 00:15:58 PDT 2026


https://github.com/sommerlukas updated https://github.com/llvm/llvm-project/pull/204526

>From e97a52da27286c7811466e1f92bfd0f1dc9a80c4 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Wed, 17 Jun 2026 11:20:07 -0500
Subject: [PATCH 1/6] [AMDGPU] Expand uniform i16 ABS to s_abs

GlobalISel already expands uniform i16 G_ABS to sign-extend to i32 and
the native s_abs instruction.

This adds a similar expansion to SelectionDAG, expanding uniform i16 ABS
to sign-extend and s_abs.

For ABS_MIN_POISON, the existing expansion to max(x, 0-x) is retained to
preserve poison semantics.

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 41 ++++++++++++++++++++++-
 llvm/lib/Target/AMDGPU/SIISelLowering.h   |  1 +
 llvm/test/CodeGen/AMDGPU/absdiff.ll       |  4 +--
 3 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 0267f696a8a93..cbf9959633dfb 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -595,6 +595,9 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
                         ISD::CTPOP},
                        MVT::i16, Promote);
 
+    setOperationAction(ISD::ABS, MVT::i16, Custom);
+    setOperationAction(ISD::ABS_MIN_POISON, MVT::i16, Custom);
+
     setOperationAction(ISD::LOAD, MVT::i16, Custom);
 
     setTruncStoreAction(MVT::i64, MVT::i16, Expand);
@@ -7492,6 +7495,36 @@ SDValue SITargetLowering::lowerROTR(SDValue Op, SelectionDAG &DAG) const {
   return DAG.UnrollVectorOp(Op.getNode());
 }
 
+SDValue SITargetLowering::lowerABS(SDValue Op, SelectionDAG &DAG) const {
+  assert(Subtarget->has16BitInsts() && "Requires 16-bit operations.");
+  [[maybe_unused]] EVT VT = Op.getValueType();
+
+  assert(VT == MVT::i16 && "Unexpected ValueType.");
+
+  // There is no integer v_abs instruction on AMDGPU, so divergent ABS needs to
+  // be expanded differently.
+  if (Op->isDivergent())
+    return SDValue();
+
+  SDLoc SL(Op);
+  // Expand plain abs by sign-extending to i32 and using the native s_abs
+  // instruction.
+  if (Op->getOpcode() == ISD::ABS) {
+    SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND, SL, MVT::i32, Op.getOperand(0));
+    SDValue Abs = DAG.getNode(ISD::ABS, SL, MVT::i32, Ext);
+    return DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Abs);
+  }
+  assert(Op->getOpcode() == ISD::ABS_MIN_POISON);
+  // We also need to handle ABS_MIN_POISON here. This is the same expansion as
+  // in TargetLowering::expandABS, but since we marked ABS custom,
+  // TargetLowering::expandABS would expand ABS_MIN_POISON to ABS and lose the
+  // poison semantics. This instead expands abs(x) to max(x, 0 - x).
+  SDValue Zero = DAG.getConstant(0, SL, VT);
+  SDValue Frozen = DAG.getFreeze(Op.getOperand(0));
+  SDValue Sub = DAG.getNode(ISD::SUB, SL, VT, Zero, Frozen);
+  return DAG.getNode(ISD::SMAX, SL, VT, Frozen, Sub);
+}
+
 // Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
 // wider vector type is legal.
 SDValue SITargetLowering::splitBinaryVectorOp(SDValue Op,
@@ -7618,7 +7651,13 @@ SDValue SITargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
     return lowerTRAP(Op, DAG);
   case ISD::DEBUGTRAP:
     return lowerDEBUGTRAP(Op, DAG);
-  case ISD::ABS:
+  case ISD::ABS: {
+    if (Op.getValueType() == MVT::i16)
+      return lowerABS(Op, DAG);
+    return splitUnaryVectorOp(Op, DAG);
+  }
+  case ISD::ABS_MIN_POISON:
+    return lowerABS(Op, DAG);
   case ISD::FABS:
   case ISD::FNEG:
   case ISD::FCANONICALIZE:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 95ff5bba7cfff..ed0ace01e8edc 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -472,6 +472,7 @@ class SITargetLowering final : public AMDGPUTargetLowering {
   SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerABS(SDValue Op, SelectionDAG &DAG) const;
 
   Register getRegisterByName(const char* RegName, LLT VT,
                              const MachineFunction &MF) const override;
diff --git a/llvm/test/CodeGen/AMDGPU/absdiff.ll b/llvm/test/CodeGen/AMDGPU/absdiff.ll
index 5e4947ea5e0b5..94385621f6b15 100644
--- a/llvm/test/CodeGen/AMDGPU/absdiff.ll
+++ b/llvm/test/CodeGen/AMDGPU/absdiff.ll
@@ -43,10 +43,8 @@ define amdgpu_ps i16 @absdiff_i16_false(i16 inreg %arg0, i16 inreg %arg1) {
 ; CHECK-LABEL: absdiff_i16_false:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_sub_i32 s0, s0, s1
-; CHECK-NEXT:    s_sext_i32_i16 s1, s0
-; CHECK-NEXT:    s_sub_i32 s0, 0, s0
 ; CHECK-NEXT:    s_sext_i32_i16 s0, s0
-; CHECK-NEXT:    s_max_i32 s0, s1, s0
+; CHECK-NEXT:    s_abs_i32 s0, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %diff = sub i16 %arg0, %arg1
   %res = call i16 @llvm.abs.i16(i16 %diff, i1 false) ; INT_MIN input returns INT_MIN

>From 2bfda188bfa939390b3218bc3718f305b1ded0d5 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Thu, 18 Jun 2026 06:40:33 -0500
Subject: [PATCH 2/6] Revert "[AMDGPU] Expand uniform i16 ABS to s_abs"

This reverts commit dc3b0beafd95453ff6392de2eb58a514647e4c8e.
---
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 41 +----------------------
 llvm/lib/Target/AMDGPU/SIISelLowering.h   |  1 -
 llvm/test/CodeGen/AMDGPU/absdiff.ll       |  4 ++-
 3 files changed, 4 insertions(+), 42 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index cbf9959633dfb..0267f696a8a93 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -595,9 +595,6 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
                         ISD::CTPOP},
                        MVT::i16, Promote);
 
-    setOperationAction(ISD::ABS, MVT::i16, Custom);
-    setOperationAction(ISD::ABS_MIN_POISON, MVT::i16, Custom);
-
     setOperationAction(ISD::LOAD, MVT::i16, Custom);
 
     setTruncStoreAction(MVT::i64, MVT::i16, Expand);
@@ -7495,36 +7492,6 @@ SDValue SITargetLowering::lowerROTR(SDValue Op, SelectionDAG &DAG) const {
   return DAG.UnrollVectorOp(Op.getNode());
 }
 
-SDValue SITargetLowering::lowerABS(SDValue Op, SelectionDAG &DAG) const {
-  assert(Subtarget->has16BitInsts() && "Requires 16-bit operations.");
-  [[maybe_unused]] EVT VT = Op.getValueType();
-
-  assert(VT == MVT::i16 && "Unexpected ValueType.");
-
-  // There is no integer v_abs instruction on AMDGPU, so divergent ABS needs to
-  // be expanded differently.
-  if (Op->isDivergent())
-    return SDValue();
-
-  SDLoc SL(Op);
-  // Expand plain abs by sign-extending to i32 and using the native s_abs
-  // instruction.
-  if (Op->getOpcode() == ISD::ABS) {
-    SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND, SL, MVT::i32, Op.getOperand(0));
-    SDValue Abs = DAG.getNode(ISD::ABS, SL, MVT::i32, Ext);
-    return DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Abs);
-  }
-  assert(Op->getOpcode() == ISD::ABS_MIN_POISON);
-  // We also need to handle ABS_MIN_POISON here. This is the same expansion as
-  // in TargetLowering::expandABS, but since we marked ABS custom,
-  // TargetLowering::expandABS would expand ABS_MIN_POISON to ABS and lose the
-  // poison semantics. This instead expands abs(x) to max(x, 0 - x).
-  SDValue Zero = DAG.getConstant(0, SL, VT);
-  SDValue Frozen = DAG.getFreeze(Op.getOperand(0));
-  SDValue Sub = DAG.getNode(ISD::SUB, SL, VT, Zero, Frozen);
-  return DAG.getNode(ISD::SMAX, SL, VT, Frozen, Sub);
-}
-
 // Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
 // wider vector type is legal.
 SDValue SITargetLowering::splitBinaryVectorOp(SDValue Op,
@@ -7651,13 +7618,7 @@ SDValue SITargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
     return lowerTRAP(Op, DAG);
   case ISD::DEBUGTRAP:
     return lowerDEBUGTRAP(Op, DAG);
-  case ISD::ABS: {
-    if (Op.getValueType() == MVT::i16)
-      return lowerABS(Op, DAG);
-    return splitUnaryVectorOp(Op, DAG);
-  }
-  case ISD::ABS_MIN_POISON:
-    return lowerABS(Op, DAG);
+  case ISD::ABS:
   case ISD::FABS:
   case ISD::FNEG:
   case ISD::FCANONICALIZE:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index ed0ace01e8edc..95ff5bba7cfff 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -472,7 +472,6 @@ class SITargetLowering final : public AMDGPUTargetLowering {
   SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const;
-  SDValue lowerABS(SDValue Op, SelectionDAG &DAG) const;
 
   Register getRegisterByName(const char* RegName, LLT VT,
                              const MachineFunction &MF) const override;
diff --git a/llvm/test/CodeGen/AMDGPU/absdiff.ll b/llvm/test/CodeGen/AMDGPU/absdiff.ll
index 94385621f6b15..5e4947ea5e0b5 100644
--- a/llvm/test/CodeGen/AMDGPU/absdiff.ll
+++ b/llvm/test/CodeGen/AMDGPU/absdiff.ll
@@ -43,8 +43,10 @@ define amdgpu_ps i16 @absdiff_i16_false(i16 inreg %arg0, i16 inreg %arg1) {
 ; CHECK-LABEL: absdiff_i16_false:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_sub_i32 s0, s0, s1
+; CHECK-NEXT:    s_sext_i32_i16 s1, s0
+; CHECK-NEXT:    s_sub_i32 s0, 0, s0
 ; CHECK-NEXT:    s_sext_i32_i16 s0, s0
-; CHECK-NEXT:    s_abs_i32 s0, s0
+; CHECK-NEXT:    s_max_i32 s0, s1, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %diff = sub i16 %arg0, %arg1
   %res = call i16 @llvm.abs.i16(i16 %diff, i1 false) ; INT_MIN input returns INT_MIN

>From 2f1deb8c6a7e0688b452ea8b83abbdd46f47e55e Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Thu, 18 Jun 2026 08:21:22 -0500
Subject: [PATCH 3/6] [AMDGPU] Expand uniform i16 ABS to i32

GlobalISel already expands uniform `i16` `G_ABS` to sign-extend to i32 and the native `s_abs` instruction.

This adds a similar expansion as DAGCombiner pattern, promoting uniform `i16` `ABS` to `i32` that can use `s_abs`.

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 12 +++++++++
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp     | 27 +++++++++++++++++++
 llvm/lib/Target/AMDGPU/SIISelLowering.h       |  1 +
 llvm/test/CodeGen/AMDGPU/absdiff.ll           |  4 +--
 4 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 7c614670c5dfa..96e462659c617 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -1041,6 +1041,18 @@ bool AMDGPUTargetLowering::isZExtFree(EVT Src, EVT Dest) const {
 bool AMDGPUTargetLowering::isNarrowingProfitable(SDNode *N, EVT SrcVT,
                                                  EVT DestVT) const {
   switch (N->getOpcode()) {
+  case ISD::ABS: {
+    // Narrowing to types smaller than 32 bit is never profitable for uniform
+    // operations. The only native instruction is s_abs for i32, so narrowing to
+    // smaller types requires less efficient expansions.
+    if (!N->isDivergent() && DestVT.getSizeInBits() < 32)
+      return false;
+    // For all other cases, i.e., divergent or types larger than 32 bit, fall
+    // through. They will either profit from narrowing to i32 or will be
+    // expanded to a combination of SUB and SMAX, so follow their profitability
+    // logic.
+    LLVM_FALLTHROUGH;
+  }
   case ISD::ADD:
   case ISD::SUB:
   case ISD::SHL:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 0267f696a8a93..2c5b158720309 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -1053,6 +1053,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
                        ISD::FMINIMUMNUM,
                        ISD::FMAXIMUMNUM,
                        ISD::FMA,
+                       ISD::ABS,
                        ISD::SMIN,
                        ISD::SMAX,
                        ISD::UMIN,
@@ -8796,6 +8797,7 @@ SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
 
 static unsigned getExtOpcodeForPromotedOp(SDValue Op) {
   switch (Op->getOpcode()) {
+  case ISD::ABS:
   case ISD::SRA:
   case ISD::SMIN:
   case ISD::SMAX:
@@ -8824,6 +8826,27 @@ static unsigned getExtOpcodeForPromotedOp(SDValue Op) {
   }
 }
 
+SDValue SITargetLowering::promoteUniformABSToI32(SDValue Op,
+                                                 DAGCombinerInfo &DCI) const {
+  assert(Op.getOpcode() == ISD::ABS);
+
+  EVT OpTy = Op.getValueType();
+  auto &DAG = DCI.DAG;
+  EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
+
+  if (Op->isDivergent() || isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
+    return SDValue();
+
+  SDLoc DL(Op);
+  SDValue Input = Op.getOperand(0);
+  const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
+  Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
+
+  SDValue NewVal = DAG.getNode(ISD::ABS, DL, ExtTy, Input);
+
+  return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
+}
+
 SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
                                                 DAGCombinerInfo &DCI) const {
   const unsigned Opc = Op.getOpcode();
@@ -18570,6 +18593,10 @@ SDValue SITargetLowering::performSelectCombine(SDNode *N,
 SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
                                             DAGCombinerInfo &DCI) const {
   switch (N->getOpcode()) {
+  case ISD::ABS:
+    if (auto Res = promoteUniformABSToI32(SDValue(N, 0), DCI))
+      return Res;
+    break;
   case ISD::ADD:
   case ISD::SUB:
   case ISD::SHL:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 95ff5bba7cfff..5612431905ebb 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -168,6 +168,7 @@ class SITargetLowering final : public AMDGPUTargetLowering {
   SDValue lowerFMINIMUM_FMAXIMUM(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const;
   SDValue promoteUniformOpToI32(SDValue Op, DAGCombinerInfo &DCI) const;
+  SDValue promoteUniformABSToI32(SDValue Op, DAGCombinerInfo &DCI) const;
   SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerMUL(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerXMULO(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/AMDGPU/absdiff.ll b/llvm/test/CodeGen/AMDGPU/absdiff.ll
index 5e4947ea5e0b5..94385621f6b15 100644
--- a/llvm/test/CodeGen/AMDGPU/absdiff.ll
+++ b/llvm/test/CodeGen/AMDGPU/absdiff.ll
@@ -43,10 +43,8 @@ define amdgpu_ps i16 @absdiff_i16_false(i16 inreg %arg0, i16 inreg %arg1) {
 ; CHECK-LABEL: absdiff_i16_false:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_sub_i32 s0, s0, s1
-; CHECK-NEXT:    s_sext_i32_i16 s1, s0
-; CHECK-NEXT:    s_sub_i32 s0, 0, s0
 ; CHECK-NEXT:    s_sext_i32_i16 s0, s0
-; CHECK-NEXT:    s_max_i32 s0, s1, s0
+; CHECK-NEXT:    s_abs_i32 s0, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %diff = sub i16 %arg0, %arg1
   %res = call i16 @llvm.abs.i16(i16 %diff, i1 false) ; INT_MIN input returns INT_MIN

>From 57d42a227c7f5699c0c827fb4fd5d1bc57abbf19 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Thu, 18 Jun 2026 08:44:52 -0500
Subject: [PATCH 4/6] Drop duplicate check

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 2c5b158720309..c5686bf121c41 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8834,7 +8834,7 @@ SDValue SITargetLowering::promoteUniformABSToI32(SDValue Op,
   auto &DAG = DCI.DAG;
   EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
 
-  if (Op->isDivergent() || isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
+  if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
     return SDValue();
 
   SDLoc DL(Op);

>From 30c6e21a0087356d3f6dfa8c8e4f5ff802beb50e Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Fri, 19 Jun 2026 10:35:36 -0500
Subject: [PATCH 5/6] Always fall through; Make helper generic

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 13 +------------
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp     | 13 ++++++-------
 llvm/lib/Target/AMDGPU/SIISelLowering.h       |  2 +-
 3 files changed, 8 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 96e462659c617..664251a4254d6 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -1041,18 +1041,7 @@ bool AMDGPUTargetLowering::isZExtFree(EVT Src, EVT Dest) const {
 bool AMDGPUTargetLowering::isNarrowingProfitable(SDNode *N, EVT SrcVT,
                                                  EVT DestVT) const {
   switch (N->getOpcode()) {
-  case ISD::ABS: {
-    // Narrowing to types smaller than 32 bit is never profitable for uniform
-    // operations. The only native instruction is s_abs for i32, so narrowing to
-    // smaller types requires less efficient expansions.
-    if (!N->isDivergent() && DestVT.getSizeInBits() < 32)
-      return false;
-    // For all other cases, i.e., divergent or types larger than 32 bit, fall
-    // through. They will either profit from narrowing to i32 or will be
-    // expanded to a combination of SUB and SMAX, so follow their profitability
-    // logic.
-    LLVM_FALLTHROUGH;
-  }
+  case ISD::ABS:
   case ISD::ADD:
   case ISD::SUB:
   case ISD::SHL:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index c5686bf121c41..966de17e3c82f 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8826,10 +8826,9 @@ static unsigned getExtOpcodeForPromotedOp(SDValue Op) {
   }
 }
 
-SDValue SITargetLowering::promoteUniformABSToI32(SDValue Op,
-                                                 DAGCombinerInfo &DCI) const {
-  assert(Op.getOpcode() == ISD::ABS);
-
+SDValue
+SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
+                                             DAGCombinerInfo &DCI) const {
   EVT OpTy = Op.getValueType();
   auto &DAG = DCI.DAG;
   EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
@@ -8842,9 +8841,9 @@ SDValue SITargetLowering::promoteUniformABSToI32(SDValue Op,
   const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
   Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
 
-  SDValue NewVal = DAG.getNode(ISD::ABS, DL, ExtTy, Input);
+  SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
 
-  return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
+  return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
 }
 
 SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
@@ -18594,7 +18593,7 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
                                             DAGCombinerInfo &DCI) const {
   switch (N->getOpcode()) {
   case ISD::ABS:
-    if (auto Res = promoteUniformABSToI32(SDValue(N, 0), DCI))
+    if (auto Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
       return Res;
     break;
   case ISD::ADD:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 5612431905ebb..22c6a74f7bf7c 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -168,7 +168,7 @@ class SITargetLowering final : public AMDGPUTargetLowering {
   SDValue lowerFMINIMUM_FMAXIMUM(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const;
   SDValue promoteUniformOpToI32(SDValue Op, DAGCombinerInfo &DCI) const;
-  SDValue promoteUniformABSToI32(SDValue Op, DAGCombinerInfo &DCI) const;
+  SDValue promoteUniformUnaryOpToI32(SDValue Op, DAGCombinerInfo &DCI) const;
   SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerMUL(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerXMULO(SDValue Op, SelectionDAG &DAG) const;

>From 49d53dc8c21f1628ce6427647cf82574e0a08147 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Mon, 22 Jun 2026 01:56:02 -0500
Subject: [PATCH 6/6] Remove uses of `auto`

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 966de17e3c82f..ec86e3703a0d0 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8830,7 +8830,7 @@ SDValue
 SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
                                              DAGCombinerInfo &DCI) const {
   EVT OpTy = Op.getValueType();
-  auto &DAG = DCI.DAG;
+  SelectionDAG &DAG = DCI.DAG;
   EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
 
   if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
@@ -18593,7 +18593,7 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
                                             DAGCombinerInfo &DCI) const {
   switch (N->getOpcode()) {
   case ISD::ABS:
-    if (auto Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
+    if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
       return Res;
     break;
   case ISD::ADD:



More information about the llvm-commits mailing list