Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1814,64 +1814,30 @@ /// This helper function folds: /// /// ((A | B) & C1) | (B & C2) +/// or: +/// ((A ^ B) & C1) | (B & C2) /// /// into: /// /// (A & C1) | B +/// or: +/// (A & C1) ^ B /// /// when the XOR of the two constants is "all ones" (-1). -static Instruction *FoldOrWithConstants(BinaryOperator &I, Value *Op, - Value *A, Value *B, Value *C, - InstCombiner::BuilderTy &Builder) { - ConstantInt *CI1 = dyn_cast(C); +static Instruction *FoldOrXorWithConstants(Instruction::BinaryOps Opc, Value *A, + Value *B, Value *C1, Value *C2, + InstCombiner::BuilderTy &Builder) { + ConstantInt *CI1 = dyn_cast(C1); if (!CI1) return nullptr; - Value *V1 = nullptr; - ConstantInt *CI2 = nullptr; - if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2)))) return nullptr; + ConstantInt *CI2 = dyn_cast(C2); + if (!C2) return nullptr; APInt Xor = CI1->getValue() ^ CI2->getValue(); if (!Xor.isAllOnesValue()) return nullptr; - if (V1 == A || V1 == B) { - Value *NewOp = Builder.CreateAnd((V1 == A) ? B : A, CI1); - return BinaryOperator::CreateOr(NewOp, V1); - } - - return nullptr; -} - -/// \brief This helper function folds: -/// -/// ((A ^ B) & C1) | (B & C2) -/// -/// into: -/// -/// (A & C1) ^ B -/// -/// when the XOR of the two constants is "all ones" (-1). -static Instruction *FoldXorWithConstants(BinaryOperator &I, Value *Op, - Value *A, Value *B, Value *C, - InstCombiner::BuilderTy &Builder) { - ConstantInt *CI1 = dyn_cast(C); - if (!CI1) - return nullptr; - - Value *V1 = nullptr; - ConstantInt *CI2 = nullptr; - if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2)))) - return nullptr; - - APInt Xor = CI1->getValue() ^ CI2->getValue(); - if (!Xor.isAllOnesValue()) - return nullptr; - - if (V1 == A || V1 == B) { - Value *NewOp = Builder.CreateAnd(V1 == A ? B : A, CI1); - return BinaryOperator::CreateXor(NewOp, V1); - } - - return nullptr; + Value *NewOp = Builder.CreateAnd(A, C1); + return BinaryOperator::Create(Opc, NewOp, B); } // FIXME: We use commutative matchers (m_c_*) for some, but not all, matches @@ -2001,22 +1967,26 @@ // ((A|B)&1)|(B&-2) -> (A&1) | B if (match(A, m_c_Or(m_Value(V1), m_Specific(B)))) { - if (Instruction *Ret = FoldOrWithConstants(I, Op1, V1, B, C, Builder)) + if (Instruction *Ret = FoldOrXorWithConstants(BinaryOperator::Or, + V1, B, C, D, Builder)) return Ret; } // (B&-2)|((A|B)&1) -> (A&1) | B if (match(B, m_c_Or(m_Specific(A), m_Value(V1)))) { - if (Instruction *Ret = FoldOrWithConstants(I, Op0, A, V1, D, Builder)) + if (Instruction *Ret = FoldOrXorWithConstants(BinaryOperator::Or, + V1, A, D, C, Builder)) return Ret; } // ((A^B)&1)|(B&-2) -> (A&1) ^ B if (match(A, m_c_Xor(m_Value(V1), m_Specific(B)))) { - if (Instruction *Ret = FoldXorWithConstants(I, Op1, V1, B, C, Builder)) + if (Instruction *Ret = FoldOrXorWithConstants(BinaryOperator::Xor, + V1, B, C, D, Builder)) return Ret; } // (B&-2)|((A^B)&1) -> (A&1) ^ B if (match(B, m_c_Xor(m_Specific(A), m_Value(V1)))) { - if (Instruction *Ret = FoldXorWithConstants(I, Op0, A, V1, D, Builder)) + if (Instruction *Ret = FoldOrXorWithConstants(BinaryOperator::Xor, + V1, A, D, C, Builder)) return Ret; } }