diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll index 6ed36ac9c8007..31c6306e87f7f 100644 --- a/llvm/test/Transforms/InstCombine/and-xor-or.ll +++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll @@ -922,3 +922,142 @@ define i32 @or_not_and_wrong_b(i32 %a, i32 %b, i32 %c, i32 %d) { %or3 = or i32 %and1, %and2 ret i32 %or3 } + +; (b & ~(a | c)) | ~(a | b) --> ~((b & c) | a) + +define i32 @or_and_not_not(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @or_and_not_not( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %b, %a + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %not2, %b + %or3 = or i32 %and, %not1 + ret i32 %or3 +} + +define i32 @or_and_not_not_commute1(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @or_and_not_not_commute1( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %b, %a + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %b, %not2 + %or3 = or i32 %and, %not1 + ret i32 %or3 +} + +define i32 @or_and_not_not_commute2(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @or_and_not_not_commute2( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %b, %a + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %not2, %b + %or3 = or i32 %and, %not1 + ret i32 %or3 +} + +define i32 @or_and_not_not_extra_not_use1(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @or_and_not_not_extra_not_use1( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: call void @use(i32 [[NOT1]]) +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %b, %a + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %not2, %b + %or3 = or i32 %and, %not1 + call void @use(i32 %not1) + ret i32 %or3 +} + +define i32 @or_and_not_not_extra_not_use2(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @or_and_not_not_extra_not_use2( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: call void @use(i32 [[NOT2]]) +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %b, %a + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %not2, %b + %or3 = or i32 %and, %not1 + call void @use(i32 %not2) + ret i32 %or3 +} + +define i32 @or_and_not_not_wrong_a(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: @or_and_not_not_wrong_a( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[D:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A:%.*]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %b, %d + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %not2, %b + %or3 = or i32 %and, %not1 + ret i32 %or3 +} + +define i32 @or_and_not_not_wrong_b(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: @or_and_not_not_wrong_b( +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[D:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[C:%.*]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[NOT2]], [[B:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND]], [[NOT1]] +; CHECK-NEXT: ret i32 [[OR3]] +; + %or1 = or i32 %d, %a + %not1 = xor i32 %or1, -1 + %or2 = or i32 %a, %c + %not2 = xor i32 %or2, -1 + %and = and i32 %not2, %b + %or3 = or i32 %and, %not1 + ret i32 %or3 +}