Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -5255,6 +5255,16 @@ Type *ReturnType = F->getReturnType(); unsigned BitWidth = ReturnType->getScalarSizeInBits(); switch (IID) { + case Intrinsic::abs: { + // abs(abs(x)) -> abs(x). We don't need to worry about the nsw arg here. + // It is always ok to pick the earlier abs. We'll just lose nsw if its only + // on the outer abs. + if (auto *II = dyn_cast(Op0)) + if (II->getIntrinsicID() == IID) + return II; + + break; + } case Intrinsic::smax: case Intrinsic::smin: case Intrinsic::umax: Index: llvm/test/Transforms/InstSimplify/call.ll =================================================================== --- llvm/test/Transforms/InstSimplify/call.ll +++ llvm/test/Transforms/InstSimplify/call.ll @@ -2,6 +2,48 @@ ; RUN: opt < %s -instsimplify -S | FileCheck %s ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s +declare i32 @llvm.abs.i32(i32, i1) + +define i32 @test_abs_abs_0(i32 %x) { +; CHECK-LABEL: @test_abs_abs_0( +; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false) +; CHECK-NEXT: ret i32 [[A]] +; + %a = call i32 @llvm.abs.i32(i32 %x, i1 false) + %b = call i32 @llvm.abs.i32(i32 %a, i1 false) + ret i32 %b +} + +define i32 @test_abs_abs_1(i32 %x) { +; CHECK-LABEL: @test_abs_abs_1( +; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) +; CHECK-NEXT: ret i32 [[A]] +; + %a = call i32 @llvm.abs.i32(i32 %x, i1 true) + %b = call i32 @llvm.abs.i32(i32 %a, i1 false) + ret i32 %b +} + +define i32 @test_abs_abs_2(i32 %x) { +; CHECK-LABEL: @test_abs_abs_2( +; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false) +; CHECK-NEXT: ret i32 [[A]] +; + %a = call i32 @llvm.abs.i32(i32 %x, i1 false) + %b = call i32 @llvm.abs.i32(i32 %a, i1 true) + ret i32 %b +} + +define i32 @test_abs_abs_3(i32 %x) { +; CHECK-LABEL: @test_abs_abs_3( +; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) +; CHECK-NEXT: ret i32 [[A]] +; + %a = call i32 @llvm.abs.i32(i32 %x, i1 true) + %b = call i32 @llvm.abs.i32(i32 %a, i1 true) + ret i32 %b +} + declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) declare {i8, i1} @llvm.sadd.with.overflow.i8(i8 %a, i8 %b) declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b)