Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2058,8 +2058,18 @@ m_Select(m_Value(), m_Specific(Op1), m_Specific(&I))) || match(UI, m_Select(m_Value(), m_Specific(&I), m_Specific(Op1))); })) { - if (Value *NegOp1 = Negator::Negate(IsNegation, Op1, *this)) + if (Value *NegOp1 = Negator::Negate(IsNegation, Op1, *this)) { + auto *InstOp1 = dyn_cast(NegOp1); + if (InstOp1 && InstOp1->getOpcode() == Instruction::Sub && + isa(Op1) && IsNegation) { + auto *Op1Inst = cast(Op1); + if (I.hasNoUnsignedWrap() && Op1Inst->hasNoUnsignedWrap()) + InstOp1->setHasNoUnsignedWrap(); + if (I.hasNoSignedWrap() && Op1Inst->hasNoSignedWrap()) + InstOp1->setHasNoSignedWrap(); + } return BinaryOperator::CreateAdd(NegOp1, Op0); + } } if (IsNegation) return TryToNarrowDeduceFlags(); // Should have been handled in Negator! Index: llvm/test/Transforms/InstCombine/abs-intrinsic.ll =================================================================== --- llvm/test/Transforms/InstCombine/abs-intrinsic.ll +++ llvm/test/Transforms/InstCombine/abs-intrinsic.ll @@ -485,7 +485,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i32 [[Y]], [[X]] +; CHECK-NEXT: [[SUB_NEG:%.*]] = sub nsw i32 [[Y]], [[X]] ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: ; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ] @@ -512,7 +512,7 @@ ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i32 [[Y]], [[X]] +; CHECK-NEXT: [[SUB_NEG:%.*]] = sub nsw i32 [[Y]], [[X]] ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: ; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ] @@ -565,7 +565,7 @@ ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i8 [[Y]], [[X]] +; CHECK-NEXT: [[SUB_NEG:%.*]] = sub nsw i8 [[Y]], [[X]] ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: ; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ] Index: llvm/test/Transforms/InstCombine/nsw.ll =================================================================== --- llvm/test/Transforms/InstCombine/nsw.ll +++ llvm/test/Transforms/InstCombine/nsw.ll @@ -145,7 +145,7 @@ define i32 @neg_sub0_sub_nsw_nsw(i32 %a, i32 %b) { ; CHECK-LABEL: @neg_sub0_sub_nsw_nsw( -; CHECK-NEXT: [[C_NEG:%.*]] = sub i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[C_NEG:%.*]] = sub nsw i32 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: ret i32 [[C_NEG]] ; %c = sub nsw i32 %a, %b @@ -181,7 +181,7 @@ define i32 @neg_mul_sub_nsw_nsw(i32 %a, i32 %b) { ; CHECK-LABEL: @neg_mul_sub_nsw_nsw( -; CHECK-NEXT: [[C_NEG:%.*]] = sub i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[C_NEG:%.*]] = sub nsw i32 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: ret i32 [[C_NEG]] ; %c = sub nsw i32 %a, %b