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

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 2 15:46:47 PST 2026


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

>From 799f64f56a2d4b8ec2631ffb68d4546b44b07d6e Mon Sep 17 00:00:00 2001
From: aryanmagoon <amagoon at nvidia.com>
Date: Fri, 27 Feb 2026 19:13:40 +0000
Subject: [PATCH] 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 |  38 +++++-
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp |   1 +
 .../SelectionDAG/LegalizeIntegerTypes.cpp     |  13 +-
 .../SelectionDAG/LegalizeVectorOps.cpp        |   2 +
 .../SelectionDAG/LegalizeVectorTypes.cpp      |   3 +
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  16 ++-
 .../SelectionDAG/SelectionDAGBuilder.cpp      |   5 +-
 .../SelectionDAG/SelectionDAGDumper.cpp       |   1 +
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |  19 ++-
 llvm/lib/CodeGen/TargetLoweringBase.cpp       |   3 +
 llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp   |  17 ++-
 llvm/lib/Target/NVPTX/NVPTXInstrInfo.td       |   5 +-
 llvm/test/CodeGen/AArch64/abds-neg.ll         |   4 +-
 llvm/test/CodeGen/AArch64/neg-abs.ll          |   4 +-
 llvm/test/CodeGen/AArch64/neon-sad.ll         |  20 ++-
 llvm/test/CodeGen/AArch64/zext-to-tbl.ll      |  20 ++-
 llvm/test/CodeGen/NVPTX/idioms.ll             |  21 +--
 llvm/test/CodeGen/Thumb2/abs.ll               |   6 +-
 llvm/test/CodeGen/X86/abds-neg.ll             |  10 +-
 llvm/test/CodeGen/X86/abs.ll                  |   7 +-
 llvm/test/CodeGen/X86/freeze-unary.ll         |  16 ++-
 llvm/test/CodeGen/X86/icmp-abs-C.ll           | 123 ++++++++++--------
 .../test/CodeGen/X86/icmp-pow2-logic-npow2.ll |  35 +++--
 llvm/test/CodeGen/X86/neg-abs.ll              |   8 +-
 27 files changed, 276 insertions(+), 135 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index b8c6788e0bc03..d02351cc3c095 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 an undefined 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..e2c3397677f5f 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,28 @@ 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
+  if (SDValue C = DAG.FoldConstantArithmetic(ISD::ABS, 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 x) -> x iff not-negative
+  if (DAG.SignBitIsZero(N0))
+    return N0;
+
+  if (SDValue ABD = foldABSToABD(N, DL))
+    return ABD;
+
+  return SDValue();
+}
+
 SDValue DAGCombiner::visitCLMUL(SDNode *N) {
   unsigned Opcode = N->getOpcode();
   SDValue N0 = N->getOperand(0);
@@ -15322,7 +15348,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 +15363,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..1e240669024e5 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:
@@ -4085,6 +4089,7 @@ void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N,
 
 void DAGTypeLegalizer::ExpandIntRes_ABS(SDNode *N, SDValue &Lo, SDValue &Hi) {
   SDLoc dl(N);
+  unsigned Opc = N->getOpcode();
 
   SDValue N0 = N->getOperand(0);
   GetExpandedInteger(N0, Lo, Hi);
@@ -4093,7 +4098,7 @@ void DAGTypeLegalizer::ExpandIntRes_ABS(SDNode *N, SDValue &Lo, SDValue &Hi) {
   // If the upper half is all sign bits, then we can perform the ABS on the
   // lower half and zero-extend.
   if (DAG.ComputeNumSignBits(N0) > NVT.getScalarSizeInBits()) {
-    Lo = DAG.getNode(ISD::ABS, dl, NVT, Lo);
+    Lo = DAG.getNode(Opc, dl, NVT, Lo);
     Hi = DAG.getConstant(0, dl, NVT);
     return;
   }
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..d5086ec94c66f 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) &&
@@ -7190,6 +7203,7 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
         return getConstant(Val.zextOrTrunc(VT.getSizeInBits()), DL, VT,
                            C->isTargetOpcode(), C->isOpaque());
       case ISD::ABS:
+      case ISD::ABS_MIN_POISON:
         return getConstant(Val.abs(), DL, VT, C->isTargetOpcode(),
                            C->isOpaque());
       case ISD::BITREVERSE:
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..c8763c8117954 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9911,11 +9911,19 @@ 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))
+    return DAG.getNode(ISD::ABS, dl, VT, Op);
+
+  bool IntMinIsPoison = N->getOpcode() == ISD::ABS_MIN_POISON;
+
   // abs(x) -> smax(x,sub(0,x))
   if (!IsNegative && isOperationLegal(ISD::SUB, VT) &&
       isOperationLegal(ISD::SMAX, VT)) {
     SDValue Zero = DAG.getConstant(0, dl, VT);
-    Op = DAG.getFreeze(Op);
+    if (!IntMinIsPoison)
+      Op = DAG.getFreeze(Op);
     return DAG.getNode(ISD::SMAX, dl, VT, Op,
                        DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
   }
@@ -9924,7 +9932,8 @@ SDValue TargetLowering::expandABS(SDNode *N, SelectionDAG &DAG,
   if (!IsNegative && isOperationLegal(ISD::SUB, VT) &&
       isOperationLegal(ISD::UMIN, VT)) {
     SDValue Zero = DAG.getConstant(0, dl, VT);
-    Op = DAG.getFreeze(Op);
+    if (!IntMinIsPoison)
+      Op = DAG.getFreeze(Op);
     return DAG.getNode(ISD::UMIN, dl, VT, Op,
                        DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
   }
@@ -9933,7 +9942,8 @@ SDValue TargetLowering::expandABS(SDNode *N, SelectionDAG &DAG,
   if (IsNegative && isOperationLegal(ISD::SUB, VT) &&
       isOperationLegal(ISD::SMIN, VT)) {
     SDValue Zero = DAG.getConstant(0, dl, VT);
-    Op = DAG.getFreeze(Op);
+    if (!IntMinIsPoison)
+      Op = DAG.getFreeze(Op);
     return DAG.getNode(ISD::SMIN, dl, VT, Op,
                        DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
   }
@@ -9946,7 +9956,8 @@ SDValue TargetLowering::expandABS(SDNode *N, SelectionDAG &DAG,
        !isOperationLegalOrCustomOrPromote(ISD::XOR, VT)))
     return SDValue();
 
-  Op = DAG.getFreeze(Op);
+  if (!IntMinIsPoison)
+    Op = DAG.getFreeze(Op);
   SDValue Shift = DAG.getNode(
       ISD::SRA, dl, VT, Op,
       DAG.getShiftAmountConstant(VT.getScalarSizeInBits() - 1, VT, dl));
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/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
index f5554be155eac..3ea8ae53efb8f 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::ABS_MIN_POISON,
+       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::ABS_MIN_POISON,
+                      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/test/CodeGen/AArch64/abds-neg.ll b/llvm/test/CodeGen/AArch64/abds-neg.ll
index 37319642f5b34..4e08140975cd1 100644
--- a/llvm/test/CodeGen/AArch64/abds-neg.ll
+++ b/llvm/test/CodeGen/AArch64/abds-neg.ll
@@ -457,7 +457,7 @@ define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: abd_subnsw_i32_undef:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    subs w8, w0, w1
-; CHECK-NEXT:    cneg w0, w8, pl
+; CHECK-NEXT:    cneg w0, w8, mi
 ; CHECK-NEXT:    ret
   %sub = sub nsw i32 %a, %b
   %abs = call i32 @llvm.abs.i32(i32 %sub, i1 true)
@@ -481,7 +481,7 @@ define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind {
 ; CHECK-LABEL: abd_subnsw_i64_undef:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    subs x8, x0, x1
-; CHECK-NEXT:    cneg x0, x8, pl
+; CHECK-NEXT:    cneg x0, x8, mi
 ; CHECK-NEXT:    ret
   %sub = sub nsw i64 %a, %b
   %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
diff --git a/llvm/test/CodeGen/AArch64/neg-abs.ll b/llvm/test/CodeGen/AArch64/neg-abs.ll
index 35cafe595ea8d..29b6214f50a7c 100644
--- a/llvm/test/CodeGen/AArch64/neg-abs.ll
+++ b/llvm/test/CodeGen/AArch64/neg-abs.ll
@@ -8,7 +8,7 @@ define i64 @neg_abs64(i64 %x) {
 ; CHECK-SD-LABEL: neg_abs64:
 ; CHECK-SD:       // %bb.0:
 ; CHECK-SD-NEXT:    cmp x0, #0
-; CHECK-SD-NEXT:    cneg x0, x0, pl
+; CHECK-SD-NEXT:    cneg x0, x0, mi
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: neg_abs64:
@@ -28,7 +28,7 @@ define i32 @neg_abs32(i32 %x) {
 ; CHECK-SD-LABEL: neg_abs32:
 ; CHECK-SD:       // %bb.0:
 ; CHECK-SD-NEXT:    cmp w0, #0
-; CHECK-SD-NEXT:    cneg w0, w0, pl
+; CHECK-SD-NEXT:    cneg w0, w0, mi
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: neg_abs32:
diff --git a/llvm/test/CodeGen/AArch64/neon-sad.ll b/llvm/test/CodeGen/AArch64/neon-sad.ll
index f21fafea50451..f13368f6237e4 100644
--- a/llvm/test/CodeGen/AArch64/neon-sad.ll
+++ b/llvm/test/CodeGen/AArch64/neon-sad.ll
@@ -9,9 +9,13 @@ define i32 @test_sad_v16i8_zext(ptr nocapture readonly %a, ptr nocapture readonl
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    ldr q0, [x0]
 ; CHECK-NEXT:    ldr q1, [x1]
-; CHECK-NEXT:    uabdl v2.8h, v1.8b, v0.8b
-; CHECK-NEXT:    uabal2 v2.8h, v1.16b, v0.16b
-; CHECK-NEXT:    uaddlv s0, v2.8h
+; CHECK-NEXT:    uabd v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ushll2 v1.8h, v0.16b, #0
+; CHECK-NEXT:    ushll v0.8h, v0.8b, #0
+; CHECK-NEXT:    uaddl2 v2.4s, v0.8h, v1.8h
+; CHECK-NEXT:    uaddl v0.4s, v0.4h, v1.4h
+; CHECK-NEXT:    add v0.4s, v0.4s, v2.4s
+; CHECK-NEXT:    addv s0, v0.4s
 ; CHECK-NEXT:    fmov w0, s0
 ; CHECK-NEXT:    ret
 entry:
@@ -30,9 +34,13 @@ define i32 @test_sad_v16i8_sext(ptr nocapture readonly %a, ptr nocapture readonl
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    ldr q0, [x0]
 ; CHECK-NEXT:    ldr q1, [x1]
-; CHECK-NEXT:    sabdl v2.8h, v1.8b, v0.8b
-; CHECK-NEXT:    sabal2 v2.8h, v1.16b, v0.16b
-; CHECK-NEXT:    uaddlv s0, v2.8h
+; CHECK-NEXT:    sabd v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ushll2 v1.8h, v0.16b, #0
+; CHECK-NEXT:    ushll v0.8h, v0.8b, #0
+; CHECK-NEXT:    uaddl2 v2.4s, v0.8h, v1.8h
+; CHECK-NEXT:    uaddl v0.4s, v0.4h, v1.4h
+; CHECK-NEXT:    add v0.4s, v0.4s, v2.4s
+; CHECK-NEXT:    addv s0, v0.4s
 ; CHECK-NEXT:    fmov w0, s0
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/zext-to-tbl.ll b/llvm/test/CodeGen/AArch64/zext-to-tbl.ll
index 74a717f1635a3..409caa10e87e6 100644
--- a/llvm/test/CodeGen/AArch64/zext-to-tbl.ll
+++ b/llvm/test/CodeGen/AArch64/zext-to-tbl.ll
@@ -2744,9 +2744,13 @@ define i32 @test_pr62620_widening_instr(ptr %p1, ptr %p2, i64 %lx, i32 %h) {
 ; CHECK-NEXT:    mov w0, wzr
 ; CHECK-NEXT:    ldr q0, [x8, x9]
 ; CHECK-NEXT:    ldr q1, [x1, x9]
-; CHECK-NEXT:    uabdl.8h v2, v0, v1
-; CHECK-NEXT:    uabal2.8h v2, v0, v1
-; CHECK-NEXT:    uaddlv.8h s0, v2
+; CHECK-NEXT:    uabd.16b v0, v0, v1
+; CHECK-NEXT:    ushll2.8h v1, v0, #0
+; CHECK-NEXT:    ushll.8h v0, v0, #0
+; CHECK-NEXT:    uaddl2.4s v2, v0, v1
+; CHECK-NEXT:    uaddl.4s v0, v0, v1
+; CHECK-NEXT:    add.4s v0, v0, v2
+; CHECK-NEXT:    addv.4s s0, v0
 ; CHECK-NEXT:    fmov w8, s0
 ; CHECK-NEXT:  LBB23_1: ; %loop
 ; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
@@ -2765,9 +2769,13 @@ define i32 @test_pr62620_widening_instr(ptr %p1, ptr %p2, i64 %lx, i32 %h) {
 ; CHECK-BE-NEXT:    add x9, x1, x9
 ; CHECK-BE-NEXT:    ld1 { v0.16b }, [x8]
 ; CHECK-BE-NEXT:    ld1 { v1.16b }, [x9]
-; CHECK-BE-NEXT:    uabdl v2.8h, v0.8b, v1.8b
-; CHECK-BE-NEXT:    uabal2 v2.8h, v0.16b, v1.16b
-; CHECK-BE-NEXT:    uaddlv s0, v2.8h
+; CHECK-BE-NEXT:    uabd v0.16b, v0.16b, v1.16b
+; CHECK-BE-NEXT:    ushll2 v1.8h, v0.16b, #0
+; CHECK-BE-NEXT:    ushll v0.8h, v0.8b, #0
+; CHECK-BE-NEXT:    uaddl2 v2.4s, v0.8h, v1.8h
+; CHECK-BE-NEXT:    uaddl v0.4s, v0.4h, v1.4h
+; CHECK-BE-NEXT:    add v0.4s, v0.4s, v2.4s
+; CHECK-BE-NEXT:    addv s0, v0.4s
 ; CHECK-BE-NEXT:    fmov w8, s0
 ; CHECK-BE-NEXT:  .LBB23_1: // %loop
 ; CHECK-BE-NEXT:    // =>This Inner Loop Header: Depth=1
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/Thumb2/abs.ll b/llvm/test/CodeGen/Thumb2/abs.ll
index 3cc3ec93e2404..3ad9bded731a2 100644
--- a/llvm/test/CodeGen/Thumb2/abs.ll
+++ b/llvm/test/CodeGen/Thumb2/abs.ll
@@ -42,14 +42,14 @@ define i32 @neg_abs32(i32 %x) {
 ; CHECKT2V7-LABEL: neg_abs32:
 ; CHECKT2V7:       @ %bb.0:
 ; CHECKT2V7-NEXT:    cmp r0, #0
-; CHECKT2V7-NEXT:    it pl
-; CHECKT2V7-NEXT:    rsbpl r0, r0, #0
+; CHECKT2V7-NEXT:    it mi
+; CHECKT2V7-NEXT:    rsbmi r0, r0, #0
 ; CHECKT2V7-NEXT:    bx lr
 ;
 ; CHECKT2V8-LABEL: neg_abs32:
 ; CHECKT2V8:       @ %bb.0:
 ; CHECKT2V8-NEXT:    cmp r0, #0
-; CHECKT2V8-NEXT:    cneg r0, r0, pl
+; CHECKT2V8-NEXT:    cneg r0, r0, mi
 ; CHECKT2V8-NEXT:    bx lr
   %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
   %neg = sub nsw i32 0, %abs
diff --git a/llvm/test/CodeGen/X86/abds-neg.ll b/llvm/test/CodeGen/X86/abds-neg.ll
index d9064c684cb20..06e604133cde1 100644
--- a/llvm/test/CodeGen/X86/abds-neg.ll
+++ b/llvm/test/CodeGen/X86/abds-neg.ll
@@ -1006,7 +1006,7 @@ define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
 ; X86-NEXT:    subw {{[0-9]+}}(%esp), %cx
 ; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:    negw %ax
-; X86-NEXT:    cmovnsw %cx, %ax
+; X86-NEXT:    cmovsw %cx, %ax
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: abd_subnsw_i16_undef:
@@ -1014,7 +1014,7 @@ define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
 ; X64-NEXT:    subl %esi, %edi
 ; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    negw %ax
-; X64-NEXT:    cmovnsw %di, %ax
+; X64-NEXT:    cmovsw %di, %ax
 ; X64-NEXT:    retq
   %sub = sub nsw i16 %a, %b
   %abs = call i16 @llvm.abs.i16(i16 %sub, i1 true)
@@ -1054,7 +1054,7 @@ define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
 ; X86-NEXT:    movl %ecx, %edx
 ; X86-NEXT:    subl %eax, %edx
 ; X86-NEXT:    subl %ecx, %eax
-; X86-NEXT:    cmovgel %edx, %eax
+; X86-NEXT:    cmovll %edx, %eax
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: abd_subnsw_i32_undef:
@@ -1062,7 +1062,7 @@ define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
 ; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    subl %esi, %eax
 ; X64-NEXT:    subl %edi, %esi
-; X64-NEXT:    cmovll %esi, %eax
+; X64-NEXT:    cmovgel %esi, %eax
 ; X64-NEXT:    retq
   %sub = sub nsw i32 %a, %b
   %abs = call i32 @llvm.abs.i32(i32 %sub, i1 true)
@@ -1124,7 +1124,7 @@ define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind {
 ; X64-NEXT:    movq %rdi, %rax
 ; X64-NEXT:    subq %rsi, %rax
 ; X64-NEXT:    subq %rdi, %rsi
-; X64-NEXT:    cmovlq %rsi, %rax
+; X64-NEXT:    cmovgeq %rsi, %rax
 ; X64-NEXT:    retq
   %sub = sub nsw i64 %a, %b
   %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
diff --git a/llvm/test/CodeGen/X86/abs.ll b/llvm/test/CodeGen/X86/abs.ll
index e252d5953e60e..0dc7d5136f425 100644
--- a/llvm/test/CodeGen/X86/abs.ll
+++ b/llvm/test/CodeGen/X86/abs.ll
@@ -661,9 +661,10 @@ define i32 @test_sextinreg_i32(i32 %a) nounwind {
 define i64 @test_sextinreg_i64(i64 %a) nounwind {
 ; X64-LABEL: test_sextinreg_i64:
 ; X64:       # %bb.0:
-; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    negl %eax
-; X64-NEXT:    cmovsl %edi, %eax
+; X64-NEXT:    movslq %edi, %rcx
+; X64-NEXT:    movq %rcx, %rax
+; X64-NEXT:    negq %rax
+; X64-NEXT:    cmovsq %rcx, %rax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: test_sextinreg_i64:
diff --git a/llvm/test/CodeGen/X86/freeze-unary.ll b/llvm/test/CodeGen/X86/freeze-unary.ll
index bc9e29957c74a..c7f61cbae78af 100644
--- a/llvm/test/CodeGen/X86/freeze-unary.ll
+++ b/llvm/test/CodeGen/X86/freeze-unary.ll
@@ -113,7 +113,10 @@ define <4 x i32> @freeze_abs_vec(<4 x i32> %a0) nounwind {
 define i32 @freeze_abs_undef(i32 %a0) nounwind {
 ; X86-LABEL: freeze_abs_undef:
 ; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    negl %ecx
+; X86-NEXT:    cmovsl %eax, %ecx
 ; X86-NEXT:    movl %ecx, %eax
 ; X86-NEXT:    negl %eax
 ; X86-NEXT:    cmovsl %ecx, %eax
@@ -121,9 +124,12 @@ define i32 @freeze_abs_undef(i32 %a0) nounwind {
 ;
 ; X64-LABEL: freeze_abs_undef:
 ; X64:       # %bb.0:
-; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    movl %edi, %ecx
+; X64-NEXT:    negl %ecx
+; X64-NEXT:    cmovsl %edi, %ecx
+; X64-NEXT:    movl %ecx, %eax
 ; X64-NEXT:    negl %eax
-; X64-NEXT:    cmovsl %edi, %eax
+; X64-NEXT:    cmovsl %ecx, %eax
 ; X64-NEXT:    retq
   %x = call i32 @llvm.abs.i32(i32 %a0, i1 -1)
   %f = freeze i32 %x
@@ -138,6 +144,10 @@ define <4 x i32> @freeze_abs_undef_vec(<4 x i32> %a0) nounwind {
 ; X86-NEXT:    psrad $31, %xmm1
 ; X86-NEXT:    pxor %xmm1, %xmm0
 ; X86-NEXT:    psubd %xmm1, %xmm0
+; X86-NEXT:    movdqa %xmm0, %xmm1
+; X86-NEXT:    psrad $31, %xmm1
+; X86-NEXT:    pxor %xmm1, %xmm0
+; X86-NEXT:    psubd %xmm1, %xmm0
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: freeze_abs_undef_vec:
diff --git a/llvm/test/CodeGen/X86/icmp-abs-C.ll b/llvm/test/CodeGen/X86/icmp-abs-C.ll
index 71893a9e4be67..3f47231831d80 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,17 @@ 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:    sarl $15, %ecx
+; X86-NEXT:    movswl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    movl %edx, %ecx
+; X86-NEXT:    shrl $15, %ecx
+; X86-NEXT:    movl %edx, %eax
 ; 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:    addl $64, %edx
 ; 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 +200,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..55744094caf5a 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)
@@ -198,7 +209,7 @@ define i1 @abs_ne_nonpow2(i16 %0) nounwind {
 ; X86:       # %bb.0:
 ; X86-NEXT:    movswl {{[0-9]+}}(%esp), %eax
 ; X86-NEXT:    movl %eax, %ecx
-; X86-NEXT:    sarl $15, %ecx
+; X86-NEXT:    shrl $15, %ecx
 ; X86-NEXT:    xorl %ecx, %eax
 ; X86-NEXT:    subl %ecx, %eax
 ; X86-NEXT:    movzwl %ax, %eax
diff --git a/llvm/test/CodeGen/X86/neg-abs.ll b/llvm/test/CodeGen/X86/neg-abs.ll
index 050610426e6bd..ac4e26738f566 100644
--- a/llvm/test/CodeGen/X86/neg-abs.ll
+++ b/llvm/test/CodeGen/X86/neg-abs.ll
@@ -36,7 +36,7 @@ define i16 @neg_abs_i16(i16 %x) nounwind {
 ; X86:       # %bb.0:
 ; X86-NEXT:    movswl {{[0-9]+}}(%esp), %ecx
 ; X86-NEXT:    movl %ecx, %eax
-; X86-NEXT:    sarl $15, %eax
+; X86-NEXT:    shrl $15, %eax
 ; X86-NEXT:    xorl %eax, %ecx
 ; X86-NEXT:    subl %ecx, %eax
 ; X86-NEXT:    # kill: def $ax killed $ax killed $eax
@@ -46,7 +46,7 @@ define i16 @neg_abs_i16(i16 %x) nounwind {
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    negw %ax
-; X64-NEXT:    cmovnsw %di, %ax
+; X64-NEXT:    cmovsw %di, %ax
 ; X64-NEXT:    retq
   %abs = tail call i16 @llvm.abs.i16(i16 %x, i1 true)
   %neg = sub nsw i16 0, %abs
@@ -67,7 +67,7 @@ define i32 @neg_abs_i32(i32 %x) nounwind {
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    negl %eax
-; X64-NEXT:    cmovnsl %edi, %eax
+; X64-NEXT:    cmovsl %edi, %eax
 ; X64-NEXT:    retq
   %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
   %neg = sub nsw i32 0, %abs
@@ -94,7 +94,7 @@ define i64 @neg_abs_i64(i64 %x) nounwind {
 ; X64:       # %bb.0:
 ; X64-NEXT:    movq %rdi, %rax
 ; X64-NEXT:    negq %rax
-; X64-NEXT:    cmovnsq %rdi, %rax
+; X64-NEXT:    cmovsq %rdi, %rax
 ; X64-NEXT:    retq
   %abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
   %neg = sub nsw i64 0, %abs



More information about the llvm-commits mailing list