Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1302,6 +1302,14 @@ if (Instruction *SatAdd = foldToUnsignedSaturatedAdd(I)) return SatAdd; + // usub.sat(A, B) + A => umax(A, B) + if (match(&I, m_c_BinOp( + m_OneUse(m_Intrinsic(m_Value(A), m_Value(B))), + m_Deferred(B)))) { + return replaceInstUsesWith(I, + Builder.CreateSelect(Builder.CreateICmpULT(A, B), B, A)); + } + return Changed ? &I : nullptr; } Index: llvm/test/Transforms/InstCombine/saturating-add-sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/saturating-add-sub.ll +++ llvm/test/Transforms/InstCombine/saturating-add-sub.ll @@ -1044,9 +1044,9 @@ define i8 @test_scalar_usub_add(i8 %a, i8 %b) { ; CHECK-LABEL: @test_scalar_usub_add( -; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) -; CHECK-NEXT: [[RES:%.*]] = add i8 [[SAT]], [[B]] -; CHECK-NEXT: ret i8 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[B]], i8 [[A]] +; CHECK-NEXT: ret i8 [[TMP2]] ; %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) %res = add i8 %sat, %b @@ -1068,9 +1068,9 @@ define i8 @test_scalar_usub_add_commuted(i8 %a, i8 %b) { ; CHECK-LABEL: @test_scalar_usub_add_commuted( -; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) -; CHECK-NEXT: [[RES:%.*]] = add i8 [[SAT]], [[B]] -; CHECK-NEXT: ret i8 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[B]], i8 [[A]] +; CHECK-NEXT: ret i8 [[TMP2]] ; %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) %res = add i8 %b, %sat @@ -1090,9 +1090,9 @@ define i8 @test_scalar_usub_add_const(i8 %a) { ; CHECK-LABEL: @test_scalar_usub_add_const( -; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 42) -; CHECK-NEXT: [[RES:%.*]] = add nuw i8 [[SAT]], 42 -; CHECK-NEXT: ret i8 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[A:%.*]], 42 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[A]], i8 42 +; CHECK-NEXT: ret i8 [[TMP2]] ; %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 42) %res = add i8 %sat, 42