diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2675,0 +2676 @@ + // ~A | (A ^ B) -> ~(A & B) @@ -2684,0 +2686,4 @@ + if (Op1->hasOneUse() && + (match(Op0, m_Not(m_Specific(A))) || match(Op0, m_Not(m_Specific(B))))) + return BinaryOperator::CreateNot(Builder.CreateAnd(A, B)); + diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -372 +371,0 @@ -; CHECK-NEXT: [[C11:%.*]] = icmp ne i16 [[L7]], 0 @@ -375 +374 @@ -; CHECK-NEXT: [[B19:%.*]] = xor i1 [[C11]], [[B15]] +; CHECK-NEXT: [[C6:%.*]] = xor i1 [[B15]], true @@ -377 +376 @@ -; CHECK-NEXT: [[C3:%.*]] = and i1 [[TMP2]], [[B19]] +; CHECK-NEXT: [[C3:%.*]] = and i1 [[TMP2]], [[C6]] diff --git a/llvm/test/Transforms/InstCombine/or-xor.ll b/llvm/test/Transforms/InstCombine/or-xor.ll --- a/llvm/test/Transforms/InstCombine/or-xor.ll +++ b/llvm/test/Transforms/InstCombine/or-xor.ll @@ -61,0 +62,14 @@ +; ~X | (X ^ Y) --> ~(X & Y) + +define i32 @test5(i32 %x, i32 %y) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[Z:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[Z]] +; + %xor = xor i32 %x, %y + %notx = xor i32 %x, -1 + %z = or i32 %xor, %notx + ret i32 %z +} +