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
+}
+
+; FIXME: 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: ret <2 x i4> [[NOTA]]
+;
+ %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