diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp index 53b34b03ca780..6e0b44c11f22a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp @@ -447,9 +447,11 @@ std::array Negator::getSortedOperandsOfBinOp(Instruction *I) { // `xor` is negatible if one of its operands is invertible. // FIXME: InstCombineInverter? But how to connect Inverter and Negator? if (auto *C = dyn_cast(Ops[1])) { - Value *Xor = Builder.CreateXor(Ops[0], ConstantExpr::getNot(C)); - return Builder.CreateAdd(Xor, ConstantInt::get(Xor->getType(), 1), - I->getName() + ".neg"); + if (IsTrulyNegation) { + Value *Xor = Builder.CreateXor(Ops[0], ConstantExpr::getNot(C)); + return Builder.CreateAdd(Xor, ConstantInt::get(Xor->getType(), 1), + I->getName() + ".neg"); + } } return nullptr; } diff --git a/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll b/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll index 7fbc78079c240..f44948e6a089f 100644 --- a/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll +++ b/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll @@ -106,9 +106,8 @@ define <2 x i1> @sub_XY_and_bit0_is_zero_fail(<2 x i8> %x, <2 x i8> %C) nounwind define i1 @sub_XY_xor_bit0_is_one_fail(i8 %x, i8 %C) nounwind { ; CHECK-LABEL: @sub_XY_xor_bit0_is_one_fail( -; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[C:%.*]], -2 -; CHECK-NEXT: [[C1_NEG:%.*]] = add i8 [[TMP1]], 1 -; CHECK-NEXT: [[Y:%.*]] = add i8 [[C1_NEG]], [[X:%.*]] +; CHECK-NEXT: [[C1:%.*]] = xor i8 [[C:%.*]], 1 +; CHECK-NEXT: [[Y:%.*]] = sub i8 [[X:%.*]], [[C1]] ; CHECK-NEXT: [[W:%.*]] = xor i8 [[Y]], [[X]] ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], 10 ; CHECK-NEXT: ret i1 [[R]] diff --git a/llvm/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll b/llvm/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll index 1e315696c3110..6f311f05fb017 100644 --- a/llvm/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll +++ b/llvm/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll @@ -22,6 +22,19 @@ define i32 @p0_scalar(i32 %x, i32 %y) { ret i32 %t1 } +define i8 @p0_scalar_not_truly_negatable(i8 %x, i8 %y) { +; CHECK-LABEL: @p0_scalar_not_truly_negatable( +; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 +; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 +; CHECK-NEXT: [[R:%.*]] = sub i8 [[XX]], [[YY]] +; CHECK-NEXT: ret i8 [[R]] +; + %xx = xor i8 %x, 123 + %yy = xor i8 %y, 45 + %r = sub i8 %xx, %yy + ret i8 %r +} + ;------------------------------------------------------------------------------; ; Vector tests ;------------------------------------------------------------------------------; @@ -79,28 +92,28 @@ define i32 @n4(i32 %x, i32 %y) { ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = xor i32 %x, -1 - %t1 = sub i32 %t0, %y ; swapped + %t1 = sub i32 %t0, %y ; swapped ret i32 %t1 } define i32 @n5_is_not_not(i32 %x, i32 %y) { ; CHECK-LABEL: @n5_is_not_not( -; CHECK-NEXT: [[T0_NEG:%.*]] = add i32 [[X:%.*]], -2147483647 -; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0_NEG]], [[Y:%.*]] +; CHECK-NEXT: [[T0:%.*]] = xor i32 [[X:%.*]], 2147483647 +; CHECK-NEXT: [[T1:%.*]] = sub i32 [[Y:%.*]], [[T0]] ; CHECK-NEXT: ret i32 [[T1]] ; - %t0 = xor i32 %x, 2147483647 ; not -1 + %t0 = xor i32 %x, 2147483647 ; not -1 %t1 = sub i32 %y, %t0 ret i32 %t1 } define <2 x i32> @n5_is_not_not_vec_splat(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @n5_is_not_not_vec_splat( -; CHECK-NEXT: [[T0_NEG:%.*]] = add <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = add <2 x i32> [[T0_NEG]], [[Y:%.*]] +; CHECK-NEXT: [[T0:%.*]] = xor <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[T1:%.*]] = sub <2 x i32> [[Y:%.*]], [[T0]] ; CHECK-NEXT: ret <2 x i32> [[T1]] ; - %t0 = xor <2 x i32> %x, ; signmask, but not -1 + %t0 = xor <2 x i32> %x, ; signmask, but not -1 %t1 = sub <2 x i32> %y, %t0 ret <2 x i32> %t1 }