1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; If we have a masked merge, in the form of: (M is constant)
9 define <2 x i4> @splat (<2 x i4> %x, <2 x i4> %y) {
10 ; CHECK-LABEL: @splat(
11 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 -2)
12 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 1)
13 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
14 ; CHECK-NEXT: ret <2 x i4> [[R]]
16 %n0 = xor <2 x i4> %x, %y
17 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
18 %r = xor <2 x i4> %n1, %y
22 define <3 x i4> @splat_undef (<3 x i4> %x, <3 x i4> %y) {
23 ; CHECK-LABEL: @splat_undef(
24 ; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], <i4 -2, i4 -1, i4 -2>
25 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i4> [[Y:%.*]], <i4 1, i4 0, i4 1>
26 ; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], [[TMP2]]
27 ; CHECK-NEXT: ret <3 x i4> [[R]]
29 %n0 = xor <3 x i4> %x, %y
30 %n1 = and <3 x i4> %n0, <i4 -2, i4 undef, i4 -2>
31 %r = xor <3 x i4> %n1, %y
35 define <2 x i4> @nonsplat (<2 x i4> %x, <2 x i4> %y) {
36 ; CHECK-LABEL: @nonsplat(
37 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 -2, i4 1>
38 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], <i4 1, i4 -2>
39 ; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
40 ; CHECK-NEXT: ret <2 x i4> [[R]]
42 %n0 = xor <2 x i4> %x, %y
43 %n1 = and <2 x i4> %n0, <i4 -2, i4 1>
44 %r = xor <2 x i4> %n1, %y
48 ; ============================================================================ ;
49 ; Various cases with %x and/or %y being a constant
50 ; ============================================================================ ;
52 define <2 x i4> @in_constant_varx_mone(<2 x i4> %x, <2 x i4> %mask) {
53 ; CHECK-LABEL: @in_constant_varx_mone(
54 ; CHECK-NEXT: [[R1:%.*]] = or <2 x i4> [[X:%.*]], splat (i4 -2)
55 ; CHECK-NEXT: ret <2 x i4> [[R1]]
57 %n0 = xor <2 x i4> %x, <i4 -1, i4 -1> ; %x
58 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
59 %r = xor <2 x i4> %n1, <i4 -1, i4 -1>
63 define <2 x i4> @in_constant_varx_14(<2 x i4> %x, <2 x i4> %mask) {
64 ; CHECK-LABEL: @in_constant_varx_14(
65 ; CHECK-NEXT: [[R1:%.*]] = or <2 x i4> [[X:%.*]], splat (i4 -2)
66 ; CHECK-NEXT: ret <2 x i4> [[R1]]
68 %n0 = xor <2 x i4> %x, <i4 14, i4 14> ; %x
69 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
70 %r = xor <2 x i4> %n1, <i4 14, i4 14>
74 define <2 x i4> @in_constant_varx_14_nonsplat(<2 x i4> %x, <2 x i4> %mask) {
75 ; CHECK-LABEL: @in_constant_varx_14_nonsplat(
76 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 1)
77 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], <i4 -2, i4 6>
78 ; CHECK-NEXT: ret <2 x i4> [[R]]
80 %n0 = xor <2 x i4> %x, <i4 14, i4 7> ; %x
81 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
82 %r = xor <2 x i4> %n1, <i4 14, i4 7>
86 define <3 x i4> @in_constant_varx_14_undef(<3 x i4> %x, <3 x i4> %mask) {
87 ; CHECK-LABEL: @in_constant_varx_14_undef(
88 ; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], <i4 1, i4 -1, i4 1>
89 ; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], <i4 -2, i4 0, i4 6>
90 ; CHECK-NEXT: ret <3 x i4> [[R]]
92 %n0 = xor <3 x i4> %x, <i4 14, i4 undef, i4 7> ; %x
93 %n1 = and <3 x i4> %n0, <i4 1, i4 undef, i4 1>
94 %r = xor <3 x i4> %n1, <i4 14, i4 undef, i4 7>
98 define <2 x i4> @in_constant_mone_vary(<2 x i4> %y, <2 x i4> %mask) {
99 ; CHECK-LABEL: @in_constant_mone_vary(
100 ; CHECK-NEXT: [[R1:%.*]] = or <2 x i4> [[Y:%.*]], splat (i4 1)
101 ; CHECK-NEXT: ret <2 x i4> [[R1]]
103 %n0 = xor <2 x i4> %y, <i4 -1, i4 -1> ; %x
104 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
105 %r = xor <2 x i4> %n1, %y
109 define <2 x i4> @in_constant_14_vary(<2 x i4> %y, <2 x i4> %mask) {
110 ; CHECK-LABEL: @in_constant_14_vary(
111 ; CHECK-NEXT: [[R:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 -2)
112 ; CHECK-NEXT: ret <2 x i4> [[R]]
114 %n0 = xor <2 x i4> %y, <i4 14, i4 14> ; %x
115 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
116 %r = xor <2 x i4> %n1, %y
120 define <2 x i4> @in_constant_14_vary_nonsplat(<2 x i4> %y, <2 x i4> %mask) {
121 ; CHECK-LABEL: @in_constant_14_vary_nonsplat(
122 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 -2)
123 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], <i4 0, i4 1>
124 ; CHECK-NEXT: ret <2 x i4> [[R]]
126 %n0 = xor <2 x i4> %y, <i4 14, i4 7> ; %x
127 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
128 %r = xor <2 x i4> %n1, %y
132 define <3 x i4> @in_constant_14_vary_undef(<3 x i4> %y, <3 x i4> %mask) {
133 ; CHECK-LABEL: @in_constant_14_vary_undef(
134 ; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[Y:%.*]], <i4 -2, i4 0, i4 -2>
135 ; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], <i4 0, i4 undef, i4 1>
136 ; CHECK-NEXT: ret <3 x i4> [[R]]
138 %n0 = xor <3 x i4> %y, <i4 14, i4 undef, i4 7> ; %x
139 %n1 = and <3 x i4> %n0, <i4 1, i4 undef, i4 1>
140 %r = xor <3 x i4> %n1, %y
144 ; ============================================================================ ;
146 ; ============================================================================ ;
148 ; Used to make sure that the IR complexity sorting does not interfere.
149 declare <2 x i4> @gen4()
151 define <2 x i4> @c_1_0_0 (<2 x i4> %x, <2 x i4> %y) {
152 ; CHECK-LABEL: @c_1_0_0(
153 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 -2)
154 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 1)
155 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
156 ; CHECK-NEXT: ret <2 x i4> [[R]]
158 %n0 = xor <2 x i4> %y, %x ; swapped order
159 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
160 %r = xor <2 x i4> %n1, %y
164 define <2 x i4> @c_0_1_0 (<2 x i4> %x, <2 x i4> %y) {
165 ; CHECK-LABEL: @c_0_1_0(
166 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 -2)
167 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 1)
168 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
169 ; CHECK-NEXT: ret <2 x i4> [[R]]
171 %n0 = xor <2 x i4> %x, %y
172 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
173 %r = xor <2 x i4> %n1, %x ; %x instead of %y
177 define <2 x i4> @c_0_0_1 () {
178 ; CHECK-LABEL: @c_0_0_1(
179 ; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4()
180 ; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4()
181 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X]], splat (i4 -2)
182 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y]], splat (i4 1)
183 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
184 ; CHECK-NEXT: ret <2 x i4> [[R]]
186 %x = call <2 x i4> @gen4()
187 %y = call <2 x i4> @gen4()
188 %n0 = xor <2 x i4> %x, %y
189 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
190 %r = xor <2 x i4> %y, %n1 ; swapped order
194 define <2 x i4> @c_1_1_0 (<2 x i4> %x, <2 x i4> %y) {
195 ; CHECK-LABEL: @c_1_1_0(
196 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 -2)
197 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 1)
198 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
199 ; CHECK-NEXT: ret <2 x i4> [[R]]
201 %n0 = xor <2 x i4> %y, %x ; swapped order
202 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
203 %r = xor <2 x i4> %n1, %x ; %x instead of %y
207 define <2 x i4> @c_1_0_1 (<2 x i4> %x) {
208 ; CHECK-LABEL: @c_1_0_1(
209 ; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4()
210 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 -2)
211 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y]], splat (i4 1)
212 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
213 ; CHECK-NEXT: ret <2 x i4> [[R]]
215 %y = call <2 x i4> @gen4()
216 %n0 = xor <2 x i4> %y, %x ; swapped order
217 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
218 %r = xor <2 x i4> %y, %n1 ; swapped order
222 define <2 x i4> @c_0_1_1 (<2 x i4> %y) {
223 ; CHECK-LABEL: @c_0_1_1(
224 ; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4()
225 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 -2)
226 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X]], splat (i4 1)
227 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
228 ; CHECK-NEXT: ret <2 x i4> [[R]]
230 %x = call <2 x i4> @gen4()
231 %n0 = xor <2 x i4> %x, %y
232 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
233 %r = xor <2 x i4> %x, %n1 ; swapped order, %x instead of %y
237 define <2 x i4> @c_1_1_1 () {
238 ; CHECK-LABEL: @c_1_1_1(
239 ; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4()
240 ; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4()
241 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y]], splat (i4 -2)
242 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X]], splat (i4 1)
243 ; CHECK-NEXT: [[R:%.*]] = or disjoint <2 x i4> [[TMP1]], [[TMP2]]
244 ; CHECK-NEXT: ret <2 x i4> [[R]]
246 %x = call <2 x i4> @gen4()
247 %y = call <2 x i4> @gen4()
248 %n0 = xor <2 x i4> %y, %x ; swapped order
249 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
250 %r = xor <2 x i4> %x, %n1 ; swapped order, %x instead of %y
254 define <2 x i4> @commutativity_constant_14_vary(<2 x i4> %y, <2 x i4> %mask) {
255 ; CHECK-LABEL: @commutativity_constant_14_vary(
256 ; CHECK-NEXT: [[R:%.*]] = and <2 x i4> [[Y:%.*]], splat (i4 -2)
257 ; CHECK-NEXT: ret <2 x i4> [[R]]
259 %n0 = xor <2 x i4> %y, <i4 14, i4 14> ; %x
260 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
261 %r = xor <2 x i4> %y, %n1 ; swapped
265 ; ============================================================================ ;
266 ; Negative tests. Should not be folded.
267 ; ============================================================================ ;
271 declare void @use4(<2 x i4>)
273 define <2 x i4> @n_oneuse_D (<2 x i4> %x, <2 x i4> %y) {
274 ; CHECK-LABEL: @n_oneuse_D(
275 ; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
276 ; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], splat (i4 -2)
277 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
278 ; CHECK-NEXT: call void @use4(<2 x i4> [[N0]])
279 ; CHECK-NEXT: ret <2 x i4> [[R]]
281 %n0 = xor <2 x i4> %x, %y ; two uses of %n0, which is going to be replaced
282 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
283 %r = xor <2 x i4> %n1, %y
284 call void @use4(<2 x i4> %n0)
288 define <2 x i4> @n_oneuse_A (<2 x i4> %x, <2 x i4> %y) {
289 ; CHECK-LABEL: @n_oneuse_A(
290 ; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
291 ; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], splat (i4 -2)
292 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
293 ; CHECK-NEXT: call void @use4(<2 x i4> [[N1]])
294 ; CHECK-NEXT: ret <2 x i4> [[R]]
296 %n0 = xor <2 x i4> %x, %y
297 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2> ; two uses of %n1, which is going to be replaced
298 %r = xor <2 x i4> %n1, %y
299 call void @use4(<2 x i4> %n1)
303 define <2 x i4> @n_oneuse_AD (<2 x i4> %x, <2 x i4> %y) {
304 ; CHECK-LABEL: @n_oneuse_AD(
305 ; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
306 ; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], splat (i4 -2)
307 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
308 ; CHECK-NEXT: call void @use4(<2 x i4> [[N0]])
309 ; CHECK-NEXT: call void @use4(<2 x i4> [[N1]])
310 ; CHECK-NEXT: ret <2 x i4> [[R]]
312 %n0 = xor <2 x i4> %x, %y
313 %n1 = and <2 x i4> %n0, <i4 -2, i4 -2> ; two uses of %n1, which is going to be replaced
314 %r = xor <2 x i4> %n1, %y
315 call void @use4(<2 x i4> %n0)
316 call void @use4(<2 x i4> %n1)
320 ; Mask is not constant
322 define <2 x i4> @n_var_mask (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
323 ; CHECK-LABEL: @n_var_mask(
324 ; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
325 ; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
326 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
327 ; CHECK-NEXT: ret <2 x i4> [[R]]
329 %n0 = xor <2 x i4> %x, %y
330 %n1 = and <2 x i4> %n0, %m
331 %r = xor <2 x i4> %n1, %y
335 ; Some third variable is used
337 define <2 x i4> @n_differenty(<2 x i4> %x, <2 x i4> %mask) {
338 ; CHECK-LABEL: @n_differenty(
339 ; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], <i4 -2, i4 7>
340 ; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], splat (i4 1)
341 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], <i4 7, i4 -2>
342 ; CHECK-NEXT: ret <2 x i4> [[R]]
344 %n0 = xor <2 x i4> %x, <i4 14, i4 7> ; %x
345 %n1 = and <2 x i4> %n0, <i4 1, i4 1>
346 %r = xor <2 x i4> %n1, <i4 7, i4 14>