[llvm] [SelectionDAG] Preserver poison for abs INT_MIN lowering (PR #183851)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 24 16:54:25 PDT 2026


https://github.com/aryanmagoon updated https://github.com/llvm/llvm-project/pull/183851

>From f49a30f0b5ee3f531a7a8a7fafcd1314cd0b23e1 Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Fri, 27 Feb 2026 19:13:40 +0000
Subject: [PATCH 1/6] SelectionDAG: Preserve poison for abs INT_MIN lowering.
 Update affected CodeGen lit tests and added a new lit test for this behavior.

---
 llvm/include/llvm/CodeGen/ISDOpcodes.h        |   4 +
 llvm/include/llvm/CodeGen/SDPatternMatch.h    |   5 +-
 .../include/llvm/Target/TargetSelectionDAG.td |   5 +-
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |  65 +++++++++-
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp |   1 +
 .../SelectionDAG/LegalizeIntegerTypes.cpp     |  15 ++-
 .../SelectionDAG/LegalizeVectorOps.cpp        |   2 +
 .../SelectionDAG/LegalizeVectorTypes.cpp      |   3 +
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  20 ++-
 .../SelectionDAG/SelectionDAGBuilder.cpp      |   5 +-
 .../SelectionDAG/SelectionDAGDumper.cpp       |   1 +
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |  10 ++
 llvm/lib/CodeGen/TargetLoweringBase.cpp       |   3 +
 .../Target/AArch64/AArch64ISelLowering.cpp    |   6 +-
 llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp   |  17 ++-
 llvm/lib/Target/NVPTX/NVPTXInstrInfo.td       |   5 +-
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  16 ++-
 llvm/test/CodeGen/NVPTX/idioms.ll             |  21 +--
 llvm/test/CodeGen/X86/icmp-abs-C.ll           | 120 ++++++++++--------
 .../test/CodeGen/X86/icmp-pow2-logic-npow2.ll |  33 +++--
 20 files changed, 254 insertions(+), 103 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index b8c6788e0bc03..f3cc61259031d 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -746,6 +746,10 @@ enum NodeType {
   /// is performed.
   ABS,
 
+  /// ABS with a poison result for INT_MIN. This corresponds to
+  /// llvm.abs(x, true) where the "int min is poison" flag is set.
+  ABS_MIN_POISON,
+
   /// Shift and rotation operations.  After legalization, the type of the
   /// shift amount is known to be TLI.getShiftAmountTy().  Before legalization
   /// the shift amount can be any type, but care must be taken to ensure it is
diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index b41443f85c3a9..a3cc419404759 100644
--- a/llvm/include/llvm/CodeGen/SDPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h
@@ -1073,8 +1073,9 @@ template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
   return UnaryOpc_match<Opnd>(ISD::TRUNCATE, Op);
 }
 
-template <typename Opnd> inline UnaryOpc_match<Opnd> m_Abs(const Opnd &Op) {
-  return UnaryOpc_match<Opnd>(ISD::ABS, Op);
+template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
+  return m_AnyOf(UnaryOpc_match<Opnd>(ISD::ABS, Op),
+                 UnaryOpc_match<Opnd>(ISD::ABS_MIN_POISON, Op));
 }
 
 template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index d689b3c1beda9..1e4940d4c1f8d 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -519,8 +519,9 @@ def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>;
 def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>;
 def zext_invec : SDNode<"ISD::ZERO_EXTEND_VECTOR_INREG", SDTExtInvec>;
 
-def abs        : SDNode<"ISD::ABS"        , SDTIntUnaryOp>;
-def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>;
+def abs            : SDNode<"ISD::ABS"            , SDTIntUnaryOp>;
+def abs_min_poison : SDNode<"ISD::ABS_MIN_POISON", SDTIntUnaryOp>;
+def bitreverse     : SDNode<"ISD::BITREVERSE"     , SDTIntUnaryOp>;
 def bswap      : SDNode<"ISD::BSWAP"      , SDTIntUnaryOp>;
 def ctlz       : SDNode<"ISD::CTLZ"       , SDTIntBitCountUnaryOp>;
 def cttz       : SDNode<"ISD::CTTZ"       , SDTIntBitCountUnaryOp>;
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 41e77e044d8a9..f4a0871e716d9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -477,6 +477,7 @@ namespace {
     SDValue visitSHLSAT(SDNode *N);
     SDValue visitRotate(SDNode *N);
     SDValue visitABS(SDNode *N);
+    SDValue visitABS_MIN_POISON(SDNode *N);
     SDValue visitCLMUL(SDNode *N);
     SDValue visitBSWAP(SDNode *N);
     SDValue visitBITREVERSE(SDNode *N);
@@ -1983,6 +1984,7 @@ SDValue DAGCombiner::visit(SDNode *N) {
   case ISD::SSHLSAT:
   case ISD::USHLSAT:            return visitSHLSAT(N);
   case ISD::ABS:                return visitABS(N);
+  case ISD::ABS_MIN_POISON:     return visitABS_MIN_POISON(N);
   case ISD::CLMUL:
   case ISD::CLMULR:
   case ISD::CLMULH:             return visitCLMUL(N);
@@ -4263,8 +4265,9 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
     }
 
     // Convert 0 - abs(x).
-    if (N1.getOpcode() == ISD::ABS && N1.hasOneUse() &&
-        !TLI.isOperationLegalOrCustom(ISD::ABS, VT))
+    if ((N1.getOpcode() == ISD::ABS || N1.getOpcode() == ISD::ABS_MIN_POISON) &&
+        N1.hasOneUse() &&
+        !TLI.isOperationLegalOrCustom(N1.getOpcode(), VT))
       if (SDValue Result = TLI.expandABS(N1.getNode(), DAG, true))
         return Result;
 
@@ -11916,7 +11919,8 @@ SDValue DAGCombiner::visitABS(SDNode *N) {
   if (SDValue C = DAG.FoldConstantArithmetic(ISD::ABS, DL, VT, {N0}))
     return C;
   // fold (abs (abs x)) -> (abs x)
-  if (N0.getOpcode() == ISD::ABS)
+  // fold (abs (abs_min_poison x)) -> (abs x)
+  if (N0.getOpcode() == ISD::ABS || N0.getOpcode() == ISD::ABS_MIN_POISON)
     return N0;
   // fold (abs x) -> x iff not-negative
   if (DAG.SignBitIsZero(N0))
@@ -11942,6 +11946,55 @@ SDValue DAGCombiner::visitABS(SDNode *N) {
   return SDValue();
 }
 
+SDValue DAGCombiner::visitABS_MIN_POISON(SDNode *N) {
+  SDValue N0 = N->getOperand(0);
+  EVT VT = N->getValueType(0);
+  SDLoc DL(N);
+
+  // fold (abs_min_poison c1) -> c2 (or poison if c1 == INT_MIN)
+  if (SDValue C =
+          DAG.FoldConstantArithmetic(ISD::ABS_MIN_POISON, DL, VT, {N0}))
+    return C;
+  // fold (abs_min_poison (abs_min_poison x)) -> (abs_min_poison x)
+  // fold (abs_min_poison (abs x)) -> (abs x)
+  if (N0.getOpcode() == ISD::ABS_MIN_POISON || N0.getOpcode() == ISD::ABS)
+    return N0;
+  // fold (abs_min_poison (freeze (abs x))) -> (freeze (abs x))
+  // fold (abs_min_poison (freeze (abs_min_poison x))) -> (freeze (abs_min_poison x))
+  // Valid because: for x != INT_MIN both sides equal abs(x); for x == INT_MIN
+  // both forms produce a non-deterministic but well-defined value since freeze
+  // already consumed the poison.
+  if (N0.getOpcode() == ISD::FREEZE) {
+    unsigned InnerOpc = N0.getOperand(0).getOpcode();
+    if (InnerOpc == ISD::ABS || InnerOpc == ISD::ABS_MIN_POISON)
+      return N0;
+  }
+  // fold (abs_min_poison x) -> x iff not-negative
+  if (DAG.SignBitIsZero(N0))
+    return N0;
+
+  if (SDValue ABD = foldABSToABD(N, DL))
+    return ABD;
+
+  // fold (abs_min_poison (sign_extend_inreg x)) ->
+  //   (zero_extend (abs_min_poison (truncate x)))
+  // iff zero_extend/truncate are free.
+  if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) {
+    EVT ExtVT = cast<VTSDNode>(N0.getOperand(1))->getVT();
+    if (TLI.isTruncateFree(VT, ExtVT) && TLI.isZExtFree(ExtVT, VT) &&
+        TLI.isTypeDesirableForOp(ISD::ABS, ExtVT) &&
+        hasOperation(ISD::ABS, ExtVT)) {
+      return DAG.getNode(
+          ISD::ZERO_EXTEND, DL, VT,
+          DAG.getNode(ISD::ABS_MIN_POISON, DL, ExtVT,
+                      DAG.getNode(ISD::TRUNCATE, DL, ExtVT,
+                                  N0.getOperand(0))));
+    }
+  }
+
+  return SDValue();
+}
+
 SDValue DAGCombiner::visitCLMUL(SDNode *N) {
   unsigned Opcode = N->getOpcode();
   SDValue N0 = N->getOperand(0);
@@ -15322,7 +15375,9 @@ static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG) {
     return SDValue();
 
   SDValue Abs = Extend->getOperand(0);
-  if (Abs.getOpcode() != ISD::ABS || !Abs.hasOneUse())
+  unsigned AbsOpc = Abs.getOpcode();
+  if ((AbsOpc != ISD::ABS && AbsOpc != ISD::ABS_MIN_POISON) ||
+      !Abs.hasOneUse())
     return SDValue();
 
   EVT AbsVT = Abs.getValueType();
@@ -15335,7 +15390,7 @@ static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG) {
 
   SDValue SExt =
       DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Abs), LegalVT, Abs.getOperand(0));
-  SDValue NewAbs = DAG.getNode(ISD::ABS, SDLoc(Abs), LegalVT, SExt);
+  SDValue NewAbs = DAG.getNode(AbsOpc, SDLoc(Abs), LegalVT, SExt);
   return DAG.getZExtOrTrunc(NewAbs, SDLoc(Extend), VT);
 }
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index eb20e7982a102..a28739d210933 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3223,6 +3223,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
   bool NeedInvert;
   switch (Node->getOpcode()) {
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
     if ((Tmp1 = TLI.expandABS(Node, DAG)))
       Results.push_back(Tmp1);
     break;
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 0d5cba405d6e3..a2dd494086c68 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -278,7 +278,8 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::UDIVFIX:
   case ISD::UDIVFIXSAT:  Res = PromoteIntRes_DIVFIX(N); break;
 
-  case ISD::ABS:         Res = PromoteIntRes_ABS(N); break;
+  case ISD::ABS:
+  case ISD::ABS_MIN_POISON: Res = PromoteIntRes_ABS(N); break;
 
   case ISD::ATOMIC_LOAD:
     Res = PromoteIntRes_Atomic0(cast<AtomicSDNode>(N)); break;
@@ -1871,6 +1872,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SADDSUBO_CARRY(SDNode *N,
 }
 
 SDValue DAGTypeLegalizer::PromoteIntRes_ABS(SDNode *N) {
+  unsigned Opc = N->getOpcode();
   EVT OVT = N->getValueType(0);
   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
 
@@ -1879,13 +1881,14 @@ SDValue DAGTypeLegalizer::PromoteIntRes_ABS(SDNode *N) {
   // in sra+xor+sub expansion.
   if (!OVT.isVector() &&
       !TLI.isOperationLegalOrCustomOrPromote(ISD::ABS, NVT) &&
+      !TLI.isOperationLegalOrCustomOrPromote(ISD::ABS_MIN_POISON, NVT) &&
       !TLI.isOperationLegal(ISD::SMAX, NVT)) {
     if (SDValue Res = TLI.expandABS(N, DAG))
       return DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), NVT, Res);
   }
 
   SDValue Op0 = SExtPromotedInteger(N->getOperand(0));
-  return DAG.getNode(ISD::ABS, SDLoc(N), Op0.getValueType(), Op0);
+  return DAG.getNode(Opc, SDLoc(N), Op0.getValueType(), Op0);
 }
 
 SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
@@ -3061,7 +3064,8 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::BSWAP:       ExpandIntRes_BSWAP(N, Lo, Hi); break;
   case ISD::PARITY:      ExpandIntRes_PARITY(N, Lo, Hi); break;
   case ISD::Constant:    ExpandIntRes_Constant(N, Lo, Hi); break;
-  case ISD::ABS:         ExpandIntRes_ABS(N, Lo, Hi); break;
+  case ISD::ABS:
+  case ISD::ABS_MIN_POISON: ExpandIntRes_ABS(N, Lo, Hi); break;
   case ISD::ABDS:
   case ISD::ABDU:        ExpandIntRes_ABD(N, Lo, Hi); break;
   case ISD::CTLZ_ZERO_UNDEF:
@@ -4091,7 +4095,10 @@ void DAGTypeLegalizer::ExpandIntRes_ABS(SDNode *N, SDValue &Lo, SDValue &Hi) {
   EVT NVT = Lo.getValueType();
 
   // If the upper half is all sign bits, then we can perform the ABS on the
-  // lower half and zero-extend.
+  // lower half and zero-extend. We must use ISD::ABS here (not ABS_MIN_POISON)
+  // because the original poison contract is for INT_MIN of the wider type,
+  // but the lower half may be INT_MIN of the narrower type for a valid
+  // (non-INT_MIN) input of the original type.
   if (DAG.ComputeNumSignBits(N0) > NVT.getScalarSizeInBits()) {
     Lo = DAG.getNode(ISD::ABS, dl, NVT, Lo);
     Hi = DAG.getConstant(0, dl, NVT);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index 0b1d5bfd078d8..f082a76bc2a4e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -376,6 +376,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
   case ISD::ROTL:
   case ISD::ROTR:
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::ABDS:
   case ISD::ABDU:
   case ISD::AVGCEILS:
@@ -1075,6 +1076,7 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
     ExpandSETCC(Node, Results);
     return;
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
     if (SDValue Expanded = TLI.expandABS(Node, DAG)) {
       Results.push_back(Expanded);
       return;
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index aeb9d4d7bdc1d..e11a6c508dc12 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -89,6 +89,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
     R = ScalarizeVecRes_VecInregOp(N);
     break;
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::ANY_EXTEND:
   case ISD::BITREVERSE:
   case ISD::BSWAP:
@@ -1311,6 +1312,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
     break;
 
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::VP_ABS:
   case ISD::BITREVERSE:
   case ISD::VP_BITREVERSE:
@@ -5190,6 +5192,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
     [[fallthrough]];
 
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::VP_ABS:
   case ISD::BITREVERSE:
   case ISD::VP_BITREVERSE:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 4a2bd811b5214..2b8fda77ebec7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2979,6 +2979,7 @@ bool SelectionDAG::isSplatValue(SDValue V, const APInt &DemandedElts,
     return false;
   }
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::TRUNCATE:
   case ISD::SIGN_EXTEND:
   case ISD::ZERO_EXTEND:
@@ -4320,7 +4321,8 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
     Known = Known2.byteSwap();
     break;
   }
-  case ISD::ABS: {
+  case ISD::ABS:
+  case ISD::ABS_MIN_POISON: {
     Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
     Known = Known2.abs();
     Known.Zero.setHighBits(
@@ -5799,6 +5801,9 @@ bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts,
     // ISD::ABS defines abs(INT_MIN) -> INT_MIN and never generates poison.
     // Different to Intrinsic::abs.
     return false;
+  case ISD::ABS_MIN_POISON:
+    // ABS_MIN_POISON may produce poison if the input is INT_MIN.
+    return true;
 
   case ISD::ADDC:
   case ISD::SUBC:
@@ -6268,6 +6273,7 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, const APInt &DemandedElts,
   case ISD::BSWAP:
   case ISD::CTPOP:
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
     return isKnownNeverZero(Op.getOperand(0), Depth + 1);
 
   case ISD::SRA:
@@ -6662,6 +6668,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
   case ISD::BF16_TO_FP:
   case ISD::BITCAST:
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::BITREVERSE:
   case ISD::BSWAP:
   case ISD::CTLZ:
@@ -6891,6 +6898,12 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     if (N1.isUndef())
       return getConstant(0, DL, VT);
     break;
+  case ISD::ABS_MIN_POISON:
+    assert(VT.isInteger() && VT == N1.getValueType() &&
+           "Invalid ABS_MIN_POISON!");
+    if (N1.isUndef())
+      return getConstant(0, DL, VT);
+    break;
   case ISD::BSWAP:
     assert(VT.isInteger() && VT == N1.getValueType() && "Invalid BSWAP!");
     assert((VT.getScalarSizeInBits() % 16 == 0) &&
@@ -7192,6 +7205,11 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
       case ISD::ABS:
         return getConstant(Val.abs(), DL, VT, C->isTargetOpcode(),
                            C->isOpaque());
+      case ISD::ABS_MIN_POISON:
+        if (Val.isMinSignedValue())
+          return getPOISON(VT);
+        return getConstant(Val.abs(), DL, VT, C->isTargetOpcode(),
+                           C->isOpaque());
       case ISD::BITREVERSE:
         return getConstant(Val.reverseBits(), DL, VT, C->isTargetOpcode(),
                            C->isOpaque());
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 392e53b99c64e..18fb2319833fa 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7427,9 +7427,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
     return;
   }
   case Intrinsic::abs: {
-    // TODO: Preserve "int min is poison" arg in SDAG?
     SDValue Op1 = getValue(I.getArgOperand(0));
-    setValue(&I, DAG.getNode(ISD::ABS, sdl, Op1.getValueType(), Op1));
+    bool IntMinIsPoison = cast<ConstantInt>(I.getArgOperand(1))->isOne();
+    unsigned Opc = IntMinIsPoison ? ISD::ABS_MIN_POISON : ISD::ABS;
+    setValue(&I, DAG.getNode(Opc, sdl, Op1.getValueType(), Op1));
     return;
   }
   case Intrinsic::scmp: {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 9453036455727..ea6d7ae14a1a6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -516,6 +516,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
 
   // Bit manipulation
   case ISD::ABS:                        return "abs";
+  case ISD::ABS_MIN_POISON:             return "abs_min_poison";
   case ISD::BITREVERSE:                 return "bitreverse";
   case ISD::BSWAP:                      return "bswap";
   case ISD::CTPOP:                      return "ctpop";
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index cc719b1e67f53..01f37e3c39343 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9911,6 +9911,16 @@ SDValue TargetLowering::expandABS(SDNode *N, SelectionDAG &DAG,
   EVT VT = N->getValueType(0);
   SDValue Op = N->getOperand(0);
 
+  // If expanding ABS_MIN_POISON, fall back to ABS if the target supports it.
+  if (N->getOpcode() == ISD::ABS_MIN_POISON &&
+      isOperationLegalOrCustom(ISD::ABS, VT)) {
+    SDValue AbsVal = DAG.getNode(ISD::ABS, dl, VT, Op);
+    if (IsNegative)
+      return DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, dl, VT),
+                         AbsVal);
+    return AbsVal;
+  }
+
   // abs(x) -> smax(x,sub(0,x))
   if (!IsNegative && isOperationLegal(ISD::SUB, VT) &&
       isOperationLegal(ISD::SMAX, VT)) {
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index cc5a4219536ac..8d59420c46125 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1165,6 +1165,9 @@ void TargetLoweringBase::initActions() {
     // These default to Expand so they will be expanded to CTLZ/CTTZ by default.
     setOperationAction({ISD::CTLZ_ZERO_UNDEF, ISD::CTTZ_ZERO_UNDEF}, VT,
                        Expand);
+
+    // This defaults to Expand so it will be expanded to ABS by default.
+    setOperationAction(ISD::ABS_MIN_POISON, VT, Expand);
     setOperationAction(ISD::CTLS, VT, Expand);
 
     setOperationAction({ISD::BITREVERSE, ISD::PARITY}, VT, Expand);
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index eb6e9146e3839..e6e5b42c887a1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -19574,7 +19574,8 @@ static SDValue performVecReduceAddCombineWithUADDLP(SDNode *N,
   // Look through an optional post-ABS ZEXT from v16i16 -> v16i32.
   if (VecReduceOp0.getOpcode() == ISD::ZERO_EXTEND &&
       VecReduceOp0->getValueType(0) == MVT::v16i32 &&
-      VecReduceOp0->getOperand(0)->getOpcode() == ISD::ABS &&
+      (VecReduceOp0->getOperand(0)->getOpcode() == ISD::ABS ||
+       VecReduceOp0->getOperand(0)->getOpcode() == ISD::ABS_MIN_POISON) &&
       VecReduceOp0->getOperand(0)->getValueType(0) == MVT::v16i16) {
     SawTrailingZext = true;
     VecReduceOp0 = VecReduceOp0.getOperand(0);
@@ -19584,7 +19585,8 @@ static SDValue performVecReduceAddCombineWithUADDLP(SDNode *N,
   MVT AbsInputVT = SawTrailingZext ? MVT::v16i16 : MVT::v16i32;
   // Assumed v16i16 or v16i32 abs input
   unsigned Opcode = VecReduceOp0.getOpcode();
-  if (Opcode != ISD::ABS || VecReduceOp0->getValueType(0) != AbsInputVT)
+  if ((Opcode != ISD::ABS && Opcode != ISD::ABS_MIN_POISON) ||
+      VecReduceOp0->getValueType(0) != AbsInputVT)
     return SDValue();
 
   SDValue ABS = VecReduceOp0;
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
index f5554be155eac..2f256ac1f3e51 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
@@ -657,7 +657,8 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM,
   // Only logical ops can be done on v4i8/v2i32 directly, others must be done
   // elementwise.
   setOperationAction(
-      {ISD::ABS,         ISD::ADD,        ISD::ADDC,        ISD::ADDE,
+      {ISD::ABS,
+       ISD::ADD,        ISD::ADDC,        ISD::ADDE,
        ISD::BITREVERSE,  ISD::CTLZ,       ISD::CTPOP,       ISD::CTTZ,
        ISD::FP_TO_SINT,  ISD::FP_TO_UINT, ISD::FSHL,        ISD::FSHR,
        ISD::MUL,         ISD::MULHS,      ISD::MULHU,       ISD::PARITY,
@@ -807,15 +808,21 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM,
   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
   setOperationAction(ISD::VAEND, MVT::Other, Expand);
 
-  setOperationAction({ISD::ABS, ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX},
+  setOperationAction({ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX},
                      {MVT::i16, MVT::i32, MVT::i64}, Legal);
+  // PTX abs.s is undefined for INT_MIN, so ISD::ABS (which requires
+  // abs(INT_MIN) == INT_MIN) must be expanded. ABS_MIN_POISON matches
+  // PTX abs semantics since INT_MIN input is poison/undefined.
+  setOperationAction(ISD::ABS, {MVT::i16, MVT::i32, MVT::i64}, Expand);
+  setOperationAction(ISD::ABS_MIN_POISON, {MVT::i16, MVT::i32, MVT::i64},
+                     Legal);
 
   setOperationAction({ISD::CTPOP, ISD::CTLZ, ISD::CTLZ_ZERO_UNDEF}, MVT::i16,
                      Promote);
   setOperationAction({ISD::CTPOP, ISD::CTLZ}, MVT::i32, Legal);
   setOperationAction({ISD::CTPOP, ISD::CTLZ}, MVT::i64, Custom);
 
-  setI16x2OperationAction(ISD::ABS, MVT::v2i16, Legal, Custom);
+  setI16x2OperationAction(ISD::ABS_MIN_POISON, MVT::v2i16, Legal, Custom);
   setI16x2OperationAction(ISD::SMIN, MVT::v2i16, Legal, Custom);
   setI16x2OperationAction(ISD::SMAX, MVT::v2i16, Legal, Custom);
   setI16x2OperationAction(ISD::UMIN, MVT::v2i16, Legal, Custom);
@@ -837,7 +844,8 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM,
                      {MVT::v2i16, MVT::v2i32}, Expand);
 
   // v2i32 is not supported for any arithmetic operations
-  setOperationAction({ISD::ABS, ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX,
+  setOperationAction({ISD::ABS,
+                      ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX,
                       ISD::CTPOP, ISD::CTLZ, ISD::ADD, ISD::SUB, ISD::MUL,
                       ISD::SHL, ISD::SRA, ISD::SRL, ISD::OR, ISD::AND, ISD::XOR,
                       ISD::SREM, ISD::UREM},
@@ -3491,6 +3499,7 @@ NVPTXTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::ROTR:
     return lowerROT(Op, DAG);
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::SMIN:
   case ISD::SMAX:
   case ISD::UMIN:
diff --git a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td
index 096c5e470ed02..dde3ef7493e3f 100644
--- a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td
+++ b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td
@@ -935,10 +935,13 @@ defm SREM : I3<"rem.s", srem, commutative = false>;
 defm UREM : I3<"rem.u", urem, commutative = false>;
 
 foreach t = [I16RT, I32RT, I64RT] in {
+  // PTX abs.s is undefined for INT_MIN, so it matches ABS_MIN_POISON
+  // semantics (where INT_MIN input is poison). ISD::ABS requires
+  // abs(INT_MIN) == INT_MIN and is expanded separately.
   def ABS_S # t.Size :
     BasicNVPTXInst<(outs t.RC:$dst), (ins t.RC:$a),
                    "abs.s" # t.Size,
-                   [(set t.Ty:$dst, (abs t.Ty:$a))]>;
+                   [(set t.Ty:$dst, (abs_min_poison t.Ty:$a))]>;
 
   def NEG_S # t.Size :
     BasicNVPTXInst<(outs t.RC:$dst), (ins t.RC:$src),
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index a8542be937a87..8cb3435c2436a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -465,12 +465,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
       (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
     setOperationAction(ISD::ABS, XLenVT, Legal);
     if (Subtarget.is64Bit())
-      setOperationAction(ISD::ABS, MVT::i32, Custom);
+      setOperationAction({ISD::ABS, ISD::ABS_MIN_POISON}, MVT::i32, Custom);
   } else if (Subtarget.hasShortForwardBranchIALU()) {
     // We can use PseudoCCSUB to implement ABS.
     setOperationAction(ISD::ABS, XLenVT, Legal);
   } else if (Subtarget.is64Bit()) {
-    setOperationAction(ISD::ABS, MVT::i32, Custom);
+    setOperationAction({ISD::ABS, ISD::ABS_MIN_POISON}, MVT::i32, Custom);
   }
 
   if (!Subtarget.useMIPSCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
@@ -1892,7 +1892,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
          ISD::VP_STORE,     ISD::VP_TRUNCATE,  ISD::EXPERIMENTAL_VP_REVERSE,
          ISD::MUL,          ISD::SDIV,         ISD::UDIV,
          ISD::SREM,         ISD::UREM,         ISD::INSERT_VECTOR_ELT,
-         ISD::ABS,          ISD::CTPOP,        ISD::VECTOR_SHUFFLE,
+         ISD::ABS,          ISD::ABS_MIN_POISON, ISD::CTPOP,        ISD::VECTOR_SHUFFLE,
          ISD::FMA,          ISD::VSELECT,      ISD::VECREDUCE_ADD});
 
   if (Subtarget.hasVendorXTHeadMemPair())
@@ -8910,6 +8910,7 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
     return DAG.getNode(ISD::SUB, dl, VT, Max, Min);
   }
   case ISD::ABS:
+  case ISD::ABS_MIN_POISON:
   case ISD::VP_ABS:
     return lowerABS(Op, DAG);
   case ISD::CTLZ:
@@ -15590,7 +15591,8 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
     Results.push_back(expandAddSubSat(N, DAG));
     return;
   }
-  case ISD::ABS: {
+  case ISD::ABS:
+  case ISD::ABS_MIN_POISON: {
     assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
            "Unexpected custom legalisation");
 
@@ -21546,7 +21548,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
     return DAG.getNode(ISD::AND, DL, VT, NewFMV,
                        DAG.getConstant(~SignBit, DL, VT));
   }
-  case ISD::ABS: {
+  case ISD::ABS:
+  case ISD::ABS_MIN_POISON: {
     EVT VT = N->getValueType(0);
     SDValue N0 = N->getOperand(0);
     // abs (sext) -> zext (abs)
@@ -21554,8 +21557,9 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
     if (VT.isVector() && N0.hasOneUse() && N0.getOpcode() == ISD::SIGN_EXTEND) {
       SDValue Src = N0.getOperand(0);
       SDLoc DL(N);
+      unsigned Opc = N->getOpcode();
       return DAG.getNode(ISD::ZERO_EXTEND, DL, VT,
-                         DAG.getNode(ISD::ABS, DL, Src.getValueType(), Src));
+                         DAG.getNode(Opc, DL, Src.getValueType(), Src));
     }
     break;
   }
diff --git a/llvm/test/CodeGen/NVPTX/idioms.ll b/llvm/test/CodeGen/NVPTX/idioms.ll
index 87c5ab27ecf9d..55e5aabe96a57 100644
--- a/llvm/test/CodeGen/NVPTX/idioms.ll
+++ b/llvm/test/CodeGen/NVPTX/idioms.ll
@@ -12,13 +12,14 @@
 define i16 @abs_i16(i16 %a) {
 ; CHECK-LABEL: abs_i16(
 ; CHECK:       {
-; CHECK-NEXT:    .reg .b16 %rs<3>;
+; CHECK-NEXT:    .reg .b16 %rs<4>;
 ; CHECK-NEXT:    .reg .b32 %r<2>;
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  // %bb.0:
 ; CHECK-NEXT:    ld.param.b16 %rs1, [abs_i16_param_0];
-; CHECK-NEXT:    abs.s16 %rs2, %rs1;
-; CHECK-NEXT:    cvt.u32.u16 %r1, %rs2;
+; CHECK-NEXT:    neg.s16 %rs2, %rs1;
+; CHECK-NEXT:    max.s16 %rs3, %rs1, %rs2;
+; CHECK-NEXT:    cvt.u32.u16 %r1, %rs3;
 ; CHECK-NEXT:    st.param.b32 [func_retval0], %r1;
 ; CHECK-NEXT:    ret;
   %neg = sub i16 0, %a
@@ -30,12 +31,13 @@ define i16 @abs_i16(i16 %a) {
 define i32 @abs_i32(i32 %a) {
 ; CHECK-LABEL: abs_i32(
 ; CHECK:       {
-; CHECK-NEXT:    .reg .b32 %r<3>;
+; CHECK-NEXT:    .reg .b32 %r<4>;
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  // %bb.0:
 ; CHECK-NEXT:    ld.param.b32 %r1, [abs_i32_param_0];
-; CHECK-NEXT:    abs.s32 %r2, %r1;
-; CHECK-NEXT:    st.param.b32 [func_retval0], %r2;
+; CHECK-NEXT:    neg.s32 %r2, %r1;
+; CHECK-NEXT:    max.s32 %r3, %r1, %r2;
+; CHECK-NEXT:    st.param.b32 [func_retval0], %r3;
 ; CHECK-NEXT:    ret;
   %neg = sub i32 0, %a
   %abs.cond = icmp sge i32 %a, 0
@@ -46,12 +48,13 @@ define i32 @abs_i32(i32 %a) {
 define i64 @abs_i64(i64 %a) {
 ; CHECK-LABEL: abs_i64(
 ; CHECK:       {
-; CHECK-NEXT:    .reg .b64 %rd<3>;
+; CHECK-NEXT:    .reg .b64 %rd<4>;
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  // %bb.0:
 ; CHECK-NEXT:    ld.param.b64 %rd1, [abs_i64_param_0];
-; CHECK-NEXT:    abs.s64 %rd2, %rd1;
-; CHECK-NEXT:    st.param.b64 [func_retval0], %rd2;
+; CHECK-NEXT:    neg.s64 %rd2, %rd1;
+; CHECK-NEXT:    max.s64 %rd3, %rd1, %rd2;
+; CHECK-NEXT:    st.param.b64 [func_retval0], %rd3;
 ; CHECK-NEXT:    ret;
   %neg = sub i64 0, %a
   %abs.cond = icmp sge i64 %a, 0
diff --git a/llvm/test/CodeGen/X86/icmp-abs-C.ll b/llvm/test/CodeGen/X86/icmp-abs-C.ll
index 71893a9e4be67..fe19174b53b42 100644
--- a/llvm/test/CodeGen/X86/icmp-abs-C.ll
+++ b/llvm/test/CodeGen/X86/icmp-abs-C.ll
@@ -13,29 +13,32 @@ define i64 @eq_or_with_dom_abs(i64 %x) nounwind {
 ; X86-NEXT:    pushl %ebx
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    movl %edx, %eax
-; X86-NEXT:    sarl $31, %eax
-; X86-NEXT:    xorl %eax, %edx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
-; X86-NEXT:    xorl %eax, %esi
-; X86-NEXT:    subl %eax, %esi
-; X86-NEXT:    sbbl %eax, %edx
-; X86-NEXT:    movl %esi, %eax
+; X86-NEXT:    movl %esi, %edi
+; X86-NEXT:    sarl $31, %edi
+; X86-NEXT:    movl %esi, %edx
+; X86-NEXT:    xorl %edi, %edx
+; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    xorl %edi, %eax
+; X86-NEXT:    subl %edi, %eax
+; X86-NEXT:    sbbl %edi, %edx
 ; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
-; X86-NEXT:    xorl $64, %esi
-; X86-NEXT:    xorl %ecx, %ecx
-; X86-NEXT:    orl %edx, %esi
-; X86-NEXT:    sete %bl
+; X86-NEXT:    addl $64, %ecx
+; X86-NEXT:    adcl $0, %esi
+; X86-NEXT:    andl $-129, %ecx
+; X86-NEXT:    xorl %ebx, %ebx
+; X86-NEXT:    orl %esi, %ecx
+; X86-NEXT:    sete %cl
 ; X86-NEXT:    xorl %esi, %esi
 ; X86-NEXT:    movl $2344, %edi # imm = 0x928
 ; X86-NEXT:    cmpl %eax, %edi
 ; X86-NEXT:    sbbl %edx, %esi
 ; X86-NEXT:    jb .LBB0_2
 ; X86-NEXT:  # %bb.1:
-; X86-NEXT:    movb %bl, %cl
+; X86-NEXT:    movb %cl, %bl
 ; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    movl %ebx, %eax
 ; X86-NEXT:  .LBB0_2:
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
@@ -47,13 +50,13 @@ define i64 @eq_or_with_dom_abs(i64 %x) nounwind {
 ; X64-NEXT:    movq %rdi, %rcx
 ; X64-NEXT:    negq %rcx
 ; X64-NEXT:    cmovsq %rdi, %rcx
-; X64-NEXT:    movq %rcx, %rdx
-; X64-NEXT:    xorq $12312, %rdx # imm = 0x3018
+; X64-NEXT:    xorq $12312, %rcx # imm = 0x3018
+; X64-NEXT:    addq $64, %rdi
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpq $64, %rcx
+; X64-NEXT:    testq $-129, %rdi
 ; X64-NEXT:    sete %al
-; X64-NEXT:    cmpq $2345, %rdx # imm = 0x929
-; X64-NEXT:    cmovaeq %rdx, %rax
+; X64-NEXT:    cmpq $2345, %rcx # imm = 0x929
+; X64-NEXT:    cmovaeq %rcx, %rax
 ; X64-NEXT:    retq
   %absx = call i64 @llvm.abs.i64(i64 %x, i1 true)
   %foo = xor i64 %absx, 12312
@@ -70,20 +73,21 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 ; X86-LABEL: eq_or_with_dom_abs_non_po2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    movl %edx, %ecx
+; X86-NEXT:    sarl $31, %ecx
 ; X86-NEXT:    movl %edx, %eax
-; X86-NEXT:    sarl $31, %eax
-; X86-NEXT:    xorl %eax, %edx
-; X86-NEXT:    subl %eax, %edx
-; X86-NEXT:    movl %edx, %eax
+; X86-NEXT:    xorl %ecx, %eax
+; X86-NEXT:    subl %ecx, %eax
 ; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
-; X86-NEXT:    xorl %ecx, %ecx
 ; X86-NEXT:    cmpl $123, %edx
+; X86-NEXT:    sete %cl
+; X86-NEXT:    cmpl $-123, %edx
 ; X86-NEXT:    sete %dl
 ; X86-NEXT:    cmpl $2345, %eax # imm = 0x929
 ; X86-NEXT:    jae .LBB1_2
 ; X86-NEXT:  # %bb.1:
-; X86-NEXT:    movb %dl, %cl
-; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    orb %dl, %cl
+; X86-NEXT:    movzbl %cl, %eax
 ; X86-NEXT:  .LBB1_2:
 ; X86-NEXT:    retl
 ;
@@ -92,13 +96,15 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 ; X64-NEXT:    movl %edi, %ecx
 ; X64-NEXT:    negl %ecx
 ; X64-NEXT:    cmovsl %edi, %ecx
-; X64-NEXT:    movl %ecx, %edx
-; X64-NEXT:    xorl $12312, %edx # imm = 0x3018
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $123, %ecx
+; X64-NEXT:    xorl $12312, %ecx # imm = 0x3018
+; X64-NEXT:    cmpl $123, %edi
 ; X64-NEXT:    sete %al
-; X64-NEXT:    cmpl $2345, %edx # imm = 0x929
-; X64-NEXT:    cmovael %edx, %eax
+; X64-NEXT:    cmpl $-123, %edi
+; X64-NEXT:    sete %dl
+; X64-NEXT:    orb %al, %dl
+; X64-NEXT:    cmpl $2345, %ecx # imm = 0x929
+; X64-NEXT:    movzbl %dl, %eax
+; X64-NEXT:    cmovael %ecx, %eax
 ; X64-NEXT:    retq
   %absx = call i32 @llvm.abs.i32(i32 %x, i1 true)
   %foo = xor i32 %absx, 12312
@@ -114,18 +120,21 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 define i8 @ne_and_with_dom_abs_non_pow2(i8 %x) nounwind {
 ; X86-LABEL: ne_and_with_dom_abs_non_pow2:
 ; X86:       # %bb.0:
-; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl %ecx, %eax
-; X86-NEXT:    sarb $7, %al
-; X86-NEXT:    xorb %al, %cl
-; X86-NEXT:    subb %al, %cl
-; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    movl %edx, %ecx
+; X86-NEXT:    sarb $7, %cl
+; X86-NEXT:    movl %edx, %eax
+; X86-NEXT:    xorb %cl, %al
+; X86-NEXT:    subb %cl, %al
 ; X86-NEXT:    xorb $12, %al
-; X86-NEXT:    cmpb $121, %cl
+; X86-NEXT:    cmpb $121, %dl
 ; X86-NEXT:    setne %cl
+; X86-NEXT:    cmpb $-121, %dl
+; X86-NEXT:    setne %dl
 ; X86-NEXT:    cmpb $24, %al
 ; X86-NEXT:    jae .LBB2_2
 ; X86-NEXT:  # %bb.1:
+; X86-NEXT:    andb %dl, %cl
 ; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:  .LBB2_2:
 ; X86-NEXT:    retl
@@ -134,16 +143,19 @@ define i8 @ne_and_with_dom_abs_non_pow2(i8 %x) nounwind {
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    sarb $7, %al
-; X64-NEXT:    xorb %al, %dil
-; X64-NEXT:    subb %al, %dil
 ; X64-NEXT:    movl %edi, %ecx
+; X64-NEXT:    xorb %al, %cl
+; X64-NEXT:    subb %al, %cl
 ; X64-NEXT:    xorb $12, %cl
-; X64-NEXT:    xorl %eax, %eax
 ; X64-NEXT:    cmpb $121, %dil
 ; X64-NEXT:    setne %al
+; X64-NEXT:    cmpb $-121, %dil
+; X64-NEXT:    setne %dl
+; X64-NEXT:    andb %al, %dl
 ; X64-NEXT:    cmpb $24, %cl
-; X64-NEXT:    movzbl %cl, %ecx
-; X64-NEXT:    cmovael %ecx, %eax
+; X64-NEXT:    movzbl %dl, %edx
+; X64-NEXT:    movzbl %cl, %eax
+; X64-NEXT:    cmovbl %edx, %eax
 ; X64-NEXT:    # kill: def $al killed $al killed $eax
 ; X64-NEXT:    retq
   %absx = call i8 @llvm.abs.i8(i8 %x, i1 true)
@@ -161,16 +173,16 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X86-LABEL: ne_and_with_dom_abs:
 ; X86:       # %bb.0:
 ; X86-NEXT:    pushl %esi
-; X86-NEXT:    movswl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movswl %ax, %ecx
 ; X86-NEXT:    sarl $15, %ecx
+; X86-NEXT:    leal 64(%eax), %edx
 ; X86-NEXT:    xorl %ecx, %eax
 ; X86-NEXT:    subl %ecx, %eax
-; X86-NEXT:    movl %eax, %edx
 ; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
 ; X86-NEXT:    movzwl %ax, %esi
 ; X86-NEXT:    xorl %ecx, %ecx
-; X86-NEXT:    cmpw $64, %dx
+; X86-NEXT:    testl $65407, %edx # imm = 0xFF7F
 ; X86-NEXT:    setne %dl
 ; X86-NEXT:    cmpl $2345, %esi # imm = 0x929
 ; X86-NEXT:    jae .LBB3_2
@@ -187,14 +199,14 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X64-NEXT:    movl %edi, %ecx
 ; X64-NEXT:    negw %cx
 ; X64-NEXT:    cmovsw %di, %cx
-; X64-NEXT:    movl %ecx, %edx
-; X64-NEXT:    xorl $12312, %edx # imm = 0x3018
-; X64-NEXT:    movzwl %dx, %esi
+; X64-NEXT:    xorl $12312, %ecx # imm = 0x3018
+; X64-NEXT:    movzwl %cx, %edx
+; X64-NEXT:    addl $64, %edi
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpw $64, %cx
+; X64-NEXT:    testl $65407, %edi # imm = 0xFF7F
 ; X64-NEXT:    setne %al
-; X64-NEXT:    cmpl $2345, %esi # imm = 0x929
-; X64-NEXT:    cmovael %edx, %eax
+; X64-NEXT:    cmpl $2345, %edx # imm = 0x929
+; X64-NEXT:    cmovael %ecx, %eax
 ; X64-NEXT:    # kill: def $ax killed $ax killed $eax
 ; X64-NEXT:    retq
   %absx = call i16 @llvm.abs.i16(i16 %x, i1 true)
diff --git a/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll b/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll
index b14fedeaae57d..298e78103e709 100644
--- a/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll
+++ b/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll
@@ -154,15 +154,20 @@ define i1 @abs_eq_pow2(i32 %0) nounwind {
 ; X86-LABEL: abs_eq_pow2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    addl $4, %eax
-; X86-NEXT:    testl $-9, %eax
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    sarl $31, %ecx
+; X86-NEXT:    xorl %ecx, %eax
+; X86-NEXT:    subl %ecx, %eax
+; X86-NEXT:    cmpl $4, %eax
 ; X86-NEXT:    sete %al
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: abs_eq_pow2:
 ; X64:       # %bb.0:
-; X64-NEXT:    addl $4, %edi
-; X64-NEXT:    testl $-9, %edi
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    negl %eax
+; X64-NEXT:    cmovsl %edi, %eax
+; X64-NEXT:    cmpl $4, %eax
 ; X64-NEXT:    sete %al
 ; X64-NEXT:    retq
   %2 = tail call i32 @llvm.abs.i32(i32 %0, i1 true)
@@ -174,18 +179,24 @@ define i1 @abs_ne_pow2(i64 %0) nounwind {
 ; X86-LABEL: abs_ne_pow2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    addl $2, %eax
-; X86-NEXT:    adcl $0, %ecx
-; X86-NEXT:    andl $-5, %eax
-; X86-NEXT:    orl %ecx, %eax
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    sarl $31, %ecx
+; X86-NEXT:    xorl %ecx, %eax
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    xorl %ecx, %edx
+; X86-NEXT:    subl %ecx, %edx
+; X86-NEXT:    sbbl %ecx, %eax
+; X86-NEXT:    xorl $2, %edx
+; X86-NEXT:    orl %eax, %edx
 ; X86-NEXT:    setne %al
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: abs_ne_pow2:
 ; X64:       # %bb.0:
-; X64-NEXT:    addq $2, %rdi
-; X64-NEXT:    testq $-5, %rdi
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    negq %rax
+; X64-NEXT:    cmovsq %rdi, %rax
+; X64-NEXT:    cmpq $2, %rax
 ; X64-NEXT:    setne %al
 ; X64-NEXT:    retq
   %2 = tail call i64 @llvm.abs.i64(i64 %0, i1 true)

>From 19df666dd01477f0ef276c5d508e7efb346e9044 Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Fri, 13 Mar 2026 20:51:01 +0000
Subject: [PATCH 2/6] fixup! SelectionDAG: Preserve poison for abs INT_MIN
 lowering. Update affected CodeGen lit tests and added a new lit test for this
 behavior.

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |  4 ++-
 llvm/lib/Target/X86/X86ISelLowering.cpp       |  4 ++-
 .../test/CodeGen/X86/icmp-pow2-logic-npow2.ll | 33 +++++++------------
 3 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e93094e544bbd..a1bdfcf7e9c40 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6916,7 +6916,9 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
     // case this is just a compare).
     if (APLhs == (-APRhs) &&
         ((TargetPreference & AndOrSETCCFoldKind::ABS) ||
-         DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0}))) {
+         DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0}) ||
+         DAG.doesNodeExist(ISD::ABS_MIN_POISON, DAG.getVTList(OpVT),
+                           {LHS0}))) {
       const APInt &C = APLhs.isNegative() ? APRhs : APLhs;
       // (icmp eq A, C) | (icmp eq A, -C)
       //    -> (icmp eq Abs(A), C)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 927a49b203968..612b7383e2e2e 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57415,7 +57415,9 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG,
     // Both of these patterns can be better optimized in
     // DAGCombiner::foldAndOrOfSETCC. Note this only applies for scalar
     // integers which is checked above.
-    if (LHS.getOpcode() == ISD::ABS && LHS.hasOneUse()) {
+    if ((LHS.getOpcode() == ISD::ABS ||
+         LHS.getOpcode() == ISD::ABS_MIN_POISON) &&
+        LHS.hasOneUse()) {
       if (auto *C = dyn_cast<ConstantSDNode>(RHS)) {
         const APInt &CInt = C->getAPIntValue();
         // We can better optimize this case in DAGCombiner::foldAndOrOfSETCC.
diff --git a/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll b/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll
index 298e78103e709..b14fedeaae57d 100644
--- a/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll
+++ b/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll
@@ -154,20 +154,15 @@ define i1 @abs_eq_pow2(i32 %0) nounwind {
 ; X86-LABEL: abs_eq_pow2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl %eax, %ecx
-; X86-NEXT:    sarl $31, %ecx
-; X86-NEXT:    xorl %ecx, %eax
-; X86-NEXT:    subl %ecx, %eax
-; X86-NEXT:    cmpl $4, %eax
+; X86-NEXT:    addl $4, %eax
+; X86-NEXT:    testl $-9, %eax
 ; X86-NEXT:    sete %al
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: abs_eq_pow2:
 ; X64:       # %bb.0:
-; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    negl %eax
-; X64-NEXT:    cmovsl %edi, %eax
-; X64-NEXT:    cmpl $4, %eax
+; X64-NEXT:    addl $4, %edi
+; X64-NEXT:    testl $-9, %edi
 ; X64-NEXT:    sete %al
 ; X64-NEXT:    retq
   %2 = tail call i32 @llvm.abs.i32(i32 %0, i1 true)
@@ -179,24 +174,18 @@ define i1 @abs_ne_pow2(i64 %0) nounwind {
 ; X86-LABEL: abs_ne_pow2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl %eax, %ecx
-; X86-NEXT:    sarl $31, %ecx
-; X86-NEXT:    xorl %ecx, %eax
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    xorl %ecx, %edx
-; X86-NEXT:    subl %ecx, %edx
-; X86-NEXT:    sbbl %ecx, %eax
-; X86-NEXT:    xorl $2, %edx
-; X86-NEXT:    orl %eax, %edx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    addl $2, %eax
+; X86-NEXT:    adcl $0, %ecx
+; X86-NEXT:    andl $-5, %eax
+; X86-NEXT:    orl %ecx, %eax
 ; X86-NEXT:    setne %al
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: abs_ne_pow2:
 ; X64:       # %bb.0:
-; X64-NEXT:    movq %rdi, %rax
-; X64-NEXT:    negq %rax
-; X64-NEXT:    cmovsq %rdi, %rax
-; X64-NEXT:    cmpq $2, %rax
+; X64-NEXT:    addq $2, %rdi
+; X64-NEXT:    testq $-5, %rdi
 ; X64-NEXT:    setne %al
 ; X64-NEXT:    retq
   %2 = tail call i64 @llvm.abs.i64(i64 %0, i1 true)

>From 8a2a95c79adb52a021b3285b3c2b3a116c0543e1 Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Fri, 13 Mar 2026 23:23:51 +0000
Subject: [PATCH 3/6] fixup! fixup! SelectionDAG: Preserve poison for abs
 INT_MIN lowering. Update affected CodeGen lit tests and added a new lit test
 for this behavior.

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |   7 +-
 llvm/test/CodeGen/X86/icmp-abs-C.ll           | 120 ++++++++----------
 2 files changed, 60 insertions(+), 67 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index a1bdfcf7e9c40..026da9eb10ec3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6924,7 +6924,12 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
       //    -> (icmp eq Abs(A), C)
       // (icmp ne A, C) & (icmp ne A, -C)
       //    -> (icmp ne Abs(A), C)
-      SDValue AbsOp = DAG.getNode(ISD::ABS, DL, OpVT, LHS0);
+      // Use ABS_MIN_POISON if that node already exists, otherwise ABS.
+      unsigned AbsOpc =
+          DAG.doesNodeExist(ISD::ABS_MIN_POISON, DAG.getVTList(OpVT), {LHS0})
+              ? ISD::ABS_MIN_POISON
+              : ISD::ABS;
+      SDValue AbsOp = DAG.getNode(AbsOpc, DL, OpVT, LHS0);
       return DAG.getNode(ISD::SETCC, DL, VT, AbsOp,
                          DAG.getConstant(C, DL, OpVT), LHS.getOperand(2));
     } else if (TargetPreference &
diff --git a/llvm/test/CodeGen/X86/icmp-abs-C.ll b/llvm/test/CodeGen/X86/icmp-abs-C.ll
index fe19174b53b42..71893a9e4be67 100644
--- a/llvm/test/CodeGen/X86/icmp-abs-C.ll
+++ b/llvm/test/CodeGen/X86/icmp-abs-C.ll
@@ -13,32 +13,29 @@ define i64 @eq_or_with_dom_abs(i64 %x) nounwind {
 ; X86-NEXT:    pushl %ebx
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    movl %edx, %eax
+; X86-NEXT:    sarl $31, %eax
+; X86-NEXT:    xorl %eax, %edx
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
-; X86-NEXT:    movl %esi, %edi
-; X86-NEXT:    sarl $31, %edi
-; X86-NEXT:    movl %esi, %edx
-; X86-NEXT:    xorl %edi, %edx
-; X86-NEXT:    movl %ecx, %eax
-; X86-NEXT:    xorl %edi, %eax
-; X86-NEXT:    subl %edi, %eax
-; X86-NEXT:    sbbl %edi, %edx
+; X86-NEXT:    xorl %eax, %esi
+; X86-NEXT:    subl %eax, %esi
+; X86-NEXT:    sbbl %eax, %edx
+; X86-NEXT:    movl %esi, %eax
 ; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
-; X86-NEXT:    addl $64, %ecx
-; X86-NEXT:    adcl $0, %esi
-; X86-NEXT:    andl $-129, %ecx
-; X86-NEXT:    xorl %ebx, %ebx
-; X86-NEXT:    orl %esi, %ecx
-; X86-NEXT:    sete %cl
+; X86-NEXT:    xorl $64, %esi
+; X86-NEXT:    xorl %ecx, %ecx
+; X86-NEXT:    orl %edx, %esi
+; X86-NEXT:    sete %bl
 ; X86-NEXT:    xorl %esi, %esi
 ; X86-NEXT:    movl $2344, %edi # imm = 0x928
 ; X86-NEXT:    cmpl %eax, %edi
 ; X86-NEXT:    sbbl %edx, %esi
 ; X86-NEXT:    jb .LBB0_2
 ; X86-NEXT:  # %bb.1:
-; X86-NEXT:    movb %cl, %bl
+; X86-NEXT:    movb %bl, %cl
 ; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    movl %ebx, %eax
+; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:  .LBB0_2:
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
@@ -50,13 +47,13 @@ define i64 @eq_or_with_dom_abs(i64 %x) nounwind {
 ; X64-NEXT:    movq %rdi, %rcx
 ; X64-NEXT:    negq %rcx
 ; X64-NEXT:    cmovsq %rdi, %rcx
-; X64-NEXT:    xorq $12312, %rcx # imm = 0x3018
-; X64-NEXT:    addq $64, %rdi
+; X64-NEXT:    movq %rcx, %rdx
+; X64-NEXT:    xorq $12312, %rdx # imm = 0x3018
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    testq $-129, %rdi
+; X64-NEXT:    cmpq $64, %rcx
 ; X64-NEXT:    sete %al
-; X64-NEXT:    cmpq $2345, %rcx # imm = 0x929
-; X64-NEXT:    cmovaeq %rcx, %rax
+; X64-NEXT:    cmpq $2345, %rdx # imm = 0x929
+; X64-NEXT:    cmovaeq %rdx, %rax
 ; X64-NEXT:    retq
   %absx = call i64 @llvm.abs.i64(i64 %x, i1 true)
   %foo = xor i64 %absx, 12312
@@ -73,21 +70,20 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 ; X86-LABEL: eq_or_with_dom_abs_non_po2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    movl %edx, %ecx
-; X86-NEXT:    sarl $31, %ecx
 ; X86-NEXT:    movl %edx, %eax
-; X86-NEXT:    xorl %ecx, %eax
-; X86-NEXT:    subl %ecx, %eax
+; X86-NEXT:    sarl $31, %eax
+; X86-NEXT:    xorl %eax, %edx
+; X86-NEXT:    subl %eax, %edx
+; X86-NEXT:    movl %edx, %eax
 ; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
+; X86-NEXT:    xorl %ecx, %ecx
 ; X86-NEXT:    cmpl $123, %edx
-; X86-NEXT:    sete %cl
-; X86-NEXT:    cmpl $-123, %edx
 ; X86-NEXT:    sete %dl
 ; X86-NEXT:    cmpl $2345, %eax # imm = 0x929
 ; X86-NEXT:    jae .LBB1_2
 ; X86-NEXT:  # %bb.1:
-; X86-NEXT:    orb %dl, %cl
-; X86-NEXT:    movzbl %cl, %eax
+; X86-NEXT:    movb %dl, %cl
+; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:  .LBB1_2:
 ; X86-NEXT:    retl
 ;
@@ -96,15 +92,13 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 ; X64-NEXT:    movl %edi, %ecx
 ; X64-NEXT:    negl %ecx
 ; X64-NEXT:    cmovsl %edi, %ecx
-; X64-NEXT:    xorl $12312, %ecx # imm = 0x3018
-; X64-NEXT:    cmpl $123, %edi
+; X64-NEXT:    movl %ecx, %edx
+; X64-NEXT:    xorl $12312, %edx # imm = 0x3018
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $123, %ecx
 ; X64-NEXT:    sete %al
-; X64-NEXT:    cmpl $-123, %edi
-; X64-NEXT:    sete %dl
-; X64-NEXT:    orb %al, %dl
-; X64-NEXT:    cmpl $2345, %ecx # imm = 0x929
-; X64-NEXT:    movzbl %dl, %eax
-; X64-NEXT:    cmovael %ecx, %eax
+; X64-NEXT:    cmpl $2345, %edx # imm = 0x929
+; X64-NEXT:    cmovael %edx, %eax
 ; X64-NEXT:    retq
   %absx = call i32 @llvm.abs.i32(i32 %x, i1 true)
   %foo = xor i32 %absx, 12312
@@ -120,21 +114,18 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 define i8 @ne_and_with_dom_abs_non_pow2(i8 %x) nounwind {
 ; X86-LABEL: ne_and_with_dom_abs_non_pow2:
 ; X86:       # %bb.0:
-; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    movl %edx, %ecx
-; X86-NEXT:    sarb $7, %cl
-; X86-NEXT:    movl %edx, %eax
-; X86-NEXT:    xorb %cl, %al
-; X86-NEXT:    subb %cl, %al
+; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    sarb $7, %al
+; X86-NEXT:    xorb %al, %cl
+; X86-NEXT:    subb %al, %cl
+; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:    xorb $12, %al
-; X86-NEXT:    cmpb $121, %dl
+; X86-NEXT:    cmpb $121, %cl
 ; X86-NEXT:    setne %cl
-; X86-NEXT:    cmpb $-121, %dl
-; X86-NEXT:    setne %dl
 ; X86-NEXT:    cmpb $24, %al
 ; X86-NEXT:    jae .LBB2_2
 ; X86-NEXT:  # %bb.1:
-; X86-NEXT:    andb %dl, %cl
 ; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:  .LBB2_2:
 ; X86-NEXT:    retl
@@ -143,19 +134,16 @@ define i8 @ne_and_with_dom_abs_non_pow2(i8 %x) nounwind {
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    sarb $7, %al
+; X64-NEXT:    xorb %al, %dil
+; X64-NEXT:    subb %al, %dil
 ; X64-NEXT:    movl %edi, %ecx
-; X64-NEXT:    xorb %al, %cl
-; X64-NEXT:    subb %al, %cl
 ; X64-NEXT:    xorb $12, %cl
+; X64-NEXT:    xorl %eax, %eax
 ; X64-NEXT:    cmpb $121, %dil
 ; X64-NEXT:    setne %al
-; X64-NEXT:    cmpb $-121, %dil
-; X64-NEXT:    setne %dl
-; X64-NEXT:    andb %al, %dl
 ; X64-NEXT:    cmpb $24, %cl
-; X64-NEXT:    movzbl %dl, %edx
-; X64-NEXT:    movzbl %cl, %eax
-; X64-NEXT:    cmovbl %edx, %eax
+; X64-NEXT:    movzbl %cl, %ecx
+; X64-NEXT:    cmovael %ecx, %eax
 ; X64-NEXT:    # kill: def $al killed $al killed $eax
 ; X64-NEXT:    retq
   %absx = call i8 @llvm.abs.i8(i8 %x, i1 true)
@@ -173,16 +161,16 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X86-LABEL: ne_and_with_dom_abs:
 ; X86:       # %bb.0:
 ; X86-NEXT:    pushl %esi
-; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movswl %ax, %ecx
+; X86-NEXT:    movswl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %eax, %ecx
 ; X86-NEXT:    sarl $15, %ecx
-; X86-NEXT:    leal 64(%eax), %edx
 ; X86-NEXT:    xorl %ecx, %eax
 ; X86-NEXT:    subl %ecx, %eax
+; X86-NEXT:    movl %eax, %edx
 ; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
 ; X86-NEXT:    movzwl %ax, %esi
 ; X86-NEXT:    xorl %ecx, %ecx
-; X86-NEXT:    testl $65407, %edx # imm = 0xFF7F
+; X86-NEXT:    cmpw $64, %dx
 ; X86-NEXT:    setne %dl
 ; X86-NEXT:    cmpl $2345, %esi # imm = 0x929
 ; X86-NEXT:    jae .LBB3_2
@@ -199,14 +187,14 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X64-NEXT:    movl %edi, %ecx
 ; X64-NEXT:    negw %cx
 ; X64-NEXT:    cmovsw %di, %cx
-; X64-NEXT:    xorl $12312, %ecx # imm = 0x3018
-; X64-NEXT:    movzwl %cx, %edx
-; X64-NEXT:    addl $64, %edi
+; X64-NEXT:    movl %ecx, %edx
+; X64-NEXT:    xorl $12312, %edx # imm = 0x3018
+; X64-NEXT:    movzwl %dx, %esi
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    testl $65407, %edi # imm = 0xFF7F
+; X64-NEXT:    cmpw $64, %cx
 ; X64-NEXT:    setne %al
-; X64-NEXT:    cmpl $2345, %edx # imm = 0x929
-; X64-NEXT:    cmovael %ecx, %eax
+; X64-NEXT:    cmpl $2345, %esi # imm = 0x929
+; X64-NEXT:    cmovael %edx, %eax
 ; X64-NEXT:    # kill: def $ax killed $ax killed $eax
 ; X64-NEXT:    retq
   %absx = call i16 @llvm.abs.i16(i16 %x, i1 true)

>From 241701fa6f04d8e6ec2ab3a9e0a17a589341fb0d Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Fri, 20 Mar 2026 22:01:45 +0000
Subject: [PATCH 4/6] fixup! fixup! fixup! SelectionDAG: Preserve poison for
 abs INT_MIN lowering. Update affected CodeGen lit tests and added a new lit
 test for this behavior.

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 11 +---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  2 +-
 llvm/test/CodeGen/X86/icmp-abs-C.ll           | 56 +++++++++++++++++--
 3 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 026da9eb10ec3..e93094e544bbd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6916,20 +6916,13 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
     // case this is just a compare).
     if (APLhs == (-APRhs) &&
         ((TargetPreference & AndOrSETCCFoldKind::ABS) ||
-         DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0}) ||
-         DAG.doesNodeExist(ISD::ABS_MIN_POISON, DAG.getVTList(OpVT),
-                           {LHS0}))) {
+         DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0}))) {
       const APInt &C = APLhs.isNegative() ? APRhs : APLhs;
       // (icmp eq A, C) | (icmp eq A, -C)
       //    -> (icmp eq Abs(A), C)
       // (icmp ne A, C) & (icmp ne A, -C)
       //    -> (icmp ne Abs(A), C)
-      // Use ABS_MIN_POISON if that node already exists, otherwise ABS.
-      unsigned AbsOpc =
-          DAG.doesNodeExist(ISD::ABS_MIN_POISON, DAG.getVTList(OpVT), {LHS0})
-              ? ISD::ABS_MIN_POISON
-              : ISD::ABS;
-      SDValue AbsOp = DAG.getNode(AbsOpc, DL, OpVT, LHS0);
+      SDValue AbsOp = DAG.getNode(ISD::ABS, DL, OpVT, LHS0);
       return DAG.getNode(ISD::SETCC, DL, VT, AbsOp,
                          DAG.getConstant(C, DL, OpVT), LHS.getOperand(2));
     } else if (TargetPreference &
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index d71ae66178430..c2dbe0dd70f8d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6349,7 +6349,7 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, const APInt &DemandedElts,
   case ISD::CTPOP:
   case ISD::ABS:
   case ISD::ABS_MIN_POISON:
-    return isKnownNeverZero(Op.getOperand(0), Depth + 1);
+    return isKnownNeverZero(Op.getOperand(0), DemandedElts, Depth + 1);
 
   case ISD::SRA:
   case ISD::SRL: {
diff --git a/llvm/test/CodeGen/X86/icmp-abs-C.ll b/llvm/test/CodeGen/X86/icmp-abs-C.ll
index 71893a9e4be67..5e2ccb4a51174 100644
--- a/llvm/test/CodeGen/X86/icmp-abs-C.ll
+++ b/llvm/test/CodeGen/X86/icmp-abs-C.ll
@@ -55,7 +55,7 @@ define i64 @eq_or_with_dom_abs(i64 %x) nounwind {
 ; X64-NEXT:    cmpq $2345, %rdx # imm = 0x929
 ; X64-NEXT:    cmovaeq %rdx, %rax
 ; X64-NEXT:    retq
-  %absx = call i64 @llvm.abs.i64(i64 %x, i1 true)
+  %absx = call i64 @llvm.abs.i64(i64 %x, i1 false)
   %foo = xor i64 %absx, 12312
   %bar = icmp ugt i64 %foo, 2344
   %cmp0 = icmp eq i64 %x, 64
@@ -100,7 +100,7 @@ define i32 @eq_or_with_dom_abs_non_po2(i32 %x) nounwind {
 ; X64-NEXT:    cmpl $2345, %edx # imm = 0x929
 ; X64-NEXT:    cmovael %edx, %eax
 ; X64-NEXT:    retq
-  %absx = call i32 @llvm.abs.i32(i32 %x, i1 true)
+  %absx = call i32 @llvm.abs.i32(i32 %x, i1 false)
   %foo = xor i32 %absx, 12312
   %bar = icmp ugt i32 %foo, 2344
   %cmp0 = icmp eq i32 %x, 123
@@ -146,7 +146,7 @@ define i8 @ne_and_with_dom_abs_non_pow2(i8 %x) nounwind {
 ; X64-NEXT:    cmovael %ecx, %eax
 ; X64-NEXT:    # kill: def $al killed $al killed $eax
 ; X64-NEXT:    retq
-  %absx = call i8 @llvm.abs.i8(i8 %x, i1 true)
+  %absx = call i8 @llvm.abs.i8(i8 %x, i1 false)
   %foo = xor i8 %absx, 12
   %bar = icmp ugt i8 %foo, 23
   %cmp0 = icmp ne i8 %x, 121
@@ -197,7 +197,7 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X64-NEXT:    cmovael %edx, %eax
 ; X64-NEXT:    # kill: def $ax killed $ax killed $eax
 ; X64-NEXT:    retq
-  %absx = call i16 @llvm.abs.i16(i16 %x, i1 true)
+  %absx = call i16 @llvm.abs.i16(i16 %x, i1 false)
   %foo = xor i16 %absx, 12312
   %bar = icmp ugt i16 %foo, 2344
   %cmp0 = icmp ne i16 %x, 64
@@ -207,3 +207,51 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
   %r = select i1 %bar, i16 %foo, i16 %cmp64
   ret i16 %r
 }
+
+; X86-LABEL: eq_or_with_dom_abs_min_poison_non_po2:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    movl %edx, %ecx
+; X86-NEXT:    sarl $31, %ecx
+; X86-NEXT:    movl %edx, %eax
+; X86-NEXT:    xorl %ecx, %eax
+; X86-NEXT:    subl %ecx, %eax
+; X86-NEXT:    xorl $12312, %eax # imm = 0x3018
+; X86-NEXT:    cmpl $123, %edx
+; X86-NEXT:    sete %cl
+; X86-NEXT:    cmpl $-123, %edx
+; X86-NEXT:    sete %dl
+; X86-NEXT:    cmpl $2345, %eax # imm = 0x929
+; X86-NEXT:    jae .LBB4_2
+; X86-NEXT:  # %bb.1:
+; X86-NEXT:    orb %dl, %cl
+; X86-NEXT:    movzbl %cl, %eax
+; X86-NEXT:  .LBB4_2:
+; X86-NEXT:    retl
+;
+; X64-LABEL: eq_or_with_dom_abs_min_poison_non_po2:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %ecx
+; X64-NEXT:    negl %ecx
+; X64-NEXT:    cmovsl %edi, %ecx
+; X64-NEXT:    xorl $12312, %ecx # imm = 0x3018
+; X64-NEXT:    cmpl $123, %edi
+; X64-NEXT:    sete %al
+; X64-NEXT:    cmpl $-123, %edi
+; X64-NEXT:    sete %dl
+; X64-NEXT:    orb %al, %dl
+; X64-NEXT:    cmpl $2345, %ecx # imm = 0x929
+; X64-NEXT:    movzbl %dl, %eax
+; X64-NEXT:    cmovael %ecx, %eax
+; X64-NEXT:    retq
+define i32 @eq_or_with_dom_abs_min_poison_non_po2(i32 %x) nounwind {
+  %absx = call i32 @llvm.abs.i32(i32 %x, i1 true)
+  %foo = xor i32 %absx, 12312
+  %bar = icmp ugt i32 %foo, 2344
+  %cmp0 = icmp eq i32 %x, 123
+  %cmp1 = icmp eq i32 %x, -123
+  %cmp = or i1 %cmp0, %cmp1
+  %cmp64 = zext i1 %cmp to i32
+  %r = select i1 %bar, i32 %foo, i32 %cmp64
+  ret i32 %r
+}

>From b23666fe07c2629ddcb72a3be4a2c0db4d50ca39 Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Tue, 24 Mar 2026 21:04:33 +0000
Subject: [PATCH 5/6] fixup! fixup! fixup! fixup! SelectionDAG: Preserve poison
 for abs INT_MIN lowering. Update affected CodeGen lit tests and added a new
 lit test for this behavior.

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp   |  7 ++++---
 .../SelectionDAG/LegalizeIntegerTypes.cpp       | 17 +++++++++--------
 .../lib/CodeGen/SelectionDAG/TargetLowering.cpp |  3 +--
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp     |  3 +--
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e93094e544bbd..20237d15561cc 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -11930,7 +11930,7 @@ SDValue DAGCombiner::visitABS(SDNode *N) {
   if (SDValue C = DAG.FoldConstantArithmetic(ISD::ABS, DL, VT, {N0}))
     return C;
   // fold (abs (abs x)) -> (abs x)
-  // fold (abs (abs_min_poison x)) -> (abs x)
+  // fold (abs (abs_min_poison x)) -> (abs_min_poison x)
   if (N0.getOpcode() == ISD::ABS || N0.getOpcode() == ISD::ABS_MIN_POISON)
     return N0;
   // fold (abs x) -> x iff not-negative
@@ -15389,7 +15389,8 @@ static SDValue widenCtPop(SDNode *Extend, SelectionDAG &DAG, const SDLoc &DL) {
 }
 
 // If we have (zext (abs X)) where X is a type that will be promoted by type
-// legalization, convert to (abs (sext X)). But don't extend past a legal type.
+// legalization, convert to (abs_min_poison (sext X)). But do not extend
+// past a legal type.
 static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG) {
   assert(Extend->getOpcode() == ISD::ZERO_EXTEND && "Expected zero extend.");
 
@@ -15413,7 +15414,7 @@ static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG) {
 
   SDValue SExt =
       DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Abs), LegalVT, Abs.getOperand(0));
-  SDValue NewAbs = DAG.getNode(AbsOpc, SDLoc(Abs), LegalVT, SExt);
+  SDValue NewAbs = DAG.getNode(ISD::ABS_MIN_POISON, SDLoc(Abs), LegalVT, SExt);
   return DAG.getZExtOrTrunc(NewAbs, SDLoc(Extend), VT);
 }
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index a37af675dce95..26a9ad52929d3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -1872,7 +1872,6 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SADDSUBO_CARRY(SDNode *N,
 }
 
 SDValue DAGTypeLegalizer::PromoteIntRes_ABS(SDNode *N) {
-  unsigned Opc = N->getOpcode();
   EVT OVT = N->getValueType(0);
   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
 
@@ -1888,7 +1887,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_ABS(SDNode *N) {
   }
 
   SDValue Op0 = SExtPromotedInteger(N->getOperand(0));
-  return DAG.getNode(Opc, SDLoc(N), Op0.getValueType(), Op0);
+  return DAG.getNode(ISD::ABS_MIN_POISON, SDLoc(N), Op0.getValueType(), Op0);
 }
 
 SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
@@ -4122,12 +4121,14 @@ void DAGTypeLegalizer::ExpandIntRes_ABS(SDNode *N, SDValue &Lo, SDValue &Hi) {
   EVT NVT = Lo.getValueType();
 
   // If the upper half is all sign bits, then we can perform the ABS on the
-  // lower half and zero-extend. We must use ISD::ABS here (not ABS_MIN_POISON)
-  // because the original poison contract is for INT_MIN of the wider type,
-  // but the lower half may be INT_MIN of the narrower type for a valid
-  // (non-INT_MIN) input of the original type.
-  if (DAG.ComputeNumSignBits(N0) > NVT.getScalarSizeInBits()) {
-    Lo = DAG.getNode(ISD::ABS, dl, NVT, Lo);
+  // lower half and zero-extend. We could use ISD::ABS_MIN_POISON here if
+  // DAG.ComputeNumSignBits(N0) is larger than NVT.getScalarSizeInBits() + 1.
+  unsigned NumSignBits = DAG.ComputeNumSignBits(N0);
+  if (NumSignBits > NVT.getScalarSizeInBits()) {
+    unsigned AbsOpc = NumSignBits > NVT.getScalarSizeInBits() + 1
+                          ? ISD::ABS_MIN_POISON
+                          : ISD::ABS;
+    Lo = DAG.getNode(AbsOpc, dl, NVT, Lo);
     Hi = DAG.getConstant(0, dl, NVT);
     return;
   }
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index f6b4542e69159..541ca37e16af6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10078,8 +10078,7 @@ SDValue TargetLowering::expandABS(SDNode *N, SelectionDAG &DAG,
       isOperationLegalOrCustom(ISD::ABS, VT)) {
     SDValue AbsVal = DAG.getNode(ISD::ABS, dl, VT, Op);
     if (IsNegative)
-      return DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, dl, VT),
-                         AbsVal);
+      return DAG.getNegative(AbsVal, dl, VT);
     return AbsVal;
   }
 
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 90b504f74ce3f..3f10a5981bdce 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21725,9 +21725,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
     if (VT.isVector() && N0.hasOneUse() && N0.getOpcode() == ISD::SIGN_EXTEND) {
       SDValue Src = N0.getOperand(0);
       SDLoc DL(N);
-      unsigned Opc = N->getOpcode();
       return DAG.getNode(ISD::ZERO_EXTEND, DL, VT,
-                         DAG.getNode(Opc, DL, Src.getValueType(), Src));
+                         DAG.getNode(ISD::ABS, DL, Src.getValueType(), Src));
     }
     break;
   }

>From 1ff4bfe6482212da560c56e5d5b2cab34b32d0d1 Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Tue, 24 Mar 2026 23:53:48 +0000
Subject: [PATCH 6/6] fixup! fixup! fixup! fixup! fixup! SelectionDAG: Preserve
 poison for abs INT_MIN lowering. Update affected CodeGen lit tests and added
 a new lit test for this behavior.

---
 llvm/test/CodeGen/X86/icmp-abs-C.ll | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/test/CodeGen/X86/icmp-abs-C.ll b/llvm/test/CodeGen/X86/icmp-abs-C.ll
index 5e2ccb4a51174..4773a369326f7 100644
--- a/llvm/test/CodeGen/X86/icmp-abs-C.ll
+++ b/llvm/test/CodeGen/X86/icmp-abs-C.ll
@@ -208,7 +208,8 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
   ret i16 %r
 }
 
-; X86-LABEL: eq_or_with_dom_abs_min_poison_non_po2:
+define i32 @eq_or_with_dom_abs_min_poison_non_pow2(i32 %x) nounwind {
+; X86-LABEL: eq_or_with_dom_abs_min_poison_non_pow2:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
 ; X86-NEXT:    movl %edx, %ecx
@@ -229,7 +230,7 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X86-NEXT:  .LBB4_2:
 ; X86-NEXT:    retl
 ;
-; X64-LABEL: eq_or_with_dom_abs_min_poison_non_po2:
+; X64-LABEL: eq_or_with_dom_abs_min_poison_non_pow2:
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %ecx
 ; X64-NEXT:    negl %ecx
@@ -244,7 +245,6 @@ define i16 @ne_and_with_dom_abs(i16 %x) nounwind {
 ; X64-NEXT:    movzbl %dl, %eax
 ; X64-NEXT:    cmovael %ecx, %eax
 ; X64-NEXT:    retq
-define i32 @eq_or_with_dom_abs_min_poison_non_po2(i32 %x) nounwind {
   %absx = call i32 @llvm.abs.i32(i32 %x, i1 true)
   %foo = xor i32 %absx, 12312
   %bar = icmp ugt i32 %foo, 2344



More information about the llvm-commits mailing list