Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -2253,6 +2253,7 @@ match(Op1, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B))))) return Op1; + // Commute the 'or' operands. // (~A ^ B) | (A & B) -> (~A ^ B) // (~A ^ B) | (B & A) -> (~A ^ B) // (B ^ ~A) | (A & B) -> (B ^ ~A) @@ -2266,9 +2267,22 @@ // (~A & B) | ~(B | A) --> ~A // (B & ~A) | ~(A | B) --> ~A // (B & ~A) | ~(B | A) --> ~A - if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) && + if (match(Op0, m_c_And(m_Not(m_Value(A)), m_Value(B))) && match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B))))) - return cast(Op0)->getOperand(0); + return cast(Op0)->getOperand(0) == B + ? cast(Op0)->getOperand(1) + : cast(Op0)->getOperand(0); + + // Commute the 'or' operands. + // ~(A | B) | (~A & B) --> ~A + // ~(B | A) | (~A & B) --> ~A + // ~(A | B) | (B & ~A) --> ~A + // ~(B | A) | (B & ~A) --> ~A + if (match(Op1, m_c_And(m_Not(m_Value(A)), m_Value(B))) && + match(Op0, m_Not(m_c_Or(m_Specific(A), m_Specific(B))))) + return cast(Op1)->getOperand(0) == B + ? cast(Op1)->getOperand(1) + : cast(Op1)->getOperand(0); if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false)) return V; Index: llvm/test/Transforms/InstSimplify/or.ll =================================================================== --- llvm/test/Transforms/InstSimplify/or.ll +++ llvm/test/Transforms/InstSimplify/or.ll @@ -395,3 +395,57 @@ %i5 = or i32 %i4, %i2 ret i32 %i5 } + +define i32 @and_or_not_or5(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or5( +; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: ret i32 [[I]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %B, %i + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define i32 @and_or_not_or6(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or6( +; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: ret i32 [[I]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %i, %B + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +define i32 @and_or_not_or7(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or7( +; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: ret i32 [[I]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %B, %i + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +define i32 @and_or_not_or8(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or8( +; CHECK-NEXT: [[I:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: ret i32 [[I]] +; + %i = xor i32 %B, -1 + %i2 = and i32 %A, %i + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +