return new ZExtInst(IsZero, Ty);
}
+ // (-(X & 1)) & Y --> (X & 1) == 0 ? 0 : Y
+ Value *Neg;
+ if (match(&I,
+ m_c_And(m_CombineAnd(m_Value(Neg),
+ m_OneUse(m_Neg(m_And(m_Value(), m_One())))),
+ m_Value(Y)))) {
+ Value *Cmp = Builder.CreateIsNull(Neg);
+ return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
+ }
+
const APInt *C;
if (match(Op1, m_APInt(C))) {
const APInt *XorC;
define i8 @negate_lowbitmask(i8 %x, i8 %y) {
; CHECK-LABEL: @negate_lowbitmask(
; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 1
-; CHECK-NEXT: [[N:%.*]] = sub nsw i8 0, [[A]]
-; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%a = and i8 %x, 1
; CHECK-LABEL: @negate_lowbitmask_commute(
; CHECK-NEXT: [[Y:%.*]] = mul <2 x i5> [[P:%.*]], [[P]]
; CHECK-NEXT: [[A:%.*]] = and <2 x i5> [[X:%.*]], <i5 1, i5 poison>
-; CHECK-NEXT: [[N:%.*]] = sub <2 x i5> <i5 poison, i5 0>, [[A]]
-; CHECK-NEXT: [[R:%.*]] = and <2 x i5> [[Y]], [[N]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i5> [[A]], <i5 poison, i5 0>
+; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP1]], <2 x i5> zeroinitializer, <2 x i5> [[Y]]
; CHECK-NEXT: ret <2 x i5> [[R]]
;
%y = mul <2 x i5> %p, %p ; thwart complexity-based canonicalization
; CHECK-LABEL: @negate_lowbitmask_use1(
; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 1
; CHECK-NEXT: call void @use8(i8 [[A]])
-; CHECK-NEXT: [[N:%.*]] = sub nsw i8 0, [[A]]
-; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%a = and i8 %x, 1
ret i8 %r
}
+; negative test
+
define i8 @negate_lowbitmask_use2(i8 %x, i8 %y) {
; CHECK-LABEL: @negate_lowbitmask_use2(
; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 1