Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.732 -> 1.733 --- Log message: Generalize the code that handles (A&B)|(A&C) to work where B/C are not constants. Add a new xform to simplify (A&B)|(~A&C). THis implements InstCombine/or2.ll:test1 --- Diffs of the changes: (+83 -30) InstructionCombining.cpp | 113 ++++++++++++++++++++++++++++++++++------------- 1 files changed, 83 insertions(+), 30 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.732 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.733 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.732 Fri Apr 6 13:57:34 2007 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Apr 8 02:47:01 2007 @@ -3709,36 +3709,89 @@ return BinaryOperator::createXor(NOr, C1); } - // (A & C1)|(B & C2) - if (match(Op0, m_And(m_Value(A), m_ConstantInt(C1))) && - match(Op1, m_And(m_Value(B), m_ConstantInt(C2)))) { - - if (A == B) // (A & C1)|(A & C2) == A & (C1|C2) - return BinaryOperator::createAnd(A, - ConstantInt::get(C1->getValue() | C2->getValue())); - - - // If we have: ((V + N) & C1) | (V & C2) - // .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 - // replace with V+N. - if (C1->getValue() == ~C2->getValue()) { - Value *V1 = 0, *V2 = 0; - if ((C2->getValue() & (C2->getValue()+1)) == 0 && // C2 == 0+1+ - match(A, m_Add(m_Value(V1), m_Value(V2)))) { - // Add commutes, try both ways. - if (V1 == B && MaskedValueIsZero(V2, C2->getValue())) - return ReplaceInstUsesWith(I, A); - if (V2 == B && MaskedValueIsZero(V1, C2->getValue())) - return ReplaceInstUsesWith(I, A); - } - // Or commutes, try both ways. - if ((C1->getValue() & (C1->getValue()+1)) == 0 && - match(B, m_Add(m_Value(V1), m_Value(V2)))) { - // Add commutes, try both ways. - if (V1 == A && MaskedValueIsZero(V2, C1->getValue())) - return ReplaceInstUsesWith(I, B); - if (V2 == A && MaskedValueIsZero(V1, C1->getValue())) - return ReplaceInstUsesWith(I, B); + // (A & C)|(B & D) + Value *C, *D; + if (match(Op0, m_And(m_Value(A), m_Value(C))) && + match(Op1, m_And(m_Value(B), m_Value(D)))) { + + // Check to see if we have any common things being and'ed. If so, find the + // terms for V1 & (V2|V3). + Value *V1 = 0, *V2 = 0, *V3 = 0; + if (isOnlyUse(Op0) || isOnlyUse(Op1)) { + if (A == B) // (A & C)|(A & D) == A & (C|D) + V1 = A, V2 = C, V3 = D; + else if (A == D) // (A & C)|(B & A) == A & (B|C) + V1 = A, V2 = B, V3 = C; + else if (C == B) // (A & C)|(C & D) == C & (A|D) + V1 = C, V2 = A, V3 = D; + else if (C == D) // (A & C)|(B & C) == C & (A|B) + V1 = C, V2 = A, V3 = B; + + if (V1) { + Value *Or = + InsertNewInstBefore(BinaryOperator::createOr(V2, V3, "tmp"), I); + return BinaryOperator::createAnd(V1, Or); + } + + // (V1 & V3)|(V2 & ~V3) -> ((V1 ^ V2) & V3) ^ V2 + if (isOnlyUse(Op0) && isOnlyUse(Op1)) { + // Try all combination of terms to find V3 and ~V3. + if (A->hasOneUse() && match(A, m_Not(m_Value(V3)))) { + if (V3 == B) + V1 = D, V2 = C; + else if (V3 == D) + V1 = B, V2 = C; + } + if (B->hasOneUse() && match(B, m_Not(m_Value(V3)))) { + if (V3 == A) + V1 = C, V2 = D; + else if (V3 == C) + V1 = A, V2 = D; + } + if (C->hasOneUse() && match(C, m_Not(m_Value(V3)))) { + if (V3 == B) + V1 = D, V2 = A; + else if (V3 == D) + V1 = B, V2 = A; + } + if (D->hasOneUse() && match(D, m_Not(m_Value(V3)))) { + if (V3 == A) + V1 = C, V2 = B; + else if (V3 == C) + V1 = A, V2 = B; + } + if (V1) { + A = InsertNewInstBefore(BinaryOperator::createXor(V1, V2, "tmp"), I); + A = InsertNewInstBefore(BinaryOperator::createAnd(A, V3, "tmp"), I); + return BinaryOperator::createXor(A, V2); + } + } + } + + C1 = dyn_cast<ConstantInt>(C); + C2 = dyn_cast<ConstantInt>(D); + if (C1 && C2) { // (A & C1)|(B & C2) + // If we have: ((V + N) & C1) | (V & C2) + // .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 + // replace with V+N. + if (C1->getValue() == ~C2->getValue()) { + if ((C2->getValue() & (C2->getValue()+1)) == 0 && // C2 == 0+1+ + match(A, m_Add(m_Value(V1), m_Value(V2)))) { + // Add commutes, try both ways. + if (V1 == B && MaskedValueIsZero(V2, C2->getValue())) + return ReplaceInstUsesWith(I, A); + if (V2 == B && MaskedValueIsZero(V1, C2->getValue())) + return ReplaceInstUsesWith(I, A); + } + // Or commutes, try both ways. + if ((C1->getValue() & (C1->getValue()+1)) == 0 && + match(B, m_Add(m_Value(V1), m_Value(V2)))) { + // Add commutes, try both ways. + if (V1 == A && MaskedValueIsZero(V2, C1->getValue())) + return ReplaceInstUsesWith(I, B); + if (V2 == A && MaskedValueIsZero(V1, C1->getValue())) + return ReplaceInstUsesWith(I, B); + } } } } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits