return new ZExtInst(Builder.CreateNUWAdd(X, NewC), Ty);
}
+ // Shifts and add used to flip and mask off the low bit:
+ // add (ashr (shl i32 X, 31), 31), 1 --> and (not X), 1
+ const APInt *C3;
+ if (*C == 1 && match(Op0, m_OneUse(m_AShr(m_Shl(m_Value(X), m_APInt(C2)),
+ m_APInt(C3)))) &&
+ C2 == C3 && *C2 == Ty->getScalarSizeInBits() - 1) {
+ Value *NotX = Builder.CreateNot(X);
+ return BinaryOperator::CreateAnd(NotX, ConstantInt::get(Ty, 1));
+ }
+
return nullptr;
}
define i32 @flip_and_mask(i32 %x) {
; CHECK-LABEL: @flip_and_mask(
-; CHECK-NEXT: [[SHL:%.*]] = shl i32 %x, 31
-; CHECK-NEXT: [[SHR:%.*]] = ashr exact i32 [[SHL]], 31
-; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[SHR]], 1
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 %x, 1
+; CHECK-NEXT: [[INC:%.*]] = xor i32 [[TMP1]], 1
; CHECK-NEXT: ret i32 [[INC]]
;
%shl = shl i32 %x, 31
define <2 x i8> @flip_and_mask_splat(<2 x i8> %x) {
; CHECK-LABEL: @flip_and_mask_splat(
-; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i8> %x, <i8 7, i8 7>
-; CHECK-NEXT: [[SHR:%.*]] = ashr exact <2 x i8> [[SHL]], <i8 7, i8 7>
-; CHECK-NEXT: [[INC:%.*]] = add nsw <2 x i8> [[SHR]], <i8 1, i8 1>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> %x, <i8 1, i8 1>
+; CHECK-NEXT: [[INC:%.*]] = and <2 x i8> [[TMP1]], <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[INC]]
;
%shl = shl <2 x i8> %x, <i8 7, i8 7>