Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -776,6 +776,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; @@ -786,6 +788,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: { Index: llvm/test/Transforms/InstCombine/abs-intrinsic.ll =================================================================== --- llvm/test/Transforms/InstCombine/abs-intrinsic.ll +++ 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