Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -3355,6 +3355,10 @@ match(Op1, m_Not(m_Specific(A)))) return BinaryOperator::CreateNot(Builder.CreateAnd(A, B)); + // (~A & B) ^ A --> A | B -- There are 4 commuted variants. + if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(A)), m_Value(B)), m_Deferred(A)))) + return BinaryOperator::CreateOr(A, B); + // (A | B) ^ (A | C) --> (B ^ C) & ~A -- There are 4 commuted variants. // TODO: Loosen one-use restriction if common operand is a constant. Value *D; Index: llvm/test/Transforms/InstCombine/xor.ll =================================================================== --- llvm/test/Transforms/InstCombine/xor.ll +++ llvm/test/Transforms/InstCombine/xor.ll @@ -1176,9 +1176,7 @@ define <2 x i32> @xor_andn_commute1(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @xor_andn_commute1( -; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[NOTA]], [[B:%.*]] -; CHECK-NEXT: [[Z:%.*]] = xor <2 x i32> [[R]], [[A]] +; CHECK-NEXT: [[Z:%.*]] = or <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret <2 x i32> [[Z]] ; %nota = xor <2 x i32> %a, @@ -1192,9 +1190,7 @@ define i33 @xor_andn_commute2(i33 %a, i33 %pb) { ; CHECK-LABEL: @xor_andn_commute2( ; CHECK-NEXT: [[B:%.*]] = udiv i33 42, [[PB:%.*]] -; CHECK-NEXT: [[NOTA:%.*]] = xor i33 [[A:%.*]], -1 -; CHECK-NEXT: [[R:%.*]] = and i33 [[B]], [[NOTA]] -; CHECK-NEXT: [[Z:%.*]] = xor i33 [[R]], [[A]] +; CHECK-NEXT: [[Z:%.*]] = or i33 [[B]], [[A:%.*]] ; CHECK-NEXT: ret i33 [[Z]] ; %b = udiv i33 42, %pb ; thwart complexity-based canonicalization @@ -1209,9 +1205,7 @@ define i32 @xor_andn_commute3(i32 %pa, i32 %b) { ; CHECK-LABEL: @xor_andn_commute3( ; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[PA:%.*]] -; CHECK-NEXT: [[NOTA:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[R:%.*]] = and i32 [[NOTA]], [[B:%.*]] -; CHECK-NEXT: [[Z:%.*]] = xor i32 [[A]], [[R]] +; CHECK-NEXT: [[Z:%.*]] = or i32 [[A]], [[B:%.*]] ; CHECK-NEXT: ret i32 [[Z]] ; %a = udiv i32 42, %pa ; thwart complexity-based canonicalization @@ -1227,9 +1221,7 @@ ; CHECK-LABEL: @xor_andn_commute4( ; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[PA:%.*]] ; CHECK-NEXT: [[B:%.*]] = udiv i32 42, [[PB:%.*]] -; CHECK-NEXT: [[NOTA:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[R:%.*]] = and i32 [[B]], [[NOTA]] -; CHECK-NEXT: [[Z:%.*]] = xor i32 [[A]], [[R]] +; CHECK-NEXT: [[Z:%.*]] = or i32 [[A]], [[B]] ; CHECK-NEXT: ret i32 [[Z]] ; %a = udiv i32 42, %pa ; thwart complexity-based canonicalization