[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / unfold-masked-merge-with-const-mask-vector.ll
blobef27891c1a8099ca7cc89938636cfa3404296ba5
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 -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
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 -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>
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:    [[R1:%.*]] = or <2 x i4> [[Y:%.*]], <i4 1, 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
106   ret <2 x i4> %r
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:%.*]], <i4 -2, 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
117   ret <2 x i4> %r
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:%.*]], <i4 -2, i4 -2>
123 ; CHECK-NEXT:    [[R:%.*]] = or <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
129   ret <2 x i4> %r
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
141   ret <3 x i4> %r
144 ; ============================================================================ ;
145 ; Commutativity
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:%.*]], <i4 -2, i4 -2>
154 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], <i4 1, i4 1>
155 ; CHECK-NEXT:    [[R:%.*]] = or <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
161   ret <2 x i4> %r
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:%.*]], <i4 -2, i4 -2>
167 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], <i4 1, i4 1>
168 ; CHECK-NEXT:    [[R:%.*]] = or <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
174   ret <2 x i4> %r
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]], <i4 -2, i4 -2>
182 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y]], <i4 1, i4 1>
183 ; CHECK-NEXT:    [[R:%.*]] = or <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
191   ret <2 x i4> %r
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:%.*]], <i4 -2, i4 -2>
197 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], <i4 1, i4 1>
198 ; CHECK-NEXT:    [[R:%.*]] = or <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
204   ret <2 x i4> %r
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:%.*]], <i4 -2, i4 -2>
211 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[Y]], <i4 1, i4 1>
212 ; CHECK-NEXT:    [[R:%.*]] = or <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
219   ret <2 x i4> %r
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:%.*]], <i4 -2, i4 -2>
226 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X]], <i4 1, i4 1>
227 ; CHECK-NEXT:    [[R:%.*]] = or <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
234   ret <2 x i4> %r
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]], <i4 -2, i4 -2>
242 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i4> [[X]], <i4 1, i4 1>
243 ; CHECK-NEXT:    [[R:%.*]] = or <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
251   ret <2 x i4> %r
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:%.*]], <i4 -2, 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
262   ret <2 x i4> %r
265 ; ============================================================================ ;
266 ; Negative tests. Should not be folded.
267 ; ============================================================================ ;
269 ; One use only.
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]], <i4 -2, 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)
285   ret <2 x i4> %r
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]], <i4 -2, 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)
300   ret <2 x i4> %r
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]], <i4 -2, 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)
317   ret <2 x i4> %r
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
332   ret <2 x i4> %r
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]], <i4 1, 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>
347   ret <2 x i4> %r