if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
- // 0 - X -> 0 if the sub is NUW.
- if (isNUW && match(Op0, m_Zero()))
- return Op0;
+ // Is this a negation?
+ if (match(Op0, m_Zero())) {
+ // 0 - X -> 0 if the sub is NUW.
+ if (isNUW)
+ return Op0;
+
+ unsigned BitWidth = Op1->getType()->getScalarSizeInBits();
+ APInt KnownZero(BitWidth, 0);
+ APInt KnownOne(BitWidth, 0);
+ computeKnownBits(Op1, KnownZero, KnownOne, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
+ if (KnownZero == ~APInt::getSignBit(BitWidth)) {
+ // Op1 is either 0 or the minimum signed value. If the sub is NSW, then
+ // Op1 must be 0 because negating the minimum signed value is undefined.
+ if (isNSW)
+ return Op0;
+
+ // 0 - X -> X if X is 0 or the minimum signed value.
+ return Op1;
+ }
+ }
// (X + Y) - Z -> X + (Y - Z) or Y + (X - Z) if everything simplifies.
// For example, (X + Y) - Y -> X; (Y + X) - Y -> X
define i8 @negate_zero_or_minsigned_nsw(i8 %x) {
; CHECK-LABEL: @negate_zero_or_minsigned_nsw(
-; CHECK-NEXT: [[SIGNBIT:%.*]] = and i8 %x, -128
-; CHECK-NEXT: [[NEG:%.*]] = sub nsw i8 0, [[SIGNBIT]]
-; CHECK-NEXT: ret i8 [[NEG]]
+; CHECK-NEXT: ret i8 0
;
%signbit = and i8 %x, 128
%neg = sub nsw i8 0, %signbit
define <2 x i8> @negate_zero_or_minsigned_nsw_vec(<2 x i8> %x) {
; CHECK-LABEL: @negate_zero_or_minsigned_nsw_vec(
-; CHECK-NEXT: [[SIGNBIT:%.*]] = shl <2 x i8> %x, <i8 7, i8 7>
-; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i8> zeroinitializer, [[SIGNBIT]]
-; CHECK-NEXT: ret <2 x i8> [[NEG]]
+; CHECK-NEXT: ret <2 x i8> zeroinitializer
;
%signbit = shl <2 x i8> %x, <i8 7, i8 7>
%neg = sub nsw <2 x i8> zeroinitializer, %signbit
define i8 @negate_zero_or_minsigned(i8 %x) {
; CHECK-LABEL: @negate_zero_or_minsigned(
; CHECK-NEXT: [[SIGNBIT:%.*]] = shl i8 %x, 7
-; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[SIGNBIT]]
-; CHECK-NEXT: ret i8 [[NEG]]
+; CHECK-NEXT: ret i8 [[SIGNBIT]]
;
%signbit = shl i8 %x, 7
%neg = sub i8 0, %signbit
define <2 x i8> @negate_zero_or_minsigned_vec(<2 x i8> %x) {
; CHECK-LABEL: @negate_zero_or_minsigned_vec(
; CHECK-NEXT: [[SIGNBIT:%.*]] = and <2 x i8> %x, <i8 -128, i8 -128>
-; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[SIGNBIT]]
-; CHECK-NEXT: ret <2 x i8> [[NEG]]
+; CHECK-NEXT: ret <2 x i8> [[SIGNBIT]]
;
%signbit = and <2 x i8> %x, <i8 128, i8 128>
%neg = sub <2 x i8> zeroinitializer, %signbit