}
// and(x, add (x, -1)) is a common idiom that always clears the low bit;
+ // xor/or(x, add (x, -1)) is an idiom that will always set the low bit.
// here we handle the more general case of adding any odd number by
- // matching the form and(x, add(x, y)) where y is odd.
+ // matching the form and/xor/or(x, add(x, y)) where y is odd.
// TODO: This could be generalized to clearing any bit set in y where the
// following bit is known to be unset in y.
- if (IsAnd && !KnownOut.Zero[0] && !KnownOut.One[0] &&
- match(I, m_c_BinOp(m_Value(X), m_c_Add(m_Deferred(X), m_Value(Y))))) {
+ if (!KnownOut.Zero[0] && !KnownOut.One[0] &&
+ (match(I, m_c_BinOp(m_Value(X), m_c_Add(m_Deferred(X), m_Value(Y)))) ||
+ match(I, m_c_BinOp(m_Value(X), m_Sub(m_Deferred(X), m_Value(Y)))) ||
+ match(I, m_c_BinOp(m_Value(X), m_Sub(m_Value(Y), m_Deferred(X)))))) {
KnownBits KnownY(BitWidth);
computeKnownBits(Y, DemandedElts, KnownY, Depth + 1, Q);
- if (KnownY.countMinTrailingOnes() > 0)
- KnownOut.Zero.setBit(0);
+ if (KnownY.countMinTrailingOnes() > 0) {
+ if (IsAnd)
+ KnownOut.Zero.setBit(0);
+ else
+ KnownOut.One.setBit(0);
+ }
}
return KnownOut;
}
define <2 x i1> @sub_XY_and_bit0_is_zero(<2 x i8> %x, <2 x i8> %C) nounwind {
; CHECK-LABEL: @sub_XY_and_bit0_is_zero(
-; CHECK-NEXT: [[C1:%.*]] = or <2 x i8> [[C:%.*]], <i8 9, i8 9>
-; CHECK-NEXT: [[Y:%.*]] = sub <2 x i8> [[X:%.*]], [[C1]]
-; CHECK-NEXT: [[W:%.*]] = and <2 x i8> [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[W]], <i8 -1, i8 -1>
-; CHECK-NEXT: ret <2 x i1> [[R]]
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%C1 = or <2 x i8> %C, <i8 9, i8 9>
%y = sub <2 x i8> %x, %C1
define i1 @sub_XY_xor_bit0_is_one(i8 %x, i8 %C) nounwind {
; CHECK-LABEL: @sub_XY_xor_bit0_is_one(
-; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1
-; CHECK-NEXT: [[Y:%.*]] = sub i8 [[X:%.*]], [[C1]]
-; CHECK-NEXT: [[W:%.*]] = xor i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], 10
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%C1 = or i8 %C, 1
%y = sub i8 %x, %C1
define i1 @sub_XY_or_bit0_is_one(i8 %x, i8 %C) nounwind {
; CHECK-LABEL: @sub_XY_or_bit0_is_one(
-; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1
-; CHECK-NEXT: [[Y:%.*]] = sub i8 [[X:%.*]], [[C1]]
-; CHECK-NEXT: [[W:%.*]] = or i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], 10
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%C1 = or i8 %C, 1
%y = sub i8 %x, %C1
define i1 @sub_YX_and_bit0_is_zero(i8 %x, i8 %C) nounwind {
; CHECK-LABEL: @sub_YX_and_bit0_is_zero(
-; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1
-; CHECK-NEXT: [[Y:%.*]] = sub i8 [[C1]], [[X:%.*]]
-; CHECK-NEXT: [[W:%.*]] = and i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], -1
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%C1 = or i8 %C, 1
%y = sub i8 %C1, %x
define <2 x i1> @sub_YX_xor_bit0_is_one(<2 x i8> %x, <2 x i8> %C) nounwind {
; CHECK-LABEL: @sub_YX_xor_bit0_is_one(
-; CHECK-NEXT: [[C1:%.*]] = or <2 x i8> [[C:%.*]], <i8 1, i8 1>
-; CHECK-NEXT: [[Y:%.*]] = sub <2 x i8> [[C1]], [[X:%.*]]
-; CHECK-NEXT: [[W:%.*]] = xor <2 x i8> [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[W]], <i8 12, i8 12>
-; CHECK-NEXT: ret <2 x i1> [[R]]
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%C1 = or <2 x i8> %C, <i8 1, i8 1>
%y = sub <2 x i8> %C1, %x
define i1 @sub_YX_or_bit0_is_one(i8 %x, i8 %C) nounwind {
; CHECK-LABEL: @sub_YX_or_bit0_is_one(
-; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1
-; CHECK-NEXT: [[Y:%.*]] = sub i8 [[C1]], [[X:%.*]]
-; CHECK-NEXT: [[W:%.*]] = or i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], 32
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%C1 = or i8 %C, 1
%y = sub i8 %C1, %x
define i1 @add_YX_xor_bit0_is_one(i8 %x, i8 %C) nounwind {
; CHECK-LABEL: @add_YX_xor_bit0_is_one(
-; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1
-; CHECK-NEXT: [[Y:%.*]] = add i8 [[C1]], [[X:%.*]]
-; CHECK-NEXT: [[W:%.*]] = xor i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], 32
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%C1 = or i8 %C, 1
%y = add i8 %C1, %x
define <2 x i1> @add_XY_or_bit0_is_one(<2 x i8> %x, <2 x i8> %C) nounwind {
; CHECK-LABEL: @add_XY_or_bit0_is_one(
-; CHECK-NEXT: [[C1:%.*]] = or <2 x i8> [[C:%.*]], <i8 1, i8 1>
-; CHECK-NEXT: [[Y:%.*]] = add <2 x i8> [[C1]], [[X:%.*]]
-; CHECK-NEXT: [[W:%.*]] = or <2 x i8> [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[W]], <i8 90, i8 90>
-; CHECK-NEXT: ret <2 x i1> [[R]]
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%C1 = or <2 x i8> %C, <i8 1, i8 1>
%y = add <2 x i8> %C1, %x