Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1995,8 +1995,16 @@ 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, C-(X+C2), (X+C2) never overflow=> (C-C2)-X never overflow + bool HasNSW = willNotOverflowSignedSub(C, C2, I); + BinaryOperator *Res = BinaryOperator::CreateSub( + ConstantExpr::getSub(C, C2, /*HasNUW=*/false, HasNSW), X); + auto *OBO1 = cast(Op1); + if (I.hasNoSignedWrap() && OBO1->hasNoSignedWrap() && HasNSW) + Res->setHasNoSignedWrap(true); + return Res; + } } auto TryToNarrowDeduceFlags = [this, &I, &Op0, &Op1]() -> Instruction * { Index: llvm/test/Transforms/InstCombine/addsub-constant-folding.ll =================================================================== --- llvm/test/Transforms/InstCombine/addsub-constant-folding.ll +++ llvm/test/Transforms/InstCombine/addsub-constant-folding.ll @@ -637,3 +637,13 @@ %r = add i8 %sub, %y ret i8 %r } + +define i8 @add_sub_nsw(i8 %x, i8 %y) { +; CHECK-LABEL: @add_sub_nsw( +; CHECK-NEXT: [[B:%.*]] = sub nsw i8 -11, [[X:%.*]] +; CHECK-NEXT: ret i8 [[B]] +; + %a = add nsw i8 %x, 12; a = x + 12 + %b = sub nsw i8 1, %a; b = 0 - a = (12 - 1 - x) + ret i8 %b +}