xref: /llvm-project/llvm/test/Transforms/InstCombine/shift-logic.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
4declare void @use(i64)
5
6define i8 @shl_and(i8 %x, i8 %y) {
7; CHECK-LABEL: @shl_and(
8; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[X:%.*]], 5
9; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[Y:%.*]], 2
10; CHECK-NEXT:    [[SH1:%.*]] = and i8 [[TMP1]], [[TMP2]]
11; CHECK-NEXT:    ret i8 [[SH1]]
12;
13  %sh0 = shl i8 %x, 3
14  %r = and i8 %sh0, %y
15  %sh1 = shl i8 %r, 2
16  ret i8 %sh1
17}
18
19define <2 x i8> @shl_and_nonuniform(<2 x i8> %x, <2 x i8> %y) {
20; CHECK-LABEL: @shl_and_nonuniform(
21; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 4>
22; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 0>
23; CHECK-NEXT:    [[SH1:%.*]] = and <2 x i8> [[TMP1]], [[TMP2]]
24; CHECK-NEXT:    ret <2 x i8> [[SH1]]
25;
26  %sh0 = shl <2 x i8> %x, <i8 3, i8 4>
27  %r = and <2 x i8> %sh0, %y
28  %sh1 = shl <2 x i8> %r, <i8 2, i8 0>
29  ret <2 x i8> %sh1
30}
31
32define i16 @shl_or(i16 %x, i16 %py) {
33; CHECK-LABEL: @shl_or(
34; CHECK-NEXT:    [[Y:%.*]] = srem i16 [[PY:%.*]], 42
35; CHECK-NEXT:    [[TMP1:%.*]] = shl i16 [[X:%.*]], 12
36; CHECK-NEXT:    [[TMP2:%.*]] = shl nsw i16 [[Y]], 7
37; CHECK-NEXT:    [[SH1:%.*]] = or i16 [[TMP1]], [[TMP2]]
38; CHECK-NEXT:    ret i16 [[SH1]]
39;
40  %y = srem i16 %py, 42 ; thwart complexity-based canonicalization
41  %sh0 = shl i16 %x, 5
42  %r = or i16 %y, %sh0
43  %sh1 = shl i16 %r, 7
44  ret i16 %sh1
45}
46
47define <2 x i16> @shl_or_poison(<2 x i16> %x, <2 x i16> %py) {
48; CHECK-LABEL: @shl_or_poison(
49; CHECK-NEXT:    [[Y:%.*]] = srem <2 x i16> [[PY:%.*]], splat (i16 42)
50; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i16> [[X:%.*]], <i16 12, i16 poison>
51; CHECK-NEXT:    [[TMP2:%.*]] = shl nsw <2 x i16> [[Y]], <i16 7, i16 poison>
52; CHECK-NEXT:    [[SH1:%.*]] = or <2 x i16> [[TMP1]], [[TMP2]]
53; CHECK-NEXT:    ret <2 x i16> [[SH1]]
54;
55  %y = srem <2 x i16> %py, <i16 42, i16 42> ; thwart complexity-based canonicalization
56  %sh0 = shl <2 x i16> %x, <i16 5, i16 poison>
57  %r = or <2 x i16> %y, %sh0
58  %sh1 = shl <2 x i16> %r, <i16 7, i16 poison>
59  ret <2 x i16> %sh1
60}
61
62define i32 @shl_xor(i32 %x, i32 %y) {
63; CHECK-LABEL: @shl_xor(
64; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 12
65; CHECK-NEXT:    [[TMP2:%.*]] = shl i32 [[Y:%.*]], 7
66; CHECK-NEXT:    [[SH1:%.*]] = xor i32 [[TMP1]], [[TMP2]]
67; CHECK-NEXT:    ret i32 [[SH1]]
68;
69  %sh0 = shl i32 %x, 5
70  %r = xor i32 %sh0, %y
71  %sh1 = shl i32 %r, 7
72  ret i32 %sh1
73}
74
75define <2 x i32> @shl_xor_nonuniform(<2 x i32> %x, <2 x i32> %y) {
76; CHECK-LABEL: @shl_xor_nonuniform(
77; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i32> [[X:%.*]], <i32 12, i32 14>
78; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i32> [[Y:%.*]], <i32 7, i32 8>
79; CHECK-NEXT:    [[SH1:%.*]] = xor <2 x i32> [[TMP1]], [[TMP2]]
80; CHECK-NEXT:    ret <2 x i32> [[SH1]]
81;
82  %sh0 = shl <2 x i32> %x, <i32 5, i32 6>
83  %r = xor <2 x i32> %sh0, %y
84  %sh1 = shl <2 x i32> %r, <i32 7, i32 8>
85  ret <2 x i32> %sh1
86}
87
88define i64 @lshr_and(i64 %x, i64 %py) {
89; CHECK-LABEL: @lshr_and(
90; CHECK-NEXT:    [[Y:%.*]] = srem i64 [[PY:%.*]], 42
91; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 12
92; CHECK-NEXT:    [[TMP2:%.*]] = lshr i64 [[Y]], 7
93; CHECK-NEXT:    [[SH1:%.*]] = and i64 [[TMP1]], [[TMP2]]
94; CHECK-NEXT:    ret i64 [[SH1]]
95;
96  %y = srem i64 %py, 42 ; thwart complexity-based canonicalization
97  %sh0 = lshr i64 %x, 5
98  %r = and i64 %y, %sh0
99  %sh1 = lshr i64 %r, 7
100  ret i64 %sh1
101}
102
103define <2 x i64> @lshr_and_poison(<2 x i64> %x, <2 x i64> %py) {
104; CHECK-LABEL: @lshr_and_poison(
105; CHECK-NEXT:    [[Y:%.*]] = srem <2 x i64> [[PY:%.*]], splat (i64 42)
106; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 12, i64 poison>
107; CHECK-NEXT:    [[TMP2:%.*]] = lshr <2 x i64> [[Y]], <i64 7, i64 poison>
108; CHECK-NEXT:    [[SH1:%.*]] = and <2 x i64> [[TMP1]], [[TMP2]]
109; CHECK-NEXT:    ret <2 x i64> [[SH1]]
110;
111  %y = srem <2 x i64> %py, <i64 42, i64 42> ; thwart complexity-based canonicalization
112  %sh0 = lshr <2 x i64> %x, <i64 5, i64 poison>
113  %r = and <2 x i64> %y, %sh0
114  %sh1 = lshr <2 x i64> %r, <i64 7, i64 poison>
115  ret <2 x i64> %sh1
116}
117
118define <4 x i32> @lshr_or(<4 x i32> %x, <4 x i32> %y) {
119; CHECK-LABEL: @lshr_or(
120; CHECK-NEXT:    [[TMP1:%.*]] = lshr <4 x i32> [[X:%.*]], splat (i32 12)
121; CHECK-NEXT:    [[TMP2:%.*]] = lshr <4 x i32> [[Y:%.*]], splat (i32 7)
122; CHECK-NEXT:    [[SH1:%.*]] = or <4 x i32> [[TMP1]], [[TMP2]]
123; CHECK-NEXT:    ret <4 x i32> [[SH1]]
124;
125  %sh0 = lshr <4 x i32> %x, <i32 5, i32 5, i32 5, i32 5>
126  %r = or <4 x i32> %sh0, %y
127  %sh1 = lshr <4 x i32> %r, <i32 7, i32 7, i32 7, i32 7>
128  ret <4 x i32> %sh1
129}
130
131define <8 x i16> @lshr_xor(<8 x i16> %x, <8 x i16> %py) {
132; CHECK-LABEL: @lshr_xor(
133; CHECK-NEXT:    [[Y:%.*]] = srem <8 x i16> [[PY:%.*]], splat (i16 42)
134; CHECK-NEXT:    [[TMP1:%.*]] = lshr <8 x i16> [[X:%.*]], splat (i16 12)
135; CHECK-NEXT:    [[TMP2:%.*]] = lshr <8 x i16> [[Y]], splat (i16 7)
136; CHECK-NEXT:    [[SH1:%.*]] = xor <8 x i16> [[TMP1]], [[TMP2]]
137; CHECK-NEXT:    ret <8 x i16> [[SH1]]
138;
139  %y = srem <8 x i16> %py, <i16 42, i16 42, i16 42, i16 42, i16 42, i16 42, i16 42, i16 -42> ; thwart complexity-based canonicalization
140  %sh0 = lshr <8 x i16> %x, <i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5>
141  %r = xor <8 x i16> %y, %sh0
142  %sh1 = lshr <8 x i16> %r, <i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7>
143  ret <8 x i16> %sh1
144}
145
146define <16 x i8> @ashr_and(<16 x i8> %x, <16 x i8> %py, <16 x i8> %pz) {
147; CHECK-LABEL: @ashr_and(
148; CHECK-NEXT:    [[Y:%.*]] = srem <16 x i8> [[PY:%.*]], [[PZ:%.*]]
149; CHECK-NEXT:    [[TMP1:%.*]] = ashr <16 x i8> [[X:%.*]], splat (i8 5)
150; CHECK-NEXT:    [[TMP2:%.*]] = ashr <16 x i8> [[Y]], splat (i8 2)
151; CHECK-NEXT:    [[SH1:%.*]] = and <16 x i8> [[TMP1]], [[TMP2]]
152; CHECK-NEXT:    ret <16 x i8> [[SH1]]
153;
154  %y = srem <16 x i8> %py, %pz ; thwart complexity-based canonicalization
155  %sh0 = ashr <16 x i8> %x, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
156  %r = and <16 x i8> %y, %sh0
157  %sh1 = ashr <16 x i8> %r, <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2>
158  ret <16 x i8> %sh1
159}
160
161define <2 x i64> @ashr_or(<2 x i64> %x, <2 x i64> %y) {
162; CHECK-LABEL: @ashr_or(
163; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i64> [[X:%.*]], splat (i64 12)
164; CHECK-NEXT:    [[TMP2:%.*]] = ashr <2 x i64> [[Y:%.*]], splat (i64 7)
165; CHECK-NEXT:    [[SH1:%.*]] = or <2 x i64> [[TMP1]], [[TMP2]]
166; CHECK-NEXT:    ret <2 x i64> [[SH1]]
167;
168  %sh0 = ashr <2 x i64> %x, <i64 5, i64 5>
169  %r = or <2 x i64> %sh0, %y
170  %sh1 = ashr <2 x i64> %r, <i64 7, i64 7>
171  ret <2 x i64> %sh1
172}
173
174define i32 @ashr_xor(i32 %x, i32 %py) {
175; CHECK-LABEL: @ashr_xor(
176; CHECK-NEXT:    [[Y:%.*]] = srem i32 [[PY:%.*]], 42
177; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 12
178; CHECK-NEXT:    [[TMP2:%.*]] = ashr i32 [[Y]], 7
179; CHECK-NEXT:    [[SH1:%.*]] = xor i32 [[TMP1]], [[TMP2]]
180; CHECK-NEXT:    ret i32 [[SH1]]
181;
182  %y = srem i32 %py, 42 ; thwart complexity-based canonicalization
183  %sh0 = ashr i32 %x, 5
184  %r = xor i32 %y, %sh0
185  %sh1 = ashr i32 %r, 7
186  ret i32 %sh1
187}
188
189define i32 @shr_mismatch_xor(i32 %x, i32 %y) {
190; CHECK-LABEL: @shr_mismatch_xor(
191; CHECK-NEXT:    [[SH0:%.*]] = ashr i32 [[X:%.*]], 5
192; CHECK-NEXT:    [[R:%.*]] = xor i32 [[Y:%.*]], [[SH0]]
193; CHECK-NEXT:    [[SH1:%.*]] = lshr i32 [[R]], 7
194; CHECK-NEXT:    ret i32 [[SH1]]
195;
196  %sh0 = ashr i32 %x, 5
197  %r = xor i32 %y, %sh0
198  %sh1 = lshr i32 %r, 7
199  ret i32 %sh1
200}
201
202define i32 @ashr_overshift_xor(i32 %x, i32 %y) {
203; CHECK-LABEL: @ashr_overshift_xor(
204; CHECK-NEXT:    [[SH0:%.*]] = ashr i32 [[X:%.*]], 15
205; CHECK-NEXT:    [[R:%.*]] = xor i32 [[Y:%.*]], [[SH0]]
206; CHECK-NEXT:    [[SH1:%.*]] = ashr i32 [[R]], 17
207; CHECK-NEXT:    ret i32 [[SH1]]
208;
209  %sh0 = ashr i32 %x, 15
210  %r = xor i32 %y, %sh0
211  %sh1 = ashr i32 %r, 17
212  ret i32 %sh1
213}
214
215define <2 x i32> @ashr_poison_poison_xor(<2 x i32> %x, <2 x i32> %y) {
216; CHECK-LABEL: @ashr_poison_poison_xor(
217; CHECK-NEXT:    [[SH0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 15, i32 poison>
218; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[Y:%.*]], [[SH0]]
219; CHECK-NEXT:    [[SH1:%.*]] = ashr <2 x i32> [[R]], <i32 poison, i32 17>
220; CHECK-NEXT:    ret <2 x i32> [[SH1]]
221;
222  %sh0 = ashr <2 x i32> %x, <i32 15, i32 poison>
223  %r = xor <2 x i32> %y, %sh0
224  %sh1 = ashr <2 x i32> %r, <i32 poison, i32 17>
225  ret <2 x i32> %sh1
226}
227
228define i32 @lshr_or_extra_use(i32 %x, i32 %y, ptr %p) {
229; CHECK-LABEL: @lshr_or_extra_use(
230; CHECK-NEXT:    [[SH0:%.*]] = lshr i32 [[X:%.*]], 5
231; CHECK-NEXT:    [[R:%.*]] = or i32 [[SH0]], [[Y:%.*]]
232; CHECK-NEXT:    store i32 [[R]], ptr [[P:%.*]], align 4
233; CHECK-NEXT:    [[SH1:%.*]] = lshr i32 [[R]], 7
234; CHECK-NEXT:    ret i32 [[SH1]]
235;
236  %sh0 = lshr i32 %x, 5
237  %r = or i32 %sh0, %y
238  store i32 %r, ptr %p
239  %sh1 = lshr i32 %r, 7
240  ret i32 %sh1
241}
242
243; Avoid crashing on constant expressions.
244
245@g = external global i32
246
247define i32 @PR44028(i32 %x) {
248; CHECK-LABEL: @PR44028(
249; CHECK-NEXT:    [[SH1:%.*]] = ashr exact i32 [[X:%.*]], 16
250; CHECK-NEXT:    [[SH2:%.*]] = shl i32 ptrtoint (ptr @g to i32), 16
251; CHECK-NEXT:    [[T0:%.*]] = xor i32 [[SH1]], [[SH2]]
252; CHECK-NEXT:    [[T27:%.*]] = ashr exact i32 [[T0]], 16
253; CHECK-NEXT:    ret i32 [[T27]]
254;
255  %sh1 = ashr exact i32 %x, 16
256  %sh2 = shl i32 ptrtoint (ptr @g to i32), 16
257  %t0 = xor i32 %sh1, %sh2
258  %t27 = ashr exact i32 %t0, 16
259  ret i32 %t27
260}
261
262define i64 @lshr_mul(i64 %0) {
263; CHECK-LABEL: @lshr_mul(
264; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw nsw i64 [[TMP0:%.*]], 13
265; CHECK-NEXT:    ret i64 [[TMP2]]
266;
267  %2 = mul nuw i64 %0, 52
268  %3 = lshr i64 %2, 2
269  ret i64 %3
270}
271
272define i64 @lshr_mul_nuw_nsw(i64 %0) {
273; CHECK-LABEL: @lshr_mul_nuw_nsw(
274; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw nsw i64 [[TMP0:%.*]], 13
275; CHECK-NEXT:    ret i64 [[TMP2]]
276;
277  %2 = mul nuw nsw i64 %0, 52
278  %3 = lshr i64 %2, 2
279  ret i64 %3
280}
281
282define <4 x i32> @lshr_mul_vector(<4 x i32> %0) {
283; CHECK-LABEL: @lshr_mul_vector(
284; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw nsw <4 x i32> [[TMP0:%.*]], splat (i32 13)
285; CHECK-NEXT:    ret <4 x i32> [[TMP2]]
286;
287  %2 = mul nuw <4 x i32> %0, <i32 52, i32 52, i32 52, i32 52>
288  %3 = lshr <4 x i32> %2, <i32 2, i32 2, i32 2, i32 2>
289  ret <4 x i32> %3
290}
291
292define i64 @lshr_mul_negative_noexact(i64 %0) {
293; CHECK-LABEL: @lshr_mul_negative_noexact(
294; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw i64 [[TMP0:%.*]], 53
295; CHECK-NEXT:    [[TMP3:%.*]] = lshr i64 [[TMP2]], 2
296; CHECK-NEXT:    ret i64 [[TMP3]]
297;
298  %2 = mul nuw i64 %0, 53
299  %3 = lshr i64 %2, 2
300  ret i64 %3
301}
302
303define i64 @lshr_mul_negative_oneuse(i64 %0) {
304; CHECK-LABEL: @lshr_mul_negative_oneuse(
305; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw i64 [[TMP0:%.*]], 52
306; CHECK-NEXT:    call void @use(i64 [[TMP2]])
307; CHECK-NEXT:    [[TMP3:%.*]] = lshr exact i64 [[TMP2]], 2
308; CHECK-NEXT:    ret i64 [[TMP3]]
309;
310  %2 = mul nuw i64 %0, 52
311  call void @use(i64 %2)
312  %3 = lshr i64 %2, 2
313  ret i64 %3
314}
315
316define i64 @lshr_mul_negative_nonuw(i64 %0) {
317; CHECK-LABEL: @lshr_mul_negative_nonuw(
318; CHECK-NEXT:    [[TMP2:%.*]] = mul i64 [[TMP0:%.*]], 52
319; CHECK-NEXT:    [[TMP3:%.*]] = lshr exact i64 [[TMP2]], 2
320; CHECK-NEXT:    ret i64 [[TMP3]]
321;
322  %2 = mul i64 %0, 52
323  %3 = lshr i64 %2, 2
324  ret i64 %3
325}
326
327define i64 @lshr_mul_negative_nsw(i64 %0) {
328; CHECK-LABEL: @lshr_mul_negative_nsw(
329; CHECK-NEXT:    [[TMP2:%.*]] = mul nsw i64 [[TMP0:%.*]], 52
330; CHECK-NEXT:    [[TMP3:%.*]] = lshr exact i64 [[TMP2]], 2
331; CHECK-NEXT:    ret i64 [[TMP3]]
332;
333  %2 = mul nsw i64 %0, 52
334  %3 = lshr i64 %2, 2
335  ret i64 %3
336}
337
338define i8 @shl_add(i8 %x, i8 %y) {
339; CHECK-LABEL: @shl_add(
340; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[X:%.*]], 5
341; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[Y:%.*]], 2
342; CHECK-NEXT:    [[SH1:%.*]] = add i8 [[TMP1]], [[TMP2]]
343; CHECK-NEXT:    ret i8 [[SH1]]
344;
345  %sh0 = shl i8 %x, 3
346  %r = add i8 %sh0, %y
347  %sh1 = shl i8 %r, 2
348  ret i8 %sh1
349}
350
351define i8 @shl_add_multiuse(i8 %x) {
352; CHECK-LABEL: @shl_add_multiuse(
353; CHECK-NEXT:    [[SH0:%.*]] = shl i8 [[X:%.*]], 3
354; CHECK-NEXT:    call void @use(i8 [[SH0]])
355; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X]], 5
356; CHECK-NEXT:    [[SH1:%.*]] = add i8 [[R]], 88
357; CHECK-NEXT:    ret i8 [[SH1]]
358;
359  %sh0 = shl i8 %x, 3
360  %r = add i8 %sh0, -42
361  call void @use(i8 %sh0)
362  %sh1 = shl i8 %r, 2
363  ret i8 %sh1
364}
365
366define i8 @shl_add_multiuse_nonconstant(i8 %x, i8 %y) {
367; CHECK-LABEL: @shl_add_multiuse_nonconstant(
368; CHECK-NEXT:    [[SH0:%.*]] = shl i8 [[X:%.*]], 3
369; CHECK-NEXT:    [[R:%.*]] = add i8 [[SH0]], [[Y:%.*]]
370; CHECK-NEXT:    call void @use(i8 [[SH0]])
371; CHECK-NEXT:    [[SH1:%.*]] = shl i8 [[R]], 2
372; CHECK-NEXT:    ret i8 [[SH1]]
373;
374  %sh0 = shl i8 %x, 3
375  %r = add i8 %sh0, %y
376  call void @use(i8 %sh0)
377  %sh1 = shl i8 %r, 2
378  ret i8 %sh1
379}
380
381define <2 x i8> @shl_add_nonuniform(<2 x i8> %x, <2 x i8> %y) {
382; CHECK-LABEL: @shl_add_nonuniform(
383; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 4>
384; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 0>
385; CHECK-NEXT:    [[SH1:%.*]] = add <2 x i8> [[TMP1]], [[TMP2]]
386; CHECK-NEXT:    ret <2 x i8> [[SH1]]
387;
388  %sh0 = shl <2 x i8> %x, <i8 3, i8 4>
389  %r = add <2 x i8> %sh0, %y
390  %sh1 = shl <2 x i8> %r, <i8 2, i8 0>
391  ret <2 x i8> %sh1
392}
393
394
395define <2 x i64> @shl_add_poison(<2 x i64> %x, <2 x i64> %py) {
396; CHECK-LABEL: @shl_add_poison(
397; CHECK-NEXT:    [[Y:%.*]] = srem <2 x i64> [[PY:%.*]], splat (i64 42)
398; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[X:%.*]], <i64 12, i64 poison>
399; CHECK-NEXT:    [[TMP2:%.*]] = shl nsw <2 x i64> [[Y]], <i64 7, i64 poison>
400; CHECK-NEXT:    [[SH1:%.*]] = add <2 x i64> [[TMP1]], [[TMP2]]
401; CHECK-NEXT:    ret <2 x i64> [[SH1]]
402;
403  %y = srem <2 x i64> %py, <i64 42, i64 42> ; thwart complexity-based canonicalization
404  %sh0 = shl <2 x i64> %x, <i64 5, i64 poison>
405  %r = add <2 x i64> %y, %sh0
406  %sh1 = shl <2 x i64> %r, <i64 7, i64 poison>
407  ret <2 x i64> %sh1
408}
409
410
411define i8 @lshr_add(i8 %x, i8 %y) {
412; CHECK-LABEL: @lshr_add(
413; CHECK-NEXT:    [[SH0:%.*]] = lshr i8 [[X:%.*]], 3
414; CHECK-NEXT:    [[R:%.*]] = add i8 [[SH0]], [[Y:%.*]]
415; CHECK-NEXT:    [[SH1:%.*]] = lshr i8 [[R]], 2
416; CHECK-NEXT:    ret i8 [[SH1]]
417;
418  %sh0 = lshr i8 %x, 3
419  %r = add i8 %sh0, %y
420  %sh1 = lshr i8 %r, 2
421  ret i8 %sh1
422}
423
424define <2 x i8> @lshr_add_nonuniform(<2 x i8> %x, <2 x i8> %y) {
425; CHECK-LABEL: @lshr_add_nonuniform(
426; CHECK-NEXT:    [[SH0:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 3, i8 4>
427; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[SH0]], [[Y:%.*]]
428; CHECK-NEXT:    [[SH1:%.*]] = lshr <2 x i8> [[R]], <i8 2, i8 0>
429; CHECK-NEXT:    ret <2 x i8> [[SH1]]
430;
431  %sh0 = lshr <2 x i8> %x, <i8 3, i8 4>
432  %r = add <2 x i8> %sh0, %y
433  %sh1 = lshr <2 x i8> %r, <i8 2, i8 0>
434  ret <2 x i8> %sh1
435}
436
437define <2 x i64> @lshr_add_poison(<2 x i64> %x, <2 x i64> %py) {
438; CHECK-LABEL: @lshr_add_poison(
439; CHECK-NEXT:    [[Y:%.*]] = srem <2 x i64> [[PY:%.*]], splat (i64 42)
440; CHECK-NEXT:    [[SH0:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 5, i64 poison>
441; CHECK-NEXT:    [[R:%.*]] = add nsw <2 x i64> [[Y]], [[SH0]]
442; CHECK-NEXT:    [[SH1:%.*]] = lshr <2 x i64> [[R]], <i64 7, i64 poison>
443; CHECK-NEXT:    ret <2 x i64> [[SH1]]
444;
445  %y = srem <2 x i64> %py, <i64 42, i64 42> ; thwart complexity-based canonicalization
446  %sh0 = lshr <2 x i64> %x, <i64 5, i64 poison>
447  %r = add <2 x i64> %y, %sh0
448  %sh1 = lshr <2 x i64> %r, <i64 7, i64 poison>
449  ret <2 x i64> %sh1
450}
451
452define i8 @shl_sub(i8 %x, i8 %y) {
453; CHECK-LABEL: @shl_sub(
454; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[X:%.*]], 5
455; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[Y:%.*]], 2
456; CHECK-NEXT:    [[SH1:%.*]] = sub i8 [[TMP1]], [[TMP2]]
457; CHECK-NEXT:    ret i8 [[SH1]]
458;
459  %sh0 = shl i8 %x, 3
460  %r = sub i8 %sh0, %y
461  %sh1 = shl i8 %r, 2
462  ret i8 %sh1
463}
464
465; Make sure we don't commute operands for sub
466define i8 @shl_sub_no_commute(i8 %x, i8 %y) {
467; CHECK-LABEL: @shl_sub_no_commute(
468; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[Y:%.*]], 5
469; CHECK-NEXT:    [[TMP2:%.*]] = shl i8 [[X:%.*]], 2
470; CHECK-NEXT:    [[SH1:%.*]] = sub i8 [[TMP2]], [[TMP1]]
471; CHECK-NEXT:    ret i8 [[SH1]]
472;
473  %sh0 = shl i8 %y, 3
474  %r = sub i8 %x, %sh0
475  %sh1 = shl i8 %r, 2
476  ret i8 %sh1
477}
478
479define <2 x i8> @shl_sub_nonuniform(<2 x i8> %x, <2 x i8> %y) {
480; CHECK-LABEL: @shl_sub_nonuniform(
481; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 4>
482; CHECK-NEXT:    [[TMP2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 0>
483; CHECK-NEXT:    [[SH1:%.*]] = sub <2 x i8> [[TMP1]], [[TMP2]]
484; CHECK-NEXT:    ret <2 x i8> [[SH1]]
485;
486  %sh0 = shl <2 x i8> %x, <i8 3, i8 4>
487  %r = sub <2 x i8> %sh0, %y
488  %sh1 = shl <2 x i8> %r, <i8 2, i8 0>
489  ret <2 x i8> %sh1
490}
491
492
493define <2 x i64> @shl_sub_poison(<2 x i64> %x, <2 x i64> %py) {
494; CHECK-LABEL: @shl_sub_poison(
495; CHECK-NEXT:    [[Y:%.*]] = srem <2 x i64> [[PY:%.*]], splat (i64 42)
496; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[X:%.*]], <i64 12, i64 poison>
497; CHECK-NEXT:    [[TMP2:%.*]] = shl nsw <2 x i64> [[Y]], <i64 7, i64 poison>
498; CHECK-NEXT:    [[SH1:%.*]] = sub <2 x i64> [[TMP2]], [[TMP1]]
499; CHECK-NEXT:    ret <2 x i64> [[SH1]]
500;
501  %y = srem <2 x i64> %py, <i64 42, i64 42> ; thwart complexity-based canonicalization
502  %sh0 = shl <2 x i64> %x, <i64 5, i64 poison>
503  %r = sub <2 x i64> %y, %sh0
504  %sh1 = shl <2 x i64> %r, <i64 7, i64 poison>
505  ret <2 x i64> %sh1
506}
507
508
509define i8 @lshr_sub(i8 %x, i8 %y) {
510; CHECK-LABEL: @lshr_sub(
511; CHECK-NEXT:    [[SH0:%.*]] = lshr i8 [[X:%.*]], 3
512; CHECK-NEXT:    [[R:%.*]] = sub i8 [[SH0]], [[Y:%.*]]
513; CHECK-NEXT:    [[SH1:%.*]] = lshr i8 [[R]], 2
514; CHECK-NEXT:    ret i8 [[SH1]]
515;
516  %sh0 = lshr i8 %x, 3
517  %r = sub i8 %sh0, %y
518  %sh1 = lshr i8 %r, 2
519  ret i8 %sh1
520}
521
522define <2 x i8> @lshr_sub_nonuniform(<2 x i8> %x, <2 x i8> %y) {
523; CHECK-LABEL: @lshr_sub_nonuniform(
524; CHECK-NEXT:    [[SH0:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 3, i8 4>
525; CHECK-NEXT:    [[R:%.*]] = sub <2 x i8> [[SH0]], [[Y:%.*]]
526; CHECK-NEXT:    [[SH1:%.*]] = lshr <2 x i8> [[R]], <i8 2, i8 0>
527; CHECK-NEXT:    ret <2 x i8> [[SH1]]
528;
529  %sh0 = lshr <2 x i8> %x, <i8 3, i8 4>
530  %r = sub <2 x i8> %sh0, %y
531  %sh1 = lshr <2 x i8> %r, <i8 2, i8 0>
532  ret <2 x i8> %sh1
533}
534
535define <2 x i64> @lshr_sub_poison(<2 x i64> %x, <2 x i64> %py) {
536; CHECK-LABEL: @lshr_sub_poison(
537; CHECK-NEXT:    [[Y:%.*]] = srem <2 x i64> [[PY:%.*]], splat (i64 42)
538; CHECK-NEXT:    [[SH0:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 5, i64 poison>
539; CHECK-NEXT:    [[R:%.*]] = sub nsw <2 x i64> [[Y]], [[SH0]]
540; CHECK-NEXT:    [[SH1:%.*]] = lshr <2 x i64> [[R]], <i64 7, i64 poison>
541; CHECK-NEXT:    ret <2 x i64> [[SH1]]
542;
543  %y = srem <2 x i64> %py, <i64 42, i64 42> ; thwart complexity-based canonicalization
544  %sh0 = lshr <2 x i64> %x, <i64 5, i64 poison>
545  %r = sub <2 x i64> %y, %sh0
546  %sh1 = lshr <2 x i64> %r, <i64 7, i64 poison>
547  ret <2 x i64> %sh1
548}
549