diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1995,8 +1995,17 @@ Constant *C2; // C-(X+C2) --> (C-C2)-X - if (match(Op1, m_Add(m_Value(X), m_ImmConstant(C2)))) - return BinaryOperator::CreateSub(ConstantExpr::getSub(C, C2), X); + if (match(Op1, m_Add(m_Value(X), m_ImmConstant(C2)))) { + // C-C2 never overflow, and C-(X+C2), (X+C2) has NSW + // => (C-C2)-X can have NSW + bool WillNotSOV = willNotOverflowSignedSub(C, C2, I); + BinaryOperator *Res = + BinaryOperator::CreateSub(ConstantExpr::getSub(C, C2), X); + auto *OBO1 = cast(Op1); + Res->setHasNoSignedWrap(I.hasNoSignedWrap() && OBO1->hasNoSignedWrap() && + WillNotSOV); + return Res; + } } auto TryToNarrowDeduceFlags = [this, &I, &Op0, &Op1]() -> Instruction * { diff --git a/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll b/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll --- a/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll +++ b/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll @@ -134,7 +134,7 @@ define i8 @add_nsw_const_const_sub_nsw(i8 %arg) { ; CHECK-LABEL: @add_nsw_const_const_sub_nsw( -; CHECK-NEXT: [[T1:%.*]] = sub i8 -128, [[ARG:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sub nsw i8 -128, [[ARG:%.*]] ; CHECK-NEXT: ret i8 [[T1]] ; %t0 = add nsw i8 %arg, 1 @@ -193,14 +193,13 @@ ret i8 %t1 } - define <2 x i8> @non_splat_vec_add_nsw_const_const_sub_nsw_not_ov1(<2 x i8> %arg) { ; CHECK-LABEL: @non_splat_vec_add_nsw_const_const_sub_nsw_not_ov1( -; CHECK-NEXT: [[T1:%.*]] = sub <2 x i8> , [[ARG:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sub nsw <2 x i8> , [[ARG:%.*]] ; CHECK-NEXT: ret <2 x i8> [[T1]] ; - %t0 = add nsw <2 x i8> %arg, - %t1 = sub nsw <2 x i8> , %t0 + %t0 = add nsw <2 x i8> %arg, + %t1 = sub nsw <2 x i8> , %t0 ret <2 x i8> %t1 }