Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1577,6 +1577,12 @@ if (match(Op1, m_OneUse(m_Add(m_Value(X), m_One())))) return BinaryOperator::CreateAdd(Builder.CreateNot(X), Op0); + // Y - ~X == X + Y + 1 + if (match(Op1, m_OneUse(m_Not(m_Value(X))))) { + return BinaryOperator::CreateAdd(Builder.CreateAdd(Op0, X), + ConstantInt::get(I.getType(), 1)); + } + if (Constant *C = dyn_cast(Op0)) { bool IsNegate = match(C, m_ZeroInt()); Value *X; Index: test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll =================================================================== --- test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll +++ test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll @@ -12,8 +12,8 @@ define i32 @p0_scalar(i32 %x, i32 %y) { ; CHECK-LABEL: @p0_scalar( -; CHECK-NEXT: [[T0:%.*]] = xor i32 [[X:%.*]], -1 -; CHECK-NEXT: [[T1:%.*]] = sub i32 [[Y:%.*]], [[T0]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[T1:%.*]] = add i32 [[TMP1]], 1 ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = xor i32 %x, -1 @@ -27,8 +27,8 @@ define <4 x i32> @p1_vector_splat(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @p1_vector_splat( -; CHECK-NEXT: [[T0:%.*]] = xor <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> [[Y:%.*]], [[T0]] +; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[TMP1]], ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = xor <4 x i32> %x, @@ -38,8 +38,8 @@ define <4 x i32> @p2_vector_undef(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @p2_vector_undef( -; CHECK-NEXT: [[T0:%.*]] = xor <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> [[Y:%.*]], [[T0]] +; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[TMP1]], ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = xor <4 x i32> %x, Index: test/Transforms/InstCombine/sub-minmax.ll =================================================================== --- test/Transforms/InstCombine/sub-minmax.ll +++ test/Transforms/InstCombine/sub-minmax.ll @@ -128,7 +128,8 @@ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32 ; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 -; CHECK-NEXT: [[X:%.*]] = sub i32 [[A]], [[TMP2]] +; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[L1]], [[A]] +; CHECK-NEXT: [[X:%.*]] = add i32 [[TMP3]], 1 ; CHECK-NEXT: call void @use32(i32 [[L1]]) ; CHECK-NEXT: ret i32 [[X]] ; @@ -301,7 +302,8 @@ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]] ; CHECK-NEXT: [[MINXY:%.*]] = xor i8 [[TMP2]], -1 -; CHECK-NEXT: [[SUBX:%.*]] = sub i8 [[X]], [[TMP2]] +; CHECK-NEXT: [[TMP3:%.*]] = add i8 [[MINXY]], [[X]] +; CHECK-NEXT: [[SUBX:%.*]] = add i8 [[TMP3]], 1 ; CHECK-NEXT: [[SUBY:%.*]] = sub i8 [[Y]], [[TMP2]] ; CHECK-NEXT: call void @use8(i8 [[SUBX]]) ; CHECK-NEXT: call void @use8(i8 [[SUBY]])