1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; This test makes sure that these instructions are properly eliminated.
3;
4; RUN: opt < %s -passes=instcombine -S | FileCheck %s
5
6declare void @use(i8)
7
8define i32 @shl_C1_add_A_C2_i32(i16 %A) {
9; CHECK-LABEL: @shl_C1_add_A_C2_i32(
10; CHECK-NEXT:    [[B:%.*]] = zext i16 [[A:%.*]] to i32
11; CHECK-NEXT:    [[D:%.*]] = shl i32 192, [[B]]
12; CHECK-NEXT:    ret i32 [[D]]
13;
14  %B = zext i16 %A to i32
15  %C = add i32 %B, 5
16  %D = shl i32 6, %C
17  ret i32 %D
18}
19
20define i32 @ashr_C1_add_A_C2_i32(i32 %A) {
21; CHECK-LABEL: @ashr_C1_add_A_C2_i32(
22; CHECK-NEXT:    ret i32 0
23;
24  %B = and i32 %A, 65535
25  %C = add i32 %B, 5
26  %D = ashr i32 6, %C
27  ret i32 %D
28}
29
30define i32 @lshr_C1_add_A_C2_i32(i32 %A) {
31; CHECK-LABEL: @lshr_C1_add_A_C2_i32(
32; CHECK-NEXT:    [[B:%.*]] = and i32 [[A:%.*]], 65535
33; CHECK-NEXT:    [[D:%.*]] = shl i32 192, [[B]]
34; CHECK-NEXT:    ret i32 [[D]]
35;
36  %B = and i32 %A, 65535
37  %C = add i32 %B, 5
38  %D = shl i32 6, %C
39  ret i32 %D
40}
41
42define <4 x i32> @shl_C1_add_A_C2_v4i32(<4 x i16> %A) {
43; CHECK-LABEL: @shl_C1_add_A_C2_v4i32(
44; CHECK-NEXT:    [[B:%.*]] = zext <4 x i16> [[A:%.*]] to <4 x i32>
45; CHECK-NEXT:    [[D:%.*]] = shl <4 x i32> <i32 6, i32 4, i32 poison, i32 -458752>, [[B]]
46; CHECK-NEXT:    ret <4 x i32> [[D]]
47;
48  %B = zext <4 x i16> %A to <4 x i32>
49  %C = add <4 x i32> %B, <i32 0, i32 1, i32 50, i32 16>
50  %D = shl <4 x i32> <i32 6, i32 2, i32 1, i32 -7>, %C
51  ret <4 x i32> %D
52}
53
54define <4 x i32> @ashr_C1_add_A_C2_v4i32(<4 x i32> %A) {
55; CHECK-LABEL: @ashr_C1_add_A_C2_v4i32(
56; CHECK-NEXT:    [[B:%.*]] = and <4 x i32> [[A:%.*]], <i32 0, i32 15, i32 255, i32 65535>
57; CHECK-NEXT:    [[D:%.*]] = ashr <4 x i32> <i32 6, i32 1, i32 poison, i32 -1>, [[B]]
58; CHECK-NEXT:    ret <4 x i32> [[D]]
59;
60  %B = and <4 x i32> %A, <i32 0, i32 15, i32 255, i32 65535>
61  %C = add <4 x i32> %B, <i32 0, i32 1, i32 50, i32 16>
62  %D = ashr <4 x i32> <i32 6, i32 2, i32 1, i32 -7>, %C
63  ret <4 x i32> %D
64}
65
66define <4 x i32> @lshr_C1_add_A_C2_v4i32(<4 x i32> %A) {
67; CHECK-LABEL: @lshr_C1_add_A_C2_v4i32(
68; CHECK-NEXT:    [[B:%.*]] = and <4 x i32> [[A:%.*]], <i32 0, i32 15, i32 255, i32 65535>
69; CHECK-NEXT:    [[D:%.*]] = lshr <4 x i32> <i32 6, i32 1, i32 poison, i32 65535>, [[B]]
70; CHECK-NEXT:    ret <4 x i32> [[D]]
71;
72  %B = and <4 x i32> %A, <i32 0, i32 15, i32 255, i32 65535>
73  %C = add <4 x i32> %B, <i32 0, i32 1, i32 50, i32 16>
74  %D = lshr <4 x i32> <i32 6, i32 2, i32 1, i32 -7>, %C
75  ret <4 x i32> %D
76}
77
78define <4 x i32> @shl_C1_add_A_C2_v4i32_splat(i16 %I) {
79; CHECK-LABEL: @shl_C1_add_A_C2_v4i32_splat(
80; CHECK-NEXT:    [[A:%.*]] = zext i16 [[I:%.*]] to i32
81; CHECK-NEXT:    [[B:%.*]] = insertelement <4 x i32> undef, i32 [[A]], i64 0
82; CHECK-NEXT:    [[C:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> undef, <4 x i32> zeroinitializer
83; CHECK-NEXT:    [[E:%.*]] = shl <4 x i32> <i32 6, i32 4, i32 poison, i32 -458752>, [[C]]
84; CHECK-NEXT:    ret <4 x i32> [[E]]
85;
86  %A = zext i16 %I to i32
87  %B = insertelement <4 x i32> undef, i32 %A, i32 0
88  %C = shufflevector <4 x i32> %B, <4 x i32> undef, <4 x i32> zeroinitializer
89  %D = add <4 x i32> %C, <i32 0, i32 1, i32 50, i32 16>
90  %E = shl <4 x i32> <i32 6, i32 2, i32 1, i32 -7>, %D
91  ret <4 x i32> %E
92}
93
94define <4 x i32> @ashr_C1_add_A_C2_v4i32_splat(i16 %I) {
95; CHECK-LABEL: @ashr_C1_add_A_C2_v4i32_splat(
96; CHECK-NEXT:    [[A:%.*]] = zext i16 [[I:%.*]] to i32
97; CHECK-NEXT:    [[B:%.*]] = insertelement <4 x i32> undef, i32 [[A]], i64 0
98; CHECK-NEXT:    [[C:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> undef, <4 x i32> zeroinitializer
99; CHECK-NEXT:    [[E:%.*]] = ashr <4 x i32> <i32 6, i32 1, i32 poison, i32 -1>, [[C]]
100; CHECK-NEXT:    ret <4 x i32> [[E]]
101;
102  %A = zext i16 %I to i32
103  %B = insertelement <4 x i32> undef, i32 %A, i32 0
104  %C = shufflevector <4 x i32> %B, <4 x i32> undef, <4 x i32> zeroinitializer
105  %D = add <4 x i32> %C, <i32 0, i32 1, i32 50, i32 16>
106  %E = ashr <4 x i32> <i32 6, i32 2, i32 1, i32 -7>, %D
107  ret <4 x i32> %E
108}
109
110define <4 x i32> @lshr_C1_add_A_C2_v4i32_splat(i16 %I) {
111; CHECK-LABEL: @lshr_C1_add_A_C2_v4i32_splat(
112; CHECK-NEXT:    [[A:%.*]] = zext i16 [[I:%.*]] to i32
113; CHECK-NEXT:    [[B:%.*]] = insertelement <4 x i32> undef, i32 [[A]], i64 0
114; CHECK-NEXT:    [[C:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> undef, <4 x i32> zeroinitializer
115; CHECK-NEXT:    [[E:%.*]] = lshr <4 x i32> <i32 6, i32 1, i32 poison, i32 65535>, [[C]]
116; CHECK-NEXT:    ret <4 x i32> [[E]]
117;
118  %A = zext i16 %I to i32
119  %B = insertelement <4 x i32> undef, i32 %A, i32 0
120  %C = shufflevector <4 x i32> %B, <4 x i32> undef, <4 x i32> zeroinitializer
121  %D = add <4 x i32> %C, <i32 0, i32 1, i32 50, i32 16>
122  %E = lshr <4 x i32> <i32 6, i32 2, i32 1, i32 -7>, %D
123  ret <4 x i32> %E
124}
125
126define i32 @shl_add_nuw(i32 %x) {
127; CHECK-LABEL: @shl_add_nuw(
128; CHECK-NEXT:    [[R:%.*]] = shl i32 192, [[X:%.*]]
129; CHECK-NEXT:    ret i32 [[R]]
130;
131  %a = add nuw i32 %x, 5
132  %r = shl i32 6, %a
133  ret i32 %r
134}
135
136; vectors with arbitrary constants work too
137
138define <2 x i12> @lshr_add_nuw(<2 x i12> %x) {
139; CHECK-LABEL: @lshr_add_nuw(
140; CHECK-NEXT:    [[R:%.*]] = lshr <2 x i12> <i12 0, i12 21>, [[X:%.*]]
141; CHECK-NEXT:    ret <2 x i12> [[R]]
142;
143  %a = add nuw <2 x i12> %x, <i12 5, i12 1>
144  %r = lshr <2 x i12> <i12 6, i12 42>, %a
145  ret <2 x i12> %r
146}
147
148; extra use is ok and in this case the result can be simplified to a constant
149
150define i32 @ashr_add_nuw(i32 %x, i32* %p) {
151; CHECK-LABEL: @ashr_add_nuw(
152; CHECK-NEXT:    [[A:%.*]] = add nuw i32 [[X:%.*]], 5
153; CHECK-NEXT:    store i32 [[A]], i32* [[P:%.*]], align 4
154; CHECK-NEXT:    ret i32 -1
155;
156  %a = add nuw i32 %x, 5
157  store i32 %a, i32* %p
158  %r = ashr i32 -6, %a
159  ret i32 %r
160}
161
162; negative test - must have 'nuw'
163
164define i32 @shl_add_nsw(i32 %x) {
165; CHECK-LABEL: @shl_add_nsw(
166; CHECK-NEXT:    [[A:%.*]] = add nsw i32 [[X:%.*]], 5
167; CHECK-NEXT:    [[R:%.*]] = shl i32 6, [[A]]
168; CHECK-NEXT:    ret i32 [[R]]
169;
170  %a = add nsw i32 %x, 5
171  %r = shl i32 6, %a
172  ret i32 %r
173}
174
175; offset precondition check (must be negative constant) for lshr_exact_add_negative_shift_positive
176
177define i32 @lshr_exact_add_positive_shift_positive(i32 %x) {
178; CHECK-LABEL: @lshr_exact_add_positive_shift_positive(
179; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 1
180; CHECK-NEXT:    [[R:%.*]] = lshr exact i32 2, [[A]]
181; CHECK-NEXT:    ret i32 [[R]]
182;
183  %a = add i32 %x, 1
184  %r = lshr exact i32 2, %a
185  ret i32 %r
186}
187
188define i32 @lshr_exact_add_big_negative_offset(i32 %x) {
189; CHECK-LABEL: @lshr_exact_add_big_negative_offset(
190; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -33
191; CHECK-NEXT:    [[R:%.*]] = lshr exact i32 2, [[A]]
192; CHECK-NEXT:    ret i32 [[R]]
193;
194  %a = add i32 %x, -33
195  %r = lshr exact i32 2, %a
196  ret i32 %r
197}
198
199; leading zeros for shifted constant precondition check for lshr_exact_add_negative_shift_positive
200
201define i32 @lshr_exact_add_negative_shift_negative(i32 %x) {
202; CHECK-LABEL: @lshr_exact_add_negative_shift_negative(
203; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -1
204; CHECK-NEXT:    [[R:%.*]] = lshr exact i32 -2, [[A]]
205; CHECK-NEXT:    ret i32 [[R]]
206;
207  %a = add i32 %x, -1
208  %r = lshr exact i32 -2, %a
209  ret i32 %r
210}
211
212; exact precondition check for lshr_exact_add_negative_shift_positive
213
214define i32 @lshr_add_negative_shift_no_exact(i32 %x) {
215; CHECK-LABEL: @lshr_add_negative_shift_no_exact(
216; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -1
217; CHECK-NEXT:    [[R:%.*]] = lshr i32 2, [[A]]
218; CHECK-NEXT:    ret i32 [[R]]
219;
220  %a = add i32 %x, -1
221  %r = lshr i32 2, %a
222  ret i32 %r
223}
224
225define i32 @lshr_exact_add_negative_shift_positive(i32 %x) {
226; CHECK-LABEL: @lshr_exact_add_negative_shift_positive(
227; CHECK-NEXT:    [[R:%.*]] = lshr exact i32 4, [[X:%.*]]
228; CHECK-NEXT:    ret i32 [[R]]
229;
230  %a = add i32 %x, -1
231  %r = lshr exact i32 2, %a
232  ret i32 %r
233}
234
235define i8 @lshr_exact_add_negative_shift_positive_extra_use(i8 %x) {
236; CHECK-LABEL: @lshr_exact_add_negative_shift_positive_extra_use(
237; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], -1
238; CHECK-NEXT:    call void @use(i8 [[A]])
239; CHECK-NEXT:    [[R:%.*]] = lshr exact i8 -128, [[X]]
240; CHECK-NEXT:    ret i8 [[R]]
241;
242  %a = add i8 %x, -1
243  call void @use(i8 %a)
244  %r = lshr exact i8 64, %a
245  ret i8 %r
246}
247
248define <2 x i9> @lshr_exact_add_negative_shift_positive_vec(<2 x i9> %x) {
249; CHECK-LABEL: @lshr_exact_add_negative_shift_positive_vec(
250; CHECK-NEXT:    [[R:%.*]] = lshr exact <2 x i9> <i9 -256, i9 -256>, [[X:%.*]]
251; CHECK-NEXT:    ret <2 x i9> [[R]]
252;
253  %a = add <2 x i9> %x, <i9 -7, i9 -7>
254  %r = lshr exact <2 x i9> <i9 2, i9 2>, %a
255  ret <2 x i9> %r
256}
257
258; not enough leading zeros in shift constant
259
260define <2 x i9> @lshr_exact_add_negative_shift_lzcnt(<2 x i9> %x) {
261; CHECK-LABEL: @lshr_exact_add_negative_shift_lzcnt(
262; CHECK-NEXT:    [[A:%.*]] = add <2 x i9> [[X:%.*]], <i9 -7, i9 -7>
263; CHECK-NEXT:    [[R:%.*]] = lshr exact <2 x i9> <i9 4, i9 4>, [[A]]
264; CHECK-NEXT:    ret <2 x i9> [[R]]
265;
266  %a = add <2 x i9> %x, <i9 -7, i9 -7>
267  %r = lshr exact <2 x i9> <i9 4, i9 4>, %a
268  ret <2 x i9> %r
269}
270
271; leading ones precondition check for ashr_exact_add_negative_shift_[positive,negative]
272
273define i8 @ashr_exact_add_negative_shift_no_trailing_zeros(i8 %x) {
274; CHECK-LABEL: @ashr_exact_add_negative_shift_no_trailing_zeros(
275; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], -4
276; CHECK-NEXT:    [[R:%.*]] = ashr exact i8 -112, [[A]]
277; CHECK-NEXT:    ret i8 [[R]]
278;
279  %a = add i8 %x, -4
280  %r = ashr exact i8 -112, %a ; 0b1001_0000
281  ret i8 %r
282}
283
284define i32 @ashr_exact_add_big_negative_offset(i32 %x) {
285; CHECK-LABEL: @ashr_exact_add_big_negative_offset(
286; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -33
287; CHECK-NEXT:    [[R:%.*]] = ashr exact i32 -2, [[A]]
288; CHECK-NEXT:    ret i32 [[R]]
289;
290  %a = add i32 %x, -33
291  %r = ashr exact i32 -2, %a
292  ret i32 %r
293}
294
295; exact precondition check for ashr_exact_add_negative_shift_[positive,negative]
296
297define i32 @ashr_add_negative_shift_no_exact(i32 %x) {
298; CHECK-LABEL: @ashr_add_negative_shift_no_exact(
299; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -1
300; CHECK-NEXT:    [[R:%.*]] = ashr i32 -2, [[A]]
301; CHECK-NEXT:    ret i32 [[R]]
302;
303  %a = add i32 %x, -1
304  %r = ashr i32 -2, %a
305  ret i32 %r
306}
307
308define i32 @ashr_exact_add_negative_shift_negative(i32 %x) {
309; CHECK-LABEL: @ashr_exact_add_negative_shift_negative(
310; CHECK-NEXT:    [[R:%.*]] = ashr exact i32 -4, [[X:%.*]]
311; CHECK-NEXT:    ret i32 [[R]]
312;
313  %a = add i32 %x, -1
314  %r = ashr exact i32 -2, %a
315  ret i32 %r
316}
317
318define i8 @ashr_exact_add_negative_shift_negative_extra_use(i8 %x) {
319; CHECK-LABEL: @ashr_exact_add_negative_shift_negative_extra_use(
320; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], -2
321; CHECK-NEXT:    call void @use(i8 [[A]])
322; CHECK-NEXT:    [[R:%.*]] = ashr exact i8 -128, [[X]]
323; CHECK-NEXT:    ret i8 [[R]]
324;
325  %a = add i8 %x, -2
326  call void @use(i8 %a)
327  %r = ashr exact i8 -32, %a
328  ret i8 %r
329}
330
331define <2 x i7> @ashr_exact_add_negative_shift_negative_vec(<2 x i7> %x) {
332; CHECK-LABEL: @ashr_exact_add_negative_shift_negative_vec(
333; CHECK-NEXT:    [[R:%.*]] = ashr exact <2 x i7> <i7 -64, i7 -64>, [[X:%.*]]
334; CHECK-NEXT:    ret <2 x i7> [[R]]
335;
336  %a = add <2 x i7> %x, <i7 -5, i7 -5>
337  %r = ashr exact <2 x i7> <i7 -2, i7 -2>, %a
338  ret <2 x i7> %r
339}
340
341; not enough leading ones in shift constant
342
343define <2 x i7> @ashr_exact_add_negative_leading_ones_vec(<2 x i7> %x) {
344; CHECK-LABEL: @ashr_exact_add_negative_leading_ones_vec(
345; CHECK-NEXT:    [[A:%.*]] = add <2 x i7> [[X:%.*]], <i7 -5, i7 -5>
346; CHECK-NEXT:    [[R:%.*]] = ashr exact <2 x i7> <i7 -4, i7 -4>, [[A]]
347; CHECK-NEXT:    ret <2 x i7> [[R]]
348;
349  %a = add <2 x i7> %x, <i7 -5, i7 -5>
350  %r = ashr exact <2 x i7> <i7 -4, i7 -4>, %a
351  ret <2 x i7> %r
352}
353
354; PR54890
355
356define i32 @shl_nsw_add_negative(i32 %x) {
357; CHECK-LABEL: @shl_nsw_add_negative(
358; CHECK-NEXT:    [[R:%.*]] = shl i32 1, [[X:%.*]]
359; CHECK-NEXT:    ret i32 [[R]]
360;
361  %a = add i32 %x, -1
362  %r = shl nsw i32 2, %a
363  ret i32 %r
364}
365
366; vectors and extra uses are allowed
367; nuw propagates to the new shift
368
369define <2 x i8> @shl_nuw_add_negative_splat_uses(<2 x i8> %x, <2 x i8>* %p) {
370; CHECK-LABEL: @shl_nuw_add_negative_splat_uses(
371; CHECK-NEXT:    [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -2, i8 -2>
372; CHECK-NEXT:    store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2
373; CHECK-NEXT:    [[R:%.*]] = shl nuw <2 x i8> <i8 3, i8 3>, [[X]]
374; CHECK-NEXT:    ret <2 x i8> [[R]]
375;
376  %a = add <2 x i8> %x, <i8 -2, i8 -2>
377  store <2 x i8> %a, <2 x i8>* %p
378  %r = shl nuw <2 x i8> <i8 12, i8 12>, %a
379  ret <2 x i8> %r
380}
381
382; negative test - shift constant must have enough trailing zeros to allow the pre-shift
383
384define i32 @shl_nsw_add_negative_invalid_constant(i32 %x) {
385; CHECK-LABEL: @shl_nsw_add_negative_invalid_constant(
386; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -2
387; CHECK-NEXT:    [[R:%.*]] = shl nsw i32 2, [[A]]
388; CHECK-NEXT:    ret i32 [[R]]
389;
390  %a = add i32 %x, -2
391  %r = shl nsw i32 2, %a
392  ret i32 %r
393}
394
395; negative test - the offset constant must be negative
396
397define i32 @shl_nsw_add_positive_invalid_constant(i32 %x) {
398; CHECK-LABEL: @shl_nsw_add_positive_invalid_constant(
399; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 2
400; CHECK-NEXT:    [[R:%.*]] = shl nsw i32 4, [[A]]
401; CHECK-NEXT:    ret i32 [[R]]
402;
403  %a = add i32 %x, 2
404  %r = shl nsw i32 4, %a
405  ret i32 %r
406}
407
408; negative test - a large shift must be detected without crashing
409
410define i32 @shl_nsw_add_negative_invalid_constant2(i32 %x) {
411; CHECK-LABEL: @shl_nsw_add_negative_invalid_constant2(
412; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -33
413; CHECK-NEXT:    [[R:%.*]] = shl nsw i32 2, [[A]]
414; CHECK-NEXT:    ret i32 [[R]]
415;
416  %a = add i32 %x, -33
417  %r = shl nsw i32 2, %a
418  ret i32 %r
419}
420
421; negative test - currently transformed to 'xor' before we see it,
422; but INT_MIN should be handled too
423
424define i4 @shl_nsw_add_negative_invalid_constant3(i4 %x) {
425; CHECK-LABEL: @shl_nsw_add_negative_invalid_constant3(
426; CHECK-NEXT:    [[A:%.*]] = xor i4 [[X:%.*]], -8
427; CHECK-NEXT:    [[R:%.*]] = shl nsw i4 2, [[A]]
428; CHECK-NEXT:    ret i4 [[R]]
429;
430  %a = add i4 %x, 8
431  %r = shl nsw i4 2, %a
432  ret i4 %r
433}
434