Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -705,15 +705,21 @@ "Unexpected isUnsigned predicate!"); // Account for swapped form of subtraction: ((a > b) ? b - a : 0). + // Checking for both a-b and a+(-b) as a constant. bool IsNegative = false; - if (match(TrueVal, m_Sub(m_Specific(B), m_Specific(A)))) + const APInt *C; + if (match(TrueVal, m_Sub(m_Specific(B), m_Specific(A))) || + (match(A, m_APInt(C)) && + match(TrueVal, m_Add(m_Specific(B), m_SpecificInt(-*C))))) IsNegative = true; - else if (!match(TrueVal, m_Sub(m_Specific(A), m_Specific(B)))) + else if (!match(TrueVal, m_Sub(m_Specific(A), m_Specific(B))) && + !(match(B, m_APInt(C)) && + match(TrueVal, m_Add(m_Specific(A), m_SpecificInt(-*C))))) return nullptr; // If sub is used anywhere else, we wouldn't be able to eliminate it // afterwards. - if (!TrueVal->hasOneUse()) + if (!TrueVal->hasOneUse() || !ICI->hasOneUse()) return nullptr; // (a > b) ? a - b : 0 -> usub.sat(a, b) Index: llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll =================================================================== --- llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll +++ llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll @@ -48,10 +48,8 @@ ; CHECK: define i64 @internal_pointer(i64 %sz) ; CHECK-NEXT: entry: -; CHECK-NEXT: %0 = add i64 %sz, -2 -; CHECK-NEXT: %1 = icmp ult i64 %sz, 2 -; CHECK-NEXT: %2 = select i1 %1, i64 0, i64 %0 -; CHECK-NEXT: ret i64 %2 +; CHECK-NEXT: %0 = call i64 @llvm.usub.sat.i64(i64 %sz, i64 2) +; CHECK-NEXT: ret i64 %0 ; CHECK-NEXT: } define i64 @uses_nullptr_no_fold() { Index: llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll +++ llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll @@ -145,10 +145,10 @@ define i64 @neg_max_sub_ugt_sel_swapped_extrause(i64 %a, i64 %b) { ; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause( ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) -; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[B]], [[A]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i64 0, i64 [[SUB]] ; CHECK-NEXT: call void @usei1(i1 [[CMP]]) -; CHECK-NEXT: ret i64 [[TMP2]] +; CHECK-NEXT: ret i64 [[SEL]] ; %cmp = icmp ugt i64 %b, %a %sub = sub i64 %b, %a @@ -177,10 +177,8 @@ define i32 @max_sub_ugt_c1(i32 %a) { ; CHECK-LABEL: @max_sub_ugt_c1( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 1 -; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -1 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1) +; CHECK-NEXT: ret i32 [[TMP1]] ; %cmp = icmp ugt i32 %a, 1 %sub = add i32 %a, -1 @@ -203,10 +201,8 @@ define i32 @max_sub_ugt_c10(i32 %a) { ; CHECK-LABEL: @max_sub_ugt_c10( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 10 -; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -10 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 10) +; CHECK-NEXT: ret i32 [[TMP1]] ; %cmp = icmp ugt i32 %a, 10 %sub = add i32 %a, -10 @@ -267,10 +263,9 @@ define i32 @max_sub_ult_c2(i32 %a) { ; CHECK-LABEL: @max_sub_ult_c2( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2 -; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[TMP2]] ; %cmp = icmp ult i32 %a, 2 %sub = add i32 %a, -2