Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1425,6 +1425,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.CreateIntrinsic(Intrinsic::umax, {I.getType()}, {A, B})); + } + 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,8 @@ 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:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 [[B:%.*]]) +; CHECK-NEXT: ret i8 [[TMP1]] ; %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) %res = add i8 %sat, %b @@ -1068,9 +1067,8 @@ 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:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 [[B:%.*]]) +; CHECK-NEXT: ret i8 [[TMP1]] ; %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) %res = add i8 %b, %sat @@ -1090,9 +1088,8 @@ 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:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 42) +; CHECK-NEXT: ret i8 [[TMP1]] ; %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 42) %res = add i8 %sat, 42 @@ -1159,8 +1156,8 @@ define i1 @scalar_uadd_eq_zero(i8 %a, i8 %b) { ; CHECK-LABEL: @scalar_uadd_eq_zero( ; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: ret i1 [[TMP2]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[CMP]] ; %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) %cmp = icmp eq i8 %sat, 0 @@ -1170,8 +1167,8 @@ define i1 @scalar_uadd_ne_zero(i8 %a, i8 %b) { ; CHECK-LABEL: @scalar_uadd_ne_zero( ; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0 -; CHECK-NEXT: ret i1 [[TMP2]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[CMP]] ; %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) %cmp = icmp ne i8 %sat, 0