1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use16(i16)
5declare void @use32(i32)
6declare void @use64(i64)
7
8define i32 @t0(i64 %data, i32 %nbits) {
9; CHECK-LABEL: @t0(
10; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
11; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
12; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
13; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
14; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
15; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
16; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
17; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
18; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
19; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
20; CHECK-NEXT:    [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]]
21; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
22; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
23;
24  %skip_high = sub i32 64, %nbits
25  call void @use32(i32 %skip_high)
26  %skip_high_wide = zext i32 %skip_high to i64
27  call void @use64(i64 %skip_high_wide)
28  %extracted = lshr i64 %data, %skip_high_wide
29  call void @use64(i64 %extracted)
30  %extracted_narrow = trunc i64 %extracted to i32
31  call void @use32(i32 %extracted_narrow)
32  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
33  call void @use32(i32 %num_high_bits_to_smear_narrow)
34  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
35  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
36  ret i32 %signextended
37}
38define i32 @t0_zext_of_nbits(i64 %data, i8 %nbits_narrow) {
39; CHECK-LABEL: @t0_zext_of_nbits(
40; CHECK-NEXT:    [[NBITS:%.*]] = zext i8 [[NBITS_NARROW:%.*]] to i16
41; CHECK-NEXT:    call void @use16(i16 [[NBITS]])
42; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub nsw i16 64, [[NBITS]]
43; CHECK-NEXT:    call void @use16(i16 [[SKIP_HIGH]])
44; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i16 [[SKIP_HIGH]] to i64
45; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
46; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
47; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
48; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
49; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
50; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW_NARROW:%.*]] = sub nsw i16 32, [[NBITS]]
51; CHECK-NEXT:    call void @use16(i16 [[NUM_HIGH_BITS_TO_SMEAR_NARROW_NARROW]])
52; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = zext i16 [[NUM_HIGH_BITS_TO_SMEAR_NARROW_NARROW]] to i32
53; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
54; CHECK-NEXT:    [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]]
55; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
56; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
57;
58  %nbits = zext i8 %nbits_narrow to i16
59  call void @use16(i16 %nbits)
60  %skip_high = sub i16 64, %nbits
61  call void @use16(i16 %skip_high)
62  %skip_high_wide = zext i16 %skip_high to i64
63  call void @use64(i64 %skip_high_wide)
64  %extracted = lshr i64 %data, %skip_high_wide
65  call void @use64(i64 %extracted)
66  %extracted_narrow = trunc i64 %extracted to i32
67  call void @use32(i32 %extracted_narrow)
68  %num_high_bits_to_smear_narrow_narrow = sub i16 32, %nbits
69  call void @use16(i16 %num_high_bits_to_smear_narrow_narrow)
70  %num_high_bits_to_smear_narrow = zext i16 %num_high_bits_to_smear_narrow_narrow to i32
71  call void @use32(i32 %num_high_bits_to_smear_narrow)
72  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
73  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
74  ret i32 %signextended
75}
76define i32 @t0_exact(i64 %data, i32 %nbits) {
77; CHECK-LABEL: @t0_exact(
78; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
79; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
80; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
81; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
82; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr exact i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
83; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
84; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
85; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
86; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
87; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
88; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i64 [[DATA]], [[SKIP_HIGH_WIDE]]
89; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
90; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
91;
92  %skip_high = sub i32 64, %nbits
93  call void @use32(i32 %skip_high)
94  %skip_high_wide = zext i32 %skip_high to i64
95  call void @use64(i64 %skip_high_wide)
96  %extracted = lshr exact i64 %data, %skip_high_wide ; We can preserve `exact`-ness of the original shift.
97  call void @use64(i64 %extracted)
98  %extracted_narrow = trunc i64 %extracted to i32
99  call void @use32(i32 %extracted_narrow)
100  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
101  call void @use32(i32 %num_high_bits_to_smear_narrow)
102  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
103  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
104  ret i32 %signextended
105}
106
107define i32 @t1_redundant_sext(i64 %data, i32 %nbits) {
108; CHECK-LABEL: @t1_redundant_sext(
109; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
110; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
111; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
112; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
113; CHECK-NEXT:    [[EXTRACTED_WITH_SIGNEXTENSION:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
114; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED_WITH_SIGNEXTENSION]])
115; CHECK-NEXT:    [[EXTRACTED_WITH_SIGNEXTENSION_NARROW:%.*]] = trunc i64 [[EXTRACTED_WITH_SIGNEXTENSION]] to i32
116; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_WITH_SIGNEXTENSION_NARROW]])
117; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
118; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
119; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_WITH_SIGNEXTENSION_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
120; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT_POSITIONED]])
121; CHECK-NEXT:    ret i32 [[EXTRACTED_WITH_SIGNEXTENSION_NARROW]]
122;
123  %skip_high = sub i32 64, %nbits
124  call void @use32(i32 %skip_high)
125  %skip_high_wide = zext i32 %skip_high to i64
126  call void @use64(i64 %skip_high_wide)
127  %extracted_with_signextension = ashr i64 %data, %skip_high_wide
128  call void @use64(i64 %extracted_with_signextension)
129  %extracted_with_signextension_narrow = trunc i64 %extracted_with_signextension to i32 ; this is already the answer.
130  call void @use32(i32 %extracted_with_signextension_narrow)
131  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
132  call void @use32(i32 %num_high_bits_to_smear_narrow)
133  %signbit_positioned = shl i32 %extracted_with_signextension_narrow, %num_high_bits_to_smear_narrow
134  call void @use32(i32 %signbit_positioned)
135  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
136  ret i32 %signextended
137}
138
139define i64 @t2_notrunc(i64 %data, i64 %nbits) {
140; CHECK-LABEL: @t2_notrunc(
141; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i64 64, [[NBITS:%.*]]
142; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH]])
143; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH]]
144; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
145; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR:%.*]] = sub i64 64, [[NBITS]]
146; CHECK-NEXT:    call void @use64(i64 [[NUM_HIGH_BITS_TO_SMEAR]])
147; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i64 [[EXTRACTED]], [[NUM_HIGH_BITS_TO_SMEAR]]
148; CHECK-NEXT:    call void @use64(i64 [[SIGNBIT_POSITIONED]])
149; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH]]
150; CHECK-NEXT:    ret i64 [[SIGNEXTENDED]]
151;
152  %skip_high = sub i64 64, %nbits
153  call void @use64(i64 %skip_high)
154  %extracted = lshr i64 %data, %skip_high
155  call void @use64(i64 %extracted)
156  %num_high_bits_to_smear = sub i64 64, %nbits
157  call void @use64(i64 %num_high_bits_to_smear)
158  %signbit_positioned = shl i64 %extracted, %num_high_bits_to_smear ;
159  call void @use64(i64 %signbit_positioned)
160  %signextended = ashr i64 %signbit_positioned, %num_high_bits_to_smear ; can just shift %data itself.
161  ret i64 %signextended
162}
163
164define i64 @t3_notrunc_redundant_sext(i64 %data, i64 %nbits) {
165; CHECK-LABEL: @t3_notrunc_redundant_sext(
166; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i64 64, [[NBITS:%.*]]
167; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH]])
168; CHECK-NEXT:    [[EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH]]
169; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
170; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR:%.*]] = sub i64 64, [[NBITS]]
171; CHECK-NEXT:    call void @use64(i64 [[NUM_HIGH_BITS_TO_SMEAR]])
172; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i64 [[EXTRACTED]], [[NUM_HIGH_BITS_TO_SMEAR]]
173; CHECK-NEXT:    call void @use64(i64 [[SIGNBIT_POSITIONED]])
174; CHECK-NEXT:    ret i64 [[EXTRACTED]]
175;
176  %skip_high = sub i64 64, %nbits
177  call void @use64(i64 %skip_high)
178  %extracted = ashr i64 %data, %skip_high ; this is already the answer.
179  call void @use64(i64 %extracted)
180  %num_high_bits_to_smear = sub i64 64, %nbits
181  call void @use64(i64 %num_high_bits_to_smear)
182  %signbit_positioned = shl i64 %extracted, %num_high_bits_to_smear
183  call void @use64(i64 %signbit_positioned)
184  %signextended = ashr i64 %signbit_positioned, %num_high_bits_to_smear
185  ret i64 %signextended
186}
187
188define <2 x i32> @t4_vec(<2 x i64> %data, <2 x i32> %nbits) {
189; CHECK-LABEL: @t4_vec(
190; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub <2 x i32> splat (i32 64), [[NBITS:%.*]]
191; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext nneg <2 x i32> [[SKIP_HIGH]] to <2 x i64>
192; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i64> [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
193; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
194; CHECK-NEXT:    ret <2 x i32> [[SIGNEXTENDED]]
195;
196  %skip_high = sub <2 x i32> <i32 64, i32 64>, %nbits
197  %skip_high_wide = zext <2 x i32> %skip_high to <2 x i64>
198  %extracted = lshr <2 x i64> %data, %skip_high_wide
199  %extracted_narrow = trunc <2 x i64> %extracted to <2 x i32>
200  %num_high_bits_to_smear_narrow = sub <2 x i32> <i32 32, i32 32>, %nbits
201  %signbit_positioned = shl <2 x i32> %extracted_narrow, %num_high_bits_to_smear_narrow
202  %signextended = ashr <2 x i32> %signbit_positioned, %num_high_bits_to_smear_narrow
203  ret <2 x i32> %signextended
204}
205
206define <3 x i32> @t5_vec_poison(<3 x i64> %data, <3 x i32> %nbits) {
207; CHECK-LABEL: @t5_vec_poison(
208; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub <3 x i32> <i32 64, i32 64, i32 poison>, [[NBITS:%.*]]
209; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext nneg <3 x i32> [[SKIP_HIGH]] to <3 x i64>
210; CHECK-NEXT:    [[TMP1:%.*]] = ashr <3 x i64> [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
211; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc <3 x i64> [[TMP1]] to <3 x i32>
212; CHECK-NEXT:    ret <3 x i32> [[SIGNEXTENDED]]
213;
214  %skip_high = sub <3 x i32> <i32 64, i32 64, i32 poison>, %nbits
215  %skip_high_wide = zext <3 x i32> %skip_high to <3 x i64>
216  %extracted = lshr <3 x i64> %data, %skip_high_wide
217  %extracted_narrow = trunc <3 x i64> %extracted to <3 x i32>
218  %num_high_bits_to_smear_narrow0 = sub <3 x i32> <i32 32, i32 32, i32 poison>, %nbits
219  %num_high_bits_to_smear_narrow1 = sub <3 x i32> <i32 poison, i32 32, i32 32>, %nbits
220  %signbit_positioned = shl <3 x i32> %extracted_narrow, %num_high_bits_to_smear_narrow0
221  %signextended = ashr <3 x i32> %signbit_positioned, %num_high_bits_to_smear_narrow1
222  ret <3 x i32> %signextended
223}
224
225; Extra-uses
226define i32 @t6_extrause_good0(i64 %data, i32 %nbits) {
227; CHECK-LABEL: @t6_extrause_good0(
228; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
229; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
230; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
231; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
232; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
233; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
234; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
235; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
236; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
237; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
238; CHECK-NEXT:    [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]]
239; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
240; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
241;
242  %skip_high = sub i32 64, %nbits
243  call void @use32(i32 %skip_high)
244  %skip_high_wide = zext i32 %skip_high to i64
245  call void @use64(i64 %skip_high_wide)
246  %extracted = lshr i64 %data, %skip_high_wide
247  call void @use64(i64 %extracted)
248  %extracted_narrow = trunc i64 %extracted to i32
249  call void @use32(i32 %extracted_narrow)
250  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
251  call void @use32(i32 %num_high_bits_to_smear_narrow)
252  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow ; will go away
253  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
254  ret i32 %signextended
255}
256define i32 @t7_extrause_good1(i64 %data, i32 %nbits) {
257; CHECK-LABEL: @t7_extrause_good1(
258; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
259; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
260; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
261; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
262; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
263; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
264; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
265; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
266; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW0:%.*]] = sub i32 32, [[NBITS]]
267; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW0]])
268; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW0]]
269; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT_POSITIONED]])
270; CHECK-NEXT:    [[TMP1:%.*]] = ashr i64 [[DATA]], [[SKIP_HIGH_WIDE]]
271; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
272; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
273;
274  %skip_high = sub i32 64, %nbits
275  call void @use32(i32 %skip_high)
276  %skip_high_wide = zext i32 %skip_high to i64
277  call void @use64(i64 %skip_high_wide)
278  %extracted = lshr i64 %data, %skip_high_wide
279  call void @use64(i64 %extracted)
280  %extracted_narrow = trunc i64 %extracted to i32
281  call void @use32(i32 %extracted_narrow)
282  %num_high_bits_to_smear_narrow0 = sub i32 32, %nbits
283  call void @use32(i32 %num_high_bits_to_smear_narrow0)
284  %num_high_bits_to_smear_narrow1 = sub i32 32, %nbits ; will go away.
285  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow0
286  call void @use32(i32 %signbit_positioned)
287  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow1
288  ret i32 %signextended
289}
290define i32 @n8_extrause_bad(i64 %data, i32 %nbits) {
291; CHECK-LABEL: @n8_extrause_bad(
292; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
293; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
294; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
295; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
296; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
297; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
298; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
299; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
300; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
301; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
302; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
303; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT_POSITIONED]])
304; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
305; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
306;
307  %skip_high = sub i32 64, %nbits
308  call void @use32(i32 %skip_high)
309  %skip_high_wide = zext i32 %skip_high to i64
310  call void @use64(i64 %skip_high_wide)
311  %extracted = lshr i64 %data, %skip_high_wide
312  call void @use64(i64 %extracted)
313  %extracted_narrow = trunc i64 %extracted to i32
314  call void @use32(i32 %extracted_narrow)
315  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
316  call void @use32(i32 %num_high_bits_to_smear_narrow)
317  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
318  call void @use32(i32 %signbit_positioned)
319  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow ; neither of operands will go away.
320  ret i32 %signextended
321}
322
323; Negative tests
324define i32 @n9(i64 %data, i32 %nbits) {
325; CHECK-LABEL: @n9(
326; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 63, [[NBITS:%.*]]
327; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
328; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
329; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
330; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
331; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
332; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
333; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
334; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
335; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
336; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
337; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
338; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
339;
340  %skip_high = sub i32 63, %nbits ; not 64
341  call void @use32(i32 %skip_high)
342  %skip_high_wide = zext i32 %skip_high to i64
343  call void @use64(i64 %skip_high_wide)
344  %extracted = lshr i64 %data, %skip_high_wide
345  call void @use64(i64 %extracted)
346  %extracted_narrow = trunc i64 %extracted to i32
347  call void @use32(i32 %extracted_narrow)
348  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
349  call void @use32(i32 %num_high_bits_to_smear_narrow)
350  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
351  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
352  ret i32 %signextended
353}
354
355define i32 @n10(i64 %data, i32 %nbits) {
356; CHECK-LABEL: @n10(
357; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
358; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
359; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
360; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
361; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
362; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
363; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
364; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
365; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 31, [[NBITS]]
366; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
367; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
368; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
369; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
370;
371  %skip_high = sub i32 64, %nbits
372  call void @use32(i32 %skip_high)
373  %skip_high_wide = zext i32 %skip_high to i64
374  call void @use64(i64 %skip_high_wide)
375  %extracted = lshr i64 %data, %skip_high_wide
376  call void @use64(i64 %extracted)
377  %extracted_narrow = trunc i64 %extracted to i32
378  call void @use32(i32 %extracted_narrow)
379  %num_high_bits_to_smear_narrow = sub i32 31, %nbits ; not 32
380  call void @use32(i32 %num_high_bits_to_smear_narrow)
381  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
382  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
383  ret i32 %signextended
384}
385
386define i32 @n11(i64 %data, i32 %nbits1, i32 %nbits2) {
387; CHECK-LABEL: @n11(
388; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS1:%.*]]
389; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
390; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
391; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
392; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
393; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
394; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
395; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
396; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS2:%.*]]
397; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
398; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
399; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
400; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
401;
402  %skip_high = sub i32 64, %nbits1 ; not %nbits2
403  call void @use32(i32 %skip_high)
404  %skip_high_wide = zext i32 %skip_high to i64
405  call void @use64(i64 %skip_high_wide)
406  %extracted = lshr i64 %data, %skip_high_wide
407  call void @use64(i64 %extracted)
408  %extracted_narrow = trunc i64 %extracted to i32
409  call void @use32(i32 %extracted_narrow)
410  %num_high_bits_to_smear_narrow = sub i32 32, %nbits2 ; not %nbits1
411  call void @use32(i32 %num_high_bits_to_smear_narrow)
412  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
413  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow
414  ret i32 %signextended
415}
416
417define i32 @n12(i64 %data, i32 %nbits1, i32 %nbits2) {
418; CHECK-LABEL: @n12(
419; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS1:%.*]]
420; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
421; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
422; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
423; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
424; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
425; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
426; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
427; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW1:%.*]] = sub i32 32, [[NBITS1]]
428; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW2:%.*]] = sub i32 32, [[NBITS2:%.*]]
429; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW1]])
430; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW2]])
431; CHECK-NEXT:    [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW1]]
432; CHECK-NEXT:    [[SIGNEXTENDED:%.*]] = ashr i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW2]]
433; CHECK-NEXT:    ret i32 [[SIGNEXTENDED]]
434;
435  %skip_high = sub i32 64, %nbits1
436  call void @use32(i32 %skip_high)
437  %skip_high_wide = zext i32 %skip_high to i64
438  call void @use64(i64 %skip_high_wide)
439  %extracted = lshr i64 %data, %skip_high_wide
440  call void @use64(i64 %extracted)
441  %extracted_narrow = trunc i64 %extracted to i32
442  call void @use32(i32 %extracted_narrow)
443  %num_high_bits_to_smear_narrow1 = sub i32 32, %nbits1 ; not %nbits2
444  %num_high_bits_to_smear_narrow2 = sub i32 32, %nbits2 ; not %nbits1
445  call void @use32(i32 %num_high_bits_to_smear_narrow1)
446  call void @use32(i32 %num_high_bits_to_smear_narrow2)
447  %signbit_positioned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow1
448  %signextended = ashr i32 %signbit_positioned, %num_high_bits_to_smear_narrow2
449  ret i32 %signextended
450}
451
452define i32 @n13(i64 %data, i32 %nbits) {
453; CHECK-LABEL: @n13(
454; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
455; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
456; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
457; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
458; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
459; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
460; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
461; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
462; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
463; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
464; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 -1, [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
465; CHECK-NEXT:    [[RES:%.*]] = and i32 [[TMP1]], [[EXTRACTED_NARROW]]
466; CHECK-NEXT:    ret i32 [[RES]]
467;
468  %skip_high = sub i32 64, %nbits
469  call void @use32(i32 %skip_high)
470  %skip_high_wide = zext i32 %skip_high to i64
471  call void @use64(i64 %skip_high_wide)
472  %extracted = lshr i64 %data, %skip_high_wide
473  call void @use64(i64 %extracted)
474  %extracted_narrow = trunc i64 %extracted to i32
475  call void @use32(i32 %extracted_narrow)
476  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
477  call void @use32(i32 %num_high_bits_to_smear_narrow)
478  %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
479  %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr
480  ret i32 %res
481}
482define i32 @n13_extrause(i64 %data, i32 %nbits) {
483; CHECK-LABEL: @n13_extrause(
484; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
485; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
486; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
487; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
488; CHECK-NEXT:    [[EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
489; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
490; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
491; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
492; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
493; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
494; CHECK-NEXT:    [[HIGHBITS_CLEANED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
495; CHECK-NEXT:    call void @use32(i32 [[HIGHBITS_CLEANED]])
496; CHECK-NEXT:    [[RES:%.*]] = lshr exact i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
497; CHECK-NEXT:    ret i32 [[RES]]
498;
499  %skip_high = sub i32 64, %nbits
500  call void @use32(i32 %skip_high)
501  %skip_high_wide = zext i32 %skip_high to i64
502  call void @use64(i64 %skip_high_wide)
503  %extracted = lshr i64 %data, %skip_high_wide
504  call void @use64(i64 %extracted)
505  %extracted_narrow = trunc i64 %extracted to i32
506  call void @use32(i32 %extracted_narrow)
507  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
508  call void @use32(i32 %num_high_bits_to_smear_narrow)
509  %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
510  call void @use32(i32 %highbits_cleaned)
511  %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr
512  ret i32 %res
513}
514define i32 @n14(i64 %data, i32 %nbits) {
515; CHECK-LABEL: @n14(
516; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
517; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
518; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
519; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
520; CHECK-NEXT:    [[EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
521; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
522; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
523; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
524; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
525; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
526; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 -1, [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
527; CHECK-NEXT:    [[RES:%.*]] = and i32 [[TMP1]], [[EXTRACTED_NARROW]]
528; CHECK-NEXT:    ret i32 [[RES]]
529;
530  %skip_high = sub i32 64, %nbits
531  call void @use32(i32 %skip_high)
532  %skip_high_wide = zext i32 %skip_high to i64
533  call void @use64(i64 %skip_high_wide)
534  %extracted = ashr i64 %data, %skip_high_wide
535  call void @use64(i64 %extracted)
536  %extracted_narrow = trunc i64 %extracted to i32
537  call void @use32(i32 %extracted_narrow)
538  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
539  call void @use32(i32 %num_high_bits_to_smear_narrow)
540  %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
541  %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr
542  ret i32 %res
543}
544define i32 @n14_extrause(i64 %data, i32 %nbits) {
545; CHECK-LABEL: @n14_extrause(
546; CHECK-NEXT:    [[SKIP_HIGH:%.*]] = sub i32 64, [[NBITS:%.*]]
547; CHECK-NEXT:    call void @use32(i32 [[SKIP_HIGH]])
548; CHECK-NEXT:    [[SKIP_HIGH_WIDE:%.*]] = zext i32 [[SKIP_HIGH]] to i64
549; CHECK-NEXT:    call void @use64(i64 [[SKIP_HIGH_WIDE]])
550; CHECK-NEXT:    [[EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[SKIP_HIGH_WIDE]]
551; CHECK-NEXT:    call void @use64(i64 [[EXTRACTED]])
552; CHECK-NEXT:    [[EXTRACTED_NARROW:%.*]] = trunc i64 [[EXTRACTED]] to i32
553; CHECK-NEXT:    call void @use32(i32 [[EXTRACTED_NARROW]])
554; CHECK-NEXT:    [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
555; CHECK-NEXT:    call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
556; CHECK-NEXT:    [[HIGHBITS_CLEANED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
557; CHECK-NEXT:    call void @use32(i32 [[HIGHBITS_CLEANED]])
558; CHECK-NEXT:    [[RES:%.*]] = lshr exact i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
559; CHECK-NEXT:    ret i32 [[RES]]
560;
561  %skip_high = sub i32 64, %nbits
562  call void @use32(i32 %skip_high)
563  %skip_high_wide = zext i32 %skip_high to i64
564  call void @use64(i64 %skip_high_wide)
565  %extracted = ashr i64 %data, %skip_high_wide
566  call void @use64(i64 %extracted)
567  %extracted_narrow = trunc i64 %extracted to i32
568  call void @use32(i32 %extracted_narrow)
569  %num_high_bits_to_smear_narrow = sub i32 32, %nbits
570  call void @use32(i32 %num_high_bits_to_smear_narrow)
571  %highbits_cleaned = shl i32 %extracted_narrow, %num_high_bits_to_smear_narrow
572  call void @use32(i32 %highbits_cleaned)
573  %res = lshr i32 %highbits_cleaned, %num_high_bits_to_smear_narrow ; not ashr
574  ret i32 %res
575}
576