diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index e80d6a9ee39..ed0e1c90888 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1462,11 +1462,17 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { if (Value *V = SimplifyUsingDistributiveLaws(I)) return ReplaceInstUsesWith(I, V); - // If this is a 'B = x-(-A)', change to B = x+A. This preserves NSW/NUW. + // If this is a 'B = x-(-A)', change to B = x+A. if (Value *V = dyn_castNegVal(Op1)) { BinaryOperator *Res = BinaryOperator::CreateAdd(Op0, V); - Res->setHasNoSignedWrap(I.hasNoSignedWrap()); - Res->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + + if (const auto *BO = dyn_cast(Op1)) { + assert(BO->getOpcode() == Instruction::Sub && + "Expected a subtraction operator!"); + if (BO->hasNoSignedWrap() && I.hasNoSignedWrap()) + Res->setHasNoSignedWrap(true); + } + return Res; } diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 67b7c4996b0..114aff7efb8 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -464,3 +464,12 @@ define i32 @test38(i32 %A) { ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[ICMP]] to i32 ; CHECK-NEXT: ret i32 [[SEXT]] } + +define i32 @test39(i32 %A, i32 %x) { + %B = sub i32 0, %A + %C = sub nsw i32 %x, %B + ret i32 %C +; CHECK-LABEL: @test39( +; CHECK: %C = add i32 %x, %A +; CHECK: ret i32 %C +}