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:    [[MASK_NOT:%.*]] = xor i4 [[MASK:%.*]], -1
56; CHECK-NEXT:    [[R:%.*]] = or i4 [[MASK_NOT]], [[Y:%.*]]
57; CHECK-NEXT:    ret i4 [[R]]
58;
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
64}
65
66define 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]]
72;
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
78}
79
80; ============================================================================ ;
81; Commutativity
82; ============================================================================ ;
83
84; Used to make sure that the IR complexity sorting does not interfere.
85declare i4 @gen4()
86
87; FIXME: should the  %n1 = and i4 %im, %n0  swapped order pattern be tested?
88
89define 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]]
95;
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
101}
102
103define 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]]
109;
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
115}
116
117define 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]]
125;
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
133}
134
135define 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]]
141;
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
147}
148
149define 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]]
156;
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
163}
164
165define 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]]
172;
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
179}
180
181define 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]]
189;
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
197}
198
199define 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]]
205;
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
211}
212
213define 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]]
219;
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
225}
226
227; ============================================================================ ;
228; Negative tests. Should not be folded.
229; ============================================================================ ;
230
231; One use only.
232
233declare void @use4(i4)
234
235define 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]]
242;
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
249}
250
251define 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]]
259;
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
266}
267
268define 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]]
277;
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
285}
286
287; Some third variable is used
288
289define 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]]
296;
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
302}
303
304define 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]]
311;
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
317}
318