Tests from D113216 are now handled by Reassociate, GVN and BDCE passes after D114462. Moving into phase ordering instead of instcombine.
293 lines
9.0 KiB
LLVM
293 lines
9.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -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)
|