xref: /llvm-project/llvm/test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-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 constant)
5;   ((x ^ y) & M) ^ y
6; Unfold it to
7;   (x & M) | (y & ~M)
8
9define <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]]
15;
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
19  ret <2 x i4> %r
20}
21
22define <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]]
28;
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
32  ret <3 x i4> %r
33}
34
35define <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]]
41;
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
45  ret <2 x i4> %r
46}
47
48; ============================================================================ ;
49; Various cases with %x and/or %y being a constant
50; ============================================================================ ;
51
52define <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]]
56;
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>
60  ret <2 x i4> %r
61}
62
63define <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]]
67;
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>
71  ret <2 x i4> %r
72}
73
74define <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]]
79;
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>
83  ret <2 x i4> %r
84}
85
86define <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]]
91;
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>
95  ret <3 x i4> %r
96}
97
98define <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]]
102;
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
106  ret <2 x i4> %r
107}
108
109define <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]]
113;
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
117  ret <2 x i4> %r
118}
119
120define <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]]
125;
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
129  ret <2 x i4> %r
130}
131
132define <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]]
137;
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
141  ret <3 x i4> %r
142}
143
144; ============================================================================ ;
145; Commutativity
146; ============================================================================ ;
147
148; Used to make sure that the IR complexity sorting does not interfere.
149declare <2 x i4> @gen4()
150
151define <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]]
157;
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
161  ret <2 x i4> %r
162}
163
164define <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]]
170;
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
174  ret <2 x i4> %r
175}
176
177define <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]]
185;
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
191  ret <2 x i4> %r
192}
193
194define <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]]
200;
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
204  ret <2 x i4> %r
205}
206
207define <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]]
214;
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
219  ret <2 x i4> %r
220}
221
222define <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]]
229;
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
234  ret <2 x i4> %r
235}
236
237define <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]]
245;
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
251  ret <2 x i4> %r
252}
253
254define <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]]
258;
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
262  ret <2 x i4> %r
263}
264
265; ============================================================================ ;
266; Negative tests. Should not be folded.
267; ============================================================================ ;
268
269; One use only.
270
271declare void @use4(<2 x i4>)
272
273define <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]]
280;
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)
285  ret <2 x i4> %r
286}
287
288define <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]]
295;
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)
300  ret <2 x i4> %r
301}
302
303define <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]]
311;
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)
317  ret <2 x i4> %r
318}
319
320; Mask is not constant
321
322define <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]]
328;
329  %n0 = xor <2 x i4> %x, %y
330  %n1 = and <2 x i4> %n0, %m
331  %r  = xor <2 x i4> %n1, %y
332  ret <2 x i4> %r
333}
334
335; Some third variable is used
336
337define <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]]
343;
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>
347  ret <2 x i4> %r
348}
349