[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