return Y;
// X + ~X -> -1 since ~X = -X-1
+ Type *Ty = Op0->getType();
if (match(Op0, m_Not(m_Specific(Op1))) ||
match(Op1, m_Not(m_Specific(Op0))))
- return Constant::getAllOnesValue(Op0->getType());
+ return Constant::getAllOnesValue(Ty);
+
+ // add nsw/nuw (xor Y, signbit), signbit --> Y
+ // The no-wrapping add guarantees that the top bit will be set by the add.
+ // Therefore, the xor must be clearing the already set sign bit of Y.
+ Constant *SignBit =
+ ConstantInt::get(Ty, APInt::getSignBit(Ty->getScalarSizeInBits()));
+ if ((isNSW || isNUW) && match(Op1, m_Specific(SignBit)) &&
+ match(Op0, m_Xor(m_Value(Y), m_Specific(SignBit))))
+ return Y;
/// i1 add -> xor.
if (MaxRecurse && Op0->getType()->isIntegerTy(1))
ret i32 %V
}
-; Add of sign bit -> xor of sign bit.
+; This is an InstSimplify fold, but test it here to make sure that
+; InstCombine does not prevent the fold.
+; With NSW, add of sign bit -> or of sign bit.
define i32 @test20(i32 %x) {
; CHECK-LABEL: @test20(
define <2 x i32> @add_nsw_signbit(<2 x i32> %x) {
; CHECK-LABEL: @add_nsw_signbit(
-; CHECK-NEXT: [[Y:%.*]] = xor <2 x i32> %x, <i32 -2147483648, i32 -2147483648>
-; CHECK-NEXT: [[Z:%.*]] = add nsw <2 x i32> [[Y]], <i32 -2147483648, i32 -2147483648>
-; CHECK-NEXT: ret <2 x i32> [[Z]]
+; CHECK-NEXT: ret <2 x i32> %x
;
%y = xor <2 x i32> %x, <i32 -2147483648, i32 -2147483648>
%z = add nsw <2 x i32> %y, <i32 -2147483648, i32 -2147483648>
define <2 x i5> @add_nuw_signbit(<2 x i5> %x) {
; CHECK-LABEL: @add_nuw_signbit(
-; CHECK-NEXT: [[Y:%.*]] = xor <2 x i5> %x, <i5 -16, i5 -16>
-; CHECK-NEXT: [[Z:%.*]] = add nuw <2 x i5> [[Y]], <i5 -16, i5 -16>
-; CHECK-NEXT: ret <2 x i5> [[Z]]
+; CHECK-NEXT: ret <2 x i5> %x
;
%y = xor <2 x i5> %x, <i5 -16, i5 -16>
%z = add nuw <2 x i5> %y, <i5 -16, i5 -16>