Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / sink-not-into-and.ll
blob9db6440a49ee71b0e7560fa917ce90057f905f9c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Transform
5 ;   z = ~(x & y)
6 ; into:
7 ;   z = ~(~x | ~y)
8 ; iff both x and y are free to invert.
10 declare void @use1(i1)
12 ; Most basic positive test
13 define i1 @t0(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
14 ; CHECK-LABEL: @t0(
15 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
16 ; CHECK-NEXT:    [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
17 ; CHECK-NEXT:    [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
18 ; CHECK-NEXT:    ret i1 [[I3_NOT]]
20   %i1 = icmp eq i32 %v0, %v1
21   %i2 = icmp eq i32 %v2, %v3
22   %i3 = and i1 %i2, %i1
23   %i4 = xor i1 %i3, -1
24   ret i1 %i4
27 ; All operands must be invertible
28 define i1 @n1(i1 %i1, i32 %v2, i32 %v3) {
29 ; CHECK-LABEL: @n1(
30 ; CHECK-NEXT:    [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
31 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I2]], [[I1:%.*]]
32 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
33 ; CHECK-NEXT:    ret i1 [[I4]]
35   %i2 = icmp eq i32 %v2, %v3
36   %i3 = and i1 %i2, %i1
37   %i4 = xor i1 %i3, -1
38   ret i1 %i4
40 define i1 @n2(i32 %v0, i32 %v1, i1 %i2) {
41 ; CHECK-LABEL: @n2(
42 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
43 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I1]], [[I2:%.*]]
44 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
45 ; CHECK-NEXT:    ret i1 [[I4]]
47   %i1 = icmp eq i32 %v0, %v1
48   %i3 = and i1 %i2, %i1
49   %i4 = xor i1 %i3, -1
50   ret i1 %i4
52 define i1 @n3(i1 %i1, i1 %i2) {
53 ; CHECK-LABEL: @n3(
54 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I2:%.*]], [[I1:%.*]]
55 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
56 ; CHECK-NEXT:    ret i1 [[I4]]
58   %i3 = and i1 %i2, %i1
59   %i4 = xor i1 %i3, -1
60   ret i1 %i4
63 ; All other uses of operands must be invertible
64 define i1 @n4(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
65 ; CHECK-LABEL: @n4(
66 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
67 ; CHECK-NEXT:    [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
68 ; CHECK-NEXT:    call void @use1(i1 [[I1]])
69 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I2]], [[I1]]
70 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
71 ; CHECK-NEXT:    ret i1 [[I4]]
73   %i1 = icmp eq i32 %v0, %v1
74   %i2 = icmp eq i32 %v2, %v3
75   call void @use1(i1 %i1)
76   %i3 = and i1 %i2, %i1
77   %i4 = xor i1 %i3, -1
78   ret i1 %i4
80 define i1 @n5(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
81 ; CHECK-LABEL: @n5(
82 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
83 ; CHECK-NEXT:    [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
84 ; CHECK-NEXT:    call void @use1(i1 [[I2]])
85 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I2]], [[I1]]
86 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
87 ; CHECK-NEXT:    ret i1 [[I4]]
89   %i1 = icmp eq i32 %v0, %v1
90   %i2 = icmp eq i32 %v2, %v3
91   call void @use1(i1 %i2)
92   %i3 = and i1 %i2, %i1
93   %i4 = xor i1 %i3, -1
94   ret i1 %i4
96 define i1 @n6(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
97 ; CHECK-LABEL: @n6(
98 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
99 ; CHECK-NEXT:    [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
100 ; CHECK-NEXT:    call void @use1(i1 [[I1]])
101 ; CHECK-NEXT:    call void @use1(i1 [[I2]])
102 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I2]], [[I1]]
103 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
104 ; CHECK-NEXT:    ret i1 [[I4]]
106   %i1 = icmp eq i32 %v0, %v1
107   %i2 = icmp eq i32 %v2, %v3
108   call void @use1(i1 %i1)
109   call void @use1(i1 %i2)
110   %i3 = and i1 %i2, %i1
111   %i4 = xor i1 %i3, -1
112   ret i1 %i4
115 ; Hands have invertible uses
116 define i1 @t7(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
117 ; CHECK-LABEL: @t7(
118 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
119 ; CHECK-NEXT:    call void @use1(i1 [[I1]])
120 ; CHECK-NEXT:    [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
121 ; CHECK-NEXT:    [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
122 ; CHECK-NEXT:    ret i1 [[I3_NOT]]
124   %i1 = icmp eq i32 %v0, %v1
125   %i1.not = xor i1 %i1, -1
126   call void @use1(i1 %i1.not)
127   %i2 = icmp eq i32 %v2, %v3
128   %i3 = and i1 %i2, %i1
129   %i4 = xor i1 %i3, -1
130   ret i1 %i4
132 define i1 @t8(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
133 ; CHECK-LABEL: @t8(
134 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
135 ; CHECK-NEXT:    [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
136 ; CHECK-NEXT:    call void @use1(i1 [[I2]])
137 ; CHECK-NEXT:    [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
138 ; CHECK-NEXT:    ret i1 [[I3_NOT]]
140   %i1 = icmp eq i32 %v0, %v1
141   %i2 = icmp eq i32 %v2, %v3
142   %i2.not = xor i1 %i2, -1
143   call void @use1(i1 %i2.not)
144   %i3 = and i1 %i2, %i1
145   %i4 = xor i1 %i3, -1
146   ret i1 %i4
148 define i1 @t9(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
149 ; CHECK-LABEL: @t9(
150 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
151 ; CHECK-NEXT:    call void @use1(i1 [[I1]])
152 ; CHECK-NEXT:    [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
153 ; CHECK-NEXT:    call void @use1(i1 [[I2]])
154 ; CHECK-NEXT:    [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
155 ; CHECK-NEXT:    ret i1 [[I3_NOT]]
157   %i1 = icmp eq i32 %v0, %v1
158   %i1.not = xor i1 %i1, -1
159   call void @use1(i1 %i1.not)
160   %i2 = icmp eq i32 %v2, %v3
161   %i2.not = xor i1 %i2, -1
162   call void @use1(i1 %i2.not)
163   %i3 = and i1 %i2, %i1
164   %i4 = xor i1 %i3, -1
165   ret i1 %i4
168 ; Select can have other uses
170 ; Not all uses can be adapted
171 define i1 @n10(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
172 ; CHECK-LABEL: @n10(
173 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
174 ; CHECK-NEXT:    [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
175 ; CHECK-NEXT:    [[I3:%.*]] = and i1 [[I2]], [[I1]]
176 ; CHECK-NEXT:    call void @use1(i1 [[I3]])
177 ; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[I3]], true
178 ; CHECK-NEXT:    ret i1 [[I4]]
180   %i1 = icmp eq i32 %v0, %v1
181   %i2 = icmp eq i32 %v2, %v3
182   %i3 = and i1 %i2, %i1
183   call void @use1(i1 %i3)
184   %i4 = xor i1 %i3, -1
185   ret i1 %i4
188 ; All other uses can be adapted.
189 define i1 @t11(i32 %v0, i32 %v1, i32 %v2, i32 %v3, i1 %v4, i1 %v5) {
190 ; CHECK-LABEL: @t11(
191 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
192 ; CHECK-NEXT:    [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
193 ; CHECK-NEXT:    [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
194 ; CHECK-NEXT:    [[I5:%.*]] = select i1 [[I3_NOT]], i1 [[V5:%.*]], i1 [[V4:%.*]]
195 ; CHECK-NEXT:    call void @use1(i1 [[I5]])
196 ; CHECK-NEXT:    ret i1 [[I3_NOT]]
198   %i1 = icmp eq i32 %v0, %v1
199   %i2 = icmp eq i32 %v2, %v3
200   %i3 = and i1 %i2, %i1
201   %i4 = xor i1 %i3, -1
202   %i5 = select i1 %i3, i1 %v4, i1 %v5
203   call void @use1(i1 %i5)
204   ret i1 %i4