xref: /llvm-project/llvm/test/Transforms/InstCombine/free-inversion.ll (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare i8 @llvm.smin.i8(i8, i8)
5declare i8 @llvm.umin.i8(i8, i8)
6declare i8 @llvm.smax.i8(i8, i8)
7declare i8 @llvm.umax.i8(i8, i8)
8
9declare void @llvm.assume(i1)
10
11declare void @use.i8(i8)
12declare void @use.i1(i1)
13
14define i8 @xor_1(i8 %a, i1 %c, i8 %x, i8 %y) {
15; CHECK-LABEL: @xor_1(
16; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
17; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
18; CHECK-NEXT:    [[NOT_BA:%.*]] = xor i8 [[TMP2]], [[A:%.*]]
19; CHECK-NEXT:    ret i8 [[NOT_BA]]
20;
21  %nx = xor i8 %x, -1
22  %yy = xor i8 %y, 123
23  %b = select i1 %c, i8 %nx, i8 %yy
24  %ba = xor i8 %b, %a
25  %not_ba = xor i8 %ba, -1
26  ret i8 %not_ba
27}
28
29define i8 @xor_2(i8 %a, i1 %c, i8 %x, i8 %y) {
30; CHECK-LABEL: @xor_2(
31; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
32; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
33; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i8 [[A:%.*]], [[TMP2]]
34; CHECK-NEXT:    ret i8 [[NOT_AB]]
35;
36  %nx = xor i8 %x, -1
37  %yy = xor i8 %y, 123
38  %b = select i1 %c, i8 %nx, i8 %yy
39  %ab = xor i8 %a, %b
40  %not_ab = xor i8 %ab, -1
41  ret i8 %not_ab
42}
43
44define i8 @xor_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
45; CHECK-LABEL: @xor_fail(
46; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
47; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[Y:%.*]]
48; CHECK-NEXT:    [[AB:%.*]] = xor i8 [[A:%.*]], [[B]]
49; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i8 [[AB]], -1
50; CHECK-NEXT:    ret i8 [[NOT_AB]]
51;
52  %nx = xor i8 %x, -1
53  %b = select i1 %c, i8 %nx, i8 %y
54  %ab = xor i8 %a, %b
55  %not_ab = xor i8 %ab, -1
56  ret i8 %not_ab
57}
58
59define i8 @add_1(i8 %a, i1 %c, i8 %x, i8 %y) {
60; CHECK-LABEL: @add_1(
61; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
62; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
63; CHECK-NEXT:    [[NOT_BA:%.*]] = sub i8 [[TMP2]], [[A:%.*]]
64; CHECK-NEXT:    ret i8 [[NOT_BA]]
65;
66  %nx = xor i8 %x, -1
67  %yy = xor i8 %y, 123
68  %b = select i1 %c, i8 %nx, i8 %yy
69  %ba = add i8 %b, %a
70  %not_ba = xor i8 %ba, -1
71  ret i8 %not_ba
72}
73
74define i8 @add_2(i8 %a, i1 %c, i8 %x, i8 %y) {
75; CHECK-LABEL: @add_2(
76; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
77; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
78; CHECK-NEXT:    [[NOT_AB:%.*]] = sub i8 [[TMP2]], [[A:%.*]]
79; CHECK-NEXT:    ret i8 [[NOT_AB]]
80;
81  %nx = xor i8 %x, -1
82  %yy = xor i8 %y, 123
83  %b = select i1 %c, i8 %nx, i8 %yy
84  %ab = add i8 %a, %b
85  %not_ab = xor i8 %ab, -1
86  ret i8 %not_ab
87}
88
89define i8 @add_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
90; CHECK-LABEL: @add_fail(
91; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], [[A:%.*]]
92; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 123
93; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
94; CHECK-NEXT:    [[AB:%.*]] = add i8 [[A]], [[B]]
95; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i8 [[AB]], -1
96; CHECK-NEXT:    ret i8 [[NOT_AB]]
97;
98  %nx = xor i8 %x, %a
99  %yy = xor i8 %y, 123
100  %b = select i1 %c, i8 %nx, i8 %yy
101  %ab = add i8 %a, %b
102  %not_ab = xor i8 %ab, -1
103  ret i8 %not_ab
104}
105
106define i8 @sub_1(i8 %a, i1 %c, i8 %x, i8 %y) {
107; CHECK-LABEL: @sub_1(
108; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
109; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
110; CHECK-NEXT:    [[NOT_BA:%.*]] = add i8 [[TMP2]], [[A:%.*]]
111; CHECK-NEXT:    ret i8 [[NOT_BA]]
112;
113  %nx = xor i8 %x, -1
114  %yy = xor i8 %y, 123
115  %b = select i1 %c, i8 %nx, i8 %yy
116  %ba = sub i8 %b, %a
117  %not_ba = xor i8 %ba, -1
118  ret i8 %not_ba
119}
120
121define i8 @sub_2(i8 %a, i1 %c, i8 %x, i8 %y) {
122; CHECK-LABEL: @sub_2(
123; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
124; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
125; CHECK-NEXT:    [[TMP3:%.*]] = add i8 [[TMP2]], [[A:%.*]]
126; CHECK-NEXT:    [[NOT_AB:%.*]] = sub i8 -2, [[TMP3]]
127; CHECK-NEXT:    ret i8 [[NOT_AB]]
128;
129  %nx = xor i8 %x, -1
130  %yy = xor i8 %y, 123
131  %b = select i1 %c, i8 %nx, i8 %yy
132  %ab = sub i8 %a, %b
133  %not_ab = xor i8 %ab, -1
134  ret i8 %not_ab
135}
136
137; Same as above but with a type larger than i64 to make sure we create -2
138; correctly.
139define i128 @sub_3(i128 %a, i1 %c, i128 %x, i128 %y) {
140; CHECK-LABEL: @sub_3(
141; CHECK-NEXT:    [[TMP1:%.*]] = xor i128 [[Y:%.*]], -124
142; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i128 [[X:%.*]], i128 [[TMP1]]
143; CHECK-NEXT:    [[TMP3:%.*]] = add i128 [[TMP2]], [[A:%.*]]
144; CHECK-NEXT:    [[NOT_AB:%.*]] = sub i128 -2, [[TMP3]]
145; CHECK-NEXT:    ret i128 [[NOT_AB]]
146;
147  %nx = xor i128 %x, -1
148  %yy = xor i128 %y, 123
149  %b = select i1 %c, i128 %nx, i128 %yy
150  %ab = sub i128 %a, %b
151  %not_ab = xor i128 %ab, -1
152  ret i128 %not_ab
153}
154
155define i8 @sub_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
156; CHECK-LABEL: @sub_fail(
157; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
158; CHECK-NEXT:    call void @use.i8(i8 [[NX]])
159; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
160; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X]], i8 [[TMP1]]
161; CHECK-NEXT:    [[NOT_BA:%.*]] = add i8 [[TMP2]], [[A:%.*]]
162; CHECK-NEXT:    ret i8 [[NOT_BA]]
163;
164  %nx = xor i8 %x, -1
165  %yy = xor i8 %y, 123
166  call void @use.i8(i8 %nx)
167  %b = select i1 %c, i8 %nx, i8 %yy
168  %ba = sub i8 %b, %a
169  %not_ba = xor i8 %ba, -1
170  ret i8 %not_ba
171}
172
173define i8 @ashr_1(i8 %a, i1 %c, i8 %x, i8 %y) {
174; CHECK-LABEL: @ashr_1(
175; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
176; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
177; CHECK-NEXT:    [[NOT_BA:%.*]] = ashr i8 [[TMP2]], [[A:%.*]]
178; CHECK-NEXT:    ret i8 [[NOT_BA]]
179;
180  %nx = xor i8 %x, -1
181  %yy = xor i8 %y, 123
182  %b = select i1 %c, i8 %nx, i8 %yy
183  %ba = ashr i8 %b, %a
184  %not_ba = xor i8 %ba, -1
185  ret i8 %not_ba
186}
187
188define i8 @ashr_2_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
189; CHECK-LABEL: @ashr_2_fail(
190; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
191; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 123
192; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
193; CHECK-NEXT:    [[AB:%.*]] = ashr i8 [[A:%.*]], [[B]]
194; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i8 [[AB]], -1
195; CHECK-NEXT:    ret i8 [[NOT_AB]]
196;
197  %nx = xor i8 %x, -1
198  %yy = xor i8 %y, 123
199  %b = select i1 %c, i8 %nx, i8 %yy
200  %ab = ashr i8 %a, %b
201  %not_ab = xor i8 %ab, -1
202  ret i8 %not_ab
203}
204
205define i8 @select_1(i1 %cc, i8 %na, i8 %aa, i1 %c, i8 %x, i8 %y) {
206; CHECK-LABEL: @select_1(
207; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[NA:%.*]], [[AA:%.*]]
208; CHECK-NEXT:    [[TMP2:%.*]] = xor i8 [[TMP1]], -46
209; CHECK-NEXT:    [[TMP3:%.*]] = xor i8 [[Y:%.*]], -124
210; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP3]]
211; CHECK-NEXT:    [[NOT_AB:%.*]] = select i1 [[CC:%.*]], i8 [[TMP2]], i8 [[TMP4]]
212; CHECK-NEXT:    ret i8 [[NOT_AB]]
213;
214  %nx = xor i8 %x, -1
215  %yy = xor i8 %y, 123
216  %b = select i1 %c, i8 %nx, i8 %yy
217  %nna = xor i8 %na, 45
218  %a = xor i8 %aa, %nna
219  %ab = select i1 %cc, i8 %a, i8 %b
220  %not_ab = xor i8 %ab, -1
221  ret i8 %not_ab
222}
223
224define i8 @select_2(i1 %cc, i8 %na, i1 %c, i8 %x, i8 %y) {
225; CHECK-LABEL: @select_2(
226; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
227; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
228; CHECK-NEXT:    [[TMP3:%.*]] = xor i8 [[NA:%.*]], -46
229; CHECK-NEXT:    [[NOT_BA:%.*]] = select i1 [[CC:%.*]], i8 [[TMP2]], i8 [[TMP3]]
230; CHECK-NEXT:    ret i8 [[NOT_BA]]
231;
232  %nx = xor i8 %x, -1
233  %yy = xor i8 %y, 123
234  %b = select i1 %c, i8 %nx, i8 %yy
235  %a = xor i8 %na, 45
236  %ba = select i1 %cc, i8 %b, i8 %a
237  %not_ba = xor i8 %ba, -1
238  ret i8 %not_ba
239}
240
241define i1 @select_logic_or_fail(i1 %cc, i1 %c, i1 %x, i8 %y) {
242; CHECK-LABEL: @select_logic_or_fail(
243; CHECK-NEXT:    [[NX:%.*]] = xor i1 [[X:%.*]], true
244; CHECK-NEXT:    [[YY:%.*]] = icmp eq i8 [[Y:%.*]], 123
245; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i1 [[NX]], i1 [[YY]]
246; CHECK-NEXT:    [[AB:%.*]] = select i1 [[CC:%.*]], i1 [[B]], i1 false
247; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i1 [[AB]], true
248; CHECK-NEXT:    ret i1 [[NOT_AB]]
249;
250  %nx = xor i1 %x, -1
251  %yy = icmp eq i8 %y, 123
252  %b = select i1 %c, i1 %nx, i1 %yy
253  %ab = select i1 %cc, i1 %b, i1 false
254  %not_ab = xor i1 %ab, -1
255  ret i1 %not_ab
256}
257
258define i1 @select_logic_and_fail(i1 %cc, i1 %c, i1 %x, i8 %y) {
259; CHECK-LABEL: @select_logic_and_fail(
260; CHECK-NEXT:    [[NX:%.*]] = xor i1 [[X:%.*]], true
261; CHECK-NEXT:    [[YY:%.*]] = icmp eq i8 [[Y:%.*]], 123
262; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i1 [[NX]], i1 [[YY]]
263; CHECK-NEXT:    [[AB:%.*]] = select i1 [[CC:%.*]], i1 true, i1 [[B]]
264; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i1 [[AB]], true
265; CHECK-NEXT:    ret i1 [[NOT_AB]]
266;
267  %nx = xor i1 %x, -1
268  %yy = icmp eq i8 %y, 123
269  %b = select i1 %c, i1 %nx, i1 %yy
270  %ab = select i1 %cc, i1 true, i1 %b
271  %not_ab = xor i1 %ab, -1
272  ret i1 %not_ab
273}
274
275define i8 @smin_1(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) {
276; CHECK-LABEL: @smin_1(
277; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[NA:%.*]], [[AA:%.*]]
278; CHECK-NEXT:    [[TMP2:%.*]] = xor i8 [[Y:%.*]], -124
279; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP2]]
280; CHECK-NEXT:    [[NOT_AB:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP3]])
281; CHECK-NEXT:    ret i8 [[NOT_AB]]
282;
283  %nx = xor i8 %x, -1
284  %yy = xor i8 %y, 123
285  %b = select i1 %c, i8 %nx, i8 %yy
286  %nna = xor i8 %na, -1
287  %a = add i8 %aa, %nna
288  %ab = call i8 @llvm.smin.i8(i8 %a, i8 %b)
289  %not_ab = xor i8 %ab, -1
290  ret i8 %not_ab
291}
292
293define i8 @smin_1_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
294; CHECK-LABEL: @smin_1_fail(
295; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
296; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 123
297; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
298; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.smin.i8(i8 [[A:%.*]], i8 [[B]])
299; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i8 [[AB]], -1
300; CHECK-NEXT:    ret i8 [[NOT_AB]]
301;
302  %nx = xor i8 %x, -1
303  %yy = xor i8 %y, 123
304  %b = select i1 %c, i8 %nx, i8 %yy
305  %ab = call i8 @llvm.smin.i8(i8 %a, i8 %b)
306  %not_ab = xor i8 %ab, -1
307  ret i8 %not_ab
308}
309
310define i8 @umin_1_fail(i1 %c, i8 %x, i8 %y) {
311; CHECK-LABEL: @umin_1_fail(
312; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
313; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[Y:%.*]]
314; CHECK-NEXT:    [[BA:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 85)
315; CHECK-NEXT:    [[NOT_BA:%.*]] = xor i8 [[BA]], -1
316; CHECK-NEXT:    ret i8 [[NOT_BA]]
317;
318  %nx = xor i8 %x, -1
319  %b = select i1 %c, i8 %nx, i8 %y
320  %ba = call i8 @llvm.umin.i8(i8 %b, i8 85)
321  %not_ba = xor i8 %ba, -1
322  ret i8 %not_ba
323}
324
325define i8 @smax_1(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) {
326; CHECK-LABEL: @smax_1(
327; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[NA:%.*]], [[AA:%.*]]
328; CHECK-NEXT:    [[TMP2:%.*]] = xor i8 [[Y:%.*]], -124
329; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP2]]
330; CHECK-NEXT:    [[NOT_AB:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP1]], i8 [[TMP3]])
331; CHECK-NEXT:    ret i8 [[NOT_AB]]
332;
333  %nx = xor i8 %x, -1
334  %yy = xor i8 %y, 123
335  %b = select i1 %c, i8 %nx, i8 %yy
336  %nna = xor i8 %na, -1
337  %a = sub i8 %nna, %aa
338  %ab = call i8 @llvm.smax.i8(i8 %a, i8 %b)
339  %not_ab = xor i8 %ab, -1
340  ret i8 %not_ab
341}
342
343define i8 @smax_1_fail(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) {
344; CHECK-LABEL: @smax_1_fail(
345; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
346; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 123
347; CHECK-NEXT:    call void @use.i8(i8 [[YY]])
348; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
349; CHECK-NEXT:    [[NNA:%.*]] = xor i8 [[NA:%.*]], -1
350; CHECK-NEXT:    [[A:%.*]] = sub i8 [[NNA]], [[AA:%.*]]
351; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 [[B]])
352; CHECK-NEXT:    [[NOT_AB:%.*]] = xor i8 [[AB]], -1
353; CHECK-NEXT:    ret i8 [[NOT_AB]]
354;
355  %nx = xor i8 %x, -1
356  %yy = xor i8 %y, 123
357  call void @use.i8(i8 %yy)
358  %b = select i1 %c, i8 %nx, i8 %yy
359  %nna = xor i8 %na, -1
360  %a = sub i8 %nna, %aa
361  %ab = call i8 @llvm.smax.i8(i8 %a, i8 %b)
362  %not_ab = xor i8 %ab, -1
363  ret i8 %not_ab
364}
365
366define i8 @umax_1(i8 %na, i1 %c, i8 %x, i8 %y) {
367; CHECK-LABEL: @umax_1(
368; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
369; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
370; CHECK-NEXT:    [[NOT_BA:%.*]] = call i8 @llvm.umin.i8(i8 [[TMP2]], i8 -86)
371; CHECK-NEXT:    ret i8 [[NOT_BA]]
372;
373  %nx = xor i8 %x, -1
374  %yy = xor i8 %y, 123
375  %b = select i1 %c, i8 %nx, i8 %yy
376  %ba = call i8 @llvm.umax.i8(i8 %b, i8 85)
377  %not_ba = xor i8 %ba, -1
378  ret i8 %not_ba
379}
380
381define i8 @umax_1_fail(i8 %na, i1 %c, i8 %x, i8 %y) {
382; CHECK-LABEL: @umax_1_fail(
383; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
384; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 123
385; CHECK-NEXT:    [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
386; CHECK-NEXT:    call void @use.i8(i8 [[B]])
387; CHECK-NEXT:    [[BA:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 85)
388; CHECK-NEXT:    [[NOT_BA:%.*]] = xor i8 [[BA]], -1
389; CHECK-NEXT:    ret i8 [[NOT_BA]]
390;
391  %nx = xor i8 %x, -1
392  %yy = xor i8 %y, 123
393  %b = select i1 %c, i8 %nx, i8 %yy
394  call void @use.i8(i8 %b)
395  %ba = call i8 @llvm.umax.i8(i8 %b, i8 85)
396  %not_ba = xor i8 %ba, -1
397  ret i8 %not_ba
398}
399
400define i8 @sub_both_freely_invertable_always(i8 %x, i8 %y) {
401; CHECK-LABEL: @sub_both_freely_invertable_always(
402; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
403; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
404; CHECK-NEXT:    [[R:%.*]] = sub i8 [[XX]], [[YY]]
405; CHECK-NEXT:    ret i8 [[R]]
406;
407  %xx = xor i8 %x, 123
408  %yy = xor i8 %y, 45
409  %r = sub i8 %xx, %yy
410  ret i8 %r
411}
412
413define i8 @add_both_freely_invertable_always(i8 %x, i8 %y) {
414; CHECK-LABEL: @add_both_freely_invertable_always(
415; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
416; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
417; CHECK-NEXT:    [[R:%.*]] = add i8 [[XX]], [[YY]]
418; CHECK-NEXT:    ret i8 [[R]]
419;
420  %xx = xor i8 %x, 123
421  %yy = xor i8 %y, 45
422  %r = add i8 %xx, %yy
423  ret i8 %r
424}
425
426define i8 @xor_both_freely_invertable_always(i8 %x, i8 %y) {
427; CHECK-LABEL: @xor_both_freely_invertable_always(
428; CHECK-NEXT:    [[XX:%.*]] = add i8 [[X:%.*]], 123
429; CHECK-NEXT:    [[YY:%.*]] = add i8 [[Y:%.*]], 45
430; CHECK-NEXT:    [[R:%.*]] = xor i8 [[XX]], [[YY]]
431; CHECK-NEXT:    ret i8 [[R]]
432;
433  %xx = add i8 %x, 123
434  %yy = add i8 %y, 45
435  %r = xor i8 %xx, %yy
436  ret i8 %r
437}
438
439define i8 @ashr_both_freely_invertable_always(i8 %x, i8 %y) {
440; CHECK-LABEL: @ashr_both_freely_invertable_always(
441; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
442; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
443; CHECK-NEXT:    [[R:%.*]] = ashr i8 [[XX]], [[YY]]
444; CHECK-NEXT:    ret i8 [[R]]
445;
446  %xx = xor i8 %x, 123
447  %yy = xor i8 %y, 45
448  %r = ashr i8 %xx, %yy
449  ret i8 %r
450}
451
452define i8 @select_both_freely_invertable_always(i1 %cc, i8 %x, i8 %y) {
453; CHECK-LABEL: @select_both_freely_invertable_always(
454; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
455; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
456; CHECK-NEXT:    [[R:%.*]] = select i1 [[CC:%.*]], i8 [[XX]], i8 [[YY]]
457; CHECK-NEXT:    ret i8 [[R]]
458;
459  %xx = xor i8 %x, 123
460  %yy = xor i8 %y, 45
461  %r = select i1 %cc, i8 %xx, i8 %yy
462  ret i8 %r
463}
464
465define i8 @umin_both_freely_invertable_always(i8 %x, i8 %y) {
466; CHECK-LABEL: @umin_both_freely_invertable_always(
467; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
468; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
469; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[XX]], i8 [[YY]])
470; CHECK-NEXT:    ret i8 [[R]]
471;
472  %xx = xor i8 %x, 123
473  %yy = xor i8 %y, 45
474  %r = call i8 @llvm.umin.i8(i8 %xx, i8 %yy)
475  ret i8 %r
476}
477
478define i8 @umax_both_freely_invertable_always(i8 %x, i8 %y) {
479; CHECK-LABEL: @umax_both_freely_invertable_always(
480; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
481; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
482; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[XX]], i8 [[YY]])
483; CHECK-NEXT:    ret i8 [[R]]
484;
485  %xx = xor i8 %x, 123
486  %yy = xor i8 %y, 45
487  %r = call i8 @llvm.umax.i8(i8 %xx, i8 %yy)
488  ret i8 %r
489}
490
491define i8 @smin_both_freely_invertable_always(i8 %x, i8 %y) {
492; CHECK-LABEL: @smin_both_freely_invertable_always(
493; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
494; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
495; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[XX]], i8 [[YY]])
496; CHECK-NEXT:    ret i8 [[R]]
497;
498  %xx = xor i8 %x, 123
499  %yy = xor i8 %y, 45
500  %r = call i8 @llvm.smin.i8(i8 %xx, i8 %yy)
501  ret i8 %r
502}
503
504define i8 @smax_both_freely_invertable_always(i8 %x, i8 %y) {
505; CHECK-LABEL: @smax_both_freely_invertable_always(
506; CHECK-NEXT:    [[XX:%.*]] = xor i8 [[X:%.*]], 123
507; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], 45
508; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[XX]], i8 [[YY]])
509; CHECK-NEXT:    ret i8 [[R]]
510;
511  %xx = xor i8 %x, 123
512  %yy = xor i8 %y, 45
513  %r = call i8 @llvm.smax.i8(i8 %xx, i8 %yy)
514  ret i8 %r
515}
516
517define i8 @lshr_nneg(i8 %x, i8 %y) {
518; CHECK-LABEL: @lshr_nneg(
519; CHECK-NEXT:    [[NEG:%.*]] = icmp slt i8 [[X:%.*]], 0
520; CHECK-NEXT:    call void @llvm.assume(i1 [[NEG]])
521; CHECK-NEXT:    [[SHR_NOT:%.*]] = ashr i8 [[X]], [[Y:%.*]]
522; CHECK-NEXT:    ret i8 [[SHR_NOT]]
523;
524  %neg = icmp slt i8 %x, 0
525  call void @llvm.assume(i1 %neg)
526  %x.not = xor i8 %x, -1
527  %shr = lshr i8 %x.not, %y
528  %shr.not = xor i8 %shr, -1
529  ret i8 %shr.not
530}
531
532define i8 @lshr_not_nneg(i8 %x, i8 %y) {
533; CHECK-LABEL: @lshr_not_nneg(
534; CHECK-NEXT:    [[X_NOT:%.*]] = xor i8 [[X:%.*]], -1
535; CHECK-NEXT:    [[SHR:%.*]] = lshr i8 [[X_NOT]], [[Y:%.*]]
536; CHECK-NEXT:    [[SHR_NOT:%.*]] = xor i8 [[SHR]], -1
537; CHECK-NEXT:    ret i8 [[SHR_NOT]]
538;
539  %x.not = xor i8 %x, -1
540  %shr = lshr i8 %x.not, %y
541  %shr.not = xor i8 %shr, -1
542  ret i8 %shr.not
543}
544
545define i8 @lshr_not_nneg2(i8 %x) {
546; CHECK-LABEL: @lshr_not_nneg2(
547; CHECK-NEXT:    [[SHR:%.*]] = lshr i8 [[X:%.*]], 1
548; CHECK-NEXT:    [[SHR_NOT:%.*]] = or disjoint i8 [[SHR]], -128
549; CHECK-NEXT:    ret i8 [[SHR_NOT]]
550;
551  %x.not = xor i8 %x, -1
552  %shr = lshr i8 %x.not, 1
553  %shr.not = xor i8 %shr, -1
554  ret i8 %shr.not
555}
556
557define i1 @test_inv_free(i1 %c1, i1 %c2, i1 %c3, i1 %c4) {
558; CHECK-LABEL: @test_inv_free(
559; CHECK-NEXT:  entry:
560; CHECK-NEXT:    br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]]
561; CHECK:       b1:
562; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]]
563; CHECK:       b2:
564; CHECK-NEXT:    br label [[EXIT]]
565; CHECK:       b3:
566; CHECK-NEXT:    br label [[EXIT]]
567; CHECK:       exit:
568; CHECK-NEXT:    [[VAL_NOT:%.*]] = phi i1 [ false, [[B1]] ], [ true, [[B2]] ], [ [[C3:%.*]], [[B3]] ]
569; CHECK-NEXT:    [[COND_NOT:%.*]] = and i1 [[VAL_NOT]], [[C4:%.*]]
570; CHECK-NEXT:    br i1 [[COND_NOT]], label [[B5:%.*]], label [[B4:%.*]]
571; CHECK:       b4:
572; CHECK-NEXT:    ret i1 true
573; CHECK:       b5:
574; CHECK-NEXT:    ret i1 false
575;
576entry:
577  br i1 %c1, label %b1, label %b2
578b1:
579  br i1 %c2, label %exit, label %b3
580b2:
581  br label %exit
582b3:
583  %invc3 = xor i1 %c3, true
584  br label %exit
585exit:
586  %val = phi i1 [ true, %b1 ], [ false, %b2 ], [ %invc3, %b3 ]
587  %inv = xor i1 %c4, true
588  %cond = or i1 %val, %inv
589  br i1 %cond, label %b4, label %b5
590b4:
591  ret i1 true
592b5:
593  ret i1 false
594}
595
596define i32 @test_inv_free_i32(i1 %c1, i1 %c2, i32 %c3, i32 %c4) {
597; CHECK-LABEL: @test_inv_free_i32(
598; CHECK-NEXT:  entry:
599; CHECK-NEXT:    br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]]
600; CHECK:       b1:
601; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]]
602; CHECK:       b2:
603; CHECK-NEXT:    br label [[EXIT]]
604; CHECK:       b3:
605; CHECK-NEXT:    br label [[EXIT]]
606; CHECK:       exit:
607; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[B1]] ], [ -1, [[B2]] ], [ [[C3:%.*]], [[B3]] ]
608; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[C4:%.*]], [[TMP0]]
609; CHECK-NEXT:    ret i32 [[COND]]
610;
611entry:
612  br i1 %c1, label %b1, label %b2
613b1:
614  br i1 %c2, label %exit, label %b3
615b2:
616  br label %exit
617b3:
618  %invc3 = xor i32 %c3, -1
619  br label %exit
620exit:
621  %val = phi i32 [ -1, %b1 ], [ 0, %b2 ], [ %invc3, %b3 ]
622  %inv = xor i32 %c4, -1
623  %cond = xor i32 %val, %inv
624  ret i32 %cond
625}
626
627; Negative tests
628
629define i1 @test_inv_free_multiuse(i1 %c1, i1 %c2, i1 %c3, i1 %c4) {
630; CHECK-LABEL: @test_inv_free_multiuse(
631; CHECK-NEXT:  entry:
632; CHECK-NEXT:    br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]]
633; CHECK:       b1:
634; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]]
635; CHECK:       b2:
636; CHECK-NEXT:    br label [[EXIT]]
637; CHECK:       b3:
638; CHECK-NEXT:    [[INVC3:%.*]] = xor i1 [[C3:%.*]], true
639; CHECK-NEXT:    br label [[EXIT]]
640; CHECK:       exit:
641; CHECK-NEXT:    [[VAL:%.*]] = phi i1 [ true, [[B1]] ], [ false, [[B2]] ], [ [[INVC3]], [[B3]] ]
642; CHECK-NEXT:    call void @use.i1(i1 [[VAL]])
643; CHECK-NEXT:    [[INV:%.*]] = xor i1 [[C4:%.*]], true
644; CHECK-NEXT:    [[COND:%.*]] = or i1 [[VAL]], [[INV]]
645; CHECK-NEXT:    br i1 [[COND]], label [[B4:%.*]], label [[B5:%.*]]
646; CHECK:       b4:
647; CHECK-NEXT:    ret i1 true
648; CHECK:       b5:
649; CHECK-NEXT:    ret i1 false
650;
651entry:
652  br i1 %c1, label %b1, label %b2
653b1:
654  br i1 %c2, label %exit, label %b3
655b2:
656  br label %exit
657b3:
658  %invc3 = xor i1 %c3, true
659  br label %exit
660exit:
661  %val = phi i1 [ true, %b1 ], [ false, %b2 ], [ %invc3, %b3 ]
662  call void @use.i1(i1 %val)
663  %inv = xor i1 %c4, true
664  %cond = or i1 %val, %inv
665  br i1 %cond, label %b4, label %b5
666b4:
667  ret i1 true
668b5:
669  ret i1 false
670}
671
672define i32 @test_inv_free_i32_newinst(i1 %c1, i1 %c2, i32 %c3, i32 %c4) {
673; CHECK-LABEL: @test_inv_free_i32_newinst(
674; CHECK-NEXT:  entry:
675; CHECK-NEXT:    br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]]
676; CHECK:       b1:
677; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]]
678; CHECK:       b2:
679; CHECK-NEXT:    br label [[EXIT]]
680; CHECK:       b3:
681; CHECK-NEXT:    [[ASHR:%.*]] = ashr i32 -8, [[C3:%.*]]
682; CHECK-NEXT:    br label [[EXIT]]
683; CHECK:       exit:
684; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ -1, [[B1]] ], [ 0, [[B2]] ], [ [[ASHR]], [[B3]] ]
685; CHECK-NEXT:    [[TMP0:%.*]] = xor i32 [[C4:%.*]], [[VAL]]
686; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[TMP0]], -1
687; CHECK-NEXT:    ret i32 [[COND]]
688;
689entry:
690  br i1 %c1, label %b1, label %b2
691b1:
692  br i1 %c2, label %exit, label %b3
693b2:
694  br label %exit
695b3:
696  %ashr = ashr i32 -8, %c3
697  br label %exit
698exit:
699  %val = phi i32 [ -1, %b1 ], [ 0, %b2 ], [ %ashr, %b3 ]
700  %inv = xor i32 %c4, -1
701  %cond = xor i32 %val, %inv
702  ret i32 %cond
703}
704
705define i1 @test_inv_free_loop(i1 %c1, i1 %c2, i1 %c3, i1 %c4) {
706; CHECK-LABEL: @test_inv_free_loop(
707; CHECK-NEXT:  entry:
708; CHECK-NEXT:    br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]]
709; CHECK:       b1:
710; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]]
711; CHECK:       b2:
712; CHECK-NEXT:    br label [[EXIT]]
713; CHECK:       b3:
714; CHECK-NEXT:    [[INVC3:%.*]] = xor i1 [[C3:%.*]], true
715; CHECK-NEXT:    br label [[EXIT]]
716; CHECK:       exit:
717; CHECK-NEXT:    [[VAL:%.*]] = phi i1 [ true, [[B1]] ], [ false, [[B2]] ], [ [[INVC3]], [[B3]] ], [ [[NOT:%.*]], [[EXIT]] ]
718; CHECK-NEXT:    [[INV:%.*]] = xor i1 [[C4:%.*]], true
719; CHECK-NEXT:    [[COND:%.*]] = or i1 [[VAL]], [[INV]]
720; CHECK-NEXT:    [[NOT]] = xor i1 [[VAL]], true
721; CHECK-NEXT:    br i1 [[COND]], label [[EXIT]], label [[B4:%.*]]
722; CHECK:       b4:
723; CHECK-NEXT:    ret i1 true
724;
725entry:
726  br i1 %c1, label %b1, label %b2
727b1:
728  br i1 %c2, label %exit, label %b3
729b2:
730  br label %exit
731b3:
732  %invc3 = xor i1 %c3, true
733  br label %exit
734exit:
735  %val = phi i1 [ true, %b1 ], [ false, %b2 ], [ %invc3, %b3 ], [ %not, %exit ]
736  %inv = xor i1 %c4, true
737  %cond = or i1 %val, %inv
738  %not = xor i1 %val, true
739  br i1 %cond, label %exit, label %b4
740b4:
741  ret i1 true
742}
743