diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2265,6 +2265,19 @@ match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B))))) return Op0; + // (A | B) | (A ^ B) --> A | B + // (B | A) | (A ^ B) --> B | A + if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && + match(Op0, m_c_Or(m_Specific(A), m_Specific(B)))) + return Op0; + + // Commute the outer 'or' operands. + // (A ^ B) | (A | B) --> A | B + // (A ^ B) | (B | A) --> B | A + if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && + match(Op1, m_c_Or(m_Specific(A), m_Specific(B)))) + return Op1; + // (~A & B) | ~(A | B) --> ~A // (~A & B) | ~(B | A) --> ~A // (B & ~A) | ~(A | B) --> ~A diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -451,9 +451,7 @@ define i69 @or_or_xor(i69 %A, i69 %B) { ; CHECK-LABEL: @or_or_xor( ; CHECK-NEXT: [[I1:%.*]] = or i69 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[I2:%.*]] = xor i69 [[A]], [[B]] -; CHECK-NEXT: [[I3:%.*]] = or i69 [[I1]], [[I2]] -; CHECK-NEXT: ret i69 [[I3]] +; CHECK-NEXT: ret i69 [[I1]] ; %i1 = or i69 %A, %B %i2 = xor i69 %A, %B @@ -461,12 +459,25 @@ ret i69 %i3 } +; (B | A) | (A ^ B) --> B | A + +define i8 @or_or_xor_inner_or_commuted(i8 %A, i8 %B) { +; CHECK-LABEL: @or_or_xor_inner_or_commuted( +; CHECK-NEXT: [[I1:%.*]] = or i8 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: ret i8 [[I1]] +; + %i1 = or i8 %B, %A + %i2 = xor i8 %A, %B + %i3 = or i8 %i1, %i2 + ret i8 %i3 +} + +; (A ^ B) | (A | B) --> A | B + define <4 x i4> @or_or_xor_commuted(<4 x i4> %A, <4 x i4> %B) { ; CHECK-LABEL: @or_or_xor_commuted( ; CHECK-NEXT: [[I1:%.*]] = or <4 x i4> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[I2:%.*]] = xor <4 x i4> [[A]], [[B]] -; CHECK-NEXT: [[I3:%.*]] = or <4 x i4> [[I2]], [[I1]] -; CHECK-NEXT: ret <4 x i4> [[I3]] +; CHECK-NEXT: ret <4 x i4> [[I1]] ; %i1 = or <4 x i4> %A, %B %i2 = xor <4 x i4> %A, %B @@ -474,6 +485,19 @@ ret <4 x i4> %i3 } +; (A ^ B) | (B | A) --> B | A + +define i4 @or_or_xor_inner_or_outer_or_commuted(i4 %A, i4 %B) { +; CHECK-LABEL: @or_or_xor_inner_or_outer_or_commuted( +; CHECK-NEXT: [[I1:%.*]] = or i4 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: ret i4 [[I1]] +; + %i1 = or i4 %B, %A + %i2 = xor i4 %A, %B + %i3 = or i4 %i2, %i1 + ret i4 %i3 +} + define i32 @shifted_all_ones(i32 %shamt) { ; CHECK-LABEL: @shifted_all_ones( ; CHECK-NEXT: ret i32 -1