1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; If we have a masked merge, in the form of: (M is not constant)
6 ; We can de-invert the M:
9 define i4 @scalar (i4 %x, i4 %y, i4 %m) {
10 ; CHECK-LABEL: @scalar(
11 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
12 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
13 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
14 ; CHECK-NEXT: ret i4 [[R]]
23 ; ============================================================================ ;
24 ; Various cases with %x and/or %y being a constant
25 ; ============================================================================ ;
27 define i4 @in_constant_varx_mone_invmask(i4 %x, i4 %mask) {
28 ; CHECK-LABEL: @in_constant_varx_mone_invmask(
29 ; CHECK-NEXT: [[N1_DEMORGAN:%.*]] = or i4 [[X:%.*]], [[MASK:%.*]]
30 ; CHECK-NEXT: ret i4 [[N1_DEMORGAN]]
32 %notmask = xor i4 %mask, -1
33 %n0 = xor i4 %x, -1 ; %x
34 %n1 = and i4 %n0, %notmask
39 define i4 @in_constant_varx_6_invmask(i4 %x, i4 %mask) {
40 ; CHECK-LABEL: @in_constant_varx_6_invmask(
41 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], 6
42 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
43 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
44 ; CHECK-NEXT: ret i4 [[R]]
46 %notmask = xor i4 %mask, -1
47 %n0 = xor i4 %x, 6 ; %x
48 %n1 = and i4 %n0, %notmask
53 define i4 @in_constant_mone_vary_invmask(i4 %y, i4 %mask) {
54 ; CHECK-LABEL: @in_constant_mone_vary_invmask(
55 ; CHECK-NEXT: [[N1_DEMORGAN:%.*]] = or i4 [[Y:%.*]], [[MASK:%.*]]
56 ; CHECK-NEXT: [[N1:%.*]] = xor i4 [[N1_DEMORGAN]], -1
57 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
58 ; CHECK-NEXT: ret i4 [[R]]
60 %notmask = xor i4 %mask, -1
61 %n0 = xor i4 -1, %y ; %x
62 %n1 = and i4 %n0, %notmask
67 define i4 @in_constant_6_vary_invmask(i4 %y, i4 %mask) {
68 ; CHECK-LABEL: @in_constant_6_vary_invmask(
69 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], 6
70 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
71 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], 6
72 ; CHECK-NEXT: ret i4 [[R]]
74 %notmask = xor i4 %mask, -1
75 %n0 = xor i4 %y, 6 ; %x
76 %n1 = and i4 %n0, %notmask
81 ; ============================================================================ ;
83 ; ============================================================================ ;
85 ; Used to make sure that the IR complexity sorting does not interfere.
88 ; FIXME: should the %n1 = and i4 %im, %n0 swapped order pattern be tested?
90 define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
91 ; CHECK-LABEL: @c_1_0_0(
92 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
93 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
94 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
95 ; CHECK-NEXT: ret i4 [[R]]
98 %n0 = xor i4 %y, %x ; swapped order
104 define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
105 ; CHECK-LABEL: @c_0_1_0(
106 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
107 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
108 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
109 ; CHECK-NEXT: ret i4 [[R]]
113 %n1 = and i4 %n0, %im
114 %r = xor i4 %n1, %x ; %x instead of %y
118 define i4 @c_0_0_1 (i4 %m) {
119 ; CHECK-LABEL: @c_0_0_1(
120 ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
121 ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
122 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y]]
123 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
124 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
125 ; CHECK-NEXT: ret i4 [[R]]
131 %n1 = and i4 %n0, %im
132 %r = xor i4 %y, %n1 ; swapped order
136 define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
137 ; CHECK-LABEL: @c_1_1_0(
138 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
139 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
140 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
141 ; CHECK-NEXT: ret i4 [[R]]
144 %n0 = xor i4 %y, %x ; swapped order
145 %n1 = and i4 %n0, %im
146 %r = xor i4 %n1, %x ; %x instead of %y
150 define i4 @c_1_0_1 (i4 %x, i4 %m) {
151 ; CHECK-LABEL: @c_1_0_1(
152 ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
153 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
154 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
155 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
156 ; CHECK-NEXT: ret i4 [[R]]
160 %n0 = xor i4 %y, %x ; swapped order
161 %n1 = and i4 %n0, %im
162 %r = xor i4 %y, %n1 ; swapped order
166 define i4 @c_0_1_1 (i4 %y, i4 %m) {
167 ; CHECK-LABEL: @c_0_1_1(
168 ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
169 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
170 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
171 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
172 ; CHECK-NEXT: ret i4 [[R]]
177 %n1 = and i4 %n0, %im
178 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y
182 define i4 @c_1_1_1 (i4 %m) {
183 ; CHECK-LABEL: @c_1_1_1(
184 ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
185 ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
186 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X]]
187 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
188 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
189 ; CHECK-NEXT: ret i4 [[R]]
194 %n0 = xor i4 %y, %x ; swapped order
195 %n1 = and i4 %n0, %im
196 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y
200 define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
201 ; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
202 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], 6
203 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
204 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
205 ; CHECK-NEXT: ret i4 [[R]]
207 %notmask = xor i4 %mask, -1
208 %n0 = xor i4 %x, 6 ; %x
209 %n1 = and i4 %notmask, %n0 ; swapped
214 define i4 @commutativity_constant_6_vary_invmask(i4 %y, i4 %mask) {
215 ; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
216 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], 6
217 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
218 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], 6
219 ; CHECK-NEXT: ret i4 [[R]]
221 %notmask = xor i4 %mask, -1
222 %n0 = xor i4 %y, 6 ; %x
223 %n1 = and i4 %notmask, %n0 ; swapped
228 ; ============================================================================ ;
229 ; Negative tests. Should not be folded.
230 ; ============================================================================ ;
234 declare void @use4(i4)
236 define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
237 ; CHECK-LABEL: @n_oneuse_D_is_ok(
238 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
239 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
240 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
241 ; CHECK-NEXT: call void @use4(i4 [[N0]])
242 ; CHECK-NEXT: ret i4 [[R]]
245 %n0 = xor i4 %x, %y ; two uses of %n0, THIS IS OK!
246 %n1 = and i4 %n0, %im
248 call void @use4(i4 %n0)
252 define i4 @n_oneuse_A (i4 %x, i4 %y, i4 %m) {
253 ; CHECK-LABEL: @n_oneuse_A(
254 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], -1
255 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
256 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
257 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
258 ; CHECK-NEXT: call void @use4(i4 [[N1]])
259 ; CHECK-NEXT: ret i4 [[R]]
263 %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
265 call void @use4(i4 %n1)
269 define i4 @n_oneuse_AD (i4 %x, i4 %y, i4 %m) {
270 ; CHECK-LABEL: @n_oneuse_AD(
271 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], -1
272 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
273 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
274 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
275 ; CHECK-NEXT: call void @use4(i4 [[N0]])
276 ; CHECK-NEXT: call void @use4(i4 [[N1]])
277 ; CHECK-NEXT: ret i4 [[R]]
281 %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
283 call void @use4(i4 %n0)
284 call void @use4(i4 %n1)
288 ; Some third variable is used
290 define i4 @n_third_var (i4 %x, i4 %y, i4 %z, i4 %m) {
291 ; CHECK-LABEL: @n_third_var(
292 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], -1
293 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
294 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
295 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
296 ; CHECK-NEXT: ret i4 [[R]]
300 %n1 = and i4 %n0, %im
301 %r = xor i4 %n1, %z ; not %x or %y
305 define i4 @n_badxor (i4 %x, i4 %y, i4 %m) {
306 ; CHECK-LABEL: @n_badxor(
307 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], 1
308 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
309 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
310 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
311 ; CHECK-NEXT: ret i4 [[R]]
313 %im = xor i4 %m, 1 ; not -1
315 %n1 = and i4 %n0, %im