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 constant)
5;   ((x ^ y) & M) ^ y
6; Unfold it to
7;   (x & M) | (y & ~M)
8
9define i4 @scalar0 (i4 %x, i4 %y) {
10; CHECK-LABEL: @scalar0(
11; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], 1
12; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y:%.*]], -2
13; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
14; CHECK-NEXT:    ret i4 [[R]]
15;
16  %n0 = xor i4 %x, %y
17  %n1 = and i4 %n0, 1
18  %r  = xor i4 %n1, %y
19  ret i4 %r
20}
21
22define i4 @scalar1 (i4 %x, i4 %y) {
23; CHECK-LABEL: @scalar1(
24; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], -2
25; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y:%.*]], 1
26; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
27; CHECK-NEXT:    ret i4 [[R]]
28;
29  %n0 = xor i4 %x, %y
30  %n1 = and i4 %n0, -2
31  %r  = xor i4 %n1, %y
32  ret i4 %r
33}
34
35; ============================================================================ ;
36; Various cases with %x and/or %y being a constant
37; ============================================================================ ;
38
39define i4 @in_constant_varx_mone(i4 %x, i4 %mask) {
40; CHECK-LABEL: @in_constant_varx_mone(
41; CHECK-NEXT:    [[R1:%.*]] = or i4 [[X:%.*]], -2
42; CHECK-NEXT:    ret i4 [[R1]]
43;
44  %n0 = xor i4 %x, -1 ; %x
45  %n1 = and i4 %n0, 1
46  %r = xor i4 %n1, -1
47  ret i4 %r
48}
49
50define i4 @in_constant_varx_14(i4 %x, i4 %mask) {
51; CHECK-LABEL: @in_constant_varx_14(
52; CHECK-NEXT:    [[R1:%.*]] = or i4 [[X:%.*]], -2
53; CHECK-NEXT:    ret i4 [[R1]]
54;
55  %n0 = xor i4 %x, 14 ; %x
56  %n1 = and i4 %n0, 1
57  %r = xor i4 %n1, 14
58  ret i4 %r
59}
60
61define i4 @in_constant_mone_vary(i4 %y, i4 %mask) {
62; CHECK-LABEL: @in_constant_mone_vary(
63; CHECK-NEXT:    [[N0:%.*]] = and i4 [[Y:%.*]], 1
64; CHECK-NEXT:    [[N1:%.*]] = xor i4 [[N0]], 1
65; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
66; CHECK-NEXT:    ret i4 [[R]]
67;
68  %n0 = xor i4 %y, -1 ; %x
69  %n1 = and i4 %n0, 1
70  %r = xor i4 %n1, %y
71  ret i4 %r
72}
73
74define i4 @in_constant_14_vary(i4 %y, i4 %mask) {
75; CHECK-LABEL: @in_constant_14_vary(
76; CHECK-NEXT:    [[R:%.*]] = and i4 [[Y:%.*]], -2
77; CHECK-NEXT:    ret i4 [[R]]
78;
79  %n0 = xor i4 %y, 14 ; %x
80  %n1 = and i4 %n0, 1
81  %r = xor i4 %n1, %y
82  ret i4 %r
83}
84
85; ============================================================================ ;
86; Commutativity
87; ============================================================================ ;
88
89; Used to make sure that the IR complexity sorting does not interfere.
90declare i4 @gen4()
91
92define i4 @c_1_0_0 (i4 %x, i4 %y) {
93; CHECK-LABEL: @c_1_0_0(
94; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], -2
95; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y:%.*]], 1
96; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
97; CHECK-NEXT:    ret i4 [[R]]
98;
99  %n0 = xor i4 %y, %x ; swapped order
100  %n1 = and i4 %n0, -2
101  %r  = xor i4 %n1, %y
102  ret i4 %r
103}
104
105define i4 @c_0_1_0 (i4 %x, i4 %y) {
106; CHECK-LABEL: @c_0_1_0(
107; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y:%.*]], -2
108; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X:%.*]], 1
109; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
110; CHECK-NEXT:    ret i4 [[R]]
111;
112  %n0 = xor i4 %x, %y
113  %n1 = and i4 %n0, -2
114  %r  = xor i4 %n1, %x ; %x instead of %y
115  ret i4 %r
116}
117
118define i4 @c_0_0_1 () {
119; CHECK-LABEL: @c_0_0_1(
120; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
121; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
122; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X]], -2
123; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y]], 1
124; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
125; CHECK-NEXT:    ret i4 [[R]]
126;
127  %x  = call i4 @gen4()
128  %y  = call i4 @gen4()
129  %n0 = xor i4 %x, %y
130  %n1 = and i4 %n0, -2
131  %r  = xor i4 %y, %n1 ; swapped order
132  ret i4 %r
133}
134
135define i4 @c_1_1_0 (i4 %x, i4 %y) {
136; CHECK-LABEL: @c_1_1_0(
137; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y:%.*]], -2
138; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X:%.*]], 1
139; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
140; CHECK-NEXT:    ret i4 [[R]]
141;
142  %n0 = xor i4 %y, %x ; swapped order
143  %n1 = and i4 %n0, -2
144  %r  = xor i4 %n1, %x ; %x instead of %y
145  ret i4 %r
146}
147
148define i4 @c_1_0_1 (i4 %x) {
149; CHECK-LABEL: @c_1_0_1(
150; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
151; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], -2
152; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y]], 1
153; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
154; CHECK-NEXT:    ret i4 [[R]]
155;
156  %y  = call i4 @gen4()
157  %n0 = xor i4 %y, %x ; swapped order
158  %n1 = and i4 %n0, -2
159  %r  = xor i4 %y, %n1 ; swapped order
160  ret i4 %r
161}
162
163define i4 @c_0_1_1 (i4 %y) {
164; CHECK-LABEL: @c_0_1_1(
165; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
166; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y:%.*]], -2
167; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X]], 1
168; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
169; CHECK-NEXT:    ret i4 [[R]]
170;
171  %x  = call i4 @gen4()
172  %n0 = xor i4 %x, %y
173  %n1 = and i4 %n0, -2
174  %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
175  ret i4 %r
176}
177
178define i4 @c_1_1_1 () {
179; CHECK-LABEL: @c_1_1_1(
180; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
181; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
182; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y]], -2
183; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X]], 1
184; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
185; CHECK-NEXT:    ret i4 [[R]]
186;
187  %x  = call i4 @gen4()
188  %y  = call i4 @gen4()
189  %n0 = xor i4 %y, %x ; swapped order
190  %n1 = and i4 %n0, -2
191  %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
192  ret i4 %r
193}
194
195define i4 @commutativity_constant_14_vary(i4 %y, i4 %mask) {
196; CHECK-LABEL: @commutativity_constant_14_vary(
197; CHECK-NEXT:    [[R:%.*]] = and i4 [[Y:%.*]], -2
198; CHECK-NEXT:    ret i4 [[R]]
199;
200  %n0 = xor i4 %y, 14 ; %x
201  %n1 = and i4 %n0, 1
202  %r = xor i4 %y, %n1 ; swapped
203  ret i4 %r
204}
205
206; ============================================================================ ;
207; Negative tests. Should not be folded.
208; ============================================================================ ;
209
210; One use only.
211
212declare void @use4(i4)
213
214define i4 @n_oneuse_D (i4 %x, i4 %y) {
215; CHECK-LABEL: @n_oneuse_D(
216; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
217; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
218; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
219; CHECK-NEXT:    call void @use4(i4 [[N0]])
220; CHECK-NEXT:    ret i4 [[R]]
221;
222  %n0 = xor i4 %x, %y ; two uses of %n0, which is going to be replaced
223  %n1 = and i4 %n0, -2
224  %r  = xor i4 %n1, %y
225  call void @use4(i4 %n0)
226  ret i4 %r
227}
228
229define i4 @n_oneuse_A (i4 %x, i4 %y) {
230; CHECK-LABEL: @n_oneuse_A(
231; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
232; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
233; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
234; CHECK-NEXT:    call void @use4(i4 [[N1]])
235; CHECK-NEXT:    ret i4 [[R]]
236;
237  %n0 = xor i4 %x, %y
238  %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced
239  %r  = xor i4 %n1, %y
240  call void @use4(i4 %n1)
241  ret i4 %r
242}
243
244define i4 @n_oneuse_AD (i4 %x, i4 %y) {
245; CHECK-LABEL: @n_oneuse_AD(
246; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
247; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
248; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
249; CHECK-NEXT:    call void @use4(i4 [[N0]])
250; CHECK-NEXT:    call void @use4(i4 [[N1]])
251; CHECK-NEXT:    ret i4 [[R]]
252;
253  %n0 = xor i4 %x, %y
254  %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced
255  %r  = xor i4 %n1, %y
256  call void @use4(i4 %n0)
257  call void @use4(i4 %n1)
258  ret i4 %r
259}
260
261; Mask is not constant
262
263define i4 @n_var_mask (i4 %x, i4 %y, i4 %m) {
264; CHECK-LABEL: @n_var_mask(
265; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
266; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[M:%.*]]
267; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
268; CHECK-NEXT:    ret i4 [[R]]
269;
270  %n0 = xor i4 %x, %y
271  %n1 = and i4 %n0, %m
272  %r  = xor i4 %n1, %y
273  ret i4 %r
274}
275
276; Some third variable is used
277
278define i4 @n_third_var (i4 %x, i4 %y, i4 %z) {
279; CHECK-LABEL: @n_third_var(
280; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
281; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
282; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
283; CHECK-NEXT:    ret i4 [[R]]
284;
285  %n0 = xor i4 %x, %y
286  %n1 = and i4 %n0, -2
287  %r  = xor i4 %n1, %z ; not %x or %y
288  ret i4 %r
289}
290