[ARM] Split large truncating MVE stores
[llvm-complete.git] / test / Transforms / InstCombine / unfold-masked-merge-with-const-mask-vector.ll
blobf87b52b974311296640210c19d2f05f7f404060a
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 constant)
5 ;   ((x ^ y) & M) ^ y
6 ; Unfold it to
7 ;   (x & M) | (y & ~M)
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:%.*]], <i4 -2, i4 -2>
12 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], <i4 1, i4 1>
13 ; CHECK-NEXT:    [[R:%.*]] = or <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
19   ret <2 x i4> %r
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 undef, i4 -2>
25 ; CHECK-NEXT:    [[TMP2:%.*]] = and <3 x i4> [[Y:%.*]], <i4 1, i4 undef, 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
32   ret <3 x i4> %r
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
45   ret <2 x i4> %r
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:%.*]], <i4 -2, 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>
60   ret <2 x i4> %r
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:%.*]], <i4 -2, 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>
71   ret <2 x i4> %r
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:%.*]], <i4 1, i4 1>
77 ; CHECK-NEXT:    [[R:%.*]] = or <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>
83   ret <2 x i4> %r
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 undef, i4 1>
89 ; CHECK-NEXT:    [[R:%.*]] = or <3 x i4> [[TMP1]], <i4 -2, i4 undef, 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>
95   ret <3 x i4> %r
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:    [[N0:%.*]] = and <2 x i4> [[Y:%.*]], <i4 1, i4 1>
101 ; CHECK-NEXT:    [[N1:%.*]] = xor <2 x i4> [[N0]], <i4 1, i4 1>
102 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
103 ; CHECK-NEXT:    ret <2 x i4> [[R]]
105   %n0 = xor <2 x i4> %y, <i4 -1, i4 -1> ; %x
106   %n1 = and <2 x i4> %n0, <i4 1, i4 1>
107   %r = xor <2 x i4> %n1, %y
108   ret <2 x i4> %r
111 define <2 x i4> @in_constant_14_vary(<2 x i4> %y, <2 x i4> %mask) {
112 ; CHECK-LABEL: @in_constant_14_vary(
113 ; CHECK-NEXT:    [[R:%.*]] = and <2 x i4> [[Y:%.*]], <i4 -2, i4 -2>
114 ; CHECK-NEXT:    ret <2 x i4> [[R]]
116   %n0 = xor <2 x i4> %y, <i4 14, i4 14> ; %x
117   %n1 = and <2 x i4> %n0, <i4 1, i4 1>
118   %r = xor <2 x i4> %n1, %y
119   ret <2 x i4> %r
122 define <2 x i4> @in_constant_14_vary_nonsplat(<2 x i4> %y, <2 x i4> %mask) {
123 ; CHECK-LABEL: @in_constant_14_vary_nonsplat(
124 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], <i4 -2, i4 -2>
125 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], <i4 0, i4 1>
126 ; CHECK-NEXT:    ret <2 x i4> [[R]]
128   %n0 = xor <2 x i4> %y, <i4 14, i4 7> ; %x
129   %n1 = and <2 x i4> %n0, <i4 1, i4 1>
130   %r = xor <2 x i4> %n1, %y
131   ret <2 x i4> %r
134 define <3 x i4> @in_constant_14_vary_undef(<3 x i4> %y, <3 x i4> %mask) {
135 ; CHECK-LABEL: @in_constant_14_vary_undef(
136 ; CHECK-NEXT:    [[TMP1:%.*]] = and <3 x i4> [[Y:%.*]], <i4 -2, i4 undef, i4 -2>
137 ; CHECK-NEXT:    [[R:%.*]] = or <3 x i4> [[TMP1]], <i4 0, i4 undef, i4 1>
138 ; CHECK-NEXT:    ret <3 x i4> [[R]]
140   %n0 = xor <3 x i4> %y, <i4 14, i4 undef, i4 7> ; %x
141   %n1 = and <3 x i4> %n0, <i4 1, i4 undef, i4 1>
142   %r = xor <3 x i4> %n1, %y
143   ret <3 x i4> %r
146 ; ============================================================================ ;
147 ; Commutativity
148 ; ============================================================================ ;
150 ; Used to make sure that the IR complexity sorting does not interfere.
151 declare <2 x i4> @gen4()
153 define <2 x i4> @c_1_0_0 (<2 x i4> %x, <2 x i4> %y) {
154 ; CHECK-LABEL: @c_1_0_0(
155 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 -2, i4 -2>
156 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], <i4 1, i4 1>
157 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
158 ; CHECK-NEXT:    ret <2 x i4> [[R]]
160   %n0 = xor <2 x i4> %y, %x ; swapped order
161   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
162   %r  = xor <2 x i4> %n1, %y
163   ret <2 x i4> %r
166 define <2 x i4> @c_0_1_0 (<2 x i4> %x, <2 x i4> %y) {
167 ; CHECK-LABEL: @c_0_1_0(
168 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], <i4 -2, i4 -2>
169 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], <i4 1, i4 1>
170 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
171 ; CHECK-NEXT:    ret <2 x i4> [[R]]
173   %n0 = xor <2 x i4> %x, %y
174   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
175   %r  = xor <2 x i4> %n1, %x ; %x instead of %y
176   ret <2 x i4> %r
179 define <2 x i4> @c_0_0_1 () {
180 ; CHECK-LABEL: @c_0_0_1(
181 ; CHECK-NEXT:    [[X:%.*]] = call <2 x i4> @gen4()
182 ; CHECK-NEXT:    [[Y:%.*]] = call <2 x i4> @gen4()
183 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X]], <i4 -2, i4 -2>
184 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y]], <i4 1, i4 1>
185 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
186 ; CHECK-NEXT:    ret <2 x i4> [[R]]
188   %x  = call <2 x i4> @gen4()
189   %y  = call <2 x i4> @gen4()
190   %n0 = xor <2 x i4> %x, %y
191   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
192   %r  = xor <2 x i4> %y, %n1 ; swapped order
193   ret <2 x i4> %r
196 define <2 x i4> @c_1_1_0 (<2 x i4> %x, <2 x i4> %y) {
197 ; CHECK-LABEL: @c_1_1_0(
198 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], <i4 -2, i4 -2>
199 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], <i4 1, i4 1>
200 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
201 ; CHECK-NEXT:    ret <2 x i4> [[R]]
203   %n0 = xor <2 x i4> %y, %x ; swapped order
204   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
205   %r  = xor <2 x i4> %n1, %x ; %x instead of %y
206   ret <2 x i4> %r
209 define <2 x i4> @c_1_0_1 (<2 x i4> %x) {
210 ; CHECK-LABEL: @c_1_0_1(
211 ; CHECK-NEXT:    [[Y:%.*]] = call <2 x i4> @gen4()
212 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 -2, i4 -2>
213 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y]], <i4 1, i4 1>
214 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
215 ; CHECK-NEXT:    ret <2 x i4> [[R]]
217   %y  = call <2 x i4> @gen4()
218   %n0 = xor <2 x i4> %y, %x ; swapped order
219   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
220   %r  = xor <2 x i4> %y, %n1 ; swapped order
221   ret <2 x i4> %r
224 define <2 x i4> @c_0_1_1 (<2 x i4> %y) {
225 ; CHECK-LABEL: @c_0_1_1(
226 ; CHECK-NEXT:    [[X:%.*]] = call <2 x i4> @gen4()
227 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], <i4 -2, i4 -2>
228 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X]], <i4 1, i4 1>
229 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
230 ; CHECK-NEXT:    ret <2 x i4> [[R]]
232   %x  = call <2 x i4> @gen4()
233   %n0 = xor <2 x i4> %x, %y
234   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
235   %r  = xor <2 x i4> %x, %n1 ; swapped order, %x instead of %y
236   ret <2 x i4> %r
239 define <2 x i4> @c_1_1_1 () {
240 ; CHECK-LABEL: @c_1_1_1(
241 ; CHECK-NEXT:    [[X:%.*]] = call <2 x i4> @gen4()
242 ; CHECK-NEXT:    [[Y:%.*]] = call <2 x i4> @gen4()
243 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[Y]], <i4 -2, i4 -2>
244 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X]], <i4 1, i4 1>
245 ; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]]
246 ; CHECK-NEXT:    ret <2 x i4> [[R]]
248   %x  = call <2 x i4> @gen4()
249   %y  = call <2 x i4> @gen4()
250   %n0 = xor <2 x i4> %y, %x ; swapped order
251   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
252   %r  = xor <2 x i4> %x, %n1 ; swapped order, %x instead of %y
253   ret <2 x i4> %r
256 define <2 x i4> @commutativity_constant_14_vary(<2 x i4> %y, <2 x i4> %mask) {
257 ; CHECK-LABEL: @commutativity_constant_14_vary(
258 ; CHECK-NEXT:    [[R:%.*]] = and <2 x i4> [[Y:%.*]], <i4 -2, i4 -2>
259 ; CHECK-NEXT:    ret <2 x i4> [[R]]
261   %n0 = xor <2 x i4> %y, <i4 14, i4 14> ; %x
262   %n1 = and <2 x i4> %n0, <i4 1, i4 1>
263   %r = xor <2 x i4> %y, %n1 ; swapped
264   ret <2 x i4> %r
267 ; ============================================================================ ;
268 ; Negative tests. Should not be folded.
269 ; ============================================================================ ;
271 ; One use only.
273 declare void @use4(<2 x i4>)
275 define <2 x i4> @n_oneuse_D (<2 x i4> %x, <2 x i4> %y) {
276 ; CHECK-LABEL: @n_oneuse_D(
277 ; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
278 ; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], <i4 -2, i4 -2>
279 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
280 ; CHECK-NEXT:    call void @use4(<2 x i4> [[N0]])
281 ; CHECK-NEXT:    ret <2 x i4> [[R]]
283   %n0 = xor <2 x i4> %x, %y ; two uses of %n0, which is going to be replaced
284   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2>
285   %r  = xor <2 x i4> %n1, %y
286   call void @use4(<2 x i4> %n0)
287   ret <2 x i4> %r
290 define <2 x i4> @n_oneuse_A (<2 x i4> %x, <2 x i4> %y) {
291 ; CHECK-LABEL: @n_oneuse_A(
292 ; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
293 ; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], <i4 -2, i4 -2>
294 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
295 ; CHECK-NEXT:    call void @use4(<2 x i4> [[N1]])
296 ; CHECK-NEXT:    ret <2 x i4> [[R]]
298   %n0 = xor <2 x i4> %x, %y
299   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2> ; two uses of %n1, which is going to be replaced
300   %r  = xor <2 x i4> %n1, %y
301   call void @use4(<2 x i4> %n1)
302   ret <2 x i4> %r
305 define <2 x i4> @n_oneuse_AD (<2 x i4> %x, <2 x i4> %y) {
306 ; CHECK-LABEL: @n_oneuse_AD(
307 ; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
308 ; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], <i4 -2, i4 -2>
309 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
310 ; CHECK-NEXT:    call void @use4(<2 x i4> [[N0]])
311 ; CHECK-NEXT:    call void @use4(<2 x i4> [[N1]])
312 ; CHECK-NEXT:    ret <2 x i4> [[R]]
314   %n0 = xor <2 x i4> %x, %y
315   %n1 = and <2 x i4> %n0, <i4 -2, i4 -2> ; two uses of %n1, which is going to be replaced
316   %r  = xor <2 x i4> %n1, %y
317   call void @use4(<2 x i4> %n0)
318   call void @use4(<2 x i4> %n1)
319   ret <2 x i4> %r
322 ; Mask is not constant
324 define <2 x i4> @n_var_mask (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
325 ; CHECK-LABEL: @n_var_mask(
326 ; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
327 ; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
328 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]]
329 ; CHECK-NEXT:    ret <2 x i4> [[R]]
331   %n0 = xor <2 x i4> %x, %y
332   %n1 = and <2 x i4> %n0, %m
333   %r  = xor <2 x i4> %n1, %y
334   ret <2 x i4> %r
337 ; Some third variable is used
339 define <2 x i4> @n_differenty(<2 x i4> %x, <2 x i4> %mask) {
340 ; CHECK-LABEL: @n_differenty(
341 ; CHECK-NEXT:    [[N0:%.*]] = xor <2 x i4> [[X:%.*]], <i4 -2, i4 7>
342 ; CHECK-NEXT:    [[N1:%.*]] = and <2 x i4> [[N0]], <i4 1, i4 1>
343 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[N1]], <i4 7, i4 -2>
344 ; CHECK-NEXT:    ret <2 x i4> [[R]]
346   %n0 = xor <2 x i4> %x, <i4 14, i4 7> ; %x
347   %n1 = and <2 x i4> %n0, <i4 1, i4 1>
348   %r = xor <2 x i4> %n1, <i4 7, i4 14>
349   ret <2 x i4> %r