Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -270,6 +270,12 @@ if (match(RHS, m_c_And(m_Not(m_Value(M)), m_Value())) && match(LHS, m_c_And(m_Specific(M), m_Value()))) return true; + + // Look for a pattern:(A & ~B) op B + if (match(LHS, m_c_And(m_Not(m_Specific(RHS)), m_Value())) || + match(RHS, m_c_And(m_Not(m_Specific(LHS)), m_Value()))) + return true; + IntegerType *IT = cast(LHS->getType()->getScalarType()); KnownBits LHSKnown(IT->getBitWidth()); KnownBits RHSKnown(IT->getBitWidth()); Index: llvm/test/Transforms/InstCombine/and-to-xor.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/and-to-xor.ll @@ -0,0 +1,28 @@ +; Try to fold (A & ~B) + B to A | B +; RUN: opt < %s -instcombine -S | FileCheck %s + +; CHECK: define i32 @and_to_xor1(i32 %0, i32 %1) local_unnamed_addr +; CHECK-NOT: %{{[0-9]+}} = xor i32 %{{[0-9]+}}, -1 +; CHECK-NOT: %{{[0-9]+}} = and i32 %{{[0-9]+}}, %{{[0-9]+}} +; CHECK: %{{[0-9]+}} = or i32 %{{[0-9]+}}, %{{[0-9]+}} +define i32 @and_to_xor1(i32 %0, i32 %1) local_unnamed_addr #0 { + %3 = shl nsw i32 %0, 1 + %4 = mul nsw i32 %1, %0 + %5 = xor i32 %4, -1 + %6 = and i32 %3, %5 + %7 = add nsw i32 %6, %4 + ret i32 %7 +} + +; CHECK: define i32 @and_to_xor2(i32 %0, i32 %1) +; CHECK-NOT: %{{[0-9]+}} = xor i32 %{{[0-9]+}}, -1 +; CHECK-NOT: %{{[0-9]+}} = and i32 %{{[0-9]+}}, %{{[0-9]+}} +; CHECK: %{{[0-9]+}} = or i32 %{{[0-9]+}}, %{{[0-9]+}} +define i32 @and_to_xor2(i32 %0, i32 %1) local_unnamed_addr #0 { + %3 = shl nsw i32 %0, 1 + %4 = mul nsw i32 %1, %0 + %5 = xor i32 %4, -1 + %6 = and i32 %3, %5 + %7 = add nsw i32 %4, %6 + ret i32 %7 +}