267 changes: 123 additions & 144 deletions llvm/test/Transforms/InstSimplify/or.ll
Original file line number Diff line number Diff line change
Expand Up @@ -348,150 +348,129 @@ define i32 @poison(i32 %x) {
ret i32 %v
}

declare void @use(i32)

define i32 @and_or_not_or(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[B:%.*]], -1
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %B, -1
%i2 = and i32 %i, %A
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i2, %i4
ret i32 %i5
}

define i32 @and_or_not_or2(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or2(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %A, -1
%i2 = and i32 %i, %B
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i2, %i4
ret i32 %i5
}

define <4 x i32> @and_or_not_or3_vec(<4 x i32> %A, <4 x i32> %B) {
; CHECK-LABEL: @and_or_not_or3_vec(
; CHECK-NEXT: [[I:%.*]] = xor <4 x i32> [[A:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
; CHECK-NEXT: ret <4 x i32> [[I]]
;
%i = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
%i2 = and <4 x i32> %i, %B
%i3 = or <4 x i32> %B, %A
%i4 = xor <4 x i32> %i3, <i32 -1, i32 -1, i32 -1, i32 -1>
%i5 = or <4 x i32> %i2, %i4
ret <4 x i32> %i5
}

define i32 @and_or_not_or4_use(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or4_use(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1
; CHECK-NEXT: [[I2:%.*]] = and i32 [[I]], [[B:%.*]]
; CHECK-NEXT: tail call void @use(i32 [[I2]])
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %A, -1
%i2 = and i32 %i, %B
tail call void @use(i32 %i2)
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i2, %i4
ret i32 %i5
}

define i32 @and_or_not_or4_use2(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or4_use2(
; CHECK-NEXT: [[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[I2:%.*]] = xor i32 [[I]], -1
; CHECK-NEXT: tail call void @use(i32 [[I2]])
; CHECK-NEXT: [[I3:%.*]] = xor i32 [[A]], -1
; CHECK-NEXT: ret i32 [[I3]]
;
%i = or i32 %B, %A
%i2 = xor i32 %i, -1
tail call void @use(i32 %i2)
%i3 = xor i32 %A, -1
%i4 = and i32 %i3, %B
%i5 = or i32 %i4, %i2
ret i32 %i5
}

define i32 @and_or_not_or4_use3(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or4_use3(
; CHECK-NEXT: [[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[I2:%.*]] = xor i32 [[I]], -1
; CHECK-NEXT: tail call void @use(i32 [[I2]])
; CHECK-NEXT: [[I3:%.*]] = xor i32 [[A]], -1
; CHECK-NEXT: [[I4:%.*]] = and i32 [[I3]], [[B]]
; CHECK-NEXT: tail call void @use(i32 [[I4]])
; CHECK-NEXT: ret i32 [[I3]]
;
%i = or i32 %B, %A
%i2 = xor i32 %i, -1
tail call void @use(i32 %i2)
%i3 = xor i32 %A, -1
%i4 = and i32 %i3, %B
tail call void @use(i32 %i4)
%i5 = or i32 %i4, %i2
ret i32 %i5
}

define i32 @and_or_not_or5(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or5(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %A, -1
%i2 = and i32 %B, %i
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i2, %i4
ret i32 %i5
}

define i32 @and_or_not_or6(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or6(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %A, -1
%i2 = and i32 %i, %B
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i4, %i2
ret i32 %i5
}

define i32 @and_or_not_or7(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or7(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %A, -1
%i2 = and i32 %B, %i
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i4, %i2
ret i32 %i5
}

define i32 @and_or_not_or8(i32 %A, i32 %B) {
; CHECK-LABEL: @and_or_not_or8(
; CHECK-NEXT: [[I:%.*]] = xor i32 [[B:%.*]], -1
; CHECK-NEXT: ret i32 [[I]]
;
%i = xor i32 %B, -1
%i2 = and i32 %A, %i
%i3 = or i32 %B, %A
%i4 = xor i32 %i3, -1
%i5 = or i32 %i4, %i2
ret i32 %i5
; (~A & B) | ~(A | B) --> ~A

define i4 @and_or_not_or_commute0(i4 %A, i4 %B) {
; CHECK-LABEL: @and_or_not_or_commute0(
; CHECK-NEXT: [[NOTA:%.*]] = xor i4 [[A:%.*]], -1
; CHECK-NEXT: ret i4 [[NOTA]]
;
%nota = xor i4 %A, -1
%and = and i4 %nota, %B
%or = or i4 %A, %B
%notab = xor i4 %or, -1
%r = or i4 %and, %notab
ret i4 %r
}

define i41 @and_or_not_or_commute1(i41 %A, i41 %B) {
; CHECK-LABEL: @and_or_not_or_commute1(
; CHECK-NEXT: [[NOTA:%.*]] = xor i41 [[A:%.*]], -1
; CHECK-NEXT: ret i41 [[NOTA]]
;
%nota = xor i41 %A, -1
%and = and i41 %B, %nota
%or = or i41 %A, %B
%notab = xor i41 %or, -1
%r = or i41 %and, %notab
ret i41 %r
}

define i8 @and_or_not_or_commute2(i8 %A, i8 %B) {
; CHECK-LABEL: @and_or_not_or_commute2(
; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1
; CHECK-NEXT: ret i8 [[NOTA]]
;
%nota = xor i8 %A, -1
%and = and i8 %nota, %B
%or = or i8 %B, %A
%notab = xor i8 %or, -1
%r = or i8 %and, %notab
ret i8 %r
}

define <2 x i4> @and_or_not_or_commute3(<2 x i4> %A, <2 x i4> %B) {
; CHECK-LABEL: @and_or_not_or_commute3(
; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], <i4 -1, i4 -1>
; CHECK-NEXT: ret <2 x i4> [[NOTA]]
;
%nota = xor <2 x i4> %A, <i4 -1, i4 -1>
%and = and <2 x i4> %B, %nota
%or = or <2 x i4> %B, %A
%notab = xor <2 x i4> %or, <i4 -1, i4 -1>
%r = or <2 x i4> %and, %notab
ret <2 x i4> %r
}

define i4 @and_or_not_or_commute4(i4 %A, i4 %B) {
; CHECK-LABEL: @and_or_not_or_commute4(
; CHECK-NEXT: [[NOTA:%.*]] = xor i4 [[A:%.*]], -1
; CHECK-NEXT: ret i4 [[NOTA]]
;
%nota = xor i4 %A, -1
%and = and i4 %nota, %B
%or = or i4 %A, %B
%notab = xor i4 %or, -1
%r = or i4 %notab, %and
ret i4 %r
}

define i41 @and_or_not_or_commute5(i41 %A, i41 %B) {
; CHECK-LABEL: @and_or_not_or_commute5(
; CHECK-NEXT: [[NOTA:%.*]] = xor i41 [[A:%.*]], -1
; CHECK-NEXT: ret i41 [[NOTA]]
;
%nota = xor i41 %A, -1
%and = and i41 %B, %nota
%or = or i41 %A, %B
%notab = xor i41 %or, -1
%r = or i41 %notab, %and
ret i41 %r
}

define i8 @and_or_not_or_commute6(i8 %A, i8 %B) {
; CHECK-LABEL: @and_or_not_or_commute6(
; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1
; CHECK-NEXT: ret i8 [[NOTA]]
;
%nota = xor i8 %A, -1
%and = and i8 %nota, %B
%or = or i8 %B, %A
%notab = xor i8 %or, -1
%r = or i8 %notab, %and
ret i8 %r
}

define <2 x i4> @and_or_not_or_commute7(<2 x i4> %A, <2 x i4> %B) {
; CHECK-LABEL: @and_or_not_or_commute7(
; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], <i4 -1, i4 -1>
; CHECK-NEXT: ret <2 x i4> [[NOTA]]
;
%nota = xor <2 x i4> %A, <i4 -1, i4 -1>
%and = and <2 x i4> %B, %nota
%or = or <2 x i4> %B, %A
%notab = xor <2 x i4> %or, <i4 -1, i4 -1>
%r = or <2 x i4> %notab, %and
ret <2 x i4> %r
}

; negative test - It is not safe to propagate an undef element from the 'not' op.

define <2 x i4> @and_or_not_or_commute7_undef_elt(<2 x i4> %A, <2 x i4> %B) {
; CHECK-LABEL: @and_or_not_or_commute7_undef_elt(
; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], <i4 undef, i4 -1>
; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[B:%.*]], [[NOTA]]
; CHECK-NEXT: [[OR:%.*]] = or <2 x i4> [[B]], [[A]]
; CHECK-NEXT: [[NOTAB:%.*]] = xor <2 x i4> [[OR]], <i4 -1, i4 -1>
; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[NOTAB]], [[AND]]
; CHECK-NEXT: ret <2 x i4> [[R]]
;
%nota = xor <2 x i4> %A, <i4 undef, i4 -1>
%and = and <2 x i4> %B, %nota
%or = or <2 x i4> %B, %A
%notab = xor <2 x i4> %or, <i4 -1, i4 -1>
%r = or <2 x i4> %notab, %and
ret <2 x i4> %r
}

; (A | B) | (A ^ B) --> A | B
Expand Down