[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / invert-variable-mask-in-masked-merge-scalar.ll
blobe1bda5903f6f5916c1a3fde3f6cde3bd1cabd8d6
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 not constant)
5 ;   ((x ^ y) & ~M) ^ y
6 ; We can de-invert the M:
7 ;   ((x ^ y) & M) ^ x
9 define i4 @scalar (i4 %x, i4 %y, i4 %m) {
10 ; CHECK-LABEL: @scalar(
11 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
12 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
13 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
14 ; CHECK-NEXT:    ret i4 [[R]]
16   %im = xor i4 %m, -1
17   %n0 = xor i4 %x, %y
18   %n1 = and i4 %n0, %im
19   %r  = xor i4 %n1, %y
20   ret i4 %r
23 ; ============================================================================ ;
24 ; Various cases with %x and/or %y being a constant
25 ; ============================================================================ ;
27 define i4 @in_constant_varx_mone_invmask(i4 %x, i4 %mask) {
28 ; CHECK-LABEL: @in_constant_varx_mone_invmask(
29 ; CHECK-NEXT:    [[N1_DEMORGAN:%.*]] = or i4 [[X:%.*]], [[MASK:%.*]]
30 ; CHECK-NEXT:    ret i4 [[N1_DEMORGAN]]
32   %notmask = xor i4 %mask, -1
33   %n0 = xor i4 %x, -1 ; %x
34   %n1 = and i4 %n0, %notmask
35   %r = xor i4 %n1, -1
36   ret i4 %r
39 define i4 @in_constant_varx_6_invmask(i4 %x, i4 %mask) {
40 ; CHECK-LABEL: @in_constant_varx_6_invmask(
41 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], 6
42 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
43 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
44 ; CHECK-NEXT:    ret i4 [[R]]
46   %notmask = xor i4 %mask, -1
47   %n0 = xor i4 %x, 6 ; %x
48   %n1 = and i4 %n0, %notmask
49   %r = xor i4 %n1, 6
50   ret i4 %r
53 define i4 @in_constant_mone_vary_invmask(i4 %y, i4 %mask) {
54 ; CHECK-LABEL: @in_constant_mone_vary_invmask(
55 ; CHECK-NEXT:    [[MASK_NOT:%.*]] = xor i4 [[MASK:%.*]], -1
56 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[MASK_NOT]], [[Y:%.*]]
57 ; CHECK-NEXT:    ret i4 [[R]]
59   %notmask = xor i4 %mask, -1
60   %n0 = xor i4 -1, %y ; %x
61   %n1 = and i4 %n0, %notmask
62   %r = xor i4 %n1, %y
63   ret i4 %r
66 define i4 @in_constant_6_vary_invmask(i4 %y, i4 %mask) {
67 ; CHECK-LABEL: @in_constant_6_vary_invmask(
68 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
69 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
70 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
71 ; CHECK-NEXT:    ret i4 [[R]]
73   %notmask = xor i4 %mask, -1
74   %n0 = xor i4 %y, 6 ; %x
75   %n1 = and i4 %n0, %notmask
76   %r = xor i4 %n1, %y
77   ret i4 %r
80 ; ============================================================================ ;
81 ; Commutativity
82 ; ============================================================================ ;
84 ; Used to make sure that the IR complexity sorting does not interfere.
85 declare i4 @gen4()
87 ; FIXME: should the  %n1 = and i4 %im, %n0  swapped order pattern be tested?
89 define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
90 ; CHECK-LABEL: @c_1_0_0(
91 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
92 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
93 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
94 ; CHECK-NEXT:    ret i4 [[R]]
96   %im = xor i4 %m, -1
97   %n0 = xor i4 %y, %x ; swapped order
98   %n1 = and i4 %n0, %im
99   %r  = xor i4 %n1, %y
100   ret i4 %r
103 define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
104 ; CHECK-LABEL: @c_0_1_0(
105 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
106 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
107 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
108 ; CHECK-NEXT:    ret i4 [[R]]
110   %im = xor i4 %m, -1
111   %n0 = xor i4 %x, %y
112   %n1 = and i4 %n0, %im
113   %r  = xor i4 %n1, %x ; %x instead of %y
114   ret i4 %r
117 define i4 @c_0_0_1 (i4 %m) {
118 ; CHECK-LABEL: @c_0_0_1(
119 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
120 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
121 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y]]
122 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
123 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
124 ; CHECK-NEXT:    ret i4 [[R]]
126   %im = xor i4 %m, -1
127   %x  = call i4 @gen4()
128   %y  = call i4 @gen4()
129   %n0 = xor i4 %x, %y
130   %n1 = and i4 %n0, %im
131   %r  = xor i4 %y, %n1 ; swapped order
132   ret i4 %r
135 define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
136 ; CHECK-LABEL: @c_1_1_0(
137 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
138 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
139 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
140 ; CHECK-NEXT:    ret i4 [[R]]
142   %im = xor i4 %m, -1
143   %n0 = xor i4 %y, %x ; swapped order
144   %n1 = and i4 %n0, %im
145   %r  = xor i4 %n1, %x ; %x instead of %y
146   ret i4 %r
149 define i4 @c_1_0_1 (i4 %x, i4 %m) {
150 ; CHECK-LABEL: @c_1_0_1(
151 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
152 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
153 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
154 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
155 ; CHECK-NEXT:    ret i4 [[R]]
157   %im = xor i4 %m, -1
158   %y  = call i4 @gen4()
159   %n0 = xor i4 %y, %x ; swapped order
160   %n1 = and i4 %n0, %im
161   %r  = xor i4 %y, %n1 ; swapped order
162   ret i4 %r
165 define i4 @c_0_1_1 (i4 %y, i4 %m) {
166 ; CHECK-LABEL: @c_0_1_1(
167 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
168 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
169 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
170 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
171 ; CHECK-NEXT:    ret i4 [[R]]
173   %im = xor i4 %m, -1
174   %x  = call i4 @gen4()
175   %n0 = xor i4 %x, %y
176   %n1 = and i4 %n0, %im
177   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
178   ret i4 %r
181 define i4 @c_1_1_1 (i4 %m) {
182 ; CHECK-LABEL: @c_1_1_1(
183 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
184 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
185 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X]]
186 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
187 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
188 ; CHECK-NEXT:    ret i4 [[R]]
190   %im = xor i4 %m, -1
191   %x  = call i4 @gen4()
192   %y  = call i4 @gen4()
193   %n0 = xor i4 %y, %x ; swapped order
194   %n1 = and i4 %n0, %im
195   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
196   ret i4 %r
199 define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
200 ; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
201 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], 6
202 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
203 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
204 ; CHECK-NEXT:    ret i4 [[R]]
206   %notmask = xor i4 %mask, -1
207   %n0 = xor i4 %x, 6 ; %x
208   %n1 = and i4 %notmask, %n0 ; swapped
209   %r = xor i4 %n1, 6
210   ret i4 %r
213 define i4 @commutativity_constant_6_vary_invmask(i4 %y, i4 %mask) {
214 ; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
215 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
216 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
217 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
218 ; CHECK-NEXT:    ret i4 [[R]]
220   %notmask = xor i4 %mask, -1
221   %n0 = xor i4 %y, 6 ; %x
222   %n1 = and i4 %notmask, %n0 ; swapped
223   %r = xor i4 %n1, %y
224   ret i4 %r
227 ; ============================================================================ ;
228 ; Negative tests. Should not be folded.
229 ; ============================================================================ ;
231 ; One use only.
233 declare void @use4(i4)
235 define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
236 ; CHECK-LABEL: @n_oneuse_D_is_ok(
237 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
238 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
239 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
240 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
241 ; CHECK-NEXT:    ret i4 [[R]]
243   %im = xor i4 %m, -1
244   %n0 = xor i4 %x, %y ; two uses of %n0, THIS IS OK!
245   %n1 = and i4 %n0, %im
246   %r  = xor i4 %n1, %y
247   call void @use4(i4 %n0)
248   ret i4 %r
251 define i4 @n_oneuse_A (i4 %x, i4 %y, i4 %m) {
252 ; CHECK-LABEL: @n_oneuse_A(
253 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
254 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
255 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
256 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
257 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
258 ; CHECK-NEXT:    ret i4 [[R]]
260   %im = xor i4 %m, -1
261   %n0 = xor i4 %x, %y
262   %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
263   %r  = xor i4 %n1, %y
264   call void @use4(i4 %n1)
265   ret i4 %r
268 define i4 @n_oneuse_AD (i4 %x, i4 %y, i4 %m) {
269 ; CHECK-LABEL: @n_oneuse_AD(
270 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
271 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
272 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
273 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
274 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
275 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
276 ; CHECK-NEXT:    ret i4 [[R]]
278   %im = xor i4 %m, -1
279   %n0 = xor i4 %x, %y
280   %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
281   %r  = xor i4 %n1, %y
282   call void @use4(i4 %n0)
283   call void @use4(i4 %n1)
284   ret i4 %r
287 ; Some third variable is used
289 define i4 @n_third_var (i4 %x, i4 %y, i4 %z, i4 %m) {
290 ; CHECK-LABEL: @n_third_var(
291 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
292 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
293 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
294 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
295 ; CHECK-NEXT:    ret i4 [[R]]
297   %im = xor i4 %m, -1
298   %n0 = xor i4 %x, %y
299   %n1 = and i4 %n0, %im
300   %r  = xor i4 %n1, %z ; not %x or %y
301   ret i4 %r
304 define i4 @n_badxor (i4 %x, i4 %y, i4 %m) {
305 ; CHECK-LABEL: @n_badxor(
306 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], 1
307 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
308 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
309 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
310 ; CHECK-NEXT:    ret i4 [[R]]
312   %im = xor i4 %m, 1 ; not -1
313   %n0 = xor i4 %x, %y
314   %n1 = and i4 %n0, %im
315   %r  = xor i4 %n1, %y
316   ret i4 %r