| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=reassociate,gvn,bdce -S | FileCheck %s |
| |
| ; (~(a | b) & c) | ~(a | (b | c)) -> ~(a | b) |
| ; (~(a | b) & c) | ~(b | (a | c)) -> ~(a | b) |
| |
| define i32 @not_or_and_or_not_or_or(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or( |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %or1 = or i32 %b, %c |
| %or2 = or i32 %or1, %a |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_commute1(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_commute1( |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %or1 = or i32 %a, %c |
| %or2 = or i32 %or1, %b |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_commute2(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_commute2( |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %or1 = or i32 %c, %b |
| %or2 = or i32 %or1, %a |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_commute3(i32 %a0, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_commute3( |
| ; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]] |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A]], [[B:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization |
| %or1 = or i32 %b, %c |
| %or2 = or i32 %a, %or1 |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %a, %b |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_commute4(i32 %a, i32 %b0, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_commute4( |
| ; CHECK-NEXT: [[B:%.*]] = sdiv i32 42, [[B0:%.*]] |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %b = sdiv i32 42, %b0 ; thwart complexity-based canonicalization |
| %or1 = or i32 %a, %c |
| %or2 = or i32 %b, %or1 |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_commute5(i32 %a, i32 %b, i32 %c0) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_commute5( |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization |
| %or1 = or i32 %c, %a |
| %or2 = or i32 %or1, %b |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %c, %not2 |
| %or4 = or i32 %and2, %not1 |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_use1(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_use1( |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] |
| ; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: call void @use(i32 [[NOT1]]) |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %or1 = or i32 %b, %c |
| %or2 = or i32 %or1, %a |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| call void @use(i32 %not1) |
| ret i32 %or4 |
| } |
| |
| define i32 @not_or_and_or_not_or_or_use2(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_or_and_or_not_or_or_use2( |
| ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] |
| ; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR1]], -1 |
| ; CHECK-NEXT: call void @use(i32 [[NOT1]]) |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %or1 = or i32 %a, %c |
| %or2 = or i32 %or1, %b |
| %not1 = xor i32 %or2, -1 |
| %or3 = or i32 %b, %a |
| %not2 = xor i32 %or3, -1 |
| %and2 = and i32 %not2, %c |
| %or4 = or i32 %and2, %not1 |
| call void @use(i32 %not1) |
| ret i32 %or4 |
| } |
| |
| ; (~(a & b) | c) & ~(a & (b & c)) -> ~(a & b) |
| ; (~(a & b) | c) & ~(b & (a & c)) -> ~(a & b) |
| |
| define i32 @not_and_or_and_not_and_and(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and( |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %and1 = and i32 %b, %c |
| %and2 = and i32 %and1, %a |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_commute1(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_commute1( |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %and1 = and i32 %a, %c |
| %and2 = and i32 %and1, %b |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_commute2(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_commute2( |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %and1 = and i32 %c, %b |
| %and2 = and i32 %and1, %a |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_commute3(i32 %a0, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_commute3( |
| ; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]] |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], [[B:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization |
| %and1 = and i32 %b, %c |
| %and2 = and i32 %a, %and1 |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %a, %b |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_commute4(i32 %a, i32 %b0, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_commute4( |
| ; CHECK-NEXT: [[B:%.*]] = sdiv i32 42, [[B0:%.*]] |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %b = sdiv i32 42, %b0 ; thwart complexity-based canonicalization |
| %and1 = and i32 %a, %c |
| %and2 = and i32 %b, %and1 |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_commute5(i32 %a, i32 %b, i32 %c0) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_commute5( |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization |
| %and1 = and i32 %c, %a |
| %and2 = and i32 %and1, %b |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %c, %not2 |
| %and4 = and i32 %or2, %not1 |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_use1(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_use1( |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] |
| ; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND2]], -1 |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: call void @use(i32 [[NOT1]]) |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %and1 = and i32 %b, %c |
| %and2 = and i32 %and1, %a |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| call void @use(i32 %not1) |
| ret i32 %and4 |
| } |
| |
| define i32 @not_and_or_and_not_and_and_use2(i32 %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @not_and_or_and_not_and_and_use2( |
| ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] |
| ; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND2]], -1 |
| ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND1]], -1 |
| ; CHECK-NEXT: call void @use(i32 [[NOT1]]) |
| ; CHECK-NEXT: ret i32 [[NOT2]] |
| ; |
| %and1 = and i32 %a, %c |
| %and2 = and i32 %and1, %b |
| %not1 = xor i32 %and2, -1 |
| %and3 = and i32 %b, %a |
| %not2 = xor i32 %and3, -1 |
| %or2 = or i32 %not2, %c |
| %and4 = and i32 %or2, %not1 |
| call void @use(i32 %not1) |
| ret i32 %and4 |
| } |
| |
| declare void @use(i32) |