xref: /llvm-project/llvm/test/Transforms/InstCombine/binop-and-shifts.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define i8 @shl_and_and(i8 %x, i8 %y) {
5; CHECK-LABEL: @shl_and_and(
6; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[Y:%.*]], [[X:%.*]]
7; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[TMP1]], 4
8; CHECK-NEXT:    [[BW1:%.*]] = and i8 [[TMP2]], 80
9; CHECK-NEXT:    ret i8 [[BW1]]
10;
11  %shift1 = shl i8 %x, 4
12  %shift2 = shl i8 %y, 4
13  %bw2 = and i8 %shift2, 88
14  %bw1 = and i8 %shift1, %bw2
15  ret i8 %bw1
16}
17
18define i8 @shl_and_and_fail(i8 %x, i8 %y) {
19; CHECK-LABEL: @shl_and_and_fail(
20; CHECK-NEXT:    [[SHIFT1:%.*]] = shl i8 [[X:%.*]], 4
21; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 [[Y:%.*]], 5
22; CHECK-NEXT:    [[BW2:%.*]] = and i8 [[SHIFT2]], 64
23; CHECK-NEXT:    [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
24; CHECK-NEXT:    ret i8 [[BW1]]
25;
26  %shift1 = shl i8 %x, 4
27  %shift2 = shl i8 %y, 5
28  %bw2 = and i8 %shift2, 88
29  %bw1 = and i8 %shift1, %bw2
30  ret i8 %bw1
31}
32
33define i8 @shl_add_add(i8 %x, i8 %y) {
34; CHECK-LABEL: @shl_add_add(
35; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[X:%.*]]
36; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[TMP1]], 2
37; CHECK-NEXT:    [[BW1:%.*]] = add i8 [[TMP2]], 48
38; CHECK-NEXT:    ret i8 [[BW1]]
39;
40  %shift1 = shl i8 %x, 2
41  %shift2 = shl i8 %y, 2
42  %bw2 = add i8 %shift2, 48
43  %bw1 = add i8 %shift1, %bw2
44  ret i8 %bw1
45}
46
47define i8 @shl_add_add_fail(i8 %x, i8 %y) {
48; CHECK-LABEL: @shl_add_add_fail(
49; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 2
50; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 2
51; CHECK-NEXT:    [[BW2:%.*]] = add nuw nsw i8 [[SHIFT2]], 48
52; CHECK-NEXT:    [[BW1:%.*]] = add nuw i8 [[SHIFT1]], [[BW2]]
53; CHECK-NEXT:    ret i8 [[BW1]]
54;
55  %shift1 = lshr i8 %x, 2
56  %shift2 = lshr i8 %y, 2
57  %bw2 = add i8 %shift2, 48
58  %bw1 = add i8 %shift1, %bw2
59  ret i8 %bw1
60}
61
62define i8 @shl_and_and_fail2(i8 %x, i8 %y) {
63; CHECK-LABEL: @shl_and_and_fail2(
64; CHECK-NEXT:    [[SHIFT1:%.*]] = shl i8 4, [[X:%.*]]
65; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 4, [[Y:%.*]]
66; CHECK-NEXT:    [[BW2:%.*]] = and i8 [[SHIFT2]], 88
67; CHECK-NEXT:    [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
68; CHECK-NEXT:    ret i8 [[BW1]]
69;
70  %shift1 = shl i8 4, %x
71  %shift2 = shl i8 4, %y
72  %bw2 = and i8 %shift2, 88
73  %bw1 = and i8 %shift1, %bw2
74  ret i8 %bw1
75}
76
77define <2 x i8> @lshr_and_or(<2 x i8> %x, <2 x i8> %y) {
78; CHECK-LABEL: @lshr_and_or(
79; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -64, i8 96>
80; CHECK-NEXT:    [[TMP2:%.*]] = or <2 x i8> [[Y:%.*]], [[TMP1]]
81; CHECK-NEXT:    [[BW1:%.*]] = lshr <2 x i8> [[TMP2]], <i8 4, i8 5>
82; CHECK-NEXT:    ret <2 x i8> [[BW1]]
83;
84  %shift1 = lshr <2 x i8> %x, <i8 4, i8 5>
85  %shift2 = lshr <2 x i8> %y, <i8 4, i8 5>
86  %bw2 = and <2 x i8> %shift1, <i8 44, i8 99>
87  %bw1 = or <2 x i8> %shift2, %bw2
88  ret <2 x i8> %bw1
89}
90
91define <2 x i8> @lshr_and_or_fail(<2 x i8> %x, <2 x i8> %y) {
92; CHECK-LABEL: @lshr_and_or_fail(
93; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 5>
94; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr <2 x i8> [[Y:%.*]], <i8 5, i8 4>
95; CHECK-NEXT:    [[BW2:%.*]] = and <2 x i8> [[SHIFT2]], <i8 44, i8 99>
96; CHECK-NEXT:    [[BW1:%.*]] = or <2 x i8> [[SHIFT1]], [[BW2]]
97; CHECK-NEXT:    ret <2 x i8> [[BW1]]
98;
99  %shift1 = lshr <2 x i8> %x, <i8 4, i8 5>
100  %shift2 = lshr <2 x i8> %y, <i8 5, i8 4>
101  %bw2 = and <2 x i8> %shift2, <i8 44, i8 99>
102  %bw1 = or <2 x i8> %shift1, %bw2
103  ret <2 x i8> %bw1
104}
105
106define i8 @shl_and_xor(i8 %x, i8 %y) {
107; CHECK-LABEL: @shl_and_xor(
108; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], 10
109; CHECK-NEXT:    [[TMP2:%.*]] = xor i8 [[Y:%.*]], [[TMP1]]
110; CHECK-NEXT:    [[BW1:%.*]] = shl i8 [[TMP2]], 1
111; CHECK-NEXT:    ret i8 [[BW1]]
112;
113  %shift1 = shl i8 %x, 1
114  %shift2 = shl i8 %y, 1
115  %bw2 = and i8 %shift1, 20
116  %bw1 = xor i8 %shift2, %bw2
117  ret i8 %bw1
118}
119
120define i8 @shl_and_add(i8 %x, i8 %y) {
121; CHECK-LABEL: @shl_and_add(
122; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[Y:%.*]], 59
123; CHECK-NEXT:    [[TMP2:%.*]] = add i8 [[X:%.*]], [[TMP1]]
124; CHECK-NEXT:    [[BW1:%.*]] = shl i8 [[TMP2]], 1
125; CHECK-NEXT:    ret i8 [[BW1]]
126;
127  %shift1 = shl i8 %x, 1
128  %shift2 = shl i8 %y, 1
129  %bw2 = and i8 %shift2, 119
130  %bw1 = add i8 %shift1, %bw2
131  ret i8 %bw1
132}
133
134define i8 @shl_xor_add_fail(i8 %x, i8 %y) {
135; CHECK-LABEL: @shl_xor_add_fail(
136; CHECK-NEXT:    [[SHIFT1:%.*]] = shl i8 [[X:%.*]], 1
137; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 [[Y:%.*]], 1
138; CHECK-NEXT:    [[BW2:%.*]] = xor i8 [[SHIFT2]], 119
139; CHECK-NEXT:    [[BW1:%.*]] = add i8 [[SHIFT1]], [[BW2]]
140; CHECK-NEXT:    ret i8 [[BW1]]
141;
142  %shift1 = shl i8 %x, 1
143  %shift2 = shl i8 %y, 1
144  %bw2 = xor i8 %shift2, 119
145  %bw1 = add i8 %shift1, %bw2
146  ret i8 %bw1
147}
148
149define i8 @lshr_or_and(i8 %x, i8 %y) {
150; CHECK-LABEL: @lshr_or_and(
151; CHECK-NEXT:    [[TMP1:%.*]] = or i8 [[X:%.*]], -64
152; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[Y:%.*]], [[TMP1]]
153; CHECK-NEXT:    [[BW1:%.*]] = lshr i8 [[TMP2]], 5
154; CHECK-NEXT:    ret i8 [[BW1]]
155;
156  %shift1 = lshr i8 %x, 5
157  %shift2 = lshr i8 %y, 5
158  %bw2 = or i8 %shift1, 198
159  %bw1 = and i8 %bw2, %shift2
160  ret i8 %bw1
161}
162
163define i8 @lshr_or_or_fail(i8 %x, i8 %y) {
164; CHECK-LABEL: @lshr_or_or_fail(
165; CHECK-NEXT:    [[TMP1:%.*]] = or i8 [[Y:%.*]], [[X:%.*]]
166; CHECK-NEXT:    [[TMP2:%.*]] = lshr i8 [[TMP1]], 5
167; CHECK-NEXT:    [[BW1:%.*]] = or i8 [[TMP2]], -58
168; CHECK-NEXT:    ret i8 [[BW1]]
169;
170  %shift1 = lshr i8 %x, 5
171  %shift2 = lshr i8 %y, 5
172  %bw2 = or i8 %shift2, 198
173  %bw1 = or i8 %shift1, %bw2
174  ret i8 %bw1
175}
176
177define <2 x i8> @shl_xor_and(<2 x i8> %x, <2 x i8> %y) {
178; CHECK-LABEL: @shl_xor_and(
179; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i8> [[Y:%.*]], <i8 11, i8 poison>
180; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i8> [[X:%.*]], [[TMP1]]
181; CHECK-NEXT:    [[BW1:%.*]] = shl <2 x i8> [[TMP2]], <i8 2, i8 poison>
182; CHECK-NEXT:    ret <2 x i8> [[BW1]]
183;
184  %shift1 = shl <2 x i8> %x, <i8 2, i8 poison>
185  %shift2 = shl <2 x i8> %y, <i8 2, i8 poison>
186  %bw2 = xor <2 x i8> %shift2, <i8 44, i8 poison>
187  %bw1 = and <2 x i8> %bw2, %shift1
188  ret <2 x i8> %bw1
189}
190
191define <2 x i8> @shl_xor_and_fail(<2 x i8> %x, <2 x i8> %y) {
192; CHECK-LABEL: @shl_xor_and_fail(
193; CHECK-NEXT:    [[SHIFT1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 2, i8 poison>
194; CHECK-NEXT:    [[SHIFT2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
195; CHECK-NEXT:    [[BW2:%.*]] = xor <2 x i8> [[SHIFT2]], <i8 44, i8 poison>
196; CHECK-NEXT:    [[BW1:%.*]] = and <2 x i8> [[SHIFT1]], [[BW2]]
197; CHECK-NEXT:    ret <2 x i8> [[BW1]]
198;
199  %shift1 = shl <2 x i8> %x, <i8 2, i8 poison>
200  %shift2 = shl <2 x i8> %y, <i8 poison, i8 2>
201  %bw2 = xor <2 x i8> %shift2, <i8 44, i8 poison>
202  %bw1 = and <2 x i8> %shift1, %bw2
203  ret <2 x i8> %bw1
204}
205
206define i8 @lshr_or_or_no_const(i8 %x, i8 %y, i8 %sh, i8 %mask) {
207; CHECK-LABEL: @lshr_or_or_no_const(
208; CHECK-NEXT:    [[TMP1:%.*]] = or i8 [[Y:%.*]], [[X:%.*]]
209; CHECK-NEXT:    [[TMP2:%.*]] = lshr i8 [[TMP1]], [[SH:%.*]]
210; CHECK-NEXT:    [[BW1:%.*]] = or i8 [[TMP2]], [[MASK:%.*]]
211; CHECK-NEXT:    ret i8 [[BW1]]
212;
213  %shift1 = lshr i8 %x, %sh
214  %shift2 = lshr i8 %y, %sh
215  %bw2 = or i8 %shift2, %mask
216  %bw1 = or i8 %shift1, %bw2
217  ret i8 %bw1
218}
219
220define i8 @lshr_or_or_no_const_fail(i8 %x, i8 %y, i8 %sh, i8 %mask) {
221; CHECK-LABEL: @lshr_or_or_no_const_fail(
222; CHECK-NEXT:    [[SHIFT1:%.*]] = shl i8 [[X:%.*]], [[SH:%.*]]
223; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], [[SH]]
224; CHECK-NEXT:    [[BW2:%.*]] = or i8 [[SHIFT2]], [[MASK:%.*]]
225; CHECK-NEXT:    [[BW1:%.*]] = or i8 [[SHIFT1]], [[BW2]]
226; CHECK-NEXT:    ret i8 [[BW1]]
227;
228  %shift1 = shl i8 %x, %sh
229  %shift2 = lshr i8 %y, %sh
230  %bw2 = or i8 %shift2, %mask
231  %bw1 = or i8 %shift1, %bw2
232  ret i8 %bw1
233}
234
235define i8 @shl_xor_xor_no_const(i8 %x, i8 %y, i8 %sh, i8 %mask) {
236; CHECK-LABEL: @shl_xor_xor_no_const(
237; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
238; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[TMP1]], [[SH:%.*]]
239; CHECK-NEXT:    [[BW1:%.*]] = xor i8 [[TMP2]], [[MASK:%.*]]
240; CHECK-NEXT:    ret i8 [[BW1]]
241;
242  %shift1 = shl i8 %x, %sh
243  %shift2 = shl i8 %y, %sh
244  %bw2 = xor i8 %shift2, %mask
245  %bw1 = xor i8 %shift1, %bw2
246  ret i8 %bw1
247}
248
249define i8 @shl_xor_and_no_const_fail(i8 %x, i8 %y, i8 %sh, i8 %mask) {
250; CHECK-LABEL: @shl_xor_and_no_const_fail(
251; CHECK-NEXT:    [[SHIFT1:%.*]] = shl i8 [[X:%.*]], [[SH:%.*]]
252; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 [[Y:%.*]], [[SH]]
253; CHECK-NEXT:    [[BW2:%.*]] = xor i8 [[SHIFT2]], [[MASK:%.*]]
254; CHECK-NEXT:    [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
255; CHECK-NEXT:    ret i8 [[BW1]]
256;
257  %shift1 = shl i8 %x, %sh
258  %shift2 = shl i8 %y, %sh
259  %bw2 = xor i8 %shift2, %mask
260  %bw1 = and i8 %shift1, %bw2
261  ret i8 %bw1
262}
263
264define <2 x i8> @shl_and_and_no_const(<2 x i8> %x, <2 x i8> %y, <2 x i8> %sh, <2 x i8> %mask) {
265; CHECK-LABEL: @shl_and_and_no_const(
266; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[Y:%.*]], [[X:%.*]]
267; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i8> [[TMP1]], [[SH:%.*]]
268; CHECK-NEXT:    [[BW1:%.*]] = and <2 x i8> [[TMP2]], [[MASK:%.*]]
269; CHECK-NEXT:    ret <2 x i8> [[BW1]]
270;
271  %shift1 = shl <2 x i8> %x, %sh
272  %shift2 = shl <2 x i8> %y, %sh
273  %bw2 = and <2 x i8> %shift2, %mask
274  %bw1 = and <2 x i8> %shift1, %bw2
275  ret <2 x i8> %bw1
276}
277
278define i8 @shl_add_add_no_const(i8 %x, i8 %y, i8 %sh, i8 %mask) {
279; CHECK-LABEL: @shl_add_add_no_const(
280; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[X:%.*]]
281; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[TMP1]], [[SH:%.*]]
282; CHECK-NEXT:    [[BW1:%.*]] = add i8 [[TMP2]], [[MASK:%.*]]
283; CHECK-NEXT:    ret i8 [[BW1]]
284;
285  %shift1 = shl i8 %x, %sh
286  %shift2 = shl i8 %y, %sh
287  %bw2 = add i8 %shift2, %mask
288  %bw1 = add i8 %shift1, %bw2
289  ret i8 %bw1
290}
291
292define i8 @lshr_add_add_no_const_fail(i8 %x, i8 %y, i8 %sh, i8 %mask) {
293; CHECK-LABEL: @lshr_add_add_no_const_fail(
294; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], [[SH:%.*]]
295; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], [[SH]]
296; CHECK-NEXT:    [[BW2:%.*]] = add i8 [[SHIFT2]], [[MASK:%.*]]
297; CHECK-NEXT:    [[BW1:%.*]] = add i8 [[SHIFT1]], [[BW2]]
298; CHECK-NEXT:    ret i8 [[BW1]]
299;
300  %shift1 = lshr i8 %x, %sh
301  %shift2 = lshr i8 %y, %sh
302  %bw2 = add i8 %shift2, %mask
303  %bw1 = add i8 %shift1, %bw2
304  ret i8 %bw1
305}
306
307define <2 x i8> @lshr_add_and(<2 x i8> %x, <2 x i8> %y) {
308; CHECK-LABEL: @lshr_add_and(
309; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[Y:%.*]], <i8 -8, i8 16>
310; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i8> [[X:%.*]], [[TMP1]]
311; CHECK-NEXT:    [[BW1:%.*]] = lshr <2 x i8> [[TMP2]], <i8 3, i8 4>
312; CHECK-NEXT:    ret <2 x i8> [[BW1]]
313;
314  %shift1 = lshr <2 x i8> %x, <i8 3, i8 4>
315  %shift2 = lshr <2 x i8> %y, <i8 3, i8 4>
316  %bw2 = add <2 x i8> %shift2, <i8 255, i8 1>
317  %bw1 = and <2 x i8> %shift1, %bw2
318  ret <2 x i8> %bw1
319}
320
321define <2 x i8> @lshr_add_or_fail_dif_masks(<2 x i8> %x, <2 x i8> %y) {
322; CHECK-LABEL: @lshr_add_or_fail_dif_masks(
323; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 3, i8 4>
324; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr <2 x i8> [[Y:%.*]], <i8 poison, i8 3>
325; CHECK-NEXT:    [[BW2:%.*]] = add nsw <2 x i8> [[SHIFT2]], <i8 -1, i8 1>
326; CHECK-NEXT:    [[BW1:%.*]] = and <2 x i8> [[SHIFT1]], [[BW2]]
327; CHECK-NEXT:    ret <2 x i8> [[BW1]]
328;
329  %shift1 = lshr <2 x i8> %x, <i8 3, i8 4>
330  %shift2 = lshr <2 x i8> %y, <i8 poison, i8 3>
331  %bw2 = add <2 x i8> %shift2, <i8 255, i8 1>
332  %bw1 = and <2 x i8> %shift1, %bw2
333  ret <2 x i8> %bw1
334}
335
336define <2 x i8> @shl_or_or_good_mask(<2 x i8> %x, <2 x i8> %y) {
337; CHECK-LABEL: @shl_or_or_good_mask(
338; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i8> [[Y:%.*]], [[X:%.*]]
339; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i8> [[TMP1]], splat (i8 1)
340; CHECK-NEXT:    [[BW1:%.*]] = or <2 x i8> [[TMP2]], <i8 18, i8 24>
341; CHECK-NEXT:    ret <2 x i8> [[BW1]]
342;
343  %shift1 = shl <2 x i8> %x, <i8 1, i8 1>
344  %shift2 = shl <2 x i8> %y, <i8 1, i8 1>
345  %bw2 = or <2 x i8> %shift2, <i8 18, i8 24>
346  %bw1 = or <2 x i8> %shift1, %bw2
347  ret <2 x i8> %bw1
348}
349
350define <2 x i8> @shl_or_or_fail_bad_mask(<2 x i8> %x, <2 x i8> %y) {
351; CHECK-LABEL: @shl_or_or_fail_bad_mask(
352; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i8> [[Y:%.*]], [[X:%.*]]
353; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i8> [[TMP1]], splat (i8 1)
354; CHECK-NEXT:    [[BW1:%.*]] = or <2 x i8> [[TMP2]], <i8 19, i8 24>
355; CHECK-NEXT:    ret <2 x i8> [[BW1]]
356;
357  %shift1 = shl <2 x i8> %x, <i8 1, i8 1>
358  %shift2 = shl <2 x i8> %y, <i8 1, i8 1>
359  %bw2 = or <2 x i8> %shift2, <i8 19, i8 24>
360  %bw1 = or <2 x i8> %shift1, %bw2
361  ret <2 x i8> %bw1
362}
363
364define i8 @lshr_xor_or_good_mask(i8 %x, i8 %y) {
365; CHECK-LABEL: @lshr_xor_or_good_mask(
366; CHECK-NEXT:    [[TMP1:%.*]] = or i8 [[Y:%.*]], [[X:%.*]]
367; CHECK-NEXT:    [[TMP2:%.*]] = lshr i8 [[TMP1]], 4
368; CHECK-NEXT:    [[BW1:%.*]] = or disjoint i8 [[TMP2]], 48
369; CHECK-NEXT:    ret i8 [[BW1]]
370;
371  %shift1 = lshr i8 %x, 4
372  %shift2 = lshr i8 %y, 4
373  %bw2 = xor i8 %shift2, 48
374  %bw1 = or i8 %shift1, %bw2
375  ret i8 %bw1
376}
377
378define i8 @lshr_xor_or_fail_bad_mask(i8 %x, i8 %y) {
379; CHECK-LABEL: @lshr_xor_or_fail_bad_mask(
380; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 6
381; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 6
382; CHECK-NEXT:    [[BW2:%.*]] = xor i8 [[SHIFT2]], -127
383; CHECK-NEXT:    [[BW1:%.*]] = or i8 [[SHIFT1]], [[BW2]]
384; CHECK-NEXT:    ret i8 [[BW1]]
385;
386  %shift1 = lshr i8 %x, 6
387  %shift2 = lshr i8 %y, 6
388  %bw2 = xor i8 %shift2, 129
389  %bw1 = or i8 %shift1, %bw2
390  ret i8 %bw1
391}
392
393define <2 x i8> @lshr_or_xor_good_mask(<2 x i8> %x, <2 x i8> %y) {
394; CHECK-LABEL: @lshr_or_xor_good_mask(
395; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i8> [[Y:%.*]], <i8 -64, i8 64>
396; CHECK-NEXT:    [[TMP2:%.*]] = xor <2 x i8> [[X:%.*]], [[TMP1]]
397; CHECK-NEXT:    [[BW1:%.*]] = lshr <2 x i8> [[TMP2]], splat (i8 6)
398; CHECK-NEXT:    ret <2 x i8> [[BW1]]
399;
400  %shift1 = lshr <2 x i8> %x, <i8 6, i8 6>
401  %shift2 = lshr <2 x i8> %y, <i8 6, i8 6>
402  %bw2 = or <2 x i8> %shift2, <i8 3, i8 1>
403  %bw1 = xor <2 x i8> %shift1, %bw2
404  ret <2 x i8> %bw1
405}
406
407define <2 x i8> @lshr_or_xor_fail_bad_mask(<2 x i8> %x, <2 x i8> %y) {
408; CHECK-LABEL: @lshr_or_xor_fail_bad_mask(
409; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr <2 x i8> [[X:%.*]], splat (i8 6)
410; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr <2 x i8> [[Y:%.*]], splat (i8 6)
411; CHECK-NEXT:    [[BW2:%.*]] = or <2 x i8> [[SHIFT2]], <i8 7, i8 1>
412; CHECK-NEXT:    [[BW1:%.*]] = xor <2 x i8> [[SHIFT1]], [[BW2]]
413; CHECK-NEXT:    ret <2 x i8> [[BW1]]
414;
415  %shift1 = lshr <2 x i8> %x, <i8 6, i8 6>
416  %shift2 = lshr <2 x i8> %y, <i8 6, i8 6>
417  %bw2 = or <2 x i8> %shift2, <i8 7, i8 1>
418  %bw1 = xor <2 x i8> %shift1, %bw2
419  ret <2 x i8> %bw1
420}
421
422define i8 @shl_xor_xor_good_mask(i8 %x, i8 %y) {
423; CHECK-LABEL: @shl_xor_xor_good_mask(
424; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
425; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[TMP1]], 1
426; CHECK-NEXT:    [[BW1:%.*]] = xor i8 [[TMP2]], 88
427; CHECK-NEXT:    ret i8 [[BW1]]
428;
429  %shift1 = shl i8 %x, 1
430  %shift2 = shl i8 %y, 1
431  %bw2 = xor i8 %shift2, 88
432  %bw1 = xor i8 %shift1, %bw2
433  ret i8 %bw1
434}
435
436define i8 @shl_xor_xor_bad_mask_distribute(i8 %x, i8 %y) {
437; CHECK-LABEL: @shl_xor_xor_bad_mask_distribute(
438; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
439; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[TMP1]], 1
440; CHECK-NEXT:    [[BW1:%.*]] = xor i8 [[TMP2]], -68
441; CHECK-NEXT:    ret i8 [[BW1]]
442;
443  %shift1 = shl i8 %x, 1
444  %shift2 = shl i8 %y, 1
445  %bw2 = xor i8 %shift2, 188
446  %bw1 = xor i8 %shift1, %bw2
447  ret i8 %bw1
448}
449
450define i8 @shl_add_and(i8 %x, i8 %y) {
451; CHECK-LABEL: @shl_add_and(
452; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], 61
453; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
454; CHECK-NEXT:    [[BW1:%.*]] = shl i8 [[TMP2]], 1
455; CHECK-NEXT:    ret i8 [[BW1]]
456;
457  %shift1 = shl i8 %x, 1
458  %shift2 = shl i8 %y, 1
459  %bw2 = add i8 %shift2, 123
460  %bw1 = and i8 %shift1, %bw2
461  ret i8 %bw1
462}
463
464define i8 @lshr_and_add_fail(i8 %x, i8 %y) {
465; CHECK-LABEL: @lshr_and_add_fail(
466; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 1
467; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
468; CHECK-NEXT:    [[BW2:%.*]] = and i8 [[SHIFT2]], 123
469; CHECK-NEXT:    [[BW1:%.*]] = add nuw i8 [[SHIFT1]], [[BW2]]
470; CHECK-NEXT:    ret i8 [[BW1]]
471;
472  %shift1 = lshr i8 %x, 1
473  %shift2 = lshr i8 %y, 1
474  %bw2 = and i8 %shift2, 123
475  %bw1 = add i8 %shift1, %bw2
476  ret i8 %bw1
477}
478
479define i8 @lshr_add_or_fail(i8 %x, i8 %y) {
480; CHECK-LABEL: @lshr_add_or_fail(
481; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 1
482; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
483; CHECK-NEXT:    [[BW2:%.*]] = add nuw i8 [[SHIFT2]], 123
484; CHECK-NEXT:    [[BW1:%.*]] = or i8 [[SHIFT1]], [[BW2]]
485; CHECK-NEXT:    ret i8 [[BW1]]
486;
487  %shift1 = lshr i8 %x, 1
488  %shift2 = lshr i8 %y, 1
489  %bw2 = add i8 %shift2, 123
490  %bw1 = or i8 %shift1, %bw2
491  ret i8 %bw1
492}
493
494define i8 @lshr_add_xor_fail(i8 %x, i8 %y) {
495; CHECK-LABEL: @lshr_add_xor_fail(
496; CHECK-NEXT:    [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 1
497; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
498; CHECK-NEXT:    [[BW2:%.*]] = add nuw i8 [[SHIFT2]], 123
499; CHECK-NEXT:    [[BW1:%.*]] = xor i8 [[SHIFT1]], [[BW2]]
500; CHECK-NEXT:    ret i8 [[BW1]]
501;
502  %shift1 = lshr i8 %x, 1
503  %shift2 = lshr i8 %y, 1
504  %bw2 = add i8 %shift2, 123
505  %bw1 = xor i8 %shift1, %bw2
506  ret i8 %bw1
507}
508
509define <2 x i8> @lshr_and_add(<2 x i8> %x, <2 x i8> %y) {
510; CHECK-LABEL: @lshr_and_add(
511; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 11, i8 3>
512; CHECK-NEXT:    [[TMP2:%.*]] = add <2 x i8> [[Y:%.*]], [[TMP1]]
513; CHECK-NEXT:    [[BW1:%.*]] = shl <2 x i8> [[TMP2]], <i8 4, i8 5>
514; CHECK-NEXT:    ret <2 x i8> [[BW1]]
515;
516  %shift1 = shl <2 x i8> %x, <i8 4, i8 5>
517  %shift2 = shl <2 x i8> %y, <i8 4, i8 5>
518  %bw2 = and <2 x i8> %shift1, <i8 189, i8 123>
519  %bw1 = add <2 x i8> %shift2, %bw2
520  ret <2 x i8> %bw1
521}
522
523define <2 x i8> @lshr_or_add_fail(<2 x i8> %x, <2 x i8> %y) {
524; CHECK-LABEL: @lshr_or_add_fail(
525; CHECK-NEXT:    [[SHIFT1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 4, i8 5>
526; CHECK-NEXT:    [[SHIFT2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 4, i8 5>
527; CHECK-NEXT:    [[BW2:%.*]] = or <2 x i8> [[SHIFT1]], <i8 -67, i8 123>
528; CHECK-NEXT:    [[BW1:%.*]] = add <2 x i8> [[SHIFT2]], [[BW2]]
529; CHECK-NEXT:    ret <2 x i8> [[BW1]]
530;
531  %shift1 = shl <2 x i8> %x, <i8 4, i8 5>
532  %shift2 = shl <2 x i8> %y, <i8 4, i8 5>
533  %bw2 = or <2 x i8> %shift1, <i8 189, i8 123>
534  %bw1 = add <2 x i8> %shift2, %bw2
535  ret <2 x i8> %bw1
536}
537
538define i8 @shl_add_and_fail_mismatch_shift(i8 %x, i8 %y) {
539; CHECK-LABEL: @shl_add_and_fail_mismatch_shift(
540; CHECK-NEXT:    [[SHIFT1:%.*]] = shl i8 [[X:%.*]], 1
541; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
542; CHECK-NEXT:    [[BW2:%.*]] = add nuw i8 [[SHIFT2]], 123
543; CHECK-NEXT:    [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
544; CHECK-NEXT:    ret i8 [[BW1]]
545;
546  %shift1 = shl i8 %x, 1
547  %shift2 = lshr i8 %y, 1
548  %bw2 = add i8 %shift2, 123
549  %bw1 = and i8 %shift1, %bw2
550  ret i8 %bw1
551}
552
553; Fold (-x >> y) & ((x >> y) ^ -1) -> (-x & ~x) >> y
554
555define i8 @and_ashr_not(i8 %x, i8 %y, i8 %shamt) {
556; CHECK-LABEL: @and_ashr_not(
557; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
558; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
559; CHECK-NEXT:    [[AND:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
560; CHECK-NEXT:    ret i8 [[AND]]
561;
562  %x.shift = ashr i8 %x, %shamt
563  %y.shift = ashr i8 %y, %shamt
564  %y.shift.not = xor i8 %y.shift, -1
565  %and = and i8 %x.shift, %y.shift.not
566  ret i8 %and
567}
568
569define i8 @and_ashr_not_commuted(i8 %x, i8 %y, i8 %shamt) {
570; CHECK-LABEL: @and_ashr_not_commuted(
571; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
572; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
573; CHECK-NEXT:    [[AND:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
574; CHECK-NEXT:    ret i8 [[AND]]
575;
576  %x.shift = ashr i8 %x, %shamt
577  %y.shift = ashr i8 %y, %shamt
578  %y.shift.not = xor i8 %y.shift, -1
579  %and = and i8 %y.shift.not, %x.shift
580  ret i8 %and
581}
582
583; Negative test: lshr instead of ashr
584
585define i8 @and_ashr_not_fail_lshr_ashr(i8 %x, i8 %y, i8 %shamt) {
586; CHECK-LABEL: @and_ashr_not_fail_lshr_ashr(
587; CHECK-NEXT:    [[X_SHIFT:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
588; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
589; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
590; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
591; CHECK-NEXT:    ret i8 [[AND]]
592;
593  %x.shift = lshr i8 %x, %shamt
594  %y.shift = ashr i8 %y, %shamt
595  %y.shift.not = xor i8 %y.shift, -1
596  %and = and i8 %x.shift, %y.shift.not
597  ret i8 %and
598}
599
600; Negative test: lshr instead of ashr
601
602define i8 @and_ashr_not_fail_ashr_lshr(i8 %x, i8 %y, i8 %shamt) {
603; CHECK-LABEL: @and_ashr_not_fail_ashr_lshr(
604; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
605; CHECK-NEXT:    [[Y_SHIFT:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
606; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
607; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
608; CHECK-NEXT:    ret i8 [[AND]]
609;
610  %x.shift = ashr i8 %x, %shamt
611  %y.shift = lshr i8 %y, %shamt
612  %y.shift.not = xor i8 %y.shift, -1
613  %and = and i8 %x.shift, %y.shift.not
614  ret i8 %and
615}
616
617; Negative test: invalid xor constant
618
619define i8 @and_ashr_not_fail_invalid_xor_constant(i8 %x, i8 %y, i8 %shamt) {
620; CHECK-LABEL: @and_ashr_not_fail_invalid_xor_constant(
621; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
622; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
623; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -2
624; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
625; CHECK-NEXT:    ret i8 [[AND]]
626;
627  %x.shift = ashr i8 %x, %shamt
628  %y.shift = ashr i8 %y, %shamt
629  %y.shift.not = xor i8 %y.shift, -2
630  %and = and i8 %x.shift, %y.shift.not
631  ret i8 %and
632}
633
634define <4 x i8> @and_ashr_not_vec(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
635; CHECK-LABEL: @and_ashr_not_vec(
636; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], splat (i8 -1)
637; CHECK-NEXT:    [[TMP2:%.*]] = and <4 x i8> [[X:%.*]], [[TMP1]]
638; CHECK-NEXT:    [[AND:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
639; CHECK-NEXT:    ret <4 x i8> [[AND]]
640;
641  %x.shift = ashr <4 x i8> %x, %shamt
642  %y.shift = ashr <4 x i8> %y, %shamt
643  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
644  %and = and <4 x i8> %x.shift, %y.shift.not
645  ret <4 x i8> %and
646}
647
648define <4 x i8> @and_ashr_not_vec_commuted(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
649; CHECK-LABEL: @and_ashr_not_vec_commuted(
650; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], splat (i8 -1)
651; CHECK-NEXT:    [[TMP2:%.*]] = and <4 x i8> [[X:%.*]], [[TMP1]]
652; CHECK-NEXT:    [[AND:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
653; CHECK-NEXT:    ret <4 x i8> [[AND]]
654;
655  %x.shift = ashr <4 x i8> %x, %shamt
656  %y.shift = ashr <4 x i8> %y, %shamt
657  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
658  %and = and <4 x i8> %y.shift.not, %x.shift
659  ret <4 x i8> %and
660}
661
662define <4 x i8> @and_ashr_not_vec_poison_1(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
663; CHECK-LABEL: @and_ashr_not_vec_poison_1(
664; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], splat (i8 -1)
665; CHECK-NEXT:    [[TMP2:%.*]] = and <4 x i8> [[X:%.*]], [[TMP1]]
666; CHECK-NEXT:    [[AND:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
667; CHECK-NEXT:    ret <4 x i8> [[AND]]
668;
669  %x.shift = ashr <4 x i8> %x, %shamt
670  %y.shift = ashr <4 x i8> %y, %shamt
671  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 poison, i8 poison, i8 poison>
672  %and = and <4 x i8> %x.shift, %y.shift.not
673  ret <4 x i8> %and
674}
675
676define <4 x i8> @and_ashr_not_vec_poison_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
677; CHECK-LABEL: @and_ashr_not_vec_poison_2(
678; CHECK-NEXT:    ret <4 x i8> poison
679;
680  %x.shift = ashr <4 x i8> %x, %shamt
681  %y.shift = ashr <4 x i8> %y, %shamt
682  %y.shift.not = xor <4 x i8> %y.shift, <i8 poison, i8 poison, i8 poison, i8 poison>
683  %and = and <4 x i8> %x.shift, %y.shift.not
684  ret <4 x i8> %and
685}
686
687; Fold (-x >> y) | ((x >> y) ^ -1) -> (-x | ~x) >> y
688
689define i8 @or_ashr_not(i8 %x, i8 %y, i8 %shamt) {
690; CHECK-LABEL: @or_ashr_not(
691; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
692; CHECK-NEXT:    [[TMP2:%.*]] = or i8 [[X:%.*]], [[TMP1]]
693; CHECK-NEXT:    [[OR:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
694; CHECK-NEXT:    ret i8 [[OR]]
695;
696  %x.shift = ashr i8 %x, %shamt
697  %y.shift = ashr i8 %y, %shamt
698  %y.shift.not = xor i8 %y.shift, -1
699  %or = or i8 %x.shift, %y.shift.not
700  ret i8 %or
701}
702
703define i8 @or_ashr_not_commuted(i8 %x, i8 %y, i8 %shamt) {
704; CHECK-LABEL: @or_ashr_not_commuted(
705; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
706; CHECK-NEXT:    [[TMP2:%.*]] = or i8 [[X:%.*]], [[TMP1]]
707; CHECK-NEXT:    [[OR:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
708; CHECK-NEXT:    ret i8 [[OR]]
709;
710  %x.shift = ashr i8 %x, %shamt
711  %y.shift = ashr i8 %y, %shamt
712  %y.shift.not = xor i8 %y.shift, -1
713  %or = or i8 %y.shift.not, %x.shift
714  ret i8 %or
715}
716
717; Negative test: lshr instead of ashr
718
719define i8 @or_ashr_not_fail_lshr_ashr(i8 %x, i8 %y, i8 %shamt) {
720; CHECK-LABEL: @or_ashr_not_fail_lshr_ashr(
721; CHECK-NEXT:    [[X_SHIFT:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
722; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
723; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
724; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
725; CHECK-NEXT:    ret i8 [[OR]]
726;
727  %x.shift = lshr i8 %x, %shamt
728  %y.shift = ashr i8 %y, %shamt
729  %y.shift.not = xor i8 %y.shift, -1
730  %or = or i8 %x.shift, %y.shift.not
731  ret i8 %or
732}
733
734; Negative test: lshr instead of ashr
735
736define i8 @or_ashr_not_fail_ashr_lshr(i8 %x, i8 %y, i8 %shamt) {
737; CHECK-LABEL: @or_ashr_not_fail_ashr_lshr(
738; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
739; CHECK-NEXT:    [[Y_SHIFT:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
740; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
741; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
742; CHECK-NEXT:    ret i8 [[OR]]
743;
744  %x.shift = ashr i8 %x, %shamt
745  %y.shift = lshr i8 %y, %shamt
746  %y.shift.not = xor i8 %y.shift, -1
747  %or = or i8 %x.shift, %y.shift.not
748  ret i8 %or
749}
750
751; Negative test: invalid xor constant
752
753define i8 @or_ashr_not_fail_invalid_xor_constant(i8 %x, i8 %y, i8 %shamt) {
754; CHECK-LABEL: @or_ashr_not_fail_invalid_xor_constant(
755; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
756; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
757; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -2
758; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
759; CHECK-NEXT:    ret i8 [[OR]]
760;
761  %x.shift = ashr i8 %x, %shamt
762  %y.shift = ashr i8 %y, %shamt
763  %y.shift.not = xor i8 %y.shift, -2
764  %or = or i8 %x.shift, %y.shift.not
765  ret i8 %or
766}
767
768define <4 x i8> @or_ashr_not_vec(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
769; CHECK-LABEL: @or_ashr_not_vec(
770; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], splat (i8 -1)
771; CHECK-NEXT:    [[TMP2:%.*]] = or <4 x i8> [[X:%.*]], [[TMP1]]
772; CHECK-NEXT:    [[OR:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
773; CHECK-NEXT:    ret <4 x i8> [[OR]]
774;
775  %x.shift = ashr <4 x i8> %x, %shamt
776  %y.shift = ashr <4 x i8> %y, %shamt
777  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
778  %or = or <4 x i8> %x.shift, %y.shift.not
779  ret <4 x i8> %or
780}
781
782define <4 x i8> @or_ashr_not_vec_commuted(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
783; CHECK-LABEL: @or_ashr_not_vec_commuted(
784; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], splat (i8 -1)
785; CHECK-NEXT:    [[TMP2:%.*]] = or <4 x i8> [[X:%.*]], [[TMP1]]
786; CHECK-NEXT:    [[OR:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
787; CHECK-NEXT:    ret <4 x i8> [[OR]]
788;
789  %x.shift = ashr <4 x i8> %x, %shamt
790  %y.shift = ashr <4 x i8> %y, %shamt
791  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
792  %or = or <4 x i8> %y.shift.not, %x.shift
793  ret <4 x i8> %or
794}
795
796define <4 x i8> @or_ashr_not_vec_poison_1(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
797; CHECK-LABEL: @or_ashr_not_vec_poison_1(
798; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], splat (i8 -1)
799; CHECK-NEXT:    [[TMP2:%.*]] = or <4 x i8> [[X:%.*]], [[TMP1]]
800; CHECK-NEXT:    [[OR:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
801; CHECK-NEXT:    ret <4 x i8> [[OR]]
802;
803  %x.shift = ashr <4 x i8> %x, %shamt
804  %y.shift = ashr <4 x i8> %y, %shamt
805  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 poison, i8 poison, i8 poison>
806  %or = or <4 x i8> %x.shift, %y.shift.not
807  ret <4 x i8> %or
808}
809
810define <4 x i8> @or_ashr_not_vec_poison_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
811; CHECK-LABEL: @or_ashr_not_vec_poison_2(
812; CHECK-NEXT:    ret <4 x i8> poison
813;
814  %x.shift = ashr <4 x i8> %x, %shamt
815  %y.shift = ashr <4 x i8> %y, %shamt
816  %y.shift.not = xor <4 x i8> %y.shift, <i8 poison, i8 poison, i8 poison, i8 poison>
817  %or = or <4 x i8> %x.shift, %y.shift.not
818  ret <4 x i8> %or
819}
820
821; Fold (-x >> y) ^ ((x >> y) ^ -1) -> (-x ^ ~x) >> y
822
823define i8 @xor_ashr_not(i8 %x, i8 %y, i8 %shamt) {
824; CHECK-LABEL: @xor_ashr_not(
825; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
826; CHECK-NEXT:    [[DOTNOT:%.*]] = ashr i8 [[TMP1]], [[SHAMT:%.*]]
827; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[DOTNOT]], -1
828; CHECK-NEXT:    ret i8 [[XOR]]
829;
830  %x.shift = ashr i8 %x, %shamt
831  %y.shift = ashr i8 %y, %shamt
832  %y.shift.not = xor i8 %y.shift, -1
833  %xor = xor i8 %x.shift, %y.shift.not
834  ret i8 %xor
835}
836
837define i8 @xor_ashr_not_commuted(i8 %x, i8 %y, i8 %shamt) {
838; CHECK-LABEL: @xor_ashr_not_commuted(
839; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
840; CHECK-NEXT:    [[DOTNOT:%.*]] = ashr i8 [[TMP1]], [[SHAMT:%.*]]
841; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[DOTNOT]], -1
842; CHECK-NEXT:    ret i8 [[XOR]]
843;
844  %x.shift = ashr i8 %x, %shamt
845  %y.shift = ashr i8 %y, %shamt
846  %y.shift.not = xor i8 %y.shift, -1
847  %xor = xor i8 %y.shift.not, %x.shift
848  ret i8 %xor
849}
850
851; Negative test: lshr instead of ashr
852
853define i8 @xor_ashr_not_fail_lshr_ashr(i8 %x, i8 %y, i8 %shamt) {
854; CHECK-LABEL: @xor_ashr_not_fail_lshr_ashr(
855; CHECK-NEXT:    [[X_SHIFT:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
856; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
857; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y_SHIFT]], [[X_SHIFT]]
858; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -1
859; CHECK-NEXT:    ret i8 [[XOR]]
860;
861  %x.shift = lshr i8 %x, %shamt
862  %y.shift = ashr i8 %y, %shamt
863  %y.shift.not = xor i8 %y.shift, -1
864  %xor = xor i8 %x.shift, %y.shift.not
865  ret i8 %xor
866}
867
868; Negative test: lshr instead of ashr
869
870define i8 @xor_ashr_not_fail_ashr_lshr(i8 %x, i8 %y, i8 %shamt) {
871; CHECK-LABEL: @xor_ashr_not_fail_ashr_lshr(
872; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
873; CHECK-NEXT:    [[Y_SHIFT:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
874; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y_SHIFT]], [[X_SHIFT]]
875; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -1
876; CHECK-NEXT:    ret i8 [[XOR]]
877;
878  %x.shift = ashr i8 %x, %shamt
879  %y.shift = lshr i8 %y, %shamt
880  %y.shift.not = xor i8 %y.shift, -1
881  %xor = xor i8 %x.shift, %y.shift.not
882  ret i8 %xor
883}
884
885; Negative test: invalid xor constant
886
887define i8 @xor_ashr_not_fail_invalid_xor_constant(i8 %x, i8 %y, i8 %shamt) {
888; CHECK-LABEL: @xor_ashr_not_fail_invalid_xor_constant(
889; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
890; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[Y_SHIFT1]], [[SHAMT:%.*]]
891; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -2
892; CHECK-NEXT:    ret i8 [[XOR]]
893;
894  %x.shift = ashr i8 %x, %shamt
895  %y.shift = ashr i8 %y, %shamt
896  %y.shift.not = xor i8 %y.shift, -2
897  %xor = xor i8 %x.shift, %y.shift.not
898  ret i8 %xor
899}
900
901define <4 x i8> @xor_ashr_not_vec(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
902; CHECK-LABEL: @xor_ashr_not_vec(
903; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
904; CHECK-NEXT:    [[DOTNOT:%.*]] = ashr <4 x i8> [[TMP1]], [[SHAMT:%.*]]
905; CHECK-NEXT:    [[XOR:%.*]] = xor <4 x i8> [[DOTNOT]], splat (i8 -1)
906; CHECK-NEXT:    ret <4 x i8> [[XOR]]
907;
908  %x.shift = ashr <4 x i8> %x, %shamt
909  %y.shift = ashr <4 x i8> %y, %shamt
910  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
911  %xor = xor <4 x i8> %x.shift, %y.shift.not
912  ret <4 x i8> %xor
913}
914
915define <4 x i8> @xor_ashr_not_vec_commuted(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
916; CHECK-LABEL: @xor_ashr_not_vec_commuted(
917; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
918; CHECK-NEXT:    [[DOTNOT:%.*]] = ashr <4 x i8> [[TMP1]], [[SHAMT:%.*]]
919; CHECK-NEXT:    [[XOR:%.*]] = xor <4 x i8> [[DOTNOT]], splat (i8 -1)
920; CHECK-NEXT:    ret <4 x i8> [[XOR]]
921;
922  %x.shift = ashr <4 x i8> %x, %shamt
923  %y.shift = ashr <4 x i8> %y, %shamt
924  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
925  %xor = xor <4 x i8> %y.shift.not, %x.shift
926  ret <4 x i8> %xor
927}
928
929define <4 x i8> @xor_ashr_not_vec_poison_1(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
930; CHECK-LABEL: @xor_ashr_not_vec_poison_1(
931; CHECK-NEXT:    [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
932; CHECK-NEXT:    [[DOTNOT:%.*]] = ashr <4 x i8> [[TMP1]], [[SHAMT:%.*]]
933; CHECK-NEXT:    [[XOR:%.*]] = xor <4 x i8> [[DOTNOT]], splat (i8 -1)
934; CHECK-NEXT:    ret <4 x i8> [[XOR]]
935;
936  %x.shift = ashr <4 x i8> %x, %shamt
937  %y.shift = ashr <4 x i8> %y, %shamt
938  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 poison, i8 poison, i8 poison>
939  %xor = xor <4 x i8> %x.shift, %y.shift.not
940  ret <4 x i8> %xor
941}
942
943define <4 x i8> @xor_ashr_not_vec_poison_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
944; CHECK-LABEL: @xor_ashr_not_vec_poison_2(
945; CHECK-NEXT:    ret <4 x i8> poison
946;
947  %x.shift = ashr <4 x i8> %x, %shamt
948  %y.shift = ashr <4 x i8> %y, %shamt
949  %y.shift.not = xor <4 x i8> %y.shift, <i8 poison, i8 poison, i8 poison, i8 poison>
950  %xor = xor <4 x i8> %x.shift, %y.shift.not
951  ret <4 x i8> %xor
952}
953
954; Negative test: invalid binop
955
956define i8 @binop_ashr_not_fail_invalid_binop(i8 %x, i8 %y, i8 %shamt) {
957; CHECK-LABEL: @binop_ashr_not_fail_invalid_binop(
958; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
959; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
960; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
961; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
962; CHECK-NEXT:    ret i8 [[ADD]]
963;
964  %x.shift = ashr i8 %x, %shamt
965  %y.shift = ashr i8 %y, %shamt
966  %y.shift.not = xor i8 %y.shift, -1
967  %add = add i8 %x.shift, %y.shift.not
968  ret i8 %add
969}
970