diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -56,6 +56,29 @@ /// /// FIXME: It's possible to create more instructions than previously existed. static bool cheapToScalarize(Value *V, Value *EI) { + // Pattern: or(and(a, mask), and(b, ~mask)) can be efficiently folded to + // bitselect instructions where ~mask = xor mask, -1 + if (isa(V)) { + Instruction *TI = cast(V); + if (TI->getOpcode() == Instruction::Or) { + Value *LHS = TI->getOperand(0); + Value *RHS = TI->getOperand(1); + Value *MaskValue = nullptr; + Value *MaskConst = nullptr; + + if (match(LHS, m_And(m_Value(), m_Value(MaskValue))) && + match(RHS, m_And(m_Value(), + m_Xor(m_Specific(MaskValue), m_Value(MaskConst))))) { + if (auto *CI = dyn_cast(MaskConst)) { + Constant *C = CI->getSplatValue(); + if (C->isAllOnesValue()) { + return false; + } + } + } + } + } + ConstantInt *CEI = dyn_cast(EI); // If we can pick a scalar constant value out of a vector, that is free.