diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -779,6 +779,8 @@ return nullptr; case Intrinsic::abs: { Value *IIOperand = II->getArgOperand(0); + bool IntMinIsPoison = cast(II->getArgOperand(1))->isOneValue(); + // abs(-x) -> abs(x) // TODO: Copy nsw if it was present on the neg? Value *X; @@ -789,6 +791,19 @@ if (match(IIOperand, m_Select(m_Value(), m_Neg(m_Value(X)), m_Deferred(X)))) return replaceOperand(*II, 0, X); + if (Optional Imp = isImpliedByDomCondition( + ICmpInst::ICMP_SGE, IIOperand, + Constant::getNullValue(IIOperand->getType()), II, DL)) { + // abs(x) -> x if x >= 0 + if (*Imp) + return replaceInstUsesWith(*II, IIOperand); + + // abs(x) -> -x if x < 0 + if (IntMinIsPoison) + return BinaryOperator::CreateNSWNeg(IIOperand); + return BinaryOperator::CreateNeg(IIOperand); + } + break; } case Intrinsic::bswap: { diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll --- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll +++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll @@ -132,10 +132,9 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1 ; CHECK-NEXT: br i1 [[CMP]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: [[A1:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) -; CHECK-NEXT: ret i32 [[A1]] +; CHECK-NEXT: ret i32 [[X]] ; CHECK: false: -; CHECK-NEXT: [[A2:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) +; CHECK-NEXT: [[A2:%.*]] = sub i32 0, [[X]] ; CHECK-NEXT: ret i32 [[A2]] ; %cmp = icmp sge i32 %x, 0 @@ -155,10 +154,9 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1 ; CHECK-NEXT: br i1 [[CMP]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: [[A1:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 true) -; CHECK-NEXT: ret i32 [[A1]] +; CHECK-NEXT: ret i32 [[X]] ; CHECK: false: -; CHECK-NEXT: [[A2:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 true) +; CHECK-NEXT: [[A2:%.*]] = sub nsw i32 0, [[X]] ; CHECK-NEXT: ret i32 [[A2]] ; %cmp = icmp sge i32 %x, 0