diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6472,6 +6472,22 @@ if (Instruction *Res = foldReductionIdiom(I, Builder, DL)) return Res; + { + Value *A, *B; + const APInt *C, *D; + // Find hidden xor optimization (only works if `and C, D` equals `0`) + // (icmp (and (select A, C, D), (select B, C, D)), 0) --> (xor A, B) + if (I.getPredicate() == ICmpInst::ICMP_EQ && match(Op0, + m_OneUse(m_c_And( + m_OneUse(m_Select(m_Value(A), m_APInt(C), m_APInt(D))), + m_OneUse(m_Select(m_Value(B), m_APInt(C), m_APInt(D))) + )) + ) && match(Op1, m_Zero())) { + if ((*C & *D) == 0) + return BinaryOperator::CreateXor(A, B); + } + } + return Changed ? &I : nullptr; }