xref: /llvm-project/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-vector.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; If we have a masked merge, in the form of: (M is not constant)
5;   ((x ^ y) & ~M) ^ y
6; We can de-invert the M:
7;   ((x ^ y) & M) ^ x
8
9define <2 x i4> @vector (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
10; CHECK-LABEL: @vector(
11; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
12; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
13; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
14; CHECK-NEXT:    ret <2 x i4> [[R]]
15;
16  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
17  %n0 = xor <2 x i4> %x, %y
18  %n1 = and <2 x i4> %n0, %im
19  %r  = xor <2 x i4> %n1, %y
20  ret <2 x i4> %r
21}
22
23define <3 x i4> @vector_poison (<3 x i4> %x, <3 x i4> %y, <3 x i4> %m) {
24; CHECK-LABEL: @vector_poison(
25; CHECK-NEXT:    [[N0:%.*]] = xor <3 x i4> [[X:%.*]], [[Y:%.*]]
26; CHECK-NEXT:    [[TMP1:%.*]] = and <3 x i4> [[N0]], [[M:%.*]]
27; CHECK-NEXT:    [[R:%.*]] = xor <3 x i4> [[TMP1]], [[X]]
28; CHECK-NEXT:    ret <3 x i4> [[R]]
29;
30  %im = xor <3 x i4> %m, <i4 -1, i4 poison, i4 -1>
31  %n0 = xor <3 x i4> %x, %y
32  %n1 = and <3 x i4> %n0, %im
33  %r  = xor <3 x i4> %n1, %y
34  ret <3 x i4> %r
35}
36
37; ============================================================================ ;
38; Various cases with %x and/or %y being a constant
39; ============================================================================ ;
40
41define <2 x i4> @in_constant_varx_mone_invmask(<2 x i4> %x, <2 x i4> %mask) {
42; CHECK-LABEL: @in_constant_varx_mone_invmask(
43; CHECK-NEXT:    [[N1_DEMORGAN:%.*]] = or <2 x i4> [[X:%.*]], [[MASK:%.*]]
44; CHECK-NEXT:    ret <2 x i4> [[N1_DEMORGAN]]
45;
46  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
47  %n0 = xor <2 x i4> %x, <i4 -1, i4 -1> ; %x
48  %n1 = and <2 x i4> %n0, %notmask
49  %r = xor <2 x i4> %n1, <i4 -1, i4 -1>
50  ret <2 x i4> %r
51}
52
53define <2 x i4> @in_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) {
54; CHECK-LABEL: @in_constant_varx_6_invmask(
55; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], splat (i4 6)
56; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
57; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
58; CHECK-NEXT:    ret <2 x i4> [[R]]
59;
60  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
61  %n0 = xor <2 x i4> %x, <i4 6, i4 6> ; %x
62  %n1 = and <2 x i4> %n0, %notmask
63  %r = xor <2 x i4> %n1, <i4 6, i4 6>
64  ret <2 x i4> %r
65}
66
67define <2 x i4> @in_constant_varx_6_invmask_nonsplat(<2 x i4> %x, <2 x i4> %mask) {
68; CHECK-LABEL: @in_constant_varx_6_invmask_nonsplat(
69; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], <i4 6, i4 7>
70; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
71; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
72; CHECK-NEXT:    ret <2 x i4> [[R]]
73;
74  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
75  %n0 = xor <2 x i4> %x, <i4 6, i4 7> ; %x
76  %n1 = and <2 x i4> %n0, %notmask
77  %r = xor <2 x i4> %n1, <i4 6, i4 7>
78  ret <2 x i4> %r
79}
80
81define <3 x i4> @in_constant_varx_6_invmask_poison(<3 x i4> %x, <3 x i4> %mask) {
82; CHECK-LABEL: @in_constant_varx_6_invmask_poison(
83; CHECK-NEXT:    [[N0:%.*]] = xor <3 x i4> [[X:%.*]], <i4 6, i4 poison, i4 7>
84; CHECK-NEXT:    [[TMP1:%.*]] = and <3 x i4> [[N0]], [[MASK:%.*]]
85; CHECK-NEXT:    [[R:%.*]] = xor <3 x i4> [[TMP1]], [[X]]
86; CHECK-NEXT:    ret <3 x i4> [[R]]
87;
88  %notmask = xor <3 x i4> %mask, <i4 -1, i4 poison, i4 -1>
89  %n0 = xor <3 x i4> %x, <i4 6, i4 poison, i4 7> ; %x
90  %n1 = and <3 x i4> %n0, %notmask
91  %r = xor <3 x i4> %n1, <i4 6, i4 poison, i4 7>
92  ret <3 x i4> %r
93}
94
95define <2 x i4> @in_constant_mone_vary_invmask(<2 x i4> %y, <2 x i4> %mask) {
96; CHECK-LABEL: @in_constant_mone_vary_invmask(
97; CHECK-NEXT:    [[MASK_NOT:%.*]] = xor <2 x i4> [[MASK:%.*]], splat (i4 -1)
98; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[Y:%.*]], [[MASK_NOT]]
99; CHECK-NEXT:    ret <2 x i4> [[R]]
100;
101  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
102  %n0 = xor <2 x i4> <i4 -1, i4 -1>, %y ; %x
103  %n1 = and <2 x i4> %n0, %notmask
104  %r = xor <2 x i4> %n1, %y
105  ret <2 x i4> %r
106}
107
108define <2 x i4> @in_constant_6_vary_invmask(<2 x i4> %y, <2 x i4> %mask) {
109; CHECK-LABEL: @in_constant_6_vary_invmask(
110; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], splat (i4 6)
111; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
112; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], splat (i4 6)
113; CHECK-NEXT:    ret <2 x i4> [[R]]
114;
115  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
116  %n0 = xor <2 x i4> %y, <i4 6, i4 6> ; %x
117  %n1 = and <2 x i4> %n0, %notmask
118  %r = xor <2 x i4> %n1, %y
119  ret <2 x i4> %r
120}
121
122define <2 x i4> @in_constant_6_vary_invmask_nonsplat(<2 x i4> %y, <2 x i4> %mask) {
123; CHECK-LABEL: @in_constant_6_vary_invmask_nonsplat(
124; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], <i4 6, i4 7>
125; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
126; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 7>
127; CHECK-NEXT:    ret <2 x i4> [[R]]
128;
129  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
130  %n0 = xor <2 x i4> %y, <i4 6, i4 7> ; %x
131  %n1 = and <2 x i4> %n0, %notmask
132  %r = xor <2 x i4> %n1, %y
133  ret <2 x i4> %r
134}
135
136define <3 x i4> @in_constant_6_vary_invmask_poison(<3 x i4> %y, <3 x i4> %mask) {
137; CHECK-LABEL: @in_constant_6_vary_invmask_poison(
138; CHECK-NEXT:    [[N0:%.*]] = xor <3 x i4> [[Y:%.*]], <i4 6, i4 poison, i4 6>
139; CHECK-NEXT:    [[TMP1:%.*]] = and <3 x i4> [[N0]], [[MASK:%.*]]
140; CHECK-NEXT:    [[R:%.*]] = xor <3 x i4> [[TMP1]], <i4 6, i4 poison, i4 6>
141; CHECK-NEXT:    ret <3 x i4> [[R]]
142;
143  %notmask = xor <3 x i4> %mask, <i4 -1, i4 poison, i4 -1>
144  %n0 = xor <3 x i4> %y, <i4 6, i4 poison, i4 6> ; %x
145  %n1 = and <3 x i4> %n0, %notmask
146  %r = xor <3 x i4> %n1, %y
147  ret <3 x i4> %r
148}
149
150; ============================================================================ ;
151; Commutativity
152; ============================================================================ ;
153
154; Used to make sure that the IR complexity sorting does not interfere.
155declare <2 x i4> @gen4()
156
157; FIXME: should  %n1 = and <2 x i4> %im, %n0  swapped order pattern be tested?
158
159define <2 x i4> @c_1_0_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
160; CHECK-LABEL: @c_1_0_0(
161; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]]
162; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
163; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
164; CHECK-NEXT:    ret <2 x i4> [[R]]
165;
166  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
167  %n0 = xor <2 x i4> %y, %x ; swapped order
168  %n1 = and <2 x i4> %n0, %im
169  %r  = xor <2 x i4> %n1, %y
170  ret <2 x i4> %r
171}
172
173define <2 x i4> @c_0_1_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
174; CHECK-LABEL: @c_0_1_0(
175; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
176; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
177; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
178; CHECK-NEXT:    ret <2 x i4> [[R]]
179;
180  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
181  %n0 = xor <2 x i4> %x, %y
182  %n1 = and <2 x i4> %n0, %im
183  %r  = xor <2 x i4> %n1, %x ; %x instead of %y
184  ret <2 x i4> %r
185}
186
187define <2 x i4> @c_0_0_1 (<2 x i4> %m) {
188; CHECK-LABEL: @c_0_0_1(
189; CHECK-NEXT:    [[X:%.*]] = call <2 x i4> @gen4()
190; CHECK-NEXT:    [[Y:%.*]] = call <2 x i4> @gen4()
191; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X]], [[Y]]
192; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
193; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
194; CHECK-NEXT:    ret <2 x i4> [[R]]
195;
196  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
197  %x  = call <2 x i4> @gen4()
198  %y  = call <2 x i4> @gen4()
199  %n0 = xor <2 x i4> %x, %y
200  %n1 = and <2 x i4> %n0, %im
201  %r  = xor <2 x i4> %y, %n1 ; swapped order
202  ret <2 x i4> %r
203}
204
205define <2 x i4> @c_1_1_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
206; CHECK-LABEL: @c_1_1_0(
207; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]]
208; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
209; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
210; CHECK-NEXT:    ret <2 x i4> [[R]]
211;
212  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
213  %n0 = xor <2 x i4> %y, %x ; swapped order
214  %n1 = and <2 x i4> %n0, %im
215  %r  = xor <2 x i4> %n1, %x ; %x instead of %y
216  ret <2 x i4> %r
217}
218
219define <2 x i4> @c_1_0_1 (<2 x i4> %x, <2 x i4> %m) {
220; CHECK-LABEL: @c_1_0_1(
221; CHECK-NEXT:    [[Y:%.*]] = call <2 x i4> @gen4()
222; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y]], [[X:%.*]]
223; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
224; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
225; CHECK-NEXT:    ret <2 x i4> [[R]]
226;
227  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
228  %y  = call <2 x i4> @gen4()
229  %n0 = xor <2 x i4> %y, %x ; swapped order
230  %n1 = and <2 x i4> %n0, %im
231  %r  = xor <2 x i4> %y, %n1 ; swapped order
232  ret <2 x i4> %r
233}
234
235define <2 x i4> @c_0_1_1 (<2 x i4> %y, <2 x i4> %m) {
236; CHECK-LABEL: @c_0_1_1(
237; CHECK-NEXT:    [[X:%.*]] = call <2 x i4> @gen4()
238; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X]], [[Y:%.*]]
239; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
240; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
241; CHECK-NEXT:    ret <2 x i4> [[R]]
242;
243  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
244  %x  = call <2 x i4> @gen4()
245  %n0 = xor <2 x i4> %x, %y
246  %n1 = and <2 x i4> %n0, %im
247  %r  = xor <2 x i4> %x, %n1 ; swapped order, %x instead of %y
248  ret <2 x i4> %r
249}
250
251define <2 x i4> @c_1_1_1 (<2 x i4> %m) {
252; CHECK-LABEL: @c_1_1_1(
253; CHECK-NEXT:    [[X:%.*]] = call <2 x i4> @gen4()
254; CHECK-NEXT:    [[Y:%.*]] = call <2 x i4> @gen4()
255; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y]], [[X]]
256; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
257; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
258; CHECK-NEXT:    ret <2 x i4> [[R]]
259;
260  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
261  %x  = call <2 x i4> @gen4()
262  %y  = call <2 x i4> @gen4()
263  %n0 = xor <2 x i4> %y, %x ; swapped order
264  %n1 = and <2 x i4> %n0, %im
265  %r  = xor <2 x i4> %x, %n1 ; swapped order, %x instead of %y
266  ret <2 x i4> %r
267}
268
269define <2 x i4> @commutativity_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) {
270; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
271; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], splat (i4 6)
272; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
273; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
274; CHECK-NEXT:    ret <2 x i4> [[R]]
275;
276  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
277  %n0 = xor <2 x i4> %x, <i4 6, i4 6> ; %x
278  %n1 = and <2 x i4> %notmask, %n0 ; swapped
279  %r = xor <2 x i4> %n1, <i4 6, i4 6>
280  ret <2 x i4> %r
281}
282
283define <2 x i4> @commutativity_constant_6_vary_invmask(<2 x i4> %y, <2 x i4> %mask) {
284; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
285; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], splat (i4 6)
286; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
287; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], splat (i4 6)
288; CHECK-NEXT:    ret <2 x i4> [[R]]
289;
290  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
291  %n0 = xor <2 x i4> %y, <i4 6, i4 6> ; %x
292  %n1 = and <2 x i4> %notmask, %n0 ; swapped
293  %r = xor <2 x i4> %n1, %y
294  ret <2 x i4> %r
295}
296
297; ============================================================================ ;
298; Negative tests. Should not be folded.
299; ============================================================================ ;
300
301; One use only.
302
303declare void @use4(<2 x i4>)
304
305define <2 x i4> @n_oneuse_D_is_ok (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
306; CHECK-LABEL: @n_oneuse_D_is_ok(
307; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
308; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
309; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
310; CHECK-NEXT:    call void @use4(<2 x i4> [[N0]])
311; CHECK-NEXT:    ret <2 x i4> [[R]]
312;
313  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
314  %n0 = xor <2 x i4> %x, %y ; two uses of %n0, THIS IS OK!
315  %n1 = and <2 x i4> %n0, %im
316  %r  = xor <2 x i4> %n1, %y
317  call void @use4(<2 x i4> %n0)
318  ret <2 x i4> %r
319}
320
321define <2 x i4> @n_oneuse_A (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
322; CHECK-LABEL: @n_oneuse_A(
323; CHECK-NEXT:    [[IM:%.*]] = xor <2 x i4> [[M:%.*]], splat (i4 -1)
324; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
325; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[IM]]
326; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
327; CHECK-NEXT:    call void @use4(<2 x i4> [[N1]])
328; CHECK-NEXT:    ret <2 x i4> [[R]]
329;
330  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
331  %n0 = xor <2 x i4> %x, %y
332  %n1 = and <2 x i4> %n0, %im ; two uses of %n1, which is going to be replaced
333  %r  = xor <2 x i4> %n1, %y
334  call void @use4(<2 x i4> %n1)
335  ret <2 x i4> %r
336}
337
338define <2 x i4> @n_oneuse_AD (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
339; CHECK-LABEL: @n_oneuse_AD(
340; CHECK-NEXT:    [[IM:%.*]] = xor <2 x i4> [[M:%.*]], splat (i4 -1)
341; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
342; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[IM]]
343; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
344; CHECK-NEXT:    call void @use4(<2 x i4> [[N0]])
345; CHECK-NEXT:    call void @use4(<2 x i4> [[N1]])
346; CHECK-NEXT:    ret <2 x i4> [[R]]
347;
348  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
349  %n0 = xor <2 x i4> %x, %y ; two uses of %n0 IS OK
350  %n1 = and <2 x i4> %n0, %im ; two uses of %n1, which is going to be replaced
351  %r  = xor <2 x i4> %n1, %y
352  call void @use4(<2 x i4> %n0)
353  call void @use4(<2 x i4> %n1)
354  ret <2 x i4> %r
355}
356
357; Some third variable is used
358
359define <2 x i4> @n_third_var (<2 x i4> %x, <2 x i4> %y, <2 x i4> %z, <2 x i4> %m) {
360; CHECK-LABEL: @n_third_var(
361; CHECK-NEXT:    [[IM:%.*]] = xor <2 x i4> [[M:%.*]], splat (i4 -1)
362; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
363; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[IM]]
364; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Z:%.*]]
365; CHECK-NEXT:    ret <2 x i4> [[R]]
366;
367  %im = xor <2 x i4> %m, <i4 -1, i4 -1>
368  %n0 = xor <2 x i4> %x, %y
369  %n1 = and <2 x i4> %n0, %im
370  %r  = xor <2 x i4> %n1, %z ; not %x or %y
371  ret <2 x i4> %r
372}
373
374
375define <2 x i4> @n_third_var_const(<2 x i4> %x, <2 x i4> %y, <2 x i4> %mask) {
376; CHECK-LABEL: @n_third_var_const(
377; CHECK-NEXT:    [[NOTMASK:%.*]] = xor <2 x i4> [[MASK:%.*]], splat (i4 -1)
378; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], <i4 6, i4 7>
379; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[NOTMASK]]
380; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], <i4 7, i4 6>
381; CHECK-NEXT:    ret <2 x i4> [[R]]
382;
383  %notmask = xor <2 x i4> %mask, <i4 -1, i4 -1>
384  %n0 = xor <2 x i4> %x, <i4 6, i4 7> ; %x
385  %n1 = and <2 x i4> %n0, %notmask
386  %r = xor <2 x i4> %n1, <i4 7, i4 6>
387  ret <2 x i4> %r
388}
389
390; Bad xor
391
392define <2 x i4> @n_badxor_splat (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
393; CHECK-LABEL: @n_badxor_splat(
394; CHECK-NEXT:    [[IM:%.*]] = xor <2 x i4> [[M:%.*]], splat (i4 1)
395; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
396; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[IM]]
397; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
398; CHECK-NEXT:    ret <2 x i4> [[R]]
399;
400  %im = xor <2 x i4> %m, <i4 1, i4 1> ; not -1
401  %n0 = xor <2 x i4> %x, %y
402  %n1 = and <2 x i4> %n0, %im ; two uses of %n1, which is going to be replaced
403  %r  = xor <2 x i4> %n1, %y
404  ret <2 x i4> %r
405}
406
407define <2 x i4> @n_badxor (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
408; CHECK-LABEL: @n_badxor(
409; CHECK-NEXT:    [[IM:%.*]] = xor <2 x i4> [[M:%.*]], <i4 -1, i4 1>
410; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
411; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[IM]]
412; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
413; CHECK-NEXT:    ret <2 x i4> [[R]]
414;
415  %im = xor <2 x i4> %m, <i4 -1, i4 1> ; not -1
416  %n0 = xor <2 x i4> %x, %y
417  %n1 = and <2 x i4> %n0, %im ; two uses of %n1, which is going to be replaced
418  %r  = xor <2 x i4> %n1, %y
419  ret <2 x i4> %r
420}
421