return BinaryOperator::CreateAnd(A, NewMask);
}
+ // ZExt (B - A) + ZExt(A) --> ZExt(B)
+ if ((match(RHS, m_ZExt(m_Value(A))) &&
+ match(LHS, m_ZExt(m_NUWSub(m_Value(B), m_Specific(A))))) ||
+ (match(LHS, m_ZExt(m_Value(A))) &&
+ match(RHS, m_ZExt(m_NUWSub(m_Value(B), m_Specific(A))))))
+ return new ZExtInst(B, LHS->getType());
+
// A+B --> A|B iff A and B have no bits set in common.
if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT))
return BinaryOperator::CreateOr(LHS, RHS);
define i16 @add_sub_zext(i8 %x, i8 %y) {
; CHECK-LABEL: @add_sub_zext(
-; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i8 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i16
-; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[X]] to i16
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i16 [[TMP2]], [[TMP3]]
-; CHECK-NEXT: ret i16 [[TMP4]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[Y:%.*]] to i16
+; CHECK-NEXT: ret i16 [[TMP1]]
;
%1 = sub nuw i8 %y, %x
%2 = zext i8 %1 to i16
define i16 @add_commute_sub_zext(i8 %x, i8 %y) {
; CHECK-LABEL: @add_commute_sub_zext(
-; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i8 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i16
-; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[X]] to i16
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i16 [[TMP3]], [[TMP2]]
-; CHECK-NEXT: ret i16 [[TMP4]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[Y:%.*]] to i16
+; CHECK-NEXT: ret i16 [[TMP1]]
;
%1 = sub nuw i8 %y, %x
%2 = zext i8 %1 to i16
define <2 x i8> @add_sub_2xi5_zext(<2 x i5> %x, <2 x i5> %y) {
; CHECK-LABEL: @add_sub_2xi5_zext(
-; CHECK-NEXT: [[TMP1:%.*]] = sub nuw <2 x i5> [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i5> [[TMP1]] to <2 x i8>
-; CHECK-NEXT: [[TMP3:%.*]] = zext <2 x i5> [[X]] to <2 x i8>
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw <2 x i8> [[TMP3]], [[TMP2]]
-; CHECK-NEXT: ret <2 x i8> [[TMP4]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i5> [[Y:%.*]] to <2 x i8>
+; CHECK-NEXT: ret <2 x i8> [[TMP1]]
;
%1 = sub nuw <2 x i5> %y, %x
%2 = zext <2 x i5> %1 to <2 x i8>
define i3 @add_commute_sub_i2_zext_i3(i2 %x, i2 %y) {
; CHECK-LABEL: @add_commute_sub_i2_zext_i3(
-; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i2 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = zext i2 [[TMP1]] to i3
-; CHECK-NEXT: [[TMP3:%.*]] = zext i2 [[X]] to i3
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw i3 [[TMP3]], [[TMP2]]
-; CHECK-NEXT: ret i3 [[TMP4]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i2 [[Y:%.*]] to i3
+; CHECK-NEXT: ret i3 [[TMP1]]
;
%1 = sub nuw i2 %y, %x
%2 = zext i2 %1 to i3
; CHECK-LABEL: @add_sub_use_zext(
; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i8 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: call void @use(i8 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i16
-; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[X]] to i16
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i16 [[TMP2]], [[TMP3]]
-; CHECK-NEXT: ret i16 [[TMP4]]
+; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[Y]] to i16
+; CHECK-NEXT: ret i16 [[TMP2]]
;
%1 = sub nuw i8 %y, %x
call void @use(i8 %1)
define i16 @add_sub_zext_constant(i8 %x) {
; CHECK-LABEL: @add_sub_zext_constant(
-; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i8 -2, [[X:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i16
-; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[X]] to i16
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i16 [[TMP2]], [[TMP3]]
-; CHECK-NEXT: ret i16 [[TMP4]]
+; CHECK-NEXT: ret i16 254
;
%1 = sub nuw i8 254, %x
%2 = zext i8 %1 to i16