Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1414,6 +1414,15 @@ m_c_And(m_Deferred(A), m_Deferred(B))))) return BinaryOperator::CreateOr(A, B); + // (add (A, (and B, (not A)))) --> (or A, B) + // (add (A, (xor (and A, B), B))) --> (or A, B) + if (match(RHS, m_c_And(m_Value(B), m_Not(m_Specific(LHS)))) || + match(RHS, m_c_Xor(m_c_And(m_Specific(LHS), m_Value(B)), m_Deferred(B)))) + return BinaryOperator::CreateOr(LHS, B); + if (match(LHS, m_c_And(m_Value(B), m_Not(m_Specific(RHS)))) || + match(LHS, m_c_Xor(m_c_And(m_Specific(RHS), m_Value(B)), m_Deferred(B)))) + return BinaryOperator::CreateOr(RHS, B); + // (add (or A, B) (and A, B)) --> (add A, B) // (add (and A, B) (or A, B)) --> (add A, B) if (match(&I, m_c_BinOp(m_Or(m_Value(A), m_Value(B)), Index: llvm/test/Transforms/InstCombine/add.ll =================================================================== --- llvm/test/Transforms/InstCombine/add.ll +++ llvm/test/Transforms/InstCombine/add.ll @@ -1395,9 +1395,7 @@ define i8 @add_and_xor(i8 %x, i8 %y) { ; CHECK-LABEL: @add_and_xor( -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR]], [[Y:%.*]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[AND]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i8 [[ADD]] ; %xor = xor i8 %x, -1 @@ -1435,9 +1433,7 @@ define i8 @add_and_xor_commuted1(i8 %x, i8 %_y) { ; CHECK-LABEL: @add_and_xor_commuted1( ; CHECK-NEXT: [[Y:%.*]] = udiv i8 42, [[_Y:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[XOR]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[AND]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[Y]], [[X:%.*]] ; CHECK-NEXT: ret i8 [[ADD]] ; %y = udiv i8 42, %_y ; thwart complexity-based canonicalization @@ -1450,9 +1446,7 @@ define i8 @add_and_xor_commuted2(i8 %_x, i8 %y) { ; CHECK-LABEL: @add_and_xor_commuted2( ; CHECK-NEXT: [[X:%.*]] = udiv i8 42, [[_X:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR]], [[Y:%.*]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[AND]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i8 [[ADD]] ; %x = udiv i8 42, %_x ; thwart complexity-based canonicalization @@ -1466,9 +1460,7 @@ ; CHECK-LABEL: @add_and_xor_commuted3( ; CHECK-NEXT: [[X:%.*]] = udiv i8 42, [[_X:%.*]] ; CHECK-NEXT: [[Y:%.*]] = udiv i8 42, [[_Y:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[XOR]] -; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i8 [[X]], [[AND]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %x = udiv i8 42, %_x ; thwart complexity-based canonicalization @@ -1485,7 +1477,7 @@ ; CHECK-NEXT: call void @use(i8 [[XOR]]) ; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[AND]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %xor = xor i8 %x, -1 @@ -1498,9 +1490,7 @@ define i8 @add_xor_and_const(i8 %x) { ; CHECK-LABEL: @add_xor_and_const( -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 42 -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], 42 -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[XOR]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X:%.*]], 42 ; CHECK-NEXT: ret i8 [[ADD]] ; %and = and i8 %x, 42 @@ -1526,8 +1516,7 @@ ; CHECK-LABEL: @add_xor_and_var( ; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[Y]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[XOR]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %and = and i8 %x, %y @@ -1571,8 +1560,7 @@ ; CHECK-LABEL: @add_xor_and_var_commuted1( ; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[Y]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[XOR]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %and = and i8 %y, %x @@ -1587,8 +1575,7 @@ ; CHECK-NEXT: [[Y:%.*]] = udiv i8 42, [[_Y:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[X:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[Y]], [[AND]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[XOR]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[Y]], [[X]] ; CHECK-NEXT: ret i8 [[ADD]] ; %y = udiv i8 42, %_y ; thwart complexity-based canonicalization @@ -1604,8 +1591,7 @@ ; CHECK-NEXT: [[Y:%.*]] = udiv i8 42, [[_Y:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[X:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[Y]], [[AND]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[XOR]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[Y]], [[X]] ; CHECK-NEXT: ret i8 [[ADD]] ; %y = udiv i8 42, %_y ; thwart complexity-based canonicalization @@ -1621,8 +1607,7 @@ ; CHECK-NEXT: [[X:%.*]] = udiv i8 42, [[_X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[Y]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[XOR]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %x = udiv i8 42, %_x ; thwart complexity-based canonicalization @@ -1638,8 +1623,7 @@ ; CHECK-NEXT: [[X:%.*]] = udiv i8 42, [[_X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[Y]] -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[XOR]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %x = udiv i8 42, %_x ; thwart complexity-based canonicalization @@ -1656,8 +1640,7 @@ ; CHECK-NEXT: [[Y:%.*]] = udiv i8 42, [[_Y:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[Y]], [[AND]] -; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i8 [[X]], [[XOR]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %x = udiv i8 42, %_x ; thwart complexity-based canonicalization @@ -1675,8 +1658,7 @@ ; CHECK-NEXT: [[Y:%.*]] = udiv i8 42, [[_Y:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[X]] ; CHECK-NEXT: call void @use(i8 [[AND]]) -; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[Y]], [[AND]] -; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i8 [[X]], [[XOR]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %x = udiv i8 42, %_x ; thwart complexity-based canonicalization @@ -1694,7 +1676,7 @@ ; CHECK-NEXT: call void @use(i8 [[AND]]) ; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[Y]] ; CHECK-NEXT: call void @use(i8 [[XOR]]) -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[XOR]], [[X]] +; CHECK-NEXT: [[ADD:%.*]] = or i8 [[X]], [[Y]] ; CHECK-NEXT: ret i8 [[ADD]] ; %and = and i8 %x, %y