return ::simplifyAndInst(Op0, Op1, Q, RecursionLimit);
}
+// TODO: Many of these folds could use LogicalAnd/LogicalOr.
static Value *simplifyOrLogic(Value *X, Value *Y) {
assert(X->getType() == Y->getType() && "Expected same type for 'or' ops");
Type *Ty = X->getType();
m_Value(B))) &&
match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
return NotA;
+ // The same is true of Logical And
+ // TODO: This could share the logic of the version above if there was a
+ // version of LogicalAnd that allowed more than just i1 types.
+ if (match(X, m_c_LogicalAnd(
+ m_CombineAnd(m_Value(NotA), m_NotForbidUndef(m_Value(A))),
+ m_Value(B))) &&
+ match(Y, m_Not(m_c_LogicalOr(m_Specific(A), m_Specific(B)))))
+ return NotA;
// ~(A ^ B) | (A & B) --> ~(A ^ B)
// ~(A ^ B) | (B & A) --> ~(A ^ B)
define <4 x i1> @and_or_not_or_logical_vec(<4 x i32> %ap, <4 x i32> %bp) {
; CHECK-LABEL: @and_or_not_or_logical_vec(
-; CHECK-NEXT: [[A:%.*]] = icmp eq <4 x i32> [[AP:%.*]], zeroinitializer
-; CHECK-NEXT: [[B:%.*]] = icmp eq <4 x i32> [[BP:%.*]], zeroinitializer
-; CHECK-NEXT: [[V:%.*]] = xor <4 x i1> [[A]], <i1 true, i1 true, i1 true, i1 true>
-; CHECK-NEXT: [[X:%.*]] = select <4 x i1> [[B]], <4 x i1> [[V]], <4 x i1> zeroinitializer
-; CHECK-NEXT: [[W:%.*]] = or <4 x i1> [[B]], [[A]]
-; CHECK-NEXT: [[Y:%.*]] = xor <4 x i1> [[W]], <i1 true, i1 true, i1 true, i1 true>
-; CHECK-NEXT: [[Z:%.*]] = or <4 x i1> [[X]], [[Y]]
-; CHECK-NEXT: ret <4 x i1> [[Z]]
+; CHECK-NEXT: [[A:%.*]] = icmp ne <4 x i32> [[AP:%.*]], zeroinitializer
+; CHECK-NEXT: ret <4 x i1> [[A]]
;
%A = icmp eq <4 x i32> %ap, zeroinitializer
%B = icmp eq <4 x i32> %bp, zeroinitializer
define i1 @and_or_not_or_logical(i1 %A, i1 %B) {
; CHECK-LABEL: @and_or_not_or_logical(
; CHECK-NEXT: [[V:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT: [[X:%.*]] = select i1 [[V]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT: [[W:%.*]] = or i1 [[B]], [[A]]
-; CHECK-NEXT: [[Y:%.*]] = xor i1 [[W]], true
-; CHECK-NEXT: [[Z:%.*]] = or i1 [[X]], [[Y]]
-; CHECK-NEXT: ret i1 [[Z]]
+; CHECK-NEXT: ret i1 [[V]]
;
%V = xor i1 %A, true
%X = select i1 %V, i1 %B, i1 false
define i1 @and_or_not_or_logical_rev(i1 %A, i1 %B) {
; CHECK-LABEL: @and_or_not_or_logical_rev(
; CHECK-NEXT: [[V:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT: [[X:%.*]] = select i1 [[B:%.*]], i1 [[V]], i1 false
-; CHECK-NEXT: [[W:%.*]] = or i1 [[B]], [[A]]
-; CHECK-NEXT: [[Y:%.*]] = xor i1 [[W]], true
-; CHECK-NEXT: [[Z:%.*]] = or i1 [[X]], [[Y]]
-; CHECK-NEXT: ret i1 [[Z]]
+; CHECK-NEXT: ret i1 [[V]]
;
%V = xor i1 %A, true
%X = select i1 %B, i1 %V, i1 false
define i1 @and_or_not_logical_or_logical_rev(i1 %A, i1 %B) {
; CHECK-LABEL: @and_or_not_logical_or_logical_rev(
; CHECK-NEXT: [[V:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT: [[X:%.*]] = select i1 [[B:%.*]], i1 [[V]], i1 false
-; CHECK-NEXT: [[W:%.*]] = select i1 [[B]], i1 true, i1 [[A]]
-; CHECK-NEXT: [[Y:%.*]] = xor i1 [[W]], true
-; CHECK-NEXT: [[Z:%.*]] = or i1 [[X]], [[Y]]
-; CHECK-NEXT: ret i1 [[Z]]
+; CHECK-NEXT: ret i1 [[V]]
;
%V = xor i1 %A, true
%X = select i1 %B, i1 %V, i1 false