1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -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 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]]
15;
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
21}
22
23; ============================================================================ ;
24; Various cases with %x and/or %y being a constant
25; ============================================================================ ;
26
27define 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]]
31;
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
37}
38
39define 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]]
45;
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
51}
52
53define i4 @in_constant_mone_vary_invmask(i4 %y, i4 %mask) {
54; CHECK-LABEL: @in_constant_mone_vary_invmask(
55; CHECK-NEXT:    [[N1_DEMORGAN:%.*]] = or i4 [[Y:%.*]], [[MASK:%.*]]
56; CHECK-NEXT:    [[N1:%.*]] = xor i4 [[N1_DEMORGAN]], -1
57; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
58; CHECK-NEXT:    ret i4 [[R]]
59;
60  %notmask = xor i4 %mask, -1
61  %n0 = xor i4 -1, %y ; %x
62  %n1 = and i4 %n0, %notmask
63  %r = xor i4 %n1, %y
64  ret i4 %r
65}
66
67define i4 @in_constant_6_vary_invmask(i4 %y, i4 %mask) {
68; CHECK-LABEL: @in_constant_6_vary_invmask(
69; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
70; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
71; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
72; CHECK-NEXT:    ret i4 [[R]]
73;
74  %notmask = xor i4 %mask, -1
75  %n0 = xor i4 %y, 6 ; %x
76  %n1 = and i4 %n0, %notmask
77  %r = xor i4 %n1, %y
78  ret i4 %r
79}
80
81; ============================================================================ ;
82; Commutativity
83; ============================================================================ ;
84
85; Used to make sure that the IR complexity sorting does not interfere.
86declare i4 @gen4()
87
88; FIXME: should the  %n1 = and i4 %im, %n0  swapped order pattern be tested?
89
90define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
91; CHECK-LABEL: @c_1_0_0(
92; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
93; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
94; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
95; CHECK-NEXT:    ret i4 [[R]]
96;
97  %im = xor i4 %m, -1
98  %n0 = xor i4 %y, %x ; swapped order
99  %n1 = and i4 %n0, %im
100  %r  = xor i4 %n1, %y
101  ret i4 %r
102}
103
104define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
105; CHECK-LABEL: @c_0_1_0(
106; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
107; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
108; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
109; CHECK-NEXT:    ret i4 [[R]]
110;
111  %im = xor i4 %m, -1
112  %n0 = xor i4 %x, %y
113  %n1 = and i4 %n0, %im
114  %r  = xor i4 %n1, %x ; %x instead of %y
115  ret i4 %r
116}
117
118define i4 @c_0_0_1 (i4 %m) {
119; CHECK-LABEL: @c_0_0_1(
120; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
121; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
122; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y]]
123; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
124; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
125; CHECK-NEXT:    ret i4 [[R]]
126;
127  %im = xor i4 %m, -1
128  %x  = call i4 @gen4()
129  %y  = call i4 @gen4()
130  %n0 = xor i4 %x, %y
131  %n1 = and i4 %n0, %im
132  %r  = xor i4 %y, %n1 ; swapped order
133  ret i4 %r
134}
135
136define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
137; CHECK-LABEL: @c_1_1_0(
138; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
139; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
140; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
141; CHECK-NEXT:    ret i4 [[R]]
142;
143  %im = xor i4 %m, -1
144  %n0 = xor i4 %y, %x ; swapped order
145  %n1 = and i4 %n0, %im
146  %r  = xor i4 %n1, %x ; %x instead of %y
147  ret i4 %r
148}
149
150define i4 @c_1_0_1 (i4 %x, i4 %m) {
151; CHECK-LABEL: @c_1_0_1(
152; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
153; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
154; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
155; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
156; CHECK-NEXT:    ret i4 [[R]]
157;
158  %im = xor i4 %m, -1
159  %y  = call i4 @gen4()
160  %n0 = xor i4 %y, %x ; swapped order
161  %n1 = and i4 %n0, %im
162  %r  = xor i4 %y, %n1 ; swapped order
163  ret i4 %r
164}
165
166define i4 @c_0_1_1 (i4 %y, i4 %m) {
167; CHECK-LABEL: @c_0_1_1(
168; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
169; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
170; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
171; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
172; CHECK-NEXT:    ret i4 [[R]]
173;
174  %im = xor i4 %m, -1
175  %x  = call i4 @gen4()
176  %n0 = xor i4 %x, %y
177  %n1 = and i4 %n0, %im
178  %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
179  ret i4 %r
180}
181
182define i4 @c_1_1_1 (i4 %m) {
183; CHECK-LABEL: @c_1_1_1(
184; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
185; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
186; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X]]
187; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
188; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
189; CHECK-NEXT:    ret i4 [[R]]
190;
191  %im = xor i4 %m, -1
192  %x  = call i4 @gen4()
193  %y  = call i4 @gen4()
194  %n0 = xor i4 %y, %x ; swapped order
195  %n1 = and i4 %n0, %im
196  %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
197  ret i4 %r
198}
199
200define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
201; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
202; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], 6
203; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
204; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
205; CHECK-NEXT:    ret i4 [[R]]
206;
207  %notmask = xor i4 %mask, -1
208  %n0 = xor i4 %x, 6 ; %x
209  %n1 = and i4 %notmask, %n0 ; swapped
210  %r = xor i4 %n1, 6
211  ret i4 %r
212}
213
214define i4 @commutativity_constant_6_vary_invmask(i4 %y, i4 %mask) {
215; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
216; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
217; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
218; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
219; CHECK-NEXT:    ret i4 [[R]]
220;
221  %notmask = xor i4 %mask, -1
222  %n0 = xor i4 %y, 6 ; %x
223  %n1 = and i4 %notmask, %n0 ; swapped
224  %r = xor i4 %n1, %y
225  ret i4 %r
226}
227
228; ============================================================================ ;
229; Negative tests. Should not be folded.
230; ============================================================================ ;
231
232; One use only.
233
234declare void @use4(i4)
235
236define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
237; CHECK-LABEL: @n_oneuse_D_is_ok(
238; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
239; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
240; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
241; CHECK-NEXT:    call void @use4(i4 [[N0]])
242; CHECK-NEXT:    ret i4 [[R]]
243;
244  %im = xor i4 %m, -1
245  %n0 = xor i4 %x, %y ; two uses of %n0, THIS IS OK!
246  %n1 = and i4 %n0, %im
247  %r  = xor i4 %n1, %y
248  call void @use4(i4 %n0)
249  ret i4 %r
250}
251
252define i4 @n_oneuse_A (i4 %x, i4 %y, i4 %m) {
253; CHECK-LABEL: @n_oneuse_A(
254; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
255; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
256; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
257; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
258; CHECK-NEXT:    call void @use4(i4 [[N1]])
259; CHECK-NEXT:    ret i4 [[R]]
260;
261  %im = xor i4 %m, -1
262  %n0 = xor i4 %x, %y
263  %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
264  %r  = xor i4 %n1, %y
265  call void @use4(i4 %n1)
266  ret i4 %r
267}
268
269define i4 @n_oneuse_AD (i4 %x, i4 %y, i4 %m) {
270; CHECK-LABEL: @n_oneuse_AD(
271; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
272; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
273; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
274; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
275; CHECK-NEXT:    call void @use4(i4 [[N0]])
276; CHECK-NEXT:    call void @use4(i4 [[N1]])
277; CHECK-NEXT:    ret i4 [[R]]
278;
279  %im = xor i4 %m, -1
280  %n0 = xor i4 %x, %y
281  %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
282  %r  = xor i4 %n1, %y
283  call void @use4(i4 %n0)
284  call void @use4(i4 %n1)
285  ret i4 %r
286}
287
288; Some third variable is used
289
290define i4 @n_third_var (i4 %x, i4 %y, i4 %z, i4 %m) {
291; CHECK-LABEL: @n_third_var(
292; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
293; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
294; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
295; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
296; CHECK-NEXT:    ret i4 [[R]]
297;
298  %im = xor i4 %m, -1
299  %n0 = xor i4 %x, %y
300  %n1 = and i4 %n0, %im
301  %r  = xor i4 %n1, %z ; not %x or %y
302  ret i4 %r
303}
304
305define i4 @n_badxor (i4 %x, i4 %y, i4 %m) {
306; CHECK-LABEL: @n_badxor(
307; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], 1
308; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
309; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
310; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
311; CHECK-NEXT:    ret i4 [[R]]
312;
313  %im = xor i4 %m, 1 ; not -1
314  %n0 = xor i4 %x, %y
315  %n1 = and i4 %n0, %im
316  %r  = xor i4 %n1, %y
317  ret i4 %r
318}
319