diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2198,6 +2198,7 @@ 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(); @@ -2262,6 +2263,14 @@ 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) diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -1564,14 +1564,8 @@ 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]], -; 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]], -; 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 diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -458,11 +458,7 @@ 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 @@ -476,11 +472,7 @@ 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 @@ -494,11 +486,7 @@ 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